Merge changes Ia90c6390,I5b3ed1b8 into sc-dev am: 9581a89057 am: 505d154c31 am: bfb9cb44f3
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/interfaces/+/15350855
Change-Id: I0a897d6650f4b58ac4fb8594798c07cabec968b9
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index e446a7f..9f4a295 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -30,6 +30,7 @@
"android.hardware.audio.common.test.utility",
"audioclient-types-aidl-cpp",
"libaudioclient_aidl_conversion",
+ "libstagefright_foundation",
],
shared_libs: [
"libbinder",
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 790adcd..2ebd1b4 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -35,6 +35,7 @@
"protocols/generic/Generic.cpp",
"protocols/generic/GenericMessageBase.cpp",
"protocols/generic/Unknown.cpp",
+ "protocols/generic/families/Mac80211hwsim.cpp",
"protocols/generic/families/Nl80211.cpp",
"protocols/route/Link.cpp",
"protocols/route/Route.cpp",
@@ -42,6 +43,7 @@
"protocols/MessageDefinition.cpp",
"protocols/NetlinkProtocol.cpp",
"protocols/all.cpp",
+ "protocols/structs.cpp",
"Attributes.cpp",
"MessageFactory.cpp",
"MessageMutator.cpp",
diff --git a/automotive/can/1.0/default/libnl++/MessageMutator.cpp b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
index 00b48a6..de2a2b1 100644
--- a/automotive/can/1.0/default/libnl++/MessageMutator.cpp
+++ b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
@@ -19,7 +19,7 @@
namespace android::nl {
MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
- : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) {
+ : mMutableBuffer(buffer), mTotalLen(totalLen) {
CHECK(totalLen >= sizeof(nlmsghdr));
}
@@ -27,8 +27,12 @@
return mMutableBuffer;
}
+Buffer<nlmsghdr> MessageMutator::constBuffer() const {
+ return {mMutableBuffer, mTotalLen};
+}
+
MessageMutator::operator Buffer<nlmsghdr>() const {
- return mConstBuffer;
+ return constBuffer();
}
uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
@@ -37,7 +41,8 @@
void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
const auto attrData = attr.data<uint64_t>();
- const auto offset = mConstBuffer.getOffset(attrData);
+ // TODO(b/177251183): deduplicate this code against fragment()
+ const auto offset = constBuffer().getOffset(attrData);
CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";
const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
@@ -47,4 +52,40 @@
memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
}
+MessageMutator MessageMutator::fragment(Buffer<nlmsghdr> buf) const {
+ const auto offset = constBuffer().getOffset(buf);
+ CHECK(offset.has_value()) << "Trying to modify a fragment outside of buffer range";
+
+ const auto writeableBuffer = reinterpret_cast<nlmsghdr*>(uintptr_t(mMutableBuffer) + *offset);
+ const auto len = buf.getRaw().len();
+ CHECK(len <= mTotalLen - *offset);
+
+ return {writeableBuffer, len};
+}
+
+MessageMutator::iterator MessageMutator::begin() const {
+ return {*this, constBuffer().begin()};
+}
+
+MessageMutator::iterator MessageMutator::end() const {
+ return {*this, constBuffer().end()};
+}
+
+MessageMutator::iterator::iterator(const MessageMutator& container,
+ Buffer<nlmsghdr>::iterator current)
+ : mContainer(container), mCurrent(current) {}
+
+MessageMutator::iterator MessageMutator::iterator::operator++() {
+ ++mCurrent;
+ return *this;
+}
+
+bool MessageMutator::iterator::operator==(const iterator& other) const {
+ return other.mCurrent == mCurrent;
+}
+
+const MessageMutator MessageMutator::iterator::operator*() const {
+ return mContainer.fragment(*mCurrent);
+}
+
} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp
index 514d9bb..b0e67be 100644
--- a/automotive/can/1.0/default/libnl++/Socket.cpp
+++ b/automotive/can/1.0/default/libnl++/Socket.cpp
@@ -68,6 +68,11 @@
return true;
}
+bool Socket::send(const Buffer<nlmsghdr>& msg, uint32_t destination) {
+ sockaddr_nl sa = {.nl_family = AF_NETLINK, .nl_pad = 0, .nl_pid = destination, .nl_groups = 0};
+ return send(msg, sa);
+}
+
bool Socket::increaseReceiveBuffer(size_t maxSize) {
if (maxSize == 0) {
LOG(ERROR) << "Maximum receive size should not be zero";
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
index d759a0a..4cabb9a 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
@@ -138,7 +138,7 @@
class raw_iterator : public iterator {
public:
iterator operator++() {
- this->mCurrent.mData++; // ignore alignment
+ ++this->mCurrent.mData; // ignore alignment
return *this;
}
const T& operator*() const { return *this->mCurrent.mData; }
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Message.h b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
index 50b3c4b..29f397d 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Message.h
@@ -34,7 +34,7 @@
* a single instance can only be used by a single thread - the one owning the underlying buffer).
*/
template <typename T>
-class Message {
+class Message : public Buffer<nlmsghdr> {
public:
/**
* Validate buffer contents as a message carrying T data and create instance of parsed message.
@@ -51,7 +51,7 @@
const auto attributes = buf.data<nlattr>(sizeof(T));
- return Message<T>(nlHeader, dataHeader, attributes);
+ return Message<T>(buf, nlHeader, dataHeader, attributes);
}
/**
@@ -94,8 +94,9 @@
const T* operator->() const { return &data; }
private:
- Message(const nlmsghdr& nlHeader, const T& dataHeader, Attributes attributes)
- : header(nlHeader), data(dataHeader), attributes(attributes) {}
+ Message(Buffer<nlmsghdr> buffer, const nlmsghdr& nlHeader, const T& dataHeader,
+ Attributes attributes)
+ : Buffer<nlmsghdr>(buffer), header(nlHeader), data(dataHeader), attributes(attributes) {}
};
} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
index 7d495e9..baadc44 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
@@ -53,9 +53,27 @@
*/
void write(Buffer<nlattr> attr, uint64_t val) const;
+ class iterator {
+ public:
+ iterator(const MessageMutator& container, Buffer<nlmsghdr>::iterator current);
+
+ iterator operator++();
+ bool operator==(const iterator& other) const;
+ const MessageMutator operator*() const;
+
+ protected:
+ const MessageMutator& mContainer;
+ Buffer<nlmsghdr>::iterator mCurrent;
+ };
+ iterator begin() const;
+ iterator end() const;
+
private:
- const Buffer<nlmsghdr> mConstBuffer;
nlmsghdr* mMutableBuffer;
+ size_t mTotalLen;
+
+ Buffer<nlmsghdr> constBuffer() const;
+ MessageMutator fragment(Buffer<nlmsghdr> buf) const;
};
} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
index 8ea3575..118b9f7 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
@@ -95,6 +95,15 @@
bool send(const Buffer<nlmsghdr>& msg, const sockaddr_nl& sa);
/**
+ * Send Netlink message.
+ *
+ * \param msg Message to send.
+ * \param destination Destination PID.
+ * \return true, if succeeded.
+ */
+ bool send(const Buffer<nlmsghdr>& msg, uint32_t destination);
+
+ /**
* Receive one or multiple Netlink messages.
*
* WARNING: the underlying buffer is owned by Socket class and the data is valid until the next
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h b/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h
new file mode 100644
index 0000000..9b811f8
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/generic/families/mac80211_hwsim.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// API definitions from kernel drivers/net/wireless/mac80211_hwsim.h
+
+#define BIT(n) (1 << (n))
+
+enum hwsim_tx_control_flags {
+ HWSIM_TX_CTL_REQ_TX_STATUS = BIT(0),
+ HWSIM_TX_CTL_NO_ACK = BIT(1),
+ HWSIM_TX_STAT_ACK = BIT(2),
+};
+
+enum {
+ HWSIM_CMD_UNSPEC,
+ HWSIM_CMD_REGISTER,
+ HWSIM_CMD_FRAME,
+ HWSIM_CMD_TX_INFO_FRAME,
+ HWSIM_CMD_NEW_RADIO,
+ HWSIM_CMD_DEL_RADIO,
+ HWSIM_CMD_GET_RADIO,
+ HWSIM_CMD_ADD_MAC_ADDR,
+ HWSIM_CMD_DEL_MAC_ADDR,
+};
+
+enum {
+ HWSIM_ATTR_UNSPEC,
+ HWSIM_ATTR_ADDR_RECEIVER,
+ HWSIM_ATTR_ADDR_TRANSMITTER,
+ HWSIM_ATTR_FRAME,
+ HWSIM_ATTR_FLAGS,
+ HWSIM_ATTR_RX_RATE,
+ HWSIM_ATTR_SIGNAL,
+ HWSIM_ATTR_TX_INFO,
+ HWSIM_ATTR_COOKIE,
+ HWSIM_ATTR_CHANNELS,
+ HWSIM_ATTR_RADIO_ID,
+ HWSIM_ATTR_REG_HINT_ALPHA2,
+ HWSIM_ATTR_REG_CUSTOM_REG,
+ HWSIM_ATTR_REG_STRICT_REG,
+ HWSIM_ATTR_SUPPORT_P2P_DEVICE,
+ HWSIM_ATTR_USE_CHANCTX,
+ HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
+ HWSIM_ATTR_RADIO_NAME,
+ HWSIM_ATTR_NO_VIF,
+ HWSIM_ATTR_FREQ,
+ HWSIM_ATTR_PAD,
+ HWSIM_ATTR_TX_INFO_FLAGS,
+ HWSIM_ATTR_PERM_ADDR,
+ HWSIM_ATTR_IFTYPE_SUPPORT,
+ HWSIM_ATTR_CIPHER_SUPPORT,
+};
+
+struct hwsim_tx_rate {
+ int8_t idx;
+ uint8_t count;
+} __packed;
+static_assert(sizeof(hwsim_tx_rate) == 2);
+
+#undef BIT
diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp
index f08897e..d540482 100644
--- a/automotive/can/1.0/default/libnl++/printer.cpp
+++ b/automotive/can/1.0/default/libnl++/printer.cpp
@@ -154,16 +154,19 @@
}
}
-std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload) {
- if (!hdr.firstOk()) return "nlmsg{buffer overflow}";
+static void toStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr, int protocol,
+ bool printPayload) {
+ if (!hdr.firstOk()) {
+ ss << "nlmsg{buffer overflow}";
+ return;
+ }
- std::stringstream ss;
ss << std::setfill('0');
auto protocolMaybe = protocols::get(protocol);
if (!protocolMaybe.has_value()) {
ss << "nlmsg{protocol=" << protocol << "}";
- return ss.str();
+ return;
}
protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
@@ -187,7 +190,7 @@
ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
ss << '}';
- if (!printPayload) return ss.str();
+ if (!printPayload) return;
ss << ' ';
if (!msgDescMaybe.has_value()) {
@@ -210,6 +213,17 @@
}
ss << "}";
+}
+
+std::string toString(const Buffer<nlmsghdr> hdrs, int protocol, bool printPayload) {
+ std::stringstream ss;
+ bool first = true;
+ for (const auto hdr : hdrs) {
+ if (!first) ss << std::endl;
+ first = false;
+
+ toStream(ss, hdr, protocol, printPayload);
+ }
return ss.str();
}
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
index 1e1ad12..478c383 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/Ctrl.cpp
@@ -16,6 +16,7 @@
#include "Ctrl.h"
+#include "families/Mac80211hwsim.h"
#include "families/Nl80211.h"
#include <libnl++/Message.h>
@@ -68,12 +69,15 @@
const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
- /* For now, we support just a single family. But if you add more, please define proper
+ /* For now, we support just two families. But if you add more, please define proper
* abstraction and not hardcode every name and class here.
*/
if (familyName == "nl80211") {
mFamilyRegister[familyId] = std::make_shared<families::Nl80211>(familyId);
}
+ if (familyName == "MAC80211_HWSIM") {
+ mFamilyRegister[familyId] = std::make_shared<families::Mac80211hwsim>(familyId);
+ }
}
} // namespace android::nl::protocols::generic
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
index b7b811b..f92d6c0 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
@@ -40,9 +40,9 @@
ss << "genlmsghdr{";
if (commandName.has_value()) {
- ss << "cmd=" << unsigned(data.cmd);
- } else {
ss << "cmd=" << *commandName;
+ } else {
+ ss << "cmd=" << unsigned(data.cmd);
}
ss << ", version=" << unsigned(data.version);
if (data.reserved != 0) ss << ", reserved=" << data.reserved;
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp
new file mode 100644
index 0000000..f85309e
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Mac80211hwsim.h"
+
+#include "../../structs.h"
+#include "common.h"
+
+#include <libnl++/generic/families/mac80211_hwsim.h>
+
+namespace android::nl::protocols::generic::families {
+
+using DataType = AttributeDefinition::DataType;
+using Flags = AttributeDefinition::Flags;
+
+static void hwsim_tx_rateToStream(std::stringstream& ss, const Buffer<nlattr> attr);
+
+static const FlagsMap txControlFlags{
+ {HWSIM_TX_CTL_REQ_TX_STATUS, "REQ_TX"},
+ {HWSIM_TX_CTL_NO_ACK, "NO_ACK"},
+ {HWSIM_TX_STAT_ACK, "ACK"},
+};
+
+// clang-format off
+Mac80211hwsim::Mac80211hwsim(nlmsgtype_t familyId) : GenericMessageBase(familyId, "hwsim", {
+ {HWSIM_CMD_UNSPEC, "UNSPEC"},
+ {HWSIM_CMD_REGISTER, "REGISTER"},
+ {HWSIM_CMD_FRAME, "FRAME"},
+ {HWSIM_CMD_TX_INFO_FRAME, "TX_INFO_FRAME"},
+ {HWSIM_CMD_NEW_RADIO, "NEW_RADIO"},
+ {HWSIM_CMD_DEL_RADIO, "DEL_RADIO"},
+ {HWSIM_CMD_GET_RADIO, "GET_RADIO"},
+ {HWSIM_CMD_ADD_MAC_ADDR, "ADD_MAC_ADDR"},
+ {HWSIM_CMD_DEL_MAC_ADDR, "DEL_MAC_ADDR"},
+}, {
+ {HWSIM_ATTR_UNSPEC, {"UNSPEC"}},
+ {HWSIM_ATTR_ADDR_RECEIVER, {"ADDR_RECEIVER", DataType::Struct, hwaddrToStream}},
+ {HWSIM_ATTR_ADDR_TRANSMITTER, {"ADDR_TRANSMITTER", DataType::Struct, hwaddrToStream}},
+ {HWSIM_ATTR_FRAME, {"FRAME", DataType::Raw, AttributeMap{}, Flags::Verbose}},
+ {HWSIM_ATTR_FLAGS, {"FLAGS", DataType::Struct, flagsToStream(txControlFlags)}},
+ {HWSIM_ATTR_RX_RATE, {"RX_RATE", DataType::Uint}},
+ {HWSIM_ATTR_SIGNAL, {"SIGNAL", DataType::Uint}},
+ {HWSIM_ATTR_TX_INFO, {"TX_INFO", DataType::Struct, hwsim_tx_rateToStream}},
+ {HWSIM_ATTR_COOKIE, {"COOKIE", DataType::Uint}},
+ {HWSIM_ATTR_CHANNELS, {"CHANNELS", DataType::Uint}},
+ {HWSIM_ATTR_RADIO_ID, {"RADIO_ID", DataType::Uint}},
+ {HWSIM_ATTR_REG_HINT_ALPHA2, {"REG_HINT_ALPHA2", DataType::String}},
+ {HWSIM_ATTR_REG_CUSTOM_REG, {"REG_CUSTOM_REG", DataType::Uint}},
+ {HWSIM_ATTR_REG_STRICT_REG, {"REG_STRICT_REG", DataType::Flag}},
+ {HWSIM_ATTR_SUPPORT_P2P_DEVICE, {"SUPPORT_P2P_DEVICE", DataType::Flag}},
+ {HWSIM_ATTR_USE_CHANCTX, {"USE_CHANCTX", DataType::Flag}},
+ {HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, {"DESTROY_RADIO_ON_CLOSE", DataType::Flag}},
+ {HWSIM_ATTR_RADIO_NAME, {"RADIO_NAME", DataType::String}},
+ {HWSIM_ATTR_NO_VIF, {"NO_VIF", DataType::Flag}},
+ {HWSIM_ATTR_FREQ, {"FREQ", DataType::Uint}},
+ {HWSIM_ATTR_PAD, {"PAD", DataType::Uint}},
+ {HWSIM_ATTR_TX_INFO_FLAGS, {"TX_INFO_FLAGS"}}, // hwsim_tx_rate_flag
+ {HWSIM_ATTR_PERM_ADDR, {"PERM_ADDR"}},
+ {HWSIM_ATTR_IFTYPE_SUPPORT, {"IFTYPE_SUPPORT", DataType::Uint}}, // NL80211_IFTYPE_STATION etc
+ {HWSIM_ATTR_CIPHER_SUPPORT, {"CIPHER_SUPPORT", DataType::Struct, arrayToStream<int32_t>}},
+}) {}
+// clang-format on
+
+static void hwsim_tx_rateToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
+ ss << '{';
+ bool first = true;
+ for (const auto rate : attr.data<hwsim_tx_rate>().getRaw()) {
+ if (rate.idx == -1) continue;
+
+ ss << (int)rate.idx << ": " << (unsigned)rate.count;
+
+ if (!first) ss << ", ";
+ first = false;
+ }
+ ss << '}';
+}
+
+} // namespace android::nl::protocols::generic::families
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h
new file mode 100644
index 0000000..c01eb93
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/families/Mac80211hwsim.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "../GenericMessageBase.h"
+
+namespace android::nl::protocols::generic::families {
+
+class Mac80211hwsim : public GenericMessageBase {
+ public:
+ Mac80211hwsim(nlmsgtype_t familyId);
+};
+
+} // namespace android::nl::protocols::generic::families
diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.cpp b/automotive/can/1.0/default/libnl++/protocols/structs.cpp
new file mode 100644
index 0000000..8ff71f0
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/structs.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "structs.h"
+
+#include <iomanip>
+
+namespace android::nl::protocols {
+
+AttributeDefinition::ToStream flagsToStream(FlagsMap flags) {
+ return [flags](std::stringstream& ss, const Buffer<nlattr> attr) {
+ auto val = attr.data<uint64_t>().copyFirst();
+
+ bool first = true;
+ for (const auto& [flag, name] : flags) {
+ if ((val & flag) != flag) continue;
+ val &= ~flag;
+
+ if (!first) ss << '|';
+ first = false;
+
+ ss << name;
+ }
+
+ if (val == 0) return;
+
+ if (!first) ss << '|';
+ ss << std::hex << val << std::dec;
+ };
+}
+
+void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
+ ss << std::hex;
+ bool first = true;
+ for (const auto byte : attr.data<uint8_t>().getRaw()) {
+ if (!first) ss << ':';
+ first = false;
+
+ ss << std::setw(2) << unsigned(byte);
+ }
+ ss << std::dec;
+}
+
+} // namespace android::nl::protocols
diff --git a/automotive/can/1.0/default/libnl++/protocols/structs.h b/automotive/can/1.0/default/libnl++/protocols/structs.h
index 44c17b8..f3a8c44 100644
--- a/automotive/can/1.0/default/libnl++/protocols/structs.h
+++ b/automotive/can/1.0/default/libnl++/protocols/structs.h
@@ -16,6 +16,8 @@
#pragma once
+#include "MessageDefinition.h"
+
#include <sstream>
namespace android::nl::protocols {
@@ -30,4 +32,9 @@
ss << '}';
}
+typedef std::map<uint64_t, std::string> FlagsMap;
+AttributeDefinition::ToStream flagsToStream(FlagsMap flags);
+
+void hwaddrToStream(std::stringstream& ss, const Buffer<nlattr> attr);
+
} // namespace android::nl::protocols
diff --git a/automotive/occupant_awareness/aidl/Android.bp b/automotive/occupant_awareness/aidl/Android.bp
index 26c53fa..288dc6d 100644
--- a/automotive/occupant_awareness/aidl/Android.bp
+++ b/automotive/occupant_awareness/aidl/Android.bp
@@ -16,7 +16,7 @@
stability: "vintf",
backend: {
java: {
- platform_apis: true,
+ sdk_version: "module_current",
},
ndk: {
vndk: {
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index ffa0c13..2e8ca66 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -47,6 +47,7 @@
cc_library_headers {
name: "vhal_v2_0_common_headers",
+ visibility: ["//visibility:public"],
vendor: true,
export_include_dirs: ["common/include/vhal_v2_0"],
}
@@ -58,6 +59,7 @@
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"common/src/Obd2SensorStore.cpp",
+ "common/src/ProtoMessageConverter.cpp",
"common/src/SubscriptionManager.cpp",
"common/src/VehicleHalManager.cpp",
"common/src/VehicleObjectPool.cpp",
@@ -68,9 +70,13 @@
],
shared_libs: [
"libbase",
+ "libprotobuf-cpp-lite",
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["common/include"],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0-libproto-native",
+ ],
}
// Vehicle default VehicleHAL implementation
@@ -80,24 +86,16 @@
defaults: ["vhal_v2_0_target_defaults"],
cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
srcs: [
- "impl/vhal_v2_0/CommConn.cpp",
- "impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
- "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+ "impl/vhal_v2_0/DefaultVehicleHal.cpp",
"impl/vhal_v2_0/VehicleHalClient.cpp",
- "impl/vhal_v2_0/VehicleHalServer.cpp",
- "impl/vhal_v2_0/VehicleEmulator.cpp",
- "impl/vhal_v2_0/PipeComm.cpp",
- "impl/vhal_v2_0/ProtoMessageConverter.cpp",
- "impl/vhal_v2_0/SocketComm.cpp",
+ "impl/vhal_v2_0/DefaultVehicleHalServer.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
"impl/vhal_v2_0/GeneratorHub.cpp",
- "impl/vhal_v2_0/qemu_pipe.cpp",
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
whole_static_libs: [
- "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
"android.hardware.automotive.vehicle@2.0-manager-lib",
],
shared_libs: [
@@ -110,19 +108,6 @@
],
}
-// Library used to emulate User HAL behavior through lshal debug requests.
-cc_library_static {
- name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
- vendor: true,
- defaults: ["vhal_v2_0_target_defaults"],
- srcs: [
- "impl/vhal_v2_0/EmulatedUserHal.cpp",
- ],
- whole_static_libs: [
- "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
- ],
-}
-
// Vehicle HAL Server reference impl lib
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-server-common-lib",
@@ -133,10 +118,14 @@
export_include_dirs: ["common/include"],
srcs: [
"common/src/Obd2SensorStore.cpp",
+ "common/src/ProtoMessageConverter.cpp",
"common/src/VehicleObjectPool.cpp",
"common/src/VehiclePropertyStore.cpp",
"common/src/VehicleUtils.cpp",
],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0-libproto-native",
+ ],
}
// Vehicle HAL Server default implementation
@@ -151,8 +140,7 @@
"impl/vhal_v2_0/GeneratorHub.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
- "impl/vhal_v2_0/ProtoMessageConverter.cpp",
- "impl/vhal_v2_0/VehicleHalServer.cpp",
+ "impl/vhal_v2_0/DefaultVehicleHalServer.cpp",
],
whole_static_libs: [
"android.hardware.automotive.vehicle@2.0-server-common-lib",
@@ -182,6 +170,17 @@
],
shared_libs: [
"libbase",
+ "libcutils",
+ ],
+ // Exclude share libraries from default because they might be missing on
+ // some test platforms and we are using static libraries instead.
+ exclude_shared_libs: [
+ "android.automotive.watchdog-V2-ndk_platform",
+ "android.hardware.automotive.vehicle@2.0",
+ ],
+ static_libs: [
+ "android.automotive.watchdog-V2-ndk_platform",
+ "android.hardware.automotive.vehicle@2.0",
],
header_libs: ["libbase_headers"],
test_suites: ["general-tests"],
@@ -193,12 +192,28 @@
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp",
+ "impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp",
],
static_libs: [
- "android.hardware.automotive.vehicle@2.0-default-impl-lib",
- "android.hardware.automotive.vehicle@2.0-libproto-native",
+ "libbase",
+ "libcutils",
+ "libgmock",
+ "libjsoncpp",
"libprotobuf-cpp-lite",
],
+ // Exclude share libraries from default because they might be missing on
+ // some test platforms and we are using static libraries instead.
+ exclude_shared_libs: [
+ "android.automotive.watchdog-V2-ndk_platform",
+ "android.hardware.automotive.vehicle@2.0",
+ ],
+ whole_static_libs: [
+ "android.automotive.watchdog-V2-ndk_platform",
+ "android.hardware.automotive.vehicle@2.0",
+ "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+ "android.hardware.automotive.vehicle@2.0-libproto-native",
+ ],
+ data: [":vhal_test_json"],
test_suites: ["general-tests"],
}
@@ -219,8 +234,8 @@
],
static_libs: [
"android.hardware.automotive.vehicle@2.0-manager-lib",
- "android.hardware.automotive.vehicle@2.0-default-impl-lib",
"android.hardware.automotive.vehicle@2.0-libproto-native",
+ "android.hardware.automotive.vehicle@2.0-emulator-impl-lib",
],
}
diff --git a/automotive/vehicle/2.0/default/TEST_MAPPING b/automotive/vehicle/2.0/default/TEST_MAPPING
new file mode 100644
index 0000000..bb58700
--- /dev/null
+++ b/automotive/vehicle/2.0/default/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "android.hardware.automotive.vehicle@2.0-manager-unit-tests"
+ },
+ {
+ "name": "android.hardware.automotive.vehicle@2.0-default-impl-unit-tests"
+ }
+ ]
+}
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 7e8deb6..ba2a606 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -20,9 +20,9 @@
#include <iostream>
-#include <vhal_v2_0/EmulatedUserHal.h>
-#include <vhal_v2_0/EmulatedVehicleConnector.h>
-#include <vhal_v2_0/EmulatedVehicleHal.h>
+#include <EmulatedUserHal.h>
+#include <EmulatedVehicleConnector.h>
+#include <EmulatedVehicleHal.h>
#include <vhal_v2_0/VehicleHalManager.h>
using namespace android;
@@ -34,7 +34,7 @@
auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
auto userHal = connector->getEmulatedUserHal();
auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
- auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
+ auto emulator = connector->getEmulator();
auto service = std::make_unique<VehicleHalManager>(hal.get());
connector->setValuePool(hal->getValuePool());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/ProtoMessageConverter.h
similarity index 100%
rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h
rename to automotive/vehicle/2.0/default/common/include/vhal_v2_0/ProtoMessageConverter.h
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index 2908a55..345c356 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -20,6 +20,7 @@
#include <vector>
#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <utils/Log.h>
#include "VehicleClient.h"
#include "VehicleServer.h"
@@ -72,7 +73,21 @@
}
bool dump(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override {
- return this->onDump(handle, options);
+ // Calls server's onDump function and print the dumped info to the handle.
+ std::vector<std::string> stdOptions;
+ for (size_t i = 0; i < options.size(); i++) {
+ stdOptions.push_back(options[i]);
+ }
+ IVehicleServer::DumpResult result = this->onDump(stdOptions);
+ int fd = handle->data[0];
+ if (fd < 0) {
+ ALOGW("Invalid fd from HIDL handle: %d", fd);
+ return false;
+ }
+ if (result.buffer.size() != 0) {
+ dprintf(fd, "[VehicleHalServer] Dumped info: %s\n", result.buffer.c_str());
+ }
+ return result.callerShouldDumpState;
}
// To be implemented:
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
private:
+ // Set unit test class as friend class to test private functions.
+ friend class VehicleHalManagerTestHelper;
+
using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
// Returns true if needs to call again shortly.
using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
static bool checkCallerHasWritePermissions(int fd);
- static bool safelyParseInt(int fd, int index, std::string s, int* out);
+ template <typename T>
+ static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+ static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+ // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+ // valid hex format, e.g. "0xABCD".
+ static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
void cmdHelp(int fd) const;
void cmdListAllProperties(int fd) const;
void cmdDumpAllProperties(int fd);
void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
- void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
static bool isSubscribable(const VehiclePropConfig& config,
SubscribeFlags flags);
@@ -120,7 +129,18 @@
static float checkSampleRate(const VehiclePropConfig& config,
float sampleRate);
static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+ // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+ // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+ static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop);
+ // Parses the options and get the values for the current option specified by "*index". "*index"
+ // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+ // the current option.
+ static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index);
+
+ private:
VehicleHal* mHal;
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
index ba9799a..2c484e8 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
@@ -28,6 +28,16 @@
*/
class IVehicleServer {
public:
+ // The return structure for onDump function.
+ struct DumpResult {
+ // If callerShouldDumpState is true, caller would print the information in buffer and
+ // continue to dump its state, otherwise would just dump the buffer and skip its own
+ // dumping logic.
+ bool callerShouldDumpState;
+ // The dumped information for the caller to print.
+ std::string buffer;
+ };
+
IVehicleServer() = default;
IVehicleServer(const IVehicleServer&) = delete;
@@ -54,15 +64,9 @@
// generated by car (ECU/fake generator/injected)
virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
- // TODO (chenhaosjtuacm): fix this since there are no HIDL in non-Android OS
-#ifdef __ANDROID__
// Dump method forwarded from HIDL's debug()
// If implemented, it must return whether the caller should dump its state.
- virtual bool onDump(const hidl_handle& /* handle */,
- const hidl_vec<hidl_string>& /* options */) {
- return true;
- }
-#endif // __ANDROID__
+ virtual DumpResult onDump(const std::vector<std::string>& options) = 0;
};
} // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp b/automotive/vehicle/2.0/default/common/src/ProtoMessageConverter.cpp
similarity index 100%
rename from automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp
rename to automotive/vehicle/2.0/default/common/src/ProtoMessageConverter.cpp
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
#include <cmath>
#include <fstream>
+#include <unordered_set>
+#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
+namespace {
+
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
const VehiclePropValue kEmptyValue{};
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+ // integer.
+ "-i",
+ // 64bit integer.
+ "-i64",
+ // float.
+ "-f",
+ // string.
+ "-s",
+ // bytes in hex format, e.g. 0xDEADBEEF.
+ "-b",
+ // Area id in integer.
+ "-a"};
+
+} // namespace
+
/**
* Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
* to store in reusable object pool.
*/
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
} else if (EqualsIgnoreCase(option, "--get")) {
cmdDumpSpecificProperties(fd, options);
} else if (EqualsIgnoreCase(option, "--set")) {
+ if (!checkCallerHasWritePermissions(fd)) {
+ dprintf(fd, "Caller does not have write permission\n");
+ return;
+ }
+ // Ignore the return value for this.
cmdSetOneProperty(fd, options);
} else {
dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
return false;
}
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
if (!android::base::ParseInt(s, out)) {
dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
return false;
@@ -247,19 +274,27 @@
return true;
}
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+ if (!android::base::ParseFloat(s, out)) {
+ dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+ return false;
+ }
+ return true;
+}
+
void VehicleHalManager::cmdHelp(int fd) const {
dprintf(fd, "Usage: \n\n");
dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
dprintf(fd, "--help: shows this help\n");
dprintf(fd, "--list: lists the ids of all supported properties\n");
dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
- // TODO: support other formats (int64, float, bytes)
dprintf(fd,
- "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
- "property PROP, using arbitrary number of key/value parameters (i for int32, "
- "s for string) and an optional area.\n"
- "Notice that the string value can be set just once, while the other can have multiple "
- "values (so they're used in the respective array)\n");
+ "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+ "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+ "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+ "Notice 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");
}
void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
VehiclePropValue input;
input.prop = prop;
input.areaId = areaId;
- auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+ auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
if (status == StatusCode::OK) {
dprintf(fd, "%s\n", toString(output).c_str());
} else {
dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
}
};
- get(input, callback);
+
+ StatusCode status;
+ auto value = mHal->get(input, &status);
+ callback(status, value.get() ? *value : kEmptyValue);
}
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
- if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
- size_t size = options.size();
-
- // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
- if (size % 2 != 0) {
- dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
- return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ if (!checkArgumentsSize(fd, options, 4)) {
+ dprintf(fd, "Requires at least 4 options, see help\n");
+ return false;
}
- int numberValues = (size - 2) / 2;
- VehiclePropValue prop;
- if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
- prop.timestamp = elapsedRealtimeNano();
- prop.status = VehiclePropertyStatus::AVAILABLE;
-
- // First pass: calculate sizes
- int sizeInt32 = 0;
- int stringIndex = 0;
- int areaIndex = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- std::string type = options[i];
- std::string value = options[i + 1];
- if (EqualsIgnoreCase(type, "i")) {
- sizeInt32++;
- } else if (EqualsIgnoreCase(type, "s")) {
- if (stringIndex != 0) {
- dprintf(fd,
- "defining string value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
- return;
- }
- stringIndex = i;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (areaIndex != 0) {
- dprintf(fd,
- "defining area value (%s) again at index %d (already defined at %d=%s"
- ")\n",
- value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
- return;
- }
- areaIndex = i;
- } else {
- dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
- return;
- }
- i += 2;
- }
- prop.value.int32Values.resize(sizeInt32);
-
- // Second pass: populate it
- int indexInt32 = 0;
- for (int i = 2, kv = 1; kv <= numberValues; kv++) {
- // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
- int valueIndex = i + 1;
- std::string type = options[i];
- std::string value = options[valueIndex];
- if (EqualsIgnoreCase(type, "i")) {
- int safeInt;
- if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
- prop.value.int32Values[indexInt32++] = safeInt;
- } else if (EqualsIgnoreCase(type, "s")) {
- prop.value.stringValue = value;
- } else if (EqualsIgnoreCase(type, "a")) {
- if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
- }
- i += 2;
+ VehiclePropValue prop = {};
+ if (!parseSetPropOptions(fd, options, &prop)) {
+ return false;
}
ALOGD("Setting prop %s", toString(prop).c_str());
- auto status = set(prop);
+
+ // Do not use VehicleHalManager::set here because we don't want to check write permission.
+ // Caller should be able to use the debug interface to set read-only properties.
+ handlePropertySetEvent(prop);
+ auto status = mHal->set(prop);
+
if (status == StatusCode::OK) {
dprintf(fd, "Set property %s\n", toString(prop).c_str());
- } else {
- dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
- toString(status).c_str());
+ return true;
}
+ dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+ toString(status).c_str());
+ return false;
}
void VehicleHalManager::init() {
ALOGI("VehicleHalManager::init");
- mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+ mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
mBatchingConsumer.run(&mEventQueue,
kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
for (const HalClientValues& cv : clientValues) {
auto vecSize = cv.values.size();
hidl_vec<VehiclePropValue> vec;
- if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+ if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
} else {
vec.resize(vecSize);
@@ -595,6 +577,158 @@
}
}
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+ size_t* index) {
+ std::vector<std::string> values;
+ while (*index < options.size()) {
+ std::string option = options[*index];
+ if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+ return std::move(values);
+ }
+ values.push_back(option);
+ (*index)++;
+ }
+ return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+ VehiclePropValue* prop) {
+ // Options format:
+ // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+ size_t optionIndex = 1;
+ int propValue;
+ if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+ dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+ return false;
+ }
+ prop->prop = propValue;
+ prop->timestamp = elapsedRealtimeNano();
+ prop->status = VehiclePropertyStatus::AVAILABLE;
+ optionIndex++;
+ std::unordered_set<std::string> parsedOptions;
+
+ while (optionIndex < options.size()) {
+ std::string type = options[optionIndex];
+ optionIndex++;
+ size_t currentIndex = optionIndex;
+ std::vector<std::string> values = getOptionValues(options, &optionIndex);
+ if (parsedOptions.find(type) != parsedOptions.end()) {
+ dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+ return false;
+ }
+ parsedOptions.insert(type);
+ if (EqualsIgnoreCase(type, "-i")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i\"\n");
+ return false;
+ }
+ prop->value.int32Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int32_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int32Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-i64")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-i64\"\n");
+ return false;
+ }
+ prop->value.int64Values.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ int64_t safeInt;
+ if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+ dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+ return false;
+ }
+ prop->value.int64Values[i] = safeInt;
+ }
+ } else if (EqualsIgnoreCase(type, "-f")) {
+ if (values.size() == 0) {
+ dprintf(fd, "no values specified when using \"-f\"\n");
+ return false;
+ }
+ prop->value.floatValues.resize(values.size());
+ for (size_t i = 0; i < values.size(); i++) {
+ float safeFloat;
+ if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+ dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+ return false;
+ }
+ prop->value.floatValues[i] = safeFloat;
+ }
+ } else if (EqualsIgnoreCase(type, "-s")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-s\"\n");
+ return false;
+ }
+ prop->value.stringValue = values[0];
+ } else if (EqualsIgnoreCase(type, "-b")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-b\"\n");
+ return false;
+ }
+ std::vector<uint8_t> bytes;
+ if (!parseHexString(fd, values[0], &bytes)) {
+ dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+ return false;
+ }
+ prop->value.bytes = bytes;
+ } else if (EqualsIgnoreCase(type, "-a")) {
+ if (values.size() != 1) {
+ dprintf(fd, "expect exact one value when using \"-a\"\n");
+ return false;
+ }
+ if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+ dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+ return false;
+ }
+ } else {
+ dprintf(fd, "unknown option: %s\n", type.c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+ if (s.size() % 2 != 0) {
+ dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+ return false;
+ }
+ if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+ dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+ return false;
+ }
+ std::string subs = s.substr(2);
+ std::transform(subs.begin(), subs.end(), subs.begin(),
+ [](unsigned char c) { return std::tolower(c); });
+
+ bool highDigit = true;
+ for (size_t i = 0; i < subs.size(); i++) {
+ char c = subs[i];
+ uint8_t v;
+ if (c >= '0' && c <= '9') {
+ v = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ v = c - 'a' + 10;
+ } else {
+ dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+ return false;
+ }
+ if (highDigit) {
+ (*bytes).push_back(v * 16);
+ } else {
+ (*bytes)[bytes->size() - 1] += v;
+ }
+ highDigit = !highDigit;
+ }
+ return true;
+}
+
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
deleted file mode 100644
index 136b2e0..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "CommConn"
-
-#include <thread>
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <log/log.h>
-
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-void CommConn::start() {
- mReadThread = std::make_unique<std::thread>(std::bind(&CommConn::readThread, this));
-}
-
-void CommConn::stop() {
- if (mReadThread->joinable()) {
- mReadThread->join();
- }
-}
-
-void CommConn::sendMessage(vhal_proto::EmulatorMessage const& msg) {
- int numBytes = msg.ByteSize();
- std::vector<uint8_t> buffer(static_cast<size_t>(numBytes));
- if (!msg.SerializeToArray(buffer.data(), numBytes)) {
- ALOGE("%s: SerializeToString failed!", __func__);
- return;
- }
-
- write(buffer);
-}
-
-void CommConn::readThread() {
- std::vector<uint8_t> buffer;
- while (isOpen()) {
- buffer = read();
- if (buffer.size() == 0) {
- ALOGI("%s: Read returned empty message, exiting read loop.", __func__);
- break;
- }
-
- vhal_proto::EmulatorMessage rxMsg;
- if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) {
- vhal_proto::EmulatorMessage respMsg;
- mMessageProcessor->processMessage(rxMsg, respMsg);
-
- sendMessage(respMsg);
- }
- }
-}
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
deleted file mode 100644
index 6d36da4..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <string>
-#include <thread>
-#include <vector>
-
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-/**
- * MessageProcess is an interface implemented by VehicleEmulator to process messages received
- * over a CommConn.
- */
-class MessageProcessor {
- public:
- virtual ~MessageProcessor() = default;
-
- /**
- * Process a single message received over a CommConn. Populate the given respMsg with the reply
- * message we should send.
- */
- virtual void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
- vhal_proto::EmulatorMessage& respMsg) = 0;
-};
-
-/**
- * This is the interface that both PipeComm and SocketComm use to represent a connection. The
- * connection will listen for commands on a separate 'read' thread.
- */
-class CommConn {
- public:
- CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {}
-
- virtual ~CommConn() {}
-
- /**
- * Start the read thread reading messages from this connection.
- */
- virtual void start();
-
- /**
- * Closes a connection if it is open.
- */
- virtual void stop();
-
- /**
- * Returns true if the connection is open and available to send/receive.
- */
- virtual bool isOpen() = 0;
-
- /**
- * Blocking call to read data from the connection.
- *
- * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be
- * an empty vector if the connection was closed or some other error occurred.
- */
- virtual std::vector<uint8_t> read() = 0;
-
- /**
- * Transmits a string of data to the emulator.
- *
- * @param data Serialized protobuf data to transmit.
- *
- * @return int Number of bytes transmitted, or -1 if failed.
- */
- virtual int write(const std::vector<uint8_t>& data) = 0;
-
- /**
- * Serialized and send the given message to the other side.
- */
- void sendMessage(vhal_proto::EmulatorMessage const& msg);
-
- protected:
- std::unique_ptr<std::thread> mReadThread;
- MessageProcessor* mMessageProcessor;
-
- /**
- * A thread that reads messages in a loop, and responds. You can stop this thread by calling
- * stop().
- */
- void readThread();
-};
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
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 f98962b..da6de74 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
@@ -124,7 +124,7 @@
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
},
- .initialValue = {.floatValues = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}},
+ .initialValue = {.int32Values = {1776, 4950, 2008, 2140, 2984, 1665, 1667, 11800}}},
{.config =
{
.prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
@@ -1064,8 +1064,8 @@
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
- .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */,
- -1, -1, -1, -1 /* Insets */}},
+ .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
+ -1, -1 /* Insets */}},
},
{
.config =
@@ -1118,9 +1118,9 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
.configArray = {0, 0, 0, 11, 0, 0, 0, 0, 16},
},
- .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */,
- -1, -1, -1, -1 /* Insets */,
- 0 /* ClusterHome */, -1 /* ClusterNone */}},
+ .initialValue = {.int32Values = {0 /* Off */, -1, -1, -1, -1 /* Bounds */, -1, -1,
+ -1, -1 /* Insets */, 0 /* ClusterHome */,
+ -1 /* ClusterNone */}},
},
{
.config =
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h
new file mode 100644
index 0000000..c3affb0
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleConnector.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
+
+#include <vhal_v2_0/VehicleConnector.h>
+
+#include "DefaultVehicleHalServer.h"
+#include "VehicleHalClient.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class DefaultVehicleConnector
+ : public IPassThroughConnector<VehicleHalClient, DefaultVehicleHalServer> {
+ public:
+ DefaultVehicleConnector() = default;
+
+ void triggerSendAllValues() { this->sendAllValuesToClient(); }
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
new file mode 100644
index 0000000..1b37cbd
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "DefaultVehicleHal_v2_0"
+
+#include <android-base/chrono_utils.h>
+#include <assert.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <vhal_v2_0/RecurrentTimer.h>
+
+#include "VehicleUtils.h"
+
+#include "DefaultVehicleHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace {
+constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;
+
+const VehicleAreaConfig* getAreaConfig(const VehiclePropValue& propValue,
+ const VehiclePropConfig* config) {
+ if (isGlobalProp(propValue.prop)) {
+ if (config->areaConfigs.size() == 0) {
+ return nullptr;
+ }
+ return &(config->areaConfigs[0]);
+ } else {
+ for (auto& c : config->areaConfigs) {
+ if (c.areaId == propValue.areaId) {
+ return &c;
+ }
+ }
+ }
+ return nullptr;
+}
+} // namespace
+
+DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+ : mPropStore(propStore), mRecurrentTimer(getTimerAction()), mVehicleClient(client) {
+ initStaticConfig();
+ mVehicleClient->registerPropertyValueCallback(
+ [this](const VehiclePropValue& value, bool updateStatus) {
+ onPropertyValue(value, updateStatus);
+ });
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(const VehiclePropValue& requestedPropValue,
+ StatusCode* outStatus) {
+ auto propId = requestedPropValue.prop;
+ ALOGV("get(%d)", propId);
+
+ VehiclePropValuePtr v = nullptr;
+ auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+ if (internalPropValue != nullptr) {
+ v = getValuePool()->obtain(*internalPropValue);
+ }
+
+ if (!v) {
+ *outStatus = StatusCode::INVALID_ARG;
+ } else if (v->status == VehiclePropertyStatus::AVAILABLE) {
+ *outStatus = StatusCode::OK;
+ } else {
+ *outStatus = StatusCode::TRY_AGAIN;
+ }
+ if (v.get()) {
+ v->timestamp = elapsedRealtimeNano();
+ }
+ return v;
+}
+
+std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties() {
+ return mPropStore->getAllConfigs();
+}
+
+bool DefaultVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+ return mVehicleClient->dump(fd, options);
+}
+
+StatusCode DefaultVehicleHal::checkPropValue(const VehiclePropValue& value,
+ const VehiclePropConfig* config) {
+ int32_t property = value.prop;
+ VehiclePropertyType type = getPropType(property);
+ switch (type) {
+ case VehiclePropertyType::BOOLEAN:
+ case VehiclePropertyType::INT32:
+ if (value.value.int32Values.size() != 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::INT32_VEC:
+ if (value.value.int32Values.size() < 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::INT64:
+ if (value.value.int64Values.size() != 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::INT64_VEC:
+ if (value.value.int64Values.size() < 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::FLOAT:
+ if (value.value.floatValues.size() != 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::FLOAT_VEC:
+ if (value.value.floatValues.size() < 1) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::BYTES:
+ // We allow setting an empty bytes array.
+ break;
+ case VehiclePropertyType::STRING:
+ // We allow setting an empty string.
+ break;
+ case VehiclePropertyType::MIXED:
+ if (getPropGroup(property) == VehiclePropertyGroup::VENDOR) {
+ // We only checks vendor mixed properties.
+ return checkVendorMixedPropValue(value, config);
+ }
+ break;
+ default:
+ ALOGW("Unknown property type: %d", type);
+ return StatusCode::INVALID_ARG;
+ }
+ return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::checkVendorMixedPropValue(const VehiclePropValue& value,
+ const VehiclePropConfig* config) {
+ auto configArray = config->configArray;
+ // configArray[0], 1 indicates the property has a String value, we allow the string value to
+ // be empty.
+
+ size_t int32Count = 0;
+ // configArray[1], 1 indicates the property has a Boolean value.
+ if (configArray[1] == 1) {
+ int32Count++;
+ }
+ // configArray[2], 1 indicates the property has an Integer value.
+ if (configArray[2] == 1) {
+ int32Count++;
+ }
+ // configArray[3], the number indicates the size of Integer[] in the property.
+ int32Count += static_cast<size_t>(configArray[3]);
+ if (value.value.int32Values.size() != int32Count) {
+ return StatusCode::INVALID_ARG;
+ }
+
+ size_t int64Count = 0;
+ // configArray[4], 1 indicates the property has a Long value.
+ if (configArray[4] == 1) {
+ int64Count++;
+ }
+ // configArray[5], the number indicates the size of Long[] in the property.
+ int64Count += static_cast<size_t>(configArray[5]);
+ if (value.value.int64Values.size() != int64Count) {
+ return StatusCode::INVALID_ARG;
+ }
+
+ size_t floatCount = 0;
+ // configArray[6], 1 indicates the property has a Float value.
+ if (configArray[6] == 1) {
+ floatCount++;
+ }
+ // configArray[7], the number indicates the size of Float[] in the property.
+ floatCount += static_cast<size_t>(configArray[7]);
+ if (value.value.floatValues.size() != floatCount) {
+ return StatusCode::INVALID_ARG;
+ }
+
+ // configArray[8], the number indicates the size of byte[] in the property.
+ if (configArray[8] != 0 && value.value.bytes.size() != static_cast<size_t>(configArray[8])) {
+ return StatusCode::INVALID_ARG;
+ }
+ return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::checkValueRange(const VehiclePropValue& value,
+ const VehicleAreaConfig* areaConfig) {
+ if (areaConfig == nullptr) {
+ return StatusCode::OK;
+ }
+ int32_t property = value.prop;
+ VehiclePropertyType type = getPropType(property);
+ switch (type) {
+ case VehiclePropertyType::INT32:
+ if (areaConfig->minInt32Value == 0 && areaConfig->maxInt32Value == 0) {
+ break;
+ }
+ // We already checked this in checkPropValue.
+ assert(value.value.int32Values.size() > 0);
+ if (value.value.int32Values[0] < areaConfig->minInt32Value ||
+ value.value.int32Values[0] > areaConfig->maxInt32Value) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::INT64:
+ if (areaConfig->minInt64Value == 0 && areaConfig->maxInt64Value == 0) {
+ break;
+ }
+ // We already checked this in checkPropValue.
+ assert(value.value.int64Values.size() > 0);
+ if (value.value.int64Values[0] < areaConfig->minInt64Value ||
+ value.value.int64Values[0] > areaConfig->maxInt64Value) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ case VehiclePropertyType::FLOAT:
+ if (areaConfig->minFloatValue == 0 && areaConfig->maxFloatValue == 0) {
+ break;
+ }
+ // We already checked this in checkPropValue.
+ assert(value.value.floatValues.size() > 0);
+ if (value.value.floatValues[0] < areaConfig->minFloatValue ||
+ value.value.floatValues[0] > areaConfig->maxFloatValue) {
+ return StatusCode::INVALID_ARG;
+ }
+ break;
+ default:
+ // We don't check the rest of property types. Additional logic needs to be added if
+ // required for real implementation. E.g., you might want to enforce the range
+ // checks on vector as well or you might want to check the range for mixed property.
+ break;
+ }
+ return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
+ if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
+ // Android side cannot set property status - this value is the
+ // purview of the HAL implementation to reflect the state of
+ // its underlying hardware
+ return StatusCode::INVALID_ARG;
+ }
+
+ int32_t property = propValue.prop;
+ const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
+ if (config == nullptr) {
+ ALOGW("no config for prop 0x%x", property);
+ return StatusCode::INVALID_ARG;
+ }
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
+ if (!isGlobalProp(property) && areaConfig == nullptr) {
+ // Ignore areaId for global property. For non global property, check whether areaId is
+ // allowed. areaId must appear in areaConfig.
+ ALOGW("invalid area ID: 0x%x for prop 0x%x, not listed in config", propValue.areaId,
+ property);
+ return StatusCode::INVALID_ARG;
+ }
+ auto status = checkPropValue(propValue, config);
+ if (status != StatusCode::OK) {
+ ALOGW("invalid property value: %s", toString(propValue).c_str());
+ return status;
+ }
+ status = checkValueRange(propValue, areaConfig);
+ if (status != StatusCode::OK) {
+ ALOGW("property value out of range: %s", toString(propValue).c_str());
+ return status;
+ }
+
+ auto currentPropValue = mPropStore->readValueOrNull(propValue);
+ if (currentPropValue && currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {
+ // do not allow Android side to set() a disabled/error property
+ return StatusCode::NOT_AVAILABLE;
+ }
+
+ // Send the value to the vehicle server, the server will talk to the (real or emulated) car
+ return mVehicleClient->setProperty(propValue, /*updateStatus=*/false);
+}
+
+// Parse supported properties list and generate vector of property values to hold current values.
+void DefaultVehicleHal::onCreate() {
+ auto configs = mVehicleClient->getAllPropertyConfig();
+
+ for (const auto& cfg : configs) {
+ int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
+
+ for (int i = 0; i < numAreas; i++) {
+ int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
+
+ // Create a separate instance for each individual zone
+ VehiclePropValue prop = {
+ .areaId = curArea,
+ .prop = cfg.prop,
+ .status = VehiclePropertyStatus::UNAVAILABLE,
+ };
+ // Allow the initial values to set status.
+ mPropStore->writeValue(prop, /*updateStatus=*/true);
+ }
+ }
+
+ mVehicleClient->triggerSendAllValues();
+ registerHeartBeatEvent();
+}
+
+DefaultVehicleHal::~DefaultVehicleHal() {
+ mRecurrentTimer.unregisterRecurrentEvent(static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
+}
+
+void DefaultVehicleHal::registerHeartBeatEvent() {
+ mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
+ static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::doInternalHealthCheck() {
+ VehicleHal::VehiclePropValuePtr v = nullptr;
+
+ // This is an example of very simple health checking. VHAL is considered healthy if we can read
+ // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
+ VehiclePropValue propValue = {
+ .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
+ };
+ auto internalPropValue = mPropStore->readValueOrNull(propValue);
+ if (internalPropValue != nullptr) {
+ v = createVhalHeartBeatProp();
+ } else {
+ ALOGW("VHAL health check failed");
+ }
+ return v;
+}
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
+ VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
+ v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
+ v->areaId = 0;
+ v->status = VehiclePropertyStatus::AVAILABLE;
+ return v;
+}
+
+void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
+ auto& pool = *getValuePool();
+
+ for (int32_t property : properties) {
+ VehiclePropValuePtr v;
+ if (isContinuousProperty(property)) {
+ auto internalPropValue = mPropStore->readValueOrNull(property);
+ if (internalPropValue != nullptr) {
+ v = pool.obtain(*internalPropValue);
+ }
+ } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
+ // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
+ // So, the update is done through onContinuousPropertyTimer.
+ v = doInternalHealthCheck();
+ } else {
+ ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
+ continue;
+ }
+
+ if (v.get()) {
+ v->timestamp = elapsedRealtimeNano();
+ doHalEvent(std::move(v));
+ }
+ }
+}
+
+RecurrentTimer::Action DefaultVehicleHal::getTimerAction() {
+ return [this](const std::vector<int32_t>& properties) {
+ onContinuousPropertyTimer(properties);
+ };
+}
+
+StatusCode DefaultVehicleHal::subscribe(int32_t property, float sampleRate) {
+ ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
+
+ if (!isContinuousProperty(property)) {
+ return StatusCode::INVALID_ARG;
+ }
+
+ // If the config does not exist, isContinuousProperty should return false.
+ const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
+ if (sampleRate < config->minSampleRate || sampleRate > config->maxSampleRate) {
+ ALOGW("sampleRate out of range");
+ return StatusCode::INVALID_ARG;
+ }
+
+ mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
+ return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::unsubscribe(int32_t property) {
+ ALOGI("%s propId: 0x%x", __func__, property);
+ if (!isContinuousProperty(property)) {
+ return StatusCode::INVALID_ARG;
+ }
+ // If the event was not registered before, this would do nothing.
+ mRecurrentTimer.unregisterRecurrentEvent(property);
+ return StatusCode::OK;
+}
+
+bool DefaultVehicleHal::isContinuousProperty(int32_t propId) const {
+ const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
+ if (config == nullptr) {
+ ALOGW("Config not found for property: 0x%x", propId);
+ return false;
+ }
+ return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
+}
+
+void DefaultVehicleHal::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
+ VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
+
+ if (mPropStore->writeValue(*updatedPropValue, updateStatus)) {
+ doHalEvent(std::move(updatedPropValue));
+ }
+}
+
+void DefaultVehicleHal::initStaticConfig() {
+ auto configs = mVehicleClient->getAllPropertyConfig();
+ for (auto&& cfg : configs) {
+ mPropStore->registerProperty(cfg, nullptr);
+ }
+}
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
new file mode 100644
index 0000000..af29143
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
+
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include "vhal_v2_0/VehiclePropertyStore.h"
+
+#include "VehicleHalClient.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
+class DefaultVehicleHal : public VehicleHal {
+ public:
+ DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client);
+ ~DefaultVehicleHal();
+
+ // Initialize VHAL. Should always call registerHeartBeatEvent() during onCreate.
+ void onCreate() override;
+ std::vector<VehiclePropConfig> listProperties() override;
+ VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+ StatusCode* outStatus) override;
+ StatusCode set(const VehiclePropValue& propValue) override;
+ StatusCode subscribe(int32_t property, float sampleRate) override;
+ StatusCode unsubscribe(int32_t property) override;
+ bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+ protected:
+ constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
+ return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
+ }
+
+ VehiclePropertyStore* mPropStore;
+ RecurrentTimer mRecurrentTimer;
+ VehicleHalClient* mVehicleClient;
+ virtual bool isContinuousProperty(int32_t propId) const;
+ virtual void initStaticConfig();
+ virtual void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+ virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
+ // Returns a lambda that could be used in mRecurrentTimer.
+ RecurrentTimer::Action getTimerAction();
+ // Check whether a propValue is valid according to its type.
+ StatusCode checkPropValue(const VehiclePropValue& propValue, const VehiclePropConfig* config);
+ // Check whether the property value is within the range according to area config.
+ StatusCode checkValueRange(const VehiclePropValue& propValue,
+ const VehicleAreaConfig* areaConfig);
+ // Register the heart beat event to be sent every 3s. This is required to inform watch dog that
+ // VHAL is alive. Subclasses should always calls this function during onCreate.
+ void registerHeartBeatEvent();
+
+ VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
+ VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
+
+ private:
+ // Check whether a vendor mixed value property is valid according to its config array.
+ // See 'VehiclePropertyType' documentation in 'types.hal' for detail.
+ StatusCode checkVendorMixedPropValue(const VehiclePropValue& value,
+ const VehiclePropConfig* config);
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
new file mode 100644
index 0000000..f61a93b
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.cpp
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DefaultVehicleHalServer"
+
+#include <fstream>
+
+#include <android-base/format.h>
+#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
+#include <android-base/parseint.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+
+#include "DefaultVehicleHalServer.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+void DefaultVehicleHalServer::storePropInitialValue(const ConfigDeclaration& config) {
+ VehiclePropConfig cfg = config.config;
+
+ // A global property will have only a single area
+ int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
+
+ for (int i = 0; i < numAreas; i++) {
+ int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
+
+ // Create a separate instance for each individual zone
+ VehiclePropValue prop = {
+ .areaId = curArea,
+ .prop = cfg.prop,
+ };
+
+ if (config.initialAreaValues.empty()) {
+ prop.value = config.initialValue;
+ } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
+ valueForAreaIt != config.initialAreaValues.end()) {
+ prop.value = valueForAreaIt->second;
+ } else {
+ LOG(WARNING) << __func__ << " failed to get default value for"
+ << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex << curArea;
+ prop.status = VehiclePropertyStatus::UNAVAILABLE;
+ }
+
+ mServerSidePropStore.writeValue(prop, true);
+ }
+}
+
+DefaultVehicleHalServer::DefaultVehicleHalServer() {
+ for (auto& it : kVehicleProperties) {
+ VehiclePropConfig cfg = it.config;
+ mServerSidePropStore.registerProperty(cfg);
+ storePropInitialValue(it);
+ }
+}
+
+void DefaultVehicleHalServer::sendAllValuesToClient() {
+ constexpr bool update_status = true;
+ auto values = mServerSidePropStore.readAllValues();
+ for (const auto& value : values) {
+ onPropertyValueFromCar(value, update_status);
+ }
+}
+
+GeneratorHub* DefaultVehicleHalServer::getGeneratorHub() {
+ return &mGeneratorHub;
+}
+
+VehiclePropValuePool* DefaultVehicleHalServer::getValuePool() const {
+ if (!mValuePool) {
+ LOG(WARNING) << __func__ << ": Value pool not set!";
+ }
+ return mValuePool;
+}
+
+void DefaultVehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
+ if (!valuePool) {
+ LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
+ }
+ mValuePool = valuePool;
+}
+
+void DefaultVehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
+ constexpr bool updateStatus = true;
+ LOG(DEBUG) << __func__ << ": " << toString(value);
+ auto updatedPropValue = getValuePool()->obtain(value);
+ if (updatedPropValue) {
+ updatedPropValue->timestamp = value.timestamp;
+ updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+ mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ }
+}
+
+std::vector<VehiclePropConfig> DefaultVehicleHalServer::onGetAllPropertyConfig() const {
+ return mServerSidePropStore.getAllConfigs();
+}
+
+StatusCode DefaultVehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
+ constexpr bool updateStatus = true;
+
+ LOG(INFO) << __func__;
+ const auto& v = request.value;
+ if (!v.int32Values.size()) {
+ LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+
+ FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
+
+ switch (command) {
+ case FakeDataCommand::StartLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (!v.int64Values.size()) {
+ LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (v.floatValues.size() < 3) {
+ LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
+ << v.floatValues.size();
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGeneratorHub()->registerGenerator(
+ cookie, std::make_unique<LinearFakeValueGenerator>(request));
+ break;
+ }
+ case FakeDataCommand::StartJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ auto generator = std::make_unique<JsonFakeValueGenerator>(request);
+ if (!generator->hasNext()) {
+ LOG(ERROR) << __func__ << ": invalid JSON file, no events";
+ return StatusCode::INVALID_ARG;
+ }
+ getGeneratorHub()->registerGenerator(cookie, std::move(generator));
+ break;
+ }
+ case FakeDataCommand::StopLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGeneratorHub()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::StopJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ getGeneratorHub()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::KeyPress: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
+ int32_t keyCode = request.value.int32Values[2];
+ int32_t display = request.value.int32Values[3];
+ // Send back to HAL
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+ updateStatus);
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+ updateStatus);
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
+ return StatusCode::INVALID_ARG;
+ }
+ }
+ return StatusCode::OK;
+}
+
+DefaultVehicleHalServer::VehiclePropValuePtr DefaultVehicleHalServer::createApPowerStateReq(
+ VehicleApPowerStateReq state, int32_t param) {
+ auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+ req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+ req->areaId = 0;
+ req->timestamp = elapsedRealtimeNano();
+ req->status = VehiclePropertyStatus::AVAILABLE;
+ req->value.int32Values[0] = toInt(state);
+ req->value.int32Values[1] = param;
+ return req;
+}
+
+DefaultVehicleHalServer::VehiclePropValuePtr DefaultVehicleHalServer::createHwInputKeyProp(
+ VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+ auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+ keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+ keyEvent->areaId = 0;
+ keyEvent->timestamp = elapsedRealtimeNano();
+ keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+ keyEvent->value.int32Values[0] = toInt(action);
+ keyEvent->value.int32Values[1] = keyCode;
+ keyEvent->value.int32Values[2] = targetDisplay;
+ return keyEvent;
+}
+
+StatusCode DefaultVehicleHalServer::onSetProperty(const VehiclePropValue& value,
+ bool updateStatus) {
+ LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
+
+ // Some properties need to be treated non-trivially
+ switch (value.prop) {
+ case kGenerateFakeDataControllingProperty:
+ return handleGenerateFakeDataRequest(value);
+
+ // set the value from vehicle side, used in end to end test.
+ case kSetIntPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetFloatPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetBooleanPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
+ updatedPropValue->prop = value.value.int32Values[1];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+
+ case AP_POWER_STATE_REPORT:
+ switch (value.value.int32Values[0]) {
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+ case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+ // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+ // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(
+ *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::ON):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+ // Do nothing
+ break;
+ default:
+ // Unknown state
+ break;
+ }
+ break;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+ case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
+ case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
+ case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
+ case VENDOR_CLUSTER_SWITCH_UI:
+ case VENDOR_CLUSTER_DISPLAY_STATE: {
+ auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
+ updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
+ if (isSystemProperty(value.prop)) {
+ updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
+ } else {
+ updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
+ }
+ updatedPropValue->value = value.value;
+ updatedPropValue->timestamp = elapsedRealtimeNano();
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
+ default:
+ break;
+ }
+
+ // In the real vhal, the value will be sent to Car ECU.
+ // We just pretend it is done here and send back to HAL
+ auto updatedPropValue = getValuePool()->obtain(value);
+ updatedPropValue->timestamp = elapsedRealtimeNano();
+
+ mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::onDump(
+ const std::vector<std::string>& options) {
+ DumpResult result;
+ if (options.size() == 0) {
+ // No options, dump all stored properties.
+ result.callerShouldDumpState = true;
+ result.buffer += "Server side properties: \n";
+ auto values = mServerSidePropStore.readAllValues();
+ size_t i = 0;
+ for (const auto& value : values) {
+ result.buffer += fmt::format("[{}]: {}\n", i, toString(value));
+ i++;
+ }
+ return result;
+ }
+ if (options[0] != "--debughal") {
+ // We only expect "debughal" command. This might be some commands that the caller knows
+ // about, so let caller handle it.
+ result.callerShouldDumpState = true;
+ return result;
+ }
+
+ return debug(options);
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::debug(const std::vector<std::string>& options) {
+ DumpResult result;
+ // This is a debug command for the HAL, caller should not continue to dump state.
+ result.callerShouldDumpState = false;
+
+ if (options.size() < 2) {
+ result.buffer += "No command specified\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+
+ std::string command = options[1];
+ if (command == "--help") {
+ result.buffer += getHelpInfo();
+ return result;
+ } else if (command == "--genfakedata") {
+ return genFakeData(options);
+ }
+
+ result.buffer += "Unknown command: \"" + command + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+}
+
+std::string DefaultVehicleHalServer::getHelpInfo() {
+ return "Help: \n"
+ "Generate Fake Data: \n"
+ "\tStart a linear generator: \n"
+ "\t--debughal --genfakedata --startlinear [propID(int32)] [middleValue(float)] "
+ "[currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]\n"
+ "\tStop a linear generator: \n"
+ "\t--debughal --genfakedata --stoplinear [propID(int32)]\n"
+ "\tStart a json generator: \n"
+ "\t--debughal --genfakedata --startjson [jsonFilePath(string)] "
+ "[repetition(int32)(optional)]\n"
+ "\tStop a json generator: \n"
+ "\t--debughal --genfakedata --stopjson [jsonFilePath(string)]\n"
+ "\tGenerate key press: \n"
+ "\t--debughal --genfakedata --keypress [keyCode(int32)] [display[int32]]\n";
+}
+
+IVehicleServer::DumpResult DefaultVehicleHalServer::genFakeData(
+ const std::vector<std::string>& options) {
+ DumpResult result;
+ // This is a debug command for the HAL, caller should not continue to dump state.
+ result.callerShouldDumpState = false;
+
+ if (options.size() < 3) {
+ result.buffer += "No subcommand specified for genfakedata\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+
+ std::string command = options[2];
+ if (command == "--startlinear") {
+ LOG(INFO) << __func__ << "FakeDataCommand::StartLinear";
+ // --debughal --genfakedata --startlinear [propID(int32)] [middleValue(float)]
+ // [currentValue(float)] [dispersion(float)] [increment(float)] [interval(int64)]
+ if (options.size() != 9) {
+ result.buffer +=
+ "incorrect argument count, need 9 arguments for --genfakedata --startlinear\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ int32_t propId;
+ float middleValue;
+ float currentValue;
+ float dispersion;
+ float increment;
+ int64_t interval;
+ if (!android::base::ParseInt(options[3], &propId)) {
+ result.buffer += "failed to parse propdID as int: \"" + options[3] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseFloat(options[4], &middleValue)) {
+ result.buffer += "failed to parse middleValue as float: \"" + options[4] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseFloat(options[5], ¤tValue)) {
+ result.buffer += "failed to parse currentValue as float: \"" + options[5] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseFloat(options[6], &dispersion)) {
+ result.buffer += "failed to parse dispersion as float: \"" + options[6] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseFloat(options[7], &increment)) {
+ result.buffer += "failed to parse increment as float: \"" + options[7] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseInt(options[8], &interval)) {
+ result.buffer += "failed to parse interval as int: \"" + options[8] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ auto generator = std::make_unique<LinearFakeValueGenerator>(
+ propId, middleValue, currentValue, dispersion, increment, interval);
+ getGeneratorHub()->registerGenerator(propId, std::move(generator));
+ return result;
+ } else if (command == "--stoplinear") {
+ LOG(INFO) << __func__ << "FakeDataCommand::StopLinear";
+ // --debughal --genfakedata --stoplinear [propID(int32)]
+ if (options.size() != 4) {
+ result.buffer +=
+ "incorrect argument count, need 4 arguments for --genfakedata --stoplinear\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ int32_t propId;
+ if (!android::base::ParseInt(options[3], &propId)) {
+ result.buffer += "failed to parse propdID as int: \"" + options[3] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ getGeneratorHub()->unregisterGenerator(propId);
+ return result;
+ } else if (command == "--startjson") {
+ LOG(INFO) << __func__ << "FakeDataCommand::StartJson";
+ // --debughal --genfakedata --startjson [jsonFilePath(string)] [repetition(int32)(optional)]
+ if (options.size() != 4 && options.size() != 5) {
+ result.buffer +=
+ "incorrect argument count, need 4 or 5 arguments for --genfakedata "
+ "--startjson\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ std::string fileName = options[3];
+ int32_t cookie = std::hash<std::string>()(fileName);
+ // Iterate infinitely if repetition number is not provided
+ int32_t repetition = -1;
+ if (options.size() == 5) {
+ if (!android::base::ParseInt(options[4], &repetition)) {
+ result.buffer += "failed to parse repetition as int: \"" + options[4] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ }
+ auto generator = std::make_unique<JsonFakeValueGenerator>(fileName, repetition);
+ if (!generator->hasNext()) {
+ result.buffer += "invalid JSON file, no events";
+ return result;
+ }
+ getGeneratorHub()->registerGenerator(cookie, std::move(generator));
+ return result;
+ } else if (command == "--stopjson") {
+ LOG(INFO) << __func__ << "FakeDataCommand::StopJson";
+ // --debughal --genfakedata --stopjson [jsonFilePath(string)]
+ if (options.size() != 4) {
+ result.buffer +=
+ "incorrect argument count, need 4 arguments for --genfakedata --stopjson\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ std::string fileName = options[3];
+ int32_t cookie = std::hash<std::string>()(fileName);
+ getGeneratorHub()->unregisterGenerator(cookie);
+ return result;
+ } else if (command == "--keypress") {
+ LOG(INFO) << __func__ << "FakeDataCommand::KeyPress";
+ int32_t keyCode;
+ int32_t display;
+ // --debughal --genfakedata --keypress [keyCode(int32)] [display[int32]]
+ if (options.size() != 5) {
+ result.buffer +=
+ "incorrect argument count, need 5 arguments for --genfakedata --keypress\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseInt(options[3], &keyCode)) {
+ result.buffer += "failed to parse keyCode as int: \"" + options[3] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ if (!android::base::ParseInt(options[4], &display)) {
+ result.buffer += "failed to parse display as int: \"" + options[4] + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+ }
+ // Send back to HAL
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+ /*updateStatus=*/true);
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+ /*updateStatus=*/true);
+ return result;
+ }
+
+ result.buffer += "Unknown command: \"" + command + "\"\n";
+ result.buffer += getHelpInfo();
+ return result;
+}
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
new file mode 100644
index 0000000..aa6cf0b
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHalServer.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_0/VehicleServer.h>
+
+#include "DefaultConfig.h"
+#include "GeneratorHub.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+// This contains the server operation for VHAL running in emulator.
+class DefaultVehicleHalServer : public IVehicleServer {
+ public:
+ DefaultVehicleHalServer();
+
+ // Send all the property values to client.
+ void sendAllValuesToClient();
+
+ // Methods from IVehicleServer
+
+ std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+ StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+ DumpResult onDump(const std::vector<std::string>& options) override;
+
+ // Set the Property Value Pool used in this server
+ void setValuePool(VehiclePropValuePool* valuePool);
+
+ protected:
+ using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+ GeneratorHub* getGeneratorHub();
+
+ VehiclePropValuePool* getValuePool() const;
+
+ void onFakeValueGenerated(const VehiclePropValue& value);
+
+ StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+ VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+ VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+ int32_t targetDisplay);
+
+ void storePropInitialValue(const ConfigDeclaration& config);
+
+ DumpResult debug(const std::vector<std::string>& options);
+
+ std::string getHelpInfo();
+
+ DumpResult genFakeData(const std::vector<std::string>& options);
+
+ protected:
+ GeneratorHub mGeneratorHub{
+ [this](const VehiclePropValue& value) { return onFakeValueGenerated(value); }};
+
+ VehiclePropValuePool* mValuePool{nullptr};
+ VehiclePropertyStore mServerSidePropStore;
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
deleted file mode 100644
index 3bdf5a8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ /dev/null
@@ -1,351 +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.
- */
-#define LOG_TAG "EmulatedUserHal"
-
-#include "EmulatedUserHal.h"
-
-#include <cutils/log.h>
-#include <utils/SystemClock.h>
-
-#include "UserHalHelper.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-namespace {
-
-using android::base::Error;
-using android::base::Result;
-
-constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
-constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
-constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
-constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
-constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
- static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
-
-Result<int32_t> getRequestId(const VehiclePropValue& value) {
- if (value.value.int32Values.size() < 1) {
- return Error(static_cast<int>(StatusCode::INVALID_ARG))
- << "no int32values on " << toString(value);
- }
- return value.value.int32Values[0];
-}
-
-Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
- if (value.value.int32Values.size() < 2) {
- return Error(static_cast<int>(StatusCode::INVALID_ARG))
- << "missing switch user message type " << toString(value);
- }
- return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
-}
-
-} // namespace
-
-bool EmulatedUserHal::isSupported(int32_t prop) {
- switch (prop) {
- case INITIAL_USER_INFO:
- case SWITCH_USER:
- case CREATE_USER:
- case REMOVE_USER:
- case USER_IDENTIFICATION_ASSOCIATION:
- return true;
- default:
- return false;
- }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
- const VehiclePropValue& value) {
- ALOGV("onSetProperty(): %s", toString(value).c_str());
-
- switch (value.prop) {
- case INITIAL_USER_INFO:
- return onSetInitialUserInfoResponse(value);
- case SWITCH_USER:
- return onSetSwitchUserResponse(value);
- case CREATE_USER:
- return onSetCreateUserResponse(value);
- case REMOVE_USER:
- ALOGI("REMOVE_USER is FYI only, nothing to do...");
- return {};
- case USER_IDENTIFICATION_ASSOCIATION:
- return onSetUserIdentificationAssociation(value);
- default:
- return Error(static_cast<int>(StatusCode::INVALID_ARG))
- << "Unsupported property: " << toString(value);
- }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
- const VehiclePropValue& value) {
- ALOGV("onGetProperty(%s)", toString(value).c_str());
- switch (value.prop) {
- case INITIAL_USER_INFO:
- case SWITCH_USER:
- case CREATE_USER:
- case REMOVE_USER:
- ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
- return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "only supported on SET";
- case USER_IDENTIFICATION_ASSOCIATION:
- return onGetUserIdentificationAssociation(value);
- default:
- ALOGE("onGetProperty(): %d is not supported", value.prop);
- return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "not supported by User HAL";
- }
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetUserIdentificationAssociation(
- const VehiclePropValue& value) {
- if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) {
- return defaultUserIdentificationAssociation(value);
- }
- ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
- toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
- auto newValue = std::unique_ptr<VehiclePropValue>(
- new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
- auto requestId = getRequestId(value);
- if (requestId.ok()) {
- // Must use the same requestId
- newValue->value.int32Values[0] = *requestId;
- } else {
- ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", toString(value).c_str());
- }
- return newValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetInitialUserInfoResponse(
- const VehiclePropValue& value) {
- auto requestId = getRequestId(value);
- if (!requestId.ok()) {
- ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s",
- requestId.error().message().c_str());
- return requestId.error();
- }
-
- if (value.areaId != 0) {
- ALOGD("set(INITIAL_USER_INFO) called from lshal; storing it: %s", toString(value).c_str());
- mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
- return {};
- }
-
- ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str());
- if (mInitialUserResponseFromCmd != nullptr) {
- ALOGI("replying INITIAL_USER_INFO with lshal value: %s",
- toString(*mInitialUserResponseFromCmd).c_str());
- return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId);
- }
-
- // Returns default response
- auto updatedValue = user_hal_helper::toVehiclePropValue(InitialUserInfoResponse{
- .requestId = *requestId,
- .action = InitialUserInfoResponseAction::DEFAULT,
- });
- ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s",
- toString(*updatedValue).c_str());
- return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
- const VehiclePropValue& value) {
- auto requestId = getRequestId(value);
- if (!requestId.ok()) {
- ALOGE("Failed to get requestId on set(SWITCH_USER): %s",
- requestId.error().message().c_str());
- return requestId.error();
- }
-
- auto messageType = getSwitchUserMessageType(value);
- if (!messageType.ok()) {
- ALOGE("Failed to get messageType on set(SWITCH_USER): %s",
- messageType.error().message().c_str());
- return messageType.error();
- }
-
- if (value.areaId != 0) {
- if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) {
- // User HAL can also request a user switch, so we need to check it first
- ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s",
- toString(value).c_str());
- return std::unique_ptr<VehiclePropValue>(new VehiclePropValue(value));
- }
- // Otherwise, we store it
- ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str());
- mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value));
- return {};
- }
- ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str());
-
- if (mSwitchUserResponseFromCmd != nullptr) {
- ALOGI("replying SWITCH_USER with lshal value: %s",
- toString(*mSwitchUserResponseFromCmd).c_str());
- return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId);
- }
-
- if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH ||
- *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) {
- ALOGI("request is %s; ignoring it", toString(*messageType).c_str());
- return {};
- }
-
- // Returns default response
- auto updatedValue = user_hal_helper::toVehiclePropValue(SwitchUserResponse{
- .requestId = *requestId,
- .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
- .status = SwitchUserStatus::SUCCESS,
- });
- ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s",
- toString(*updatedValue).c_str());
- return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
- const VehiclePropValue& value) {
- auto requestId = getRequestId(value);
- if (!requestId.ok()) {
- ALOGE("Failed to get requestId on set(CREATE_USER): %s",
- requestId.error().message().c_str());
- return requestId.error();
- }
-
- if (value.areaId != 0) {
- ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str());
- mCreateUserResponseFromCmd.reset(new VehiclePropValue(value));
- return {};
- }
- ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str());
-
- if (mCreateUserResponseFromCmd != nullptr) {
- ALOGI("replying CREATE_USER with lshal value: %s",
- toString(*mCreateUserResponseFromCmd).c_str());
- return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId);
- }
-
- // Returns default response
- auto updatedValue = user_hal_helper::toVehiclePropValue(CreateUserResponse{
- .requestId = *requestId,
- .status = CreateUserStatus::SUCCESS,
- });
- ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str());
- return updatedValue;
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetUserIdentificationAssociation(
- const VehiclePropValue& value) {
- auto requestId = getRequestId(value);
- if (!requestId.ok()) {
- ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s",
- requestId.error().message().c_str());
- return requestId.error();
- }
-
- if (value.areaId != 0) {
- ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s",
- toString(value).c_str());
- mSetUserIdentificationAssociationResponseFromCmd.reset(new VehiclePropValue(value));
- return {};
- }
- ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str());
-
- if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value: %s",
- toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
- // Not moving response so it can be used on GET requests
- auto copy = std::unique_ptr<VehiclePropValue>(
- new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
- return sendUserHalResponse(std::move(copy), *requestId);
- }
- // Returns default response
- return defaultUserIdentificationAssociation(value);
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::defaultUserIdentificationAssociation(
- const VehiclePropValue& request) {
- // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types
- ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str());
- return Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
-}
-
-Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
- std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
- switch (response->areaId) {
- case 1:
- ALOGD("returning response with right request id");
- response->value.int32Values[0] = requestId;
- break;
- case 2:
- ALOGD("returning response with wrong request id");
- response->value.int32Values[0] = -requestId;
- break;
- case 3:
- ALOGD("not generating a property change event because of lshal prop: %s",
- toString(*response).c_str());
- return Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
- << "not generating a property change event because of lshal prop: "
- << toString(*response);
- default:
- ALOGE("invalid action on lshal response: %s", toString(*response).c_str());
- return Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
- << "invalid action on lshal response: " << toString(*response);
- }
-
- ALOGD("updating property to: %s", toString(*response).c_str());
- return response;
-}
-
-void EmulatedUserHal::showDumpHelp(int fd) {
- dprintf(fd, "%s: dumps state used for user management\n", kUserHalDumpOption);
-}
-
-void EmulatedUserHal::dump(int fd, std::string indent) {
- if (mInitialUserResponseFromCmd != nullptr) {
- dprintf(fd, "%sInitialUserInfo response: %s\n", indent.c_str(),
- toString(*mInitialUserResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo InitialUserInfo response\n", indent.c_str());
- }
- if (mSwitchUserResponseFromCmd != nullptr) {
- dprintf(fd, "%sSwitchUser response: %s\n", indent.c_str(),
- toString(*mSwitchUserResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
- }
- if (mCreateUserResponseFromCmd != nullptr) {
- dprintf(fd, "%sCreateUser response: %s\n", indent.c_str(),
- toString(*mCreateUserResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo CreateUser response\n", indent.c_str());
- }
- if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- dprintf(fd, "%sSetUserIdentificationAssociation response: %s\n", indent.c_str(),
- toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
- } else {
- dprintf(fd, "%sNo SetUserIdentificationAssociation response\n", indent.c_str());
- }
-}
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
deleted file mode 100644
index db2f117..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
+++ /dev/null
@@ -1,151 +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.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
-
-#include <android-base/result.h>
-
-#include <android/hardware/automotive/vehicle/2.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-constexpr char kUserHalDumpOption[] = "--user-hal";
-
-/**
- * Class used to emulate User HAL behavior through lshal debug requests.
- */
-class EmulatedUserHal {
- public:
- EmulatedUserHal() {}
-
- ~EmulatedUserHal() = default;
-
- /**
- * Checks if the emulator can handle the property.
- */
- bool isSupported(int32_t prop);
-
- /**
- * Lets the emulator set the property.
- *
- * @return updated property and StatusCode
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onSetProperty(
- const VehiclePropValue& value);
-
- /**
- * Gets the property value from the emulator.
- *
- * @return property value and StatusCode
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(
- const VehiclePropValue& value);
-
- /**
- * Shows the User HAL emulation help.
- */
- void showDumpHelp(int fd);
-
- /**
- * Dump its contents.
- */
- void dump(int fd, std::string indent);
-
- private:
- /**
- * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
- * indicating what the initial user should be.
- *
- * During normal circumstances, the emulator will reply right away, passing a response if
- * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which
- * user to boot).
- *
- * But during development / testing, the behavior can be changed using lshal dump, which must
- * use the areaId to indicate what should happen next.
- *
- * So, the behavior of set(INITIAL_USER_INFO) is:
- *
- * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called
- * by lshal).
- * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id
- * and InitialUserInfoResponseAction::DEFAULT
- * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
- * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
- * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can
- * test this error scenario)
- * - if it's 3, then don't send a property change (so Android can emulate a timeout)
- *
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onSetInitialUserInfoResponse(
- const VehiclePropValue& value);
-
- /**
- * Used to emulate SWITCH_USER - see onSetInitialUserInfoResponse() for usage.
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onSetSwitchUserResponse(
- const VehiclePropValue& value);
-
- /**
- * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
- const VehiclePropValue& value);
-
- /**
- * Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
- * usage.
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onSetUserIdentificationAssociation(
- const VehiclePropValue& value);
-
- /**
- * Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
- * usage.
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> onGetUserIdentificationAssociation(
- const VehiclePropValue& value);
-
- /**
- * Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
- */
- android::base::Result<std::unique_ptr<VehiclePropValue>> defaultUserIdentificationAssociation(
- const VehiclePropValue& request);
-
- android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
- std::unique_ptr<VehiclePropValue> response, int32_t requestId);
-
- std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
- std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
- std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
- std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
-};
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedUserHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
deleted file mode 100644
index eae58d0..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "automotive.vehicle@2.0-connector"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "EmulatedVehicleConnector.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() {
- return &mEmulatedUserHal;
-}
-
-void EmulatedVehicleConnector::triggerSendAllValues() {
- sendAllValuesToClient();
-}
-
-StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value,
- bool updateStatus) {
- if (mEmulatedUserHal.isSupported(value.prop)) {
- LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
-
- const auto& ret = mEmulatedUserHal.onSetProperty(value);
- if (!ret.ok()) {
- LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
- return StatusCode(ret.error().code());
- }
- auto updatedValue = ret.value().get();
- if (updatedValue != nullptr) {
- LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
- << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- }
- return StatusCode::OK;
- }
- return this->VehicleHalServer::onSetProperty(value, updateStatus);
-}
-
-bool EmulatedVehicleConnector::onDump(const hidl_handle& handle,
- const hidl_vec<hidl_string>& options) {
- int fd = handle->data[0];
-
- if (options.size() > 0) {
- if (options[0] == "--help") {
- dprintf(fd, "Emulator-specific usage:\n");
- mEmulatedUserHal.showDumpHelp(fd);
- dprintf(fd, "\n");
- // Include caller's help options
- return true;
- } else if (options[0] == kUserHalDumpOption) {
- mEmulatedUserHal.dump(fd, "");
- return false;
-
- } else {
- // Let caller handle the options...
- return true;
- }
- }
-
- dprintf(fd, "Emulator-specific state:\n");
- mEmulatedUserHal.dump(fd, " ");
- dprintf(fd, "\n");
-
- return true;
-}
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
deleted file mode 100644
index 31ac7d8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
-
-#include <vhal_v2_0/VehicleConnector.h>
-
-#include "EmulatedUserHal.h"
-#include "VehicleHalClient.h"
-#include "VehicleHalServer.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
- public:
- EmulatedVehicleConnector() = default;
-
- EmulatedUserHal* getEmulatedUserHal();
-
- // Methods from VehicleHalServer
- void triggerSendAllValues() override;
-
- StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
- bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
- private:
- EmulatedUserHal mEmulatedUserHal;
-};
-
-} // namespace impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
deleted file mode 100644
index e8b79dc..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_TAG "DefaultVehicleHal_v2_0"
-
-#include <android-base/chrono_utils.h>
-#include <android-base/macros.h>
-#include <android-base/properties.h>
-#include <android/log.h>
-#include <dirent.h>
-#include <sys/system_properties.h>
-#include <utils/SystemClock.h>
-#include <fstream>
-#include <regex>
-
-#include "EmulatedVehicleHal.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-static constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;
-
-static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
- size_t numVendorFloatSensors) {
- std::unique_ptr<Obd2SensorStore> sensorStore(
- new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
-
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
- toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
- toInt(Obd2IgnitionMonitorKind::SPARK));
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
- Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
- Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
- Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
- Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
- toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
- sensorStore->setIntegerSensor(
- DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
- sensorStore->setIntegerSensor(
- DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
- sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
- toInt(Obd2FuelType::GASOLINE));
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
- -0.373);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
- 190.);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
- sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
-
- return sensorStore;
-}
-
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
- EmulatedUserHal* emulatedUserHal)
- : mPropStore(propStore),
- mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
- mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
- std::placeholders::_1)),
- mVehicleClient(client),
- mEmulatedUserHal(emulatedUserHal) {
- initStaticConfig();
- mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
- this, std::placeholders::_1,
- std::placeholders::_2));
-
- mInitVhalValueOverride =
- android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
- if (mInitVhalValueOverride) {
- getAllPropertiesOverride();
- }
-}
-
-void EmulatedVehicleHal::getAllPropertiesOverride() {
- if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
- std::regex reg_json(".*[.]json", std::regex::icase);
- while (auto f = readdir(dir)) {
- if (!regex_match(f->d_name, reg_json)) {
- continue;
- }
- std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
- JsonFakeValueGenerator tmpGenerator(file);
-
- std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
- mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
- std::begin(propvalues), std::end(propvalues));
- }
- closedir(dir);
- }
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
- const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
- auto propId = requestedPropValue.prop;
- ALOGV("get(%d)", propId);
-
- auto& pool = *getValuePool();
- VehiclePropValuePtr v = nullptr;
-
- switch (propId) {
- case OBD2_FREEZE_FRAME:
- v = pool.obtainComplex();
- *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
- break;
- case OBD2_FREEZE_FRAME_INFO:
- v = pool.obtainComplex();
- *outStatus = fillObd2DtcInfo(v.get());
- break;
- default:
- if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) {
- ALOGI("get(): getting value for prop %d from User HAL", propId);
- const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue);
- if (!ret.ok()) {
- ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
- *outStatus = StatusCode(ret.error().code());
- } else {
- auto value = ret.value().get();
- if (value != nullptr) {
- ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
- v = getValuePool()->obtain(*value);
- *outStatus = StatusCode::OK;
- } else {
- ALOGE("get(): User HAL returned null value");
- *outStatus = StatusCode::INTERNAL_ERROR;
- }
- }
- break;
- }
-
- auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
- if (internalPropValue != nullptr) {
- v = getValuePool()->obtain(*internalPropValue);
- }
-
- if (!v) {
- *outStatus = StatusCode::INVALID_ARG;
- } else if (v->status == VehiclePropertyStatus::AVAILABLE) {
- *outStatus = StatusCode::OK;
- } else {
- *outStatus = StatusCode::TRY_AGAIN;
- }
- break;
- }
- if (v.get()) {
- v->timestamp = elapsedRealtimeNano();
- }
- return v;
-}
-
-bool EmulatedVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
- return mVehicleClient->dump(fd, options);
-}
-
-StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
- constexpr bool updateStatus = false;
-
- if (propValue.prop == kGenerateFakeDataControllingProperty) {
- // Send the generator controlling request to the server.
- // 'updateStatus' flag is only for the value sent by setProperty (propValue in this case)
- // instead of the generated values triggered by it. 'propValue' works as a control signal
- // here, since we never send the control signal back, the value of 'updateStatus' flag
- // does not matter here.
- auto status = mVehicleClient->setProperty(propValue, updateStatus);
- return status;
- } else if (mHvacPowerProps.count(propValue.prop)) {
- auto hvacPowerOn = mPropStore->readValueOrNull(
- toInt(VehicleProperty::HVAC_POWER_ON),
- (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
- VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
- VehicleAreaSeat::ROW_2_RIGHT));
-
- if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
- && hvacPowerOn->value.int32Values[0] == 0) {
- return StatusCode::NOT_AVAILABLE;
- }
- } else {
- // Handle property specific code
- switch (propValue.prop) {
- case OBD2_FREEZE_FRAME_CLEAR:
- return clearObd2FreezeFrames(propValue);
- case VEHICLE_MAP_SERVICE:
- // Placeholder for future implementation of VMS property in the default hal. For
- // now, just returns OK; otherwise, hal clients crash with property not supported.
- return StatusCode::OK;
- }
- }
-
- if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
- // Android side cannot set property status - this value is the
- // purview of the HAL implementation to reflect the state of
- // its underlying hardware
- return StatusCode::INVALID_ARG;
- }
- auto currentPropValue = mPropStore->readValueOrNull(propValue);
-
- if (currentPropValue == nullptr) {
- return StatusCode::INVALID_ARG;
- }
- if (currentPropValue->status != VehiclePropertyStatus::AVAILABLE) {
- // do not allow Android side to set() a disabled/error property
- return StatusCode::NOT_AVAILABLE;
- }
-
- if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
- // Emulator does not support remote brightness control, b/139959479
- // do not send it down so that it does not bring unnecessary property change event
- // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
- // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
- return StatusCode::OK;
- }
-
- /**
- * After checking all conditions, such as the property is available, a real vhal will
- * sent the events to Car ECU to take actions.
- */
-
- // Send the value to the vehicle server, the server will talk to the (real or emulated) car
- auto setValueStatus = mVehicleClient->setProperty(propValue, updateStatus);
- if (setValueStatus != StatusCode::OK) {
- return setValueStatus;
- }
-
- return StatusCode::OK;
-}
-
-static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
- switch (propConfig.prop) {
- case OBD2_LIVE_FRAME:
- case OBD2_FREEZE_FRAME:
- case OBD2_FREEZE_FRAME_CLEAR:
- case OBD2_FREEZE_FRAME_INFO:
- return true;
- }
- return false;
-}
-
-// Parse supported properties list and generate vector of property values to hold current values.
-void EmulatedVehicleHal::onCreate() {
- static constexpr bool shouldUpdateStatus = true;
-
- auto configs = mVehicleClient->getAllPropertyConfig();
-
- for (const auto& cfg : configs) {
- if (isDiagnosticProperty(cfg)) {
- // do not write an initial empty value for the diagnostic properties
- // as we will initialize those separately.
- continue;
- }
-
- int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
-
- for (int i = 0; i < numAreas; i++) {
- int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
-
- // Create a separate instance for each individual zone
- VehiclePropValue prop = {
- .areaId = curArea,
- .prop = cfg.prop,
- .status = VehiclePropertyStatus::UNAVAILABLE,
- };
-
- if (mInitVhalValueOverride) {
- for (auto& itOverride : mVehiclePropertiesOverride) {
- if (itOverride.prop == cfg.prop) {
- prop.status = VehiclePropertyStatus::AVAILABLE;
- prop.value = itOverride.value;
- }
- }
- }
- mPropStore->writeValue(prop, shouldUpdateStatus);
- }
- }
-
- mVehicleClient->triggerSendAllValues();
-
- initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
- initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
- mInEmulator = isInEmulator();
- ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
- mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
- static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
-}
-
-std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
- return mPropStore->getAllConfigs();
-}
-
-void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
- VehiclePropValuePtr v;
-
- auto& pool = *getValuePool();
-
- for (int32_t property : properties) {
- if (isContinuousProperty(property)) {
- auto internalPropValue = mPropStore->readValueOrNull(property);
- if (internalPropValue != nullptr) {
- v = pool.obtain(*internalPropValue);
- }
- } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
- // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
- // So, the update is done through onContinuousPropertyTimer.
- v = doInternalHealthCheck();
- } else {
- ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
- }
-
- if (v.get()) {
- v->timestamp = elapsedRealtimeNano();
- doHalEvent(std::move(v));
- }
- }
-}
-
-StatusCode EmulatedVehicleHal::subscribe(int32_t property, float sampleRate) {
- ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
-
- if (isContinuousProperty(property)) {
- mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
- }
- return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {
- ALOGI("%s propId: 0x%x", __func__, property);
- if (isContinuousProperty(property)) {
- mRecurrentTimer.unregisterRecurrentEvent(property);
- }
- return StatusCode::OK;
-}
-
-bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
- const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
- if (config == nullptr) {
- ALOGW("Config not found for property: 0x%x", propId);
- return false;
- }
- return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
-}
-
-bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
- constexpr bool updateStatus = true;
- return mVehicleClient->setProperty(propValue, updateStatus) == StatusCode::OK;
-}
-
-std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const {
- return mPropStore->readAllValues();
-}
-
-void EmulatedVehicleHal::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
- VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value);
-
- if (mPropStore->writeValue(*updatedPropValue, updateStatus)) {
- getEmulatorOrDie()->doSetValueFromClient(*updatedPropValue);
- doHalEvent(std::move(updatedPropValue));
- }
-}
-
-void EmulatedVehicleHal::initStaticConfig() {
- auto configs = mVehicleClient->getAllPropertyConfig();
- for (auto&& cfg : configs) {
- VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
-
- switch (cfg.prop) {
- case OBD2_FREEZE_FRAME: {
- tokenFunction = [](const VehiclePropValue& propValue) {
- return propValue.timestamp;
- };
- break;
- }
- default:
- break;
- }
-
- mPropStore->registerProperty(cfg, tokenFunction);
- }
-}
-
-void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
- static constexpr bool shouldUpdateStatus = true;
-
- auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
- auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
- static_cast<size_t>(propConfig.configArray[1]));
- sensorStore->fillPropValue("", liveObd2Frame.get());
- liveObd2Frame->prop = OBD2_LIVE_FRAME;
-
- mPropStore->writeValue(*liveObd2Frame, shouldUpdateStatus);
-}
-
-void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
- static constexpr bool shouldUpdateStatus = true;
-
- auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
- static_cast<size_t>(propConfig.configArray[1]));
-
- static std::vector<std::string> sampleDtcs = {"P0070",
- "P0102"
- "P0123"};
- for (auto&& dtc : sampleDtcs) {
- auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
- sensorStore->fillPropValue(dtc, freezeFrame.get());
- freezeFrame->prop = OBD2_FREEZE_FRAME;
-
- mPropStore->writeValue(*freezeFrame, shouldUpdateStatus);
- }
-}
-
-StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
- VehiclePropValue* outValue) {
- if (requestedPropValue.value.int64Values.size() != 1) {
- ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
- return StatusCode::INVALID_ARG;
- }
- auto timestamp = requestedPropValue.value.int64Values[0];
- auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
- if (freezeFrame == nullptr) {
- ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
- return StatusCode::INVALID_ARG;
- }
- outValue->prop = OBD2_FREEZE_FRAME;
- outValue->value.int32Values = freezeFrame->value.int32Values;
- outValue->value.floatValues = freezeFrame->value.floatValues;
- outValue->value.bytes = freezeFrame->value.bytes;
- outValue->value.stringValue = freezeFrame->value.stringValue;
- outValue->timestamp = freezeFrame->timestamp;
- return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
- if (propValue.value.int64Values.size() == 0) {
- mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
- return StatusCode::OK;
- } else {
- for (int64_t timestamp : propValue.value.int64Values) {
- auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
- if (freezeFrame == nullptr) {
- ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
- return StatusCode::INVALID_ARG;
- }
- mPropStore->removeValue(*freezeFrame);
- }
- }
- return StatusCode::OK;
-}
-
-StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
- std::vector<int64_t> timestamps;
- for (const auto& freezeFrame : mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
- timestamps.push_back(freezeFrame.timestamp);
- }
- outValue->value.int64Values = timestamps;
- outValue->prop = OBD2_FREEZE_FRAME_INFO;
- return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::doInternalHealthCheck() {
- VehicleHal::VehiclePropValuePtr v = nullptr;
-
- // This is an example of very simpe health checking. VHAL is considered healthy if we can read
- // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
- VehiclePropValue propValue = {
- .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
- };
- auto internalPropValue = mPropStore->readValueOrNull(propValue);
- if (internalPropValue != nullptr) {
- v = createVhalHeartBeatProp();
- } else {
- ALOGW("VHAL health check failed");
- }
- return v;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createVhalHeartBeatProp() {
- VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
- v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
- v->areaId = 0;
- v->status = VehiclePropertyStatus::AVAILABLE;
- return v;
-}
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 7871c7b..1387f85 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,26 +14,14 @@
* limitations under the License.
*/
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+// This file is just used for soft migration from EmulatedVehicleHal to DefaultVehicleHal.
+// The virtualized VHAL that uses EmulatedVehicleHal is at a different repo and cannot be updated
+// together with this repo, so we need a soft migration. Once the rename is finished at the
+// virtualized VHAL side, this file would be removed.
-#include <map>
-#include <memory>
-#include <sys/socket.h>
-#include <thread>
-#include <unordered_set>
+#pragma once
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/RecurrentTimer.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include "vhal_v2_0/VehiclePropertyStore.h"
-
-#include "EmulatedUserHal.h"
-#include "EmulatedVehicleConnector.h"
-#include "GeneratorHub.h"
-#include "PropertyUtils.h"
-#include "VehicleEmulator.h"
+#include "DefaultVehicleHal.h"
namespace android {
namespace hardware {
@@ -43,66 +31,16 @@
namespace impl {
-/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
-class EmulatedVehicleHal : public EmulatedVehicleHalIface {
-public:
- EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
- EmulatedUserHal* emulatedUserHal = nullptr);
- ~EmulatedVehicleHal() = default;
-
- // Methods from VehicleHal
- void onCreate() override;
- std::vector<VehiclePropConfig> listProperties() override;
- VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
- StatusCode* outStatus) override;
- StatusCode set(const VehiclePropValue& propValue) override;
- StatusCode subscribe(int32_t property, float sampleRate) override;
- StatusCode unsubscribe(int32_t property) override;
- bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
- // Methods from EmulatedVehicleHalIface
- bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
- std::vector<VehiclePropValue> getAllProperties() const override;
- void getAllPropertiesOverride();
-
-private:
- constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
- return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
- }
-
- StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
- void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
-
- void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
- bool isContinuousProperty(int32_t propId) const;
- void initStaticConfig();
- void initObd2LiveFrame(const VehiclePropConfig& propConfig);
- void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
- StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
- VehiclePropValue* outValue);
- StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
- StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
- VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
- VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
-
- /* Private members */
- VehiclePropertyStore* mPropStore;
- std::unordered_set<int32_t> mHvacPowerProps;
- RecurrentTimer mRecurrentTimer;
- VehicleHalClient* mVehicleClient;
- bool mInEmulator;
- bool mInitVhalValueOverride;
- std::vector<VehiclePropValue> mVehiclePropertiesOverride;
- EmulatedUserHal* mEmulatedUserHal;
+class EmulatedVehicleHal : public DefaultVehicleHal {
+ public:
+ EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+ : DefaultVehicleHal(propStore, client){};
};
-} // impl
+} // namespace impl
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
} // namespace hardware
} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index b62918f..b728d62 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -33,12 +33,37 @@
namespace impl {
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t repetition) {
+ const char* file = path.c_str();
+ std::ifstream ifs(file);
+ if (!ifs) {
+ ALOGE("%s: couldn't open %s for parsing.", __func__, file);
+ mGenCfg = {
+ .index = 0,
+ .events = {},
+ };
+ mNumOfIterations = 0;
+ return;
+ }
+ mGenCfg = {
+ .index = 0,
+ .events = parseFakeValueJson(ifs),
+ };
+ mNumOfIterations = repetition;
+}
+
JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
const char* file = v.stringValue.c_str();
std::ifstream ifs(file);
if (!ifs) {
ALOGE("%s: couldn't open %s for parsing.", __func__, file);
+ mGenCfg = {
+ .index = 0,
+ .events = {},
+ };
+ mNumOfIterations = 0;
+ return;
}
mGenCfg = {
.index = 0,
@@ -48,10 +73,16 @@
mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
-JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
+JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
std::ifstream ifs(path);
if (!ifs) {
ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
+ mGenCfg = {
+ .index = 0,
+ .events = {},
+ };
+ mNumOfIterations = 0;
+ return;
}
mGenCfg = {
.index = 0,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index dc8ff66..caa3417 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,7 +41,8 @@
public:
JsonFakeValueGenerator(const VehiclePropValue& request);
- JsonFakeValueGenerator(std::string path);
+ JsonFakeValueGenerator(const std::string& path, int32_t repetition);
+ JsonFakeValueGenerator(const std::string& path);
~JsonFakeValueGenerator() = default;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 96aaafe..a2278bd 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -29,23 +29,36 @@
namespace impl {
+LinearFakeValueGenerator::LinearFakeValueGenerator(int32_t propId, float middleValue,
+ float currentValue, float dispersion,
+ float increment, int64_t interval) {
+ initGenCfg(propId, middleValue, currentValue, dispersion, increment, interval);
+}
+
LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
+ initGenCfg(v.int32Values[1], v.floatValues[0], v.floatValues[0], v.floatValues[1],
+ v.floatValues[2], v.int64Values[0]);
+}
+
+void LinearFakeValueGenerator::initGenCfg(int32_t propId, float middleValue, float currentValue,
+ float dispersion, float increment, int64_t interval) {
+ if (currentValue < middleValue - dispersion || currentValue >= middleValue + dispersion) {
+ ALOGW("%s: invalid initValue: %f, out of range, default to %f", __func__, currentValue,
+ middleValue);
+ currentValue = middleValue;
+ }
mGenCfg = GeneratorCfg{
- .propId = v.int32Values[1],
- .initialValue = v.floatValues[0],
- .currentValue = v.floatValues[0],
- .dispersion = v.floatValues[1],
- .increment = v.floatValues[2],
- .interval = Nanos(v.int64Values[0]),
+ .propId = propId,
+ .middleValue = middleValue,
+ .currentValue = currentValue,
+ .dispersion = dispersion,
+ .increment = increment,
+ .interval = Nanos(interval),
};
}
VehiclePropValue LinearFakeValueGenerator::nextEvent() {
- mGenCfg.currentValue += mGenCfg.increment;
- if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
- mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
- }
// TODO: (chenhaosjtuacm) remove "{}" if AGL compiler updated
VehiclePropValue event = {.timestamp = {}, .areaId = {}, .prop = mGenCfg.propId};
auto& value = event.value;
@@ -67,6 +80,12 @@
}
TimePoint eventTime = Clock::now() + mGenCfg.interval;
event.timestamp = eventTime.time_since_epoch().count();
+
+ mGenCfg.currentValue += mGenCfg.increment;
+ if (mGenCfg.currentValue >= mGenCfg.middleValue + mGenCfg.dispersion) {
+ // Wrap around, (i - d) + c - (i + d) = c - 2 * d
+ mGenCfg.currentValue = mGenCfg.currentValue - 2 * mGenCfg.dispersion;
+ }
return event;
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
index d3b666d..d870209 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
@@ -35,8 +35,8 @@
struct GeneratorCfg {
int32_t propId;
- float initialValue;
- float currentValue; // Should be in range (initialValue +/- dispersion).
+ float middleValue;
+ float currentValue; // Should be in range (middleValue +/- dispersion).
float dispersion; // Defines minimum and maximum value based on initial value.
float increment; // Value that we will be added to currentValue with each timer tick.
Nanos interval;
@@ -44,6 +44,11 @@
public:
LinearFakeValueGenerator(const VehiclePropValue& request);
+ // A linear value generator in range [middleValue - dispersion, middleValue + dispersion),
+ // starts at 'currentValue' and at each 'interval', increase by 'increment' and loop back if
+ // exceeds middleValue + dispersion.
+ LinearFakeValueGenerator(int32_t propId, float middleValue, float currentValue,
+ float dispersion, float increment, int64_t interval);
~LinearFakeValueGenerator() = default;
VehiclePropValue nextEvent();
@@ -52,6 +57,9 @@
private:
GeneratorCfg mGenCfg;
+
+ void initGenCfg(int32_t propId, float middleValue, float currentValue, float dispersion,
+ float increment, int64_t interval);
};
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
deleted file mode 100644
index 81e7c78..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "PipeComm"
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <log/log.h>
-
-#include "PipeComm.h"
-#include "qemu_pipe.h"
-
-#define CAR_SERVICE_NAME "pipe:qemud:car"
-
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {}
-
-void PipeComm::start() {
- int fd = qemu_pipe_open(CAR_SERVICE_NAME);
-
- if (fd < 0) {
- ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd);
- return;
- }
-
- ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd);
- mPipeFd = fd;
-
- CommConn::start();
-}
-
-void PipeComm::stop() {
- if (mPipeFd > 0) {
- ::close(mPipeFd);
- mPipeFd = -1;
- }
- CommConn::stop();
-}
-
-std::vector<uint8_t> PipeComm::read() {
- static constexpr int MAX_RX_MSG_SZ = 2048;
- std::vector<uint8_t> msg = std::vector<uint8_t>(MAX_RX_MSG_SZ);
- int numBytes;
-
- numBytes = qemu_pipe_frame_recv(mPipeFd, msg.data(), msg.size());
-
- if (numBytes == MAX_RX_MSG_SZ) {
- ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ);
- } else if (numBytes > 0) {
- msg.resize(numBytes);
- return msg;
- } else {
- ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes);
- mPipeFd = -1;
- }
-
- return std::vector<uint8_t>();
-}
-
-int PipeComm::write(const std::vector<uint8_t>& data) {
- int retVal = 0;
-
- if (mPipeFd != -1) {
- retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size());
- }
-
- if (retVal < 0) {
- retVal = -errno;
- ALOGE("%s: send_cmd: (fd=%d): ERROR: %s", __FUNCTION__, mPipeFd, strerror(errno));
- }
-
- return retVal;
-}
-
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
deleted file mode 100644
index c8eabb8..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
-
-#include <mutex>
-#include <vector>
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-/**
- * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the
- * Vehicle HAL and simulate changing properties.
- *
- * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open
- * at a time.
- */
-class PipeComm : public CommConn {
- public:
- PipeComm(MessageProcessor* messageProcessor);
-
- void start() override;
- void stop() override;
-
- std::vector<uint8_t> read() override;
- int write(const std::vector<uint8_t>& data) override;
-
- inline bool isOpen() override { return mPipeFd > 0; }
-
- private:
- int mPipeFd;
-};
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_PipeComm_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
deleted file mode 100644
index 916c320..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "SocketComm"
-
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
-#include <android/log.h>
-#include <arpa/inet.h>
-#include <log/log.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "SocketComm.h"
-
-// Socket to use when communicating with Host PC
-static constexpr int DEBUG_SOCKET = 33452;
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-SocketComm::SocketComm(MessageProcessor* messageProcessor)
- : mListenFd(-1), mMessageProcessor(messageProcessor) {}
-
-SocketComm::~SocketComm() {
-}
-
-void SocketComm::start() {
- if (!listen()) {
- return;
- }
-
- mListenThread = std::make_unique<std::thread>(std::bind(&SocketComm::listenThread, this));
-}
-
-void SocketComm::stop() {
- if (mListenFd > 0) {
- ::close(mListenFd);
- if (mListenThread->joinable()) {
- mListenThread->join();
- }
- mListenFd = -1;
- }
-}
-
-void SocketComm::sendMessage(vhal_proto::EmulatorMessage const& msg) {
- std::lock_guard<std::mutex> lock(mMutex);
- for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) {
- conn->sendMessage(msg);
- }
-}
-
-bool SocketComm::listen() {
- int retVal;
- struct sockaddr_in servAddr;
-
- mListenFd = socket(AF_INET, SOCK_STREAM, 0);
- if (mListenFd < 0) {
- ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno);
- mListenFd = -1;
- return false;
- }
-
- memset(&servAddr, 0, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = INADDR_ANY;
- servAddr.sin_port = htons(DEBUG_SOCKET);
-
- retVal = bind(mListenFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
- if(retVal < 0) {
- ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno);
- close(mListenFd);
- mListenFd = -1;
- return false;
- }
-
- ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET);
- if (::listen(mListenFd, 1) == -1) {
- ALOGE("%s: Error on listening: errno: %d: %s", __FUNCTION__, errno, strerror(errno));
- return false;
- }
- return true;
-}
-
-SocketConn* SocketComm::accept() {
- sockaddr_in cliAddr;
- socklen_t cliLen = sizeof(cliAddr);
- int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
-
- if (sfd > 0) {
- char addr[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN);
-
- ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port);
- return new SocketConn(mMessageProcessor, sfd);
- }
-
- return nullptr;
-}
-
-void SocketComm::listenThread() {
- while (true) {
- SocketConn* conn = accept();
- if (conn == nullptr) {
- return;
- }
-
- conn->start();
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn));
- }
- }
-}
-
-/**
- * Called occasionally to clean up connections that have been closed.
- */
-void SocketComm::removeClosedConnections() {
- std::lock_guard<std::mutex> lock(mMutex);
- std::remove_if(mOpenConnections.begin(), mOpenConnections.end(),
- [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); });
-}
-
-SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd)
- : CommConn(messageProcessor), mSockFd(sfd) {}
-
-/**
- * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns
- * an empty buffer, otherwise will return exactly the given number of bytes.
- */
-std::vector<uint8_t> readExactly(int fd, int numBytes) {
- std::vector<uint8_t> buffer(numBytes);
- int totalRead = 0;
- int offset = 0;
- while (totalRead < numBytes) {
- int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset);
- if (numRead == 0) {
- buffer.resize(0);
- return buffer;
- }
-
- totalRead += numRead;
- }
- return buffer;
-}
-
-/**
- * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns
- * -1.
- */
-int32_t readInt(int fd) {
- std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t));
- if (buffer.size() == 0) {
- return -1;
- }
-
- int32_t value = *reinterpret_cast<int32_t*>(buffer.data());
- return ntohl(value);
-}
-
-std::vector<uint8_t> SocketConn::read() {
- int32_t msgSize = readInt(mSockFd);
- if (msgSize <= 0) {
- ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd);
- return std::vector<uint8_t>();
- }
-
- return readExactly(mSockFd, msgSize);
-}
-
-void SocketConn::stop() {
- if (mSockFd > 0) {
- close(mSockFd);
- mSockFd = -1;
- }
-}
-
-int SocketConn::write(const std::vector<uint8_t>& data) {
- static constexpr int MSG_HEADER_LEN = 4;
- int retVal = 0;
- union {
- uint32_t msgLen;
- uint8_t msgLenBytes[MSG_HEADER_LEN];
- };
-
- // Prepare header for the message
- msgLen = static_cast<uint32_t>(data.size());
- msgLen = htonl(msgLen);
-
- if (mSockFd > 0) {
- retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN);
-
- if (retVal == MSG_HEADER_LEN) {
- retVal = ::write(mSockFd, data.data(), data.size());
- }
- }
-
- return retVal;
-}
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
deleted file mode 100644
index 52326b9..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
-
-#include <mutex>
-#include <thread>
-#include <vector>
-#include "CommConn.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class SocketConn;
-
-/**
- * SocketComm opens a socket, and listens for connections from clients. Typically the client will be
- * adb's TCP port-forwarding to enable a host PC to connect to the VehicleHAL.
- */
-class SocketComm {
- public:
- SocketComm(MessageProcessor* messageProcessor);
- virtual ~SocketComm();
-
- void start();
- void stop();
-
- /**
- * Serialized and send the given message to all connected clients.
- */
- void sendMessage(vhal_proto::EmulatorMessage const& msg);
-
- private:
- int mListenFd;
- std::unique_ptr<std::thread> mListenThread;
- std::vector<std::unique_ptr<SocketConn>> mOpenConnections;
- MessageProcessor* mMessageProcessor;
- std::mutex mMutex;
-
- /**
- * Opens the socket and begins listening.
- *
- * @return bool Returns true on success.
- */
- bool listen();
-
- /**
- * Blocks and waits for a connection from a client, returns a new SocketConn with the connection
- * or null, if the connection has been closed.
- *
- * @return int Returns fd or socket number if connection is successful.
- * Otherwise, returns -1 if no connection is availble.
- */
- SocketConn* accept();
-
- void listenThread();
-
- void removeClosedConnections();
-};
-
-/**
- * SocketConn represents a single connection to a client.
- */
-class SocketConn : public CommConn {
- public:
- SocketConn(MessageProcessor* messageProcessor, int sfd);
- virtual ~SocketConn() = default;
-
- /**
- * Blocking call to read data from the connection.
- *
- * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be
- * an empty vector if the connection was closed or some other error occurred.
- */
- std::vector<uint8_t> read() override;
-
- /**
- * Closes a connection if it is open.
- */
- void stop() override;
-
- /**
- * Transmits a string of data to the emulator.
- *
- * @param data Serialized protobuf data to transmit.
- *
- * @return int Number of bytes transmitted, or -1 if failed.
- */
- int write(const std::vector<uint8_t>& data) override;
-
- inline bool isOpen() override { return mSockFd > 0; }
-
- private:
- int mSockFd;
-};
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
deleted file mode 100644
index f7d0854..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "VehicleEmulator_v2_0"
-#include <android/log.h>
-
-#include <android-base/properties.h>
-#include <log/log.h>
-#include <utils/SystemClock.h>
-#include <algorithm>
-
-#include <vhal_v2_0/VehicleUtils.h>
-
-#include "PipeComm.h"
-#include "ProtoMessageConverter.h"
-#include "SocketComm.h"
-
-#include "VehicleEmulator.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} {
- mHal->registerEmulator(this);
-
- ALOGI("Starting SocketComm");
- mSocketComm = std::make_unique<SocketComm>(this);
- mSocketComm->start();
-
- if (isInEmulator()) {
- ALOGI("Starting PipeComm");
- mPipeComm = std::make_unique<PipeComm>(this);
- mPipeComm->start();
- }
-}
-
-VehicleEmulator::~VehicleEmulator() {
- mSocketComm->stop();
- if (mPipeComm) {
- mPipeComm->stop();
- }
-}
-
-/**
- * This is called by the HAL when a property changes. We need to notify our clients that it has
- * changed.
- */
-void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
- vhal_proto::EmulatorMessage msg;
- vhal_proto::VehiclePropValue* val = msg.add_value();
- populateProtoVehiclePropValue(val, &propValue);
- msg.set_status(vhal_proto::RESULT_OK);
- msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC);
-
- mSocketComm->sendMessage(msg);
- if (mPipeComm) {
- mPipeComm->sendMessage(msg);
- }
-}
-
-void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage const& rxMsg,
- VehicleEmulator::EmulatorMessage& respMsg) {
- std::vector<VehiclePropConfig> configs = mHal->listProperties();
- vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
-
- respMsg.set_msg_type(vhal_proto::GET_CONFIG_RESP);
- respMsg.set_status(vhal_proto::ERROR_INVALID_PROPERTY);
-
- for (auto& config : configs) {
- // Find the config we are looking for
- if (config.prop == getProp.prop()) {
- vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
- populateProtoVehicleConfig(protoCfg, config);
- respMsg.set_status(vhal_proto::RESULT_OK);
- break;
- }
- }
-}
-
-void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
- VehicleEmulator::EmulatorMessage& respMsg) {
- std::vector<VehiclePropConfig> configs = mHal->listProperties();
-
- respMsg.set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP);
- respMsg.set_status(vhal_proto::RESULT_OK);
-
- for (auto& config : configs) {
- vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
- populateProtoVehicleConfig(protoCfg, config);
- }
-}
-
-void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
- VehicleEmulator::EmulatorMessage& respMsg) {
- int32_t areaId = 0;
- vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
- int32_t propId = getProp.prop();
- vhal_proto::Status status = vhal_proto::ERROR_INVALID_PROPERTY;
-
- respMsg.set_msg_type(vhal_proto::GET_PROPERTY_RESP);
-
- if (getProp.has_area_id()) {
- areaId = getProp.area_id();
- }
-
- {
- VehiclePropValue request = {
- .areaId = areaId,
- .prop = propId,
- };
- StatusCode halStatus;
- auto val = mHal->get(request, &halStatus);
- if (val != nullptr) {
- vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
- populateProtoVehiclePropValue(protoVal, val.get());
- status = vhal_proto::RESULT_OK;
- }
- }
-
- respMsg.set_status(status);
-}
-
-void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
- VehicleEmulator::EmulatorMessage& respMsg) {
- respMsg.set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP);
- respMsg.set_status(vhal_proto::RESULT_OK);
-
- {
- for (const auto& prop : mHal->getAllProperties()) {
- vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
- populateProtoVehiclePropValue(protoVal, &prop);
- }
- }
-}
-
-void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
- VehicleEmulator::EmulatorMessage& respMsg) {
- vhal_proto::VehiclePropValue protoVal = rxMsg.value(0);
- VehiclePropValue val = {
- .timestamp = elapsedRealtimeNano(),
- .areaId = protoVal.area_id(),
- .prop = protoVal.prop(),
- .status = (VehiclePropertyStatus)protoVal.status(),
- };
-
- respMsg.set_msg_type(vhal_proto::SET_PROPERTY_RESP);
-
- // Copy value data if it is set. This automatically handles complex data types if needed.
- if (protoVal.has_string_value()) {
- val.value.stringValue = protoVal.string_value().c_str();
- }
-
- if (protoVal.has_bytes_value()) {
- val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
- protoVal.bytes_value().end() };
- }
-
- if (protoVal.int32_values_size() > 0) {
- val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
- protoVal.int32_values().end() };
- }
-
- if (protoVal.int64_values_size() > 0) {
- val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
- protoVal.int64_values().end() };
- }
-
- if (protoVal.float_values_size() > 0) {
- val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
- protoVal.float_values().end() };
- }
-
- bool halRes = mHal->setPropertyFromVehicle(val);
- respMsg.set_status(halRes ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY);
-}
-
-void VehicleEmulator::processMessage(vhal_proto::EmulatorMessage const& rxMsg,
- vhal_proto::EmulatorMessage& respMsg) {
- switch (rxMsg.msg_type()) {
- case vhal_proto::GET_CONFIG_CMD:
- doGetConfig(rxMsg, respMsg);
- break;
- case vhal_proto::GET_CONFIG_ALL_CMD:
- doGetConfigAll(rxMsg, respMsg);
- break;
- case vhal_proto::GET_PROPERTY_CMD:
- doGetProperty(rxMsg, respMsg);
- break;
- case vhal_proto::GET_PROPERTY_ALL_CMD:
- doGetPropertyAll(rxMsg, respMsg);
- break;
- case vhal_proto::SET_PROPERTY_CMD:
- doSetProperty(rxMsg, respMsg);
- break;
- default:
- ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
- respMsg.set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);
- break;
- }
-}
-
-void VehicleEmulator::populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
- const VehiclePropConfig& cfg) {
- return proto_msg_converter::toProto(protoCfg, cfg);
-}
-
-void VehicleEmulator::populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
- const VehiclePropValue* val) {
- return proto_msg_converter::toProto(protoVal, *val);
-}
-
-bool isInEmulator() {
- return android::base::GetBoolProperty("ro.boot.qemu", false);
-}
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
deleted file mode 100644
index 434d79b..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
-
-#include <log/log.h>
-#include <memory>
-#include <thread>
-#include <vector>
-
-#include "vhal_v2_0/VehicleHal.h"
-
-#include "CommConn.h"
-#include "PipeComm.h"
-#include "SocketComm.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class VehicleEmulator; // Forward declaration.
-
-/** Extension of VehicleHal that used by VehicleEmulator. */
-class EmulatedVehicleHalIface : public VehicleHal {
-public:
- virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
- virtual std::vector<VehiclePropValue> getAllProperties() const = 0;
-
- void registerEmulator(VehicleEmulator* emulator) {
- ALOGI("%s, emulator: %p", __func__, emulator);
- std::lock_guard<std::mutex> g(mEmulatorLock);
- mEmulator = emulator;
- }
-
-protected:
- VehicleEmulator* getEmulatorOrDie() {
- std::lock_guard<std::mutex> g(mEmulatorLock);
- if (mEmulator == nullptr) abort();
- return mEmulator;
- }
-
-private:
- mutable std::mutex mEmulatorLock;
- VehicleEmulator* mEmulator;
-};
-
-/**
- * Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
- */
-class VehicleEmulator : public MessageProcessor {
- public:
- VehicleEmulator(EmulatedVehicleHalIface* hal);
- virtual ~VehicleEmulator();
-
- void doSetValueFromClient(const VehiclePropValue& propValue);
- void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
- vhal_proto::EmulatorMessage& respMsg) override;
-
- private:
- friend class ConnectionThread;
- using EmulatorMessage = vhal_proto::EmulatorMessage;
-
- void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
- const VehiclePropConfig& cfg);
- void populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
- const VehiclePropValue* val);
-
-private:
- EmulatedVehicleHalIface* mHal;
- std::unique_ptr<SocketComm> mSocketComm;
- std::unique_ptr<PipeComm> mPipeComm;
-};
-
-// determine if it's running inside Android Emulator
-bool isInEmulator();
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
index 25ffc6d..bafd170 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
@@ -18,7 +18,13 @@
#include <android-base/logging.h>
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
void VehicleHalClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
if (!mPropCallback) {
@@ -36,4 +42,10 @@
mPropCallback = std::move(callback);
}
-} // namespace android::hardware::automotive::vehicle::V2_0::impl
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
index 81dfca1..2473f19 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
@@ -18,7 +18,13 @@
#include <vhal_v2_0/VehicleClient.h>
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
// The common client operations that may be used by both native and
// virtualized VHAL clients.
@@ -40,4 +46,10 @@
PropertyCallBackType mPropCallback;
};
-} // namespace android::hardware::automotive::vehicle::V2_0::impl
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
deleted file mode 100644
index 57dd7d4..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ /dev/null
@@ -1,340 +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.
- */
-
-#define LOG_TAG "VehicleHalServer"
-
-#include "VehicleHalServer.h"
-
-#include <fstream>
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "DefaultConfig.h"
-#include "JsonFakeValueGenerator.h"
-#include "LinearFakeValueGenerator.h"
-#include "Obd2SensorStore.h"
-
-namespace android::hardware::automotive::vehicle::V2_0::impl {
-
-static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
- switch (propConfig.prop) {
- case OBD2_LIVE_FRAME:
- case OBD2_FREEZE_FRAME:
- case OBD2_FREEZE_FRAME_CLEAR:
- case OBD2_FREEZE_FRAME_INFO:
- return true;
- }
- return false;
-}
-
-VehicleHalServer::VehicleHalServer() {
- constexpr bool shouldUpdateStatus = true;
-
- for (auto& it : kVehicleProperties) {
- VehiclePropConfig cfg = it.config;
-
- mServerSidePropStore.registerProperty(cfg);
-
- if (isDiagnosticProperty(cfg)) {
- continue;
- }
-
- // A global property will have only a single area
- int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
-
- for (int i = 0; i < numAreas; i++) {
- int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
-
- // Create a separate instance for each individual zone
- VehiclePropValue prop = {
- .areaId = curArea,
- .prop = cfg.prop,
- };
-
- if (it.initialAreaValues.empty()) {
- prop.value = it.initialValue;
- } else if (auto valueForAreaIt = it.initialAreaValues.find(curArea);
- valueForAreaIt != it.initialAreaValues.end()) {
- prop.value = valueForAreaIt->second;
- } else {
- LOG(WARNING) << __func__ << " failed to get default value for"
- << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex
- << curArea;
- prop.status = VehiclePropertyStatus::UNAVAILABLE;
- }
-
- mServerSidePropStore.writeValue(prop, shouldUpdateStatus);
- }
- }
-}
-
-void VehicleHalServer::sendAllValuesToClient() {
- constexpr bool update_status = true;
- auto values = mServerSidePropStore.readAllValues();
- for (const auto& value : values) {
- onPropertyValueFromCar(value, update_status);
- }
-}
-
-GeneratorHub* VehicleHalServer::getGenerator() {
- return &mGeneratorHub;
-}
-
-VehiclePropValuePool* VehicleHalServer::getValuePool() const {
- if (!mValuePool) {
- LOG(WARNING) << __func__ << ": Value pool not set!";
- }
- return mValuePool;
-}
-
-void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
- if (!valuePool) {
- LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
- }
- mValuePool = valuePool;
-}
-
-void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
- constexpr bool updateStatus = true;
- LOG(DEBUG) << __func__ << ": " << toString(value);
- auto updatedPropValue = getValuePool()->obtain(value);
- if (updatedPropValue) {
- updatedPropValue->timestamp = value.timestamp;
- updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
- mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- }
-}
-
-std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
- return mServerSidePropStore.getAllConfigs();
-}
-
-StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
- constexpr bool updateStatus = true;
-
- LOG(INFO) << __func__;
- const auto& v = request.value;
- if (!v.int32Values.size()) {
- LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
- return StatusCode::INVALID_ARG;
- }
-
- FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
- switch (command) {
- case FakeDataCommand::StartLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- if (!v.int64Values.size()) {
- LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
- return StatusCode::INVALID_ARG;
- }
- if (v.floatValues.size() < 3) {
- LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
- << v.floatValues.size();
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->registerGenerator(cookie,
- std::make_unique<LinearFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StartJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->registerGenerator(cookie,
- std::make_unique<JsonFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StopLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::StopJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::KeyPress: {
- LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
- int32_t keyCode = request.value.int32Values[2];
- int32_t display = request.value.int32Values[3];
- // Send back to HAL
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
- updateStatus);
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
- updateStatus);
- break;
- }
- default: {
- LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
- return StatusCode::INVALID_ARG;
- }
- }
- return StatusCode::OK;
-}
-
-VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
- VehicleApPowerStateReq state, int32_t param) {
- auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
- req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
- req->areaId = 0;
- req->timestamp = elapsedRealtimeNano();
- req->status = VehiclePropertyStatus::AVAILABLE;
- req->value.int32Values[0] = toInt(state);
- req->value.int32Values[1] = param;
- return req;
-}
-
-VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
- VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
- auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
- keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
- keyEvent->areaId = 0;
- keyEvent->timestamp = elapsedRealtimeNano();
- keyEvent->status = VehiclePropertyStatus::AVAILABLE;
- keyEvent->value.int32Values[0] = toInt(action);
- keyEvent->value.int32Values[1] = keyCode;
- keyEvent->value.int32Values[2] = targetDisplay;
- return keyEvent;
-}
-
-StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
- LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
-
- // Some properties need to be treated non-trivially
- switch (value.prop) {
- case kGenerateFakeDataControllingProperty:
- return handleGenerateFakeDataRequest(value);
-
- // set the value from vehicle side, used in end to end test.
- case kSetIntPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetFloatPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetBooleanPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
- updatedPropValue->prop = value.value.int32Values[1];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
-
- case AP_POWER_STATE_REPORT:
- switch (value.value.int32Values[0]) {
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
- case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
- // CPMS is in WAIT_FOR_VHAL state, simply move to ON
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
- // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(
- *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::ON):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
- // Do nothing
- break;
- default:
- // Unknown state
- break;
- }
- break;
-
-#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
- case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
- case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
- case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
- case VENDOR_CLUSTER_SWITCH_UI:
- case VENDOR_CLUSTER_DISPLAY_STATE: {
- auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
- updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
- if (isSystemProperty(value.prop)) {
- updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
- } else {
- updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
- }
- updatedPropValue->value = value.value;
- updatedPropValue->timestamp = elapsedRealtimeNano();
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
-#endif // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
-
- default:
- break;
- }
-
- // In the real vhal, the value will be sent to Car ECU.
- // We just pretend it is done here and send back to HAL
- auto updatedPropValue = getValuePool()->obtain(value);
- updatedPropValue->timestamp = elapsedRealtimeNano();
-
- mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
-}
-
-} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
index be88cd9..1290f30 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,56 +14,32 @@
* limitations under the License.
*/
+// This file is just used for soft migration from VehicleHalServer to DefaultVehicleHalServer.
+// The virtualized VHAL that uses VehichleHalServer is at a different repo and cannot be updated
+// together with this repo, so we need a soft migration. Once the rename is finished at the
+// virtualized VHAL side, this file would be removed.
+
#pragma once
-#include <vhal_v2_0/VehicleObjectPool.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_0/VehicleServer.h>
+#include "DefaultVehicleHalServer.h"
-#include "GeneratorHub.h"
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
-namespace android::hardware::automotive::vehicle::V2_0::impl {
+namespace impl {
-// This contains the common server operations that will be used by
-// both native and virtualized VHAL server. Notice that in the virtualized
-// scenario, the server may be run on a different OS than Android.
-class VehicleHalServer : public IVehicleServer {
+class VehicleHalServer : public DefaultVehicleHalServer {
public:
- VehicleHalServer();
-
- void sendAllValuesToClient();
-
- // Methods from IVehicleServer
-
- std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
-
- StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
- // Set the Property Value Pool used in this server
- void setValuePool(VehiclePropValuePool* valuePool);
-
- private:
- using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
-
- GeneratorHub* getGenerator();
-
- VehiclePropValuePool* getValuePool() const;
-
- void onFakeValueGenerated(const VehiclePropValue& value);
-
- StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-
- VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-
- VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
- int32_t targetDisplay);
-
- private:
- GeneratorHub mGeneratorHub{
- std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
-
- VehiclePropValuePool* mValuePool{nullptr};
- VehiclePropertyStore mServerSidePropStore;
+ VehicleHalServer() : DefaultVehicleHalServer(){};
};
-} // namespace android::hardware::automotive::vehicle::V2_0::impl
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
index 6e85ae9..3307bd6 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -24,6 +24,10 @@
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-libproto-native",
+ visibility: [
+ "//hardware/interfaces/automotive/vehicle/2.0/default:__subpackages__",
+ "//device/generic/car/emulator/vhal_v2_0:__subpackages__",
+ ],
vendor: true,
host_supported: true,
proto: {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
deleted file mode 100644
index cf1a002..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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 "qemu_pipe.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <android-base/file.h>
-
-using android::base::ReadFully;
-using android::base::WriteFully;
-
-// Define QEMU_PIPE_DEBUG if you want to print error messages when an error
-// occurs during pipe operations. The macro should simply take a printf-style
-// formatting string followed by optional arguments.
-#ifndef QEMU_PIPE_DEBUG
-#define QEMU_PIPE_DEBUG(...) (void)0
-#endif
-
-int qemu_pipe_open(const char* pipeName) {
- if (!pipeName) {
- errno = EINVAL;
- return -1;
- }
-
- int fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR));
- if (fd < 0) {
- QEMU_PIPE_DEBUG("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno));
- return -1;
- }
-
- // Write the pipe name, *including* the trailing zero which is necessary.
- size_t pipeNameLen = strlen(pipeName);
- if (WriteFully(fd, pipeName, pipeNameLen + 1U)) {
- return fd;
- }
-
- // now, add 'pipe:' prefix and try again
- // Note: host side will wait for the trailing '\0' to start
- // service lookup.
- const char pipe_prefix[] = "pipe:";
- if (WriteFully(fd, pipe_prefix, strlen(pipe_prefix)) &&
- WriteFully(fd, pipeName, pipeNameLen + 1U)) {
- return fd;
- }
- QEMU_PIPE_DEBUG("%s: Could not write to %s pipe service: %s", __FUNCTION__, pipeName,
- strerror(errno));
- close(fd);
- return -1;
-}
-
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len) {
- char header[5];
- snprintf(header, sizeof(header), "%04zx", len);
- if (!WriteFully(fd, header, 4)) {
- QEMU_PIPE_DEBUG("Can't write qemud frame header: %s", strerror(errno));
- return -1;
- }
- if (!WriteFully(fd, buff, len)) {
- QEMU_PIPE_DEBUG("Can't write qemud frame payload: %s", strerror(errno));
- return -1;
- }
- return 0;
-}
-
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len) {
- char header[5];
- if (!ReadFully(fd, header, 4)) {
- QEMU_PIPE_DEBUG("Can't read qemud frame header: %s", strerror(errno));
- return -1;
- }
- header[4] = '\0';
- size_t size;
- if (sscanf(header, "%04zx", &size) != 1) {
- QEMU_PIPE_DEBUG("Malformed qemud frame header: [%.*s]", 4, header);
- return -1;
- }
- if (size > len) {
- QEMU_PIPE_DEBUG("Oversized qemud frame (% bytes, expected <= %)", size, len);
- return -1;
- }
- if (!ReadFully(fd, buff, size)) {
- QEMU_PIPE_DEBUG("Could not read qemud frame payload: %s", strerror(errno));
- return -1;
- }
- return size;
-}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
deleted file mode 100644
index 0987498..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/qemu_pipe.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-#define ANDROID_CORE_INCLUDE_QEMU_PIPE_H
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-// Try to open a new Qemu fast-pipe. This function returns a file descriptor
-// that can be used to communicate with a named service managed by the
-// emulator.
-//
-// This file descriptor can be used as a standard pipe/socket descriptor.
-//
-// 'pipeName' is the name of the emulator service you want to connect to,
-// and should begin with 'pipe:' (e.g. 'pipe:camera' or 'pipe:opengles').
-// For backward compatibility, the 'pipe:' prefix can be omitted, and in
-// that case, qemu_pipe_open will add it for you.
-
-// On success, return a valid file descriptor, or -1/errno on failure. E.g.:
-//
-// EINVAL -> unknown/unsupported pipeName
-// ENOSYS -> fast pipes not available in this system.
-//
-// ENOSYS should never happen, except if you're trying to run within a
-// misconfigured emulator.
-//
-// You should be able to open several pipes to the same pipe service,
-// except for a few special cases (e.g. GSM modem), where EBUSY will be
-// returned if more than one client tries to connect to it.
-int qemu_pipe_open(const char* pipeName);
-
-// Send a framed message |buff| of |len| bytes through the |fd| descriptor.
-// This really adds a 4-hexchar prefix describing the payload size.
-// Returns 0 on success, and -1 on error.
-int qemu_pipe_frame_send(int fd, const void* buff, size_t len);
-
-// Read a frame message from |fd|, and store it into |buff| of |len| bytes.
-// If the framed message is larger than |len|, then this returns -1 and the
-// content is lost. Otherwise, this returns the size of the message. NOTE:
-// empty messages are possible in a framed wire protocol and do not mean
-// end-of-stream.
-int qemu_pipe_frame_recv(int fd, void* buff, size_t len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ANDROID_CORE_INCLUDE_QEMU_PIPE_H */
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
new file mode 100644
index 0000000..5762223
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/Android.bp
@@ -0,0 +1,18 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+filegroup {
+ name: "vhal_test_json",
+ srcs: ["prop.json"],
+}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
new file mode 100644
index 0000000..891d8d6
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/DefaultVhalImpl_test.cpp
@@ -0,0 +1,771 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <sys/mman.h>
+#include <vhal_v2_0/ConcurrentQueue.h>
+#include <vhal_v2_0/DefaultConfig.h>
+#include <vhal_v2_0/DefaultVehicleConnector.h>
+#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/PropertyUtils.h>
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+
+namespace {
+
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::automotive::vehicle::V2_0::FuelType;
+using ::android::hardware::automotive::vehicle::V2_0::recyclable_ptr;
+using ::android::hardware::automotive::vehicle::V2_0::StatusCode;
+using ::android::hardware::automotive::vehicle::V2_0::VehicleHwKeyInputAction;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig;
+using ::android::hardware::automotive::vehicle::V2_0::VehicleProperty;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStatus;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStore;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue;
+using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValuePool;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleConnector;
+using ::android::hardware::automotive::vehicle::V2_0::impl::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_ALL;
+using ::android::hardware::automotive::vehicle::V2_0::impl::HVAC_LEFT;
+using ::android::hardware::automotive::vehicle::V2_0::impl::kMixedTypePropertyForTest;
+
+using ::testing::HasSubstr;
+
+using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+// The maximum length of property ID in string.
+const size_t MAX_PROP_ID_LENGTH = 100;
+
+class DefaultVhalImplTest : public ::testing::Test {
+ public:
+ ~DefaultVhalImplTest() {
+ mEventQueue.deactivate();
+ mHeartBeatQueue.deactivate();
+ // Destroy mHal before destroying its dependencies.
+ mHal.reset();
+ mConnector.reset();
+ mPropStore.reset();
+ }
+
+ protected:
+ void SetUp() override {
+ mPropStore.reset(new VehiclePropertyStore);
+ mConnector.reset(new DefaultVehicleConnector);
+ mConnector->setValuePool(&mValueObjectPool);
+ mHal.reset(new DefaultVehicleHal(mPropStore.get(), mConnector.get()));
+ mHal->init(&mValueObjectPool,
+ std::bind(&DefaultVhalImplTest::onHalEvent, this, std::placeholders::_1),
+ std::bind(&DefaultVhalImplTest::onHalPropertySetError, this,
+ std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
+ }
+
+ private:
+ void onHalEvent(VehiclePropValuePtr v) {
+ if (v->prop != toInt(VehicleProperty::VHAL_HEARTBEAT)) {
+ // Ignore heartbeat properties.
+ mEventQueue.push(std::move(v));
+ } else {
+ mHeartBeatQueue.push(std::move(v));
+ }
+ }
+
+ void onHalPropertySetError(StatusCode /*errorCode*/, int32_t /*property*/, int32_t /*areaId*/) {
+ }
+
+ protected:
+ std::unique_ptr<DefaultVehicleHal> mHal;
+ std::unique_ptr<DefaultVehicleConnector> mConnector;
+ std::unique_ptr<VehiclePropertyStore> mPropStore;
+ VehiclePropValuePool mValueObjectPool;
+ android::ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
+ android::ConcurrentQueue<VehiclePropValuePtr> mHeartBeatQueue;
+};
+
+TEST_F(DefaultVhalImplTest, testListProperties) {
+ std::vector<VehiclePropConfig> configs = mHal->listProperties();
+
+ EXPECT_EQ((size_t)121, configs.size());
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyFloat) {
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+
+ auto gotValue = mHal->get(value, &status);
+
+ EXPECT_EQ(StatusCode::OK, status);
+ ASSERT_EQ((unsigned int)1, gotValue->value.floatValues.size());
+ EXPECT_EQ(15000.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyEnum) {
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = toInt(VehicleProperty::INFO_FUEL_TYPE);
+
+ auto gotValue = mHal->get(value, &status);
+
+ EXPECT_EQ(StatusCode::OK, status);
+ ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+ EXPECT_EQ((int)FuelType::FUEL_TYPE_UNLEADED, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyInt) {
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+
+ auto gotValue = mHal->get(value, &status);
+
+ EXPECT_EQ(StatusCode::OK, status);
+ ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+ EXPECT_EQ(2020, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testGetDefaultPropertyString) {
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = toInt(VehicleProperty::INFO_MAKE);
+
+ auto gotValue = mHal->get(value, &status);
+
+ EXPECT_EQ(StatusCode::OK, status);
+ EXPECT_EQ("Toy Vehicle", gotValue->value.stringValue);
+}
+
+TEST_F(DefaultVhalImplTest, testGetUnknownProperty) {
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = 0;
+
+ auto gotValue = mHal->get(value, &status);
+
+ EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testSetFloat) {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+ value.value.floatValues.resize(1);
+ value.value.floatValues[0] = 1.0f;
+
+ StatusCode status = mHal->set(value);
+ ASSERT_EQ(StatusCode::OK, status);
+
+ auto gotValue = mHal->get(value, &status);
+ EXPECT_EQ(StatusCode::OK, status);
+ ASSERT_EQ((unsigned int)1, gotValue->value.floatValues.size());
+ EXPECT_EQ(1.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetEnum) {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INFO_FUEL_TYPE);
+ value.value.int32Values.resize(1);
+ value.value.int32Values[0] = (int)FuelType::FUEL_TYPE_LEADED;
+
+ StatusCode status = mHal->set(value);
+ ASSERT_EQ(StatusCode::OK, status);
+
+ auto gotValue = mHal->get(value, &status);
+ EXPECT_EQ(StatusCode::OK, status);
+ ASSERT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+ EXPECT_EQ((int)FuelType::FUEL_TYPE_LEADED, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetInt) {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+ value.value.int32Values.resize(1);
+ value.value.int32Values[0] = 2021;
+
+ StatusCode status = mHal->set(value);
+ EXPECT_EQ(StatusCode::OK, status);
+
+ auto gotValue = mHal->get(value, &status);
+ EXPECT_EQ(StatusCode::OK, status);
+ EXPECT_EQ((unsigned int)1, gotValue->value.int32Values.size());
+ EXPECT_EQ(2021, gotValue->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetString) {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INFO_MAKE);
+ value.value.stringValue = "My Vehicle";
+
+ StatusCode status = mHal->set(value);
+ ASSERT_EQ(StatusCode::OK, status);
+
+ auto gotValue = mHal->get(value, &status);
+ EXPECT_EQ(StatusCode::OK, status);
+ EXPECT_EQ("My Vehicle", gotValue->value.stringValue);
+}
+
+TEST_F(DefaultVhalImplTest, testSetMixed) {
+ VehiclePropValue value;
+ value.prop = kMixedTypePropertyForTest;
+ // mixed prop.
+ // .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}
+ // 1 string, 1 int, 0 bool, 2 ints, 0 int64, 0 int64s, 1 float, 0 floats, 0 bytes
+ value.value.stringValue = "test";
+ value.value.int32Values.resize(3);
+ value.value.int32Values[0] = 1;
+ value.value.int32Values[1] = 2;
+ value.value.int32Values[2] = 3;
+ value.value.floatValues.resize(1);
+ value.value.floatValues[0] = 1.0f;
+
+ StatusCode status = mHal->set(value);
+ ASSERT_EQ(StatusCode::OK, status);
+
+ auto gotValue = mHal->get(value, &status);
+ EXPECT_EQ(StatusCode::OK, status);
+ EXPECT_EQ("test", gotValue->value.stringValue);
+ ASSERT_EQ((size_t)3, gotValue->value.int32Values.size());
+ EXPECT_EQ(1, gotValue->value.int32Values[0]);
+ EXPECT_EQ(2, gotValue->value.int32Values[1]);
+ EXPECT_EQ(3, gotValue->value.int32Values[2]);
+ ASSERT_EQ((size_t)1, gotValue->value.floatValues.size());
+ EXPECT_EQ(1.0f, gotValue->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSetUnknownProperty) {
+ VehiclePropValue value;
+ value.prop = 0;
+
+ EXPECT_EQ(StatusCode::INVALID_ARG, mHal->set(value));
+}
+
+TEST_F(DefaultVhalImplTest, testSetStatusNotAllowed) {
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY);
+ value.status = VehiclePropertyStatus::UNAVAILABLE;
+ value.value.floatValues.resize(1);
+ value.value.floatValues[0] = 1.0f;
+
+ StatusCode status = mHal->set(value);
+
+ EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribe) {
+ // Clear existing events.
+ mEventQueue.flush();
+
+ auto status = mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10);
+
+ ASSERT_EQ(StatusCode::OK, status);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+ // Modify the speed after 0.5 seconds.
+ VehiclePropValue value;
+ value.prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED);
+ value.value.floatValues.resize(1);
+ value.value.floatValues[0] = 1.0f;
+ ASSERT_EQ(StatusCode::OK, mHal->set(value));
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+ auto events = mEventQueue.flush();
+ ASSERT_LE((size_t)10, events.size());
+
+ // The first event should be the default value.
+ ASSERT_EQ((size_t)1, events[0]->value.floatValues.size());
+ EXPECT_EQ(0.0f, events[0]->value.floatValues[0]);
+ // The last event should be the value after update.
+ ASSERT_EQ((size_t)1, events[events.size() - 1]->value.floatValues.size());
+ EXPECT_EQ(1.0f, events[events.size() - 1]->value.floatValues[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribeInvalidProp) {
+ EXPECT_EQ(StatusCode::INVALID_ARG, mHal->subscribe(toInt(VehicleProperty::INFO_MAKE), 10));
+}
+
+TEST_F(DefaultVhalImplTest, testSubscribeSampleRateOutOfRange) {
+ EXPECT_EQ(StatusCode::INVALID_ARG,
+ mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10.1));
+ EXPECT_EQ(StatusCode::INVALID_ARG,
+ mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 0.5));
+}
+
+TEST_F(DefaultVhalImplTest, testUnsubscribe) {
+ auto status = mHal->subscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED), 10);
+ ASSERT_EQ(StatusCode::OK, status);
+
+ // Wait for 0.5 seconds to generate some events.
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+ status = mHal->unsubscribe(toInt(VehicleProperty::PERF_VEHICLE_SPEED));
+ ASSERT_EQ(StatusCode::OK, status);
+
+ // Clear all the events.
+ mEventQueue.flush();
+
+ // Wait for 0.5 seconds.
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+ // There should be no new events generated.
+ auto events = mEventQueue.flush();
+ EXPECT_EQ((size_t)0, events.size());
+}
+
+TEST_F(DefaultVhalImplTest, testUnsubscribeInvalidProp) {
+ EXPECT_EQ(StatusCode::INVALID_ARG, mHal->unsubscribe(toInt(VehicleProperty::INFO_MAKE)));
+}
+
+int createMemfd(hidl_handle* fd) {
+ native_handle_t* handle = native_handle_create(/*numFds=*/1, /*numInts=*/0);
+ int memfd = memfd_create("memfile", 0);
+ handle->data[0] = dup(memfd);
+ fd->setTo(handle, /*shouldOwn=*/true);
+ return memfd;
+}
+
+TEST_F(DefaultVhalImplTest, testDump) {
+ hidl_vec<hidl_string> options;
+ hidl_handle fd = {};
+ int memfd = createMemfd(&fd);
+
+ ASSERT_TRUE(mHal->dump(fd, options));
+
+ lseek(memfd, 0, SEEK_SET);
+ char buf[10240] = {};
+ read(memfd, buf, sizeof(buf));
+ close(memfd);
+
+ // Read one property and check that it is in the dumped info.
+ VehiclePropValue value;
+ StatusCode status;
+ value.prop = toInt(VehicleProperty::INFO_MAKE);
+ auto gotValue = mHal->get(value, &status);
+ ASSERT_EQ(StatusCode::OK, status);
+ // Server side prop store does not have timestamp.
+ gotValue->timestamp = 0;
+
+ std::string infoMake = toString(*gotValue);
+ EXPECT_THAT(std::string(buf), HasSubstr(infoMake));
+}
+
+TEST_F(DefaultVhalImplTest, testSetPropInvalidAreaId) {
+ VehiclePropValue propNormal = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = HVAC_ALL,
+ .value.int32Values = {3}};
+ StatusCode status = mHal->set(propNormal);
+
+ EXPECT_EQ(StatusCode::OK, status);
+
+ // HVAC_FAN_SPEED only have HVAC_ALL area config and is not allowed to set by LEFT/RIGHT.
+ VehiclePropValue propWrongId = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = HVAC_LEFT,
+ .value.int32Values = {3}};
+
+ status = mHal->set(propWrongId);
+
+ EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+class DefaultVhalImplSetInvalidPropTest : public DefaultVhalImplTest,
+ public testing::WithParamInterface<VehiclePropValue> {};
+
+std::vector<VehiclePropValue> GenSetInvalidPropParams() {
+ std::vector<VehiclePropValue> props;
+ // int prop with no value.
+ VehiclePropValue intProp = {.prop = toInt(VehicleProperty::INFO_MODEL_YEAR)};
+ props.push_back(intProp);
+
+ // int prop with more than one value.
+ VehiclePropValue intPropWithValues = {.prop = toInt(VehicleProperty::INFO_MODEL_YEAR)};
+ intPropWithValues.value.int32Values.resize(2);
+ props.push_back(intPropWithValues);
+
+ // int vec prop with no value.
+ VehiclePropValue intVecProp = {.prop = toInt(VehicleProperty::INFO_FUEL_TYPE)};
+ props.push_back(intVecProp);
+
+ // int64 prop with no value.
+ VehiclePropValue int64Prop = {.prop = toInt(VehicleProperty::EPOCH_TIME)};
+ props.push_back(int64Prop);
+
+ // int64 prop with more than one value.
+ VehiclePropValue int64PropWithValues = {.prop = toInt(VehicleProperty::EPOCH_TIME)};
+ int64PropWithValues.value.int64Values.resize(2);
+ props.push_back(int64PropWithValues);
+
+ // int64 vec prop with no value.
+ VehiclePropValue int64VecProp = {.prop = toInt(VehicleProperty::WHEEL_TICK)};
+ props.push_back(int64VecProp);
+
+ // float prop with no value.
+ VehiclePropValue floatProp = {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY)};
+ props.push_back(floatProp);
+
+ // float prop with more than one value.
+ VehiclePropValue floatPropWithValues = {.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY)};
+ floatPropWithValues.value.floatValues.resize(2);
+ props.push_back(floatPropWithValues);
+
+ // float vec prop with no value.
+ VehiclePropValue floatVecProp = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION)};
+ props.push_back(floatVecProp);
+
+ // bool prop with no value.
+ VehiclePropValue boolProp = {
+ .prop = toInt(VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)};
+ props.push_back(boolProp);
+
+ // bool prop with more than one value.
+ VehiclePropValue boolPropWithValues = {
+ .prop = toInt(VehicleProperty::FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME)};
+ boolPropWithValues.value.int32Values.resize(2);
+ props.push_back(boolPropWithValues);
+
+ // mixed prop.
+ // .configArray = {1, 1, 0, 2, 0, 0, 1, 0, 0}
+ // 1 string, 1 int, 0 bool, 2 ints, 0 int64, 0 int64s, 1 float, 0 floats, 0 bytes
+ VehiclePropValue mixedProp1 = {.prop = kMixedTypePropertyForTest};
+ // Expect 1 bool, and 2 ints, we only have 1 value.
+ mixedProp1.value.int32Values.resize(1);
+ mixedProp1.value.floatValues.resize(1);
+ props.push_back(mixedProp1);
+
+ VehiclePropValue mixedProp2 = {.prop = kMixedTypePropertyForTest};
+ mixedProp2.value.int32Values.resize(3);
+ // Missing float value.
+ mixedProp2.value.floatValues.resize(0);
+ props.push_back(mixedProp2);
+
+ return props;
+}
+
+TEST_P(DefaultVhalImplSetInvalidPropTest, testSetInvalidPropValue) {
+ VehiclePropValue value = GetParam();
+
+ StatusCode status = mHal->set(value);
+
+ EXPECT_EQ(StatusCode::INVALID_ARG, status);
+}
+
+INSTANTIATE_TEST_SUITE_P(DefaultVhalImplSetInvalidPropTests, DefaultVhalImplSetInvalidPropTest,
+ testing::ValuesIn(GenSetInvalidPropParams()));
+
+struct SetPropRangeTestCase {
+ std::string name;
+ VehiclePropValue prop;
+ StatusCode code;
+};
+
+class DefaultVhalImplSetPropRangeTest : public DefaultVhalImplTest,
+ public testing::WithParamInterface<SetPropRangeTestCase> {};
+
+std::vector<SetPropRangeTestCase> GenSetPropRangeParams() {
+ std::vector<SetPropRangeTestCase> tc;
+ VehiclePropValue intPropNormal = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = HVAC_ALL,
+ // min: 1, max: 7
+ .value.int32Values = {3}};
+ tc.push_back({"normal_case_int", intPropNormal, StatusCode::OK});
+
+ VehiclePropValue intPropSmall = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = HVAC_ALL,
+ // min: 1, max: 7
+ .value.int32Values = {0}};
+ tc.push_back({"normal_case_int_too_small", intPropSmall, StatusCode::INVALID_ARG});
+
+ VehiclePropValue intPropLarge = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .areaId = HVAC_ALL,
+ // min: 1, max: 7
+ .value.int32Values = {8}};
+ tc.push_back({"normal_case_int_too_large", intPropLarge, StatusCode::INVALID_ARG});
+
+ VehiclePropValue floatPropNormal = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+ .areaId = HVAC_LEFT,
+ // min: 16, max: 32
+ .value.floatValues = {26}};
+ tc.push_back({"normal_case_float", floatPropNormal, StatusCode::OK});
+ VehiclePropValue floatPropSmall = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+ .areaId = HVAC_LEFT,
+ // min: 16, max: 32
+ .value.floatValues = {15.5}};
+ tc.push_back({"normal_case_float_too_small", floatPropSmall, StatusCode::INVALID_ARG});
+ VehiclePropValue floatPropLarge = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+ .areaId = HVAC_LEFT,
+ // min: 16, max: 32
+ .value.floatValues = {32.6}};
+ tc.push_back({"normal_case_float_too_large", floatPropLarge, StatusCode::INVALID_ARG});
+
+ return tc;
+}
+
+TEST_P(DefaultVhalImplSetPropRangeTest, testSetPropRange) {
+ SetPropRangeTestCase tc = GetParam();
+
+ StatusCode status = mHal->set(tc.prop);
+
+ EXPECT_EQ(tc.code, status);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DefaultVhalImplSetPropRangeTests, DefaultVhalImplSetPropRangeTest,
+ testing::ValuesIn(GenSetPropRangeParams()),
+ [](const testing::TestParamInfo<DefaultVhalImplSetPropRangeTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+std::string getPropIdString(VehicleProperty prop) {
+ char s[MAX_PROP_ID_LENGTH] = {};
+ snprintf(s, sizeof(s), "%d", toInt(prop));
+ return std::string(s);
+}
+
+struct OptionsTestCase {
+ std::string name;
+ hidl_vec<hidl_string> options;
+ std::string expectMsg;
+};
+
+class DefaultVhalImplOptionsTest : public DefaultVhalImplTest,
+ public testing::WithParamInterface<OptionsTestCase> {};
+
+TEST_P(DefaultVhalImplOptionsTest, testInvalidOptions) {
+ auto tc = GetParam();
+ hidl_handle fd = {};
+ int memfd = createMemfd(&fd);
+
+ bool shouldDump = mHal->dump(fd, tc.options);
+
+ EXPECT_FALSE(shouldDump);
+ char buf[10240] = {};
+ lseek(memfd, 0, SEEK_SET);
+ read(memfd, buf, sizeof(buf));
+ EXPECT_THAT(std::string(buf), HasSubstr(tc.expectMsg));
+}
+
+std::vector<OptionsTestCase> GenInvalidOptions() {
+ return {{"no_command", {"--debughal"}, "No command specified"},
+ {"unknown_command", {"--debughal", "--unknown"}, "Unknown command: \"--unknown\""},
+ {"help", {"--debughal", "--help"}, "Help:"},
+ {"genfakedata_no_subcommand",
+ {"--debughal", "--genfakedata"},
+ "No subcommand specified for genfakedata"},
+ {"genfakedata_unknown_subcommand",
+ {"--debughal", "--genfakedata", "--unknown"},
+ "Unknown command: \"--unknown\""},
+ {"genfakedata_start_linear_no_args",
+ {"--debughal", "--genfakedata", "--startlinear"},
+ "incorrect argument count"},
+ {"genfakedata_start_linear_invalid_propId",
+ {"--debughal", "--genfakedata", "--startlinear", "abcd", "0.1", "0.1", "0.1", "0.1",
+ "100000000"},
+ "failed to parse propdID as int: \"abcd\""},
+ {"genfakedata_start_linear_invalid_middleValue",
+ {"--debughal", "--genfakedata", "--startlinear", "1", "abcd", "0.1", "0.1", "0.1",
+ "100000000"},
+ "failed to parse middleValue as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_currentValue",
+ {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "abcd", "0.1", "0.1",
+ "100000000"},
+ "failed to parse currentValue as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_dispersion",
+ {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "abcd", "0.1",
+ "100000000"},
+ "failed to parse dispersion as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_increment",
+ {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "abcd",
+ "100000000"},
+ "failed to parse increment as float: \"abcd\""},
+ {"genfakedata_start_linear_invalid_interval",
+ {"--debughal", "--genfakedata", "--startlinear", "1", "0.1", "0.1", "0.1", "0.1",
+ "0.1"},
+ "failed to parse interval as int: \"0.1\""},
+ {"genfakedata_stop_linear_no_args",
+ {"--debughal", "--genfakedata", "--stoplinear"},
+ "incorrect argument count"},
+ {"genfakedata_stop_linear_invalid_propId",
+ {"--debughal", "--genfakedata", "--stoplinear", "abcd"},
+ "failed to parse propdID as int: \"abcd\""},
+ {"genfakedata_startjson_no_args",
+ {"--debughal", "--genfakedata", "--startjson"},
+ "incorrect argument count"},
+ {"genfakedata_startjson_invalid_repetition",
+ {"--debughal", "--genfakedata", "--startjson", "file", "0.1"},
+ "failed to parse repetition as int: \"0.1\""},
+ {"genfakedata_startjson_invalid_json_file",
+ {"--debughal", "--genfakedata", "--startjson", "file", "1"},
+ "invalid JSON file"},
+ {"genfakedata_stopjson_no_args",
+ {"--debughal", "--genfakedata", "--stopjson"},
+ "incorrect argument count"},
+ {"genfakedata_keypress_no_args",
+ {"--debughal", "--genfakedata", "--keypress"},
+ "incorrect argument count"},
+ {"genfakedata_keypress_invalid_keyCode",
+ {"--debughal", "--genfakedata", "--keypress", "0.1", "1"},
+ "failed to parse keyCode as int: \"0.1\""},
+ {"genfakedata_keypress_invalid_display",
+ {"--debughal", "--genfakedata", "--keypress", "1", "0.1"},
+ "failed to parse display as int: \"0.1\""}};
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ DefaultVhalImplOptionsTests, DefaultVhalImplOptionsTest,
+ testing::ValuesIn(GenInvalidOptions()),
+ [](const testing::TestParamInfo<DefaultVhalImplOptionsTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataLinear) {
+ // Start a fake linear data generator for vehicle speed at 0.1s interval.
+ // range: 0 - 100, current value: 30, step: 20.
+ hidl_vec<hidl_string> options = {"--debughal",
+ "--genfakedata",
+ "--startlinear",
+ getPropIdString(VehicleProperty::PERF_VEHICLE_SPEED),
+ /*middleValue=*/"50",
+ /*currentValue=*/"30",
+ /*dispersion=*/"50",
+ /*increment=*/"20",
+ /*interval=*/"100000000"};
+ hidl_handle fd = {};
+ int memfd = createMemfd(&fd);
+ // Clear existing events.
+ mEventQueue.flush();
+
+ EXPECT_FALSE(mHal->dump(fd, options));
+
+ lseek(memfd, 0, SEEK_SET);
+ char buf[10240] = {};
+ // The dumped info should be empty.
+ read(memfd, buf, sizeof(buf));
+ EXPECT_STREQ("", buf);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+ auto events = mEventQueue.flush();
+ // We should get 10 events ideally, but let's be safe here.
+ ASSERT_LE((size_t)5, events.size());
+ int32_t value = 30;
+ for (size_t i = 0; i < 5; i++) {
+ ASSERT_EQ((size_t)1, events[i]->value.floatValues.size());
+ EXPECT_EQ((float)value, events[i]->value.floatValues[0]);
+ value = (value + 20) % 100;
+ }
+
+ // Stop the linear generator.
+ options = {"--debughal", "--genfakedata", "--stoplinear",
+ getPropIdString(VehicleProperty::PERF_VEHICLE_SPEED)};
+ EXPECT_FALSE(mHal->dump(fd, options));
+
+ // The dumped info should be empty.
+ lseek(memfd, 0, SEEK_SET);
+ read(memfd, buf, sizeof(buf));
+ EXPECT_STREQ("", buf);
+
+ close(memfd);
+
+ // Clear existing events.
+ mEventQueue.flush();
+ std::this_thread::sleep_for(std::chrono::milliseconds(500));
+ // There should be no new events generated.
+ EXPECT_EQ((size_t)0, mEventQueue.flush().size());
+}
+
+std::string getTestFilePath(const char* filename) {
+ static std::string baseDir = android::base::GetExecutableDirectory();
+ return baseDir + "/" + filename;
+}
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataJson) {
+ hidl_vec<hidl_string> options = {"--debughal", "--genfakedata", "--startjson",
+ getTestFilePath("prop.json"), "2"};
+ hidl_handle fd = {};
+ int memfd = createMemfd(&fd);
+ // Clear existing events.
+ mEventQueue.flush();
+
+ EXPECT_FALSE(mHal->dump(fd, options));
+
+ lseek(memfd, 0, SEEK_SET);
+ char buf[10240] = {};
+ // The dumped info should be empty.
+ read(memfd, buf, sizeof(buf));
+ EXPECT_STREQ("", buf);
+
+ // wait for some time.
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+
+ auto events = mEventQueue.flush();
+ ASSERT_EQ((size_t)8, events.size());
+ // First set of events, we test 1st and the last.
+ EXPECT_EQ((size_t)1, events[0]->value.int32Values.size());
+ EXPECT_EQ(8, events[0]->value.int32Values[0]);
+ EXPECT_EQ((size_t)1, events[3]->value.int32Values.size());
+ EXPECT_EQ(4, events[3]->value.int32Values[0]);
+ // Second set of the same events.
+ EXPECT_EQ((size_t)1, events[4]->value.int32Values.size());
+ EXPECT_EQ(8, events[4]->value.int32Values[0]);
+ EXPECT_EQ((size_t)1, events[7]->value.int32Values.size());
+ EXPECT_EQ(4, events[7]->value.int32Values[0]);
+}
+
+TEST_F(DefaultVhalImplTest, testDebugGenFakeDataKeyPress) {
+ hidl_vec<hidl_string> options = {"--debughal", "--genfakedata", "--keypress", "1", "2"};
+ hidl_handle fd = {};
+ int memfd = createMemfd(&fd);
+ // Clear existing events.
+ mEventQueue.flush();
+
+ EXPECT_FALSE(mHal->dump(fd, options));
+
+ lseek(memfd, 0, SEEK_SET);
+ char buf[10240] = {};
+ // The dumped info should be empty.
+ read(memfd, buf, sizeof(buf));
+ EXPECT_STREQ("", buf);
+
+ auto events = mEventQueue.flush();
+ ASSERT_EQ((size_t)2, events.size());
+ EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[0]->prop);
+ EXPECT_EQ(toInt(VehicleProperty::HW_KEY_INPUT), events[1]->prop);
+ ASSERT_EQ((size_t)3, events[0]->value.int32Values.size());
+ ASSERT_EQ((size_t)3, events[1]->value.int32Values.size());
+ EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_DOWN), events[0]->value.int32Values[0]);
+ EXPECT_EQ(1, events[0]->value.int32Values[1]);
+ EXPECT_EQ(2, events[0]->value.int32Values[2]);
+ EXPECT_EQ(toInt(VehicleHwKeyInputAction::ACTION_UP), events[1]->value.int32Values[0]);
+ EXPECT_EQ(1, events[1]->value.int32Values[1]);
+ EXPECT_EQ(2, events[1]->value.int32Values[2]);
+}
+
+TEST_F(DefaultVhalImplTest, testHeartBeatEvent) {
+ // A heart beat would be sent every 3s, but let's wait for 6s to be sure at least 2 events have
+ // been generated (at 0s and 3s).
+ std::this_thread::sleep_for(std::chrono::milliseconds(6000));
+
+ auto events = mHeartBeatQueue.flush();
+ ASSERT_GE(events.size(), (size_t)2);
+ ASSERT_EQ(toInt(VehicleProperty::VHAL_HEARTBEAT), events[0]->prop);
+}
+
+} // namespace
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
index 3817e44..a507b50 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
@@ -17,9 +17,9 @@
#include <gtest/gtest.h>
#include <utils/SystemClock.h>
+#include <vhal_v2_0/ProtoMessageConverter.h>
#include "vhal_v2_0/DefaultConfig.h"
-#include "vhal_v2_0/ProtoMessageConverter.h"
#include "vhal_v2_0/VehicleUtils.h"
namespace android {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
new file mode 100644
index 0000000..2e77a44
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/prop.json
@@ -0,0 +1,26 @@
+[
+ {
+ "timestamp": 1000000,
+ "areaId": 0,
+ "value": 8,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 2000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 3000000,
+ "areaId": 0,
+ "value": 16,
+ "prop": 289408000
+ },
+ {
+ "timestamp": 4000000,
+ "areaId": 0,
+ "value": 4,
+ "prop": 289408000
+ }
+]
diff --git a/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp b/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
index 9fc17c6..d7547f6 100644
--- a/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/RecurrentTimer_test.cpp
@@ -41,7 +41,8 @@
timer.registerRecurrentEvent(milliseconds(1), 0xdead);
std::this_thread::sleep_for(milliseconds(100));
- ASSERT_EQ_WITH_TOLERANCE(100, counter.load(), 20);
+ // This test is unstable, so set the tolerance to 50.
+ ASSERT_EQ_WITH_TOLERANCE(100, counter.load(), 50);
}
TEST(RecurrentTimerTest, multipleIntervals) {
@@ -66,7 +67,8 @@
timer.registerRecurrentEvent(milliseconds(5), 0xbeef);
std::this_thread::sleep_for(milliseconds(100));
- ASSERT_EQ_WITH_TOLERANCE(100, counter1ms.load(), 20);
+ // This test is unstable, so set the tolerance to 50.
+ ASSERT_EQ_WITH_TOLERANCE(100, counter1ms.load(), 50);
ASSERT_EQ_WITH_TOLERANCE(20, counter5ms.load(), 5);
}
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
#include <iostream>
#include <android-base/macros.h>
+#include <cutils/native_handle.h>
#include <utils/SystemClock.h>
#include <gtest/gtest.h>
@@ -32,6 +33,18 @@
namespace vehicle {
namespace V2_0 {
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+ public:
+ VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+ bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+ return mManager->cmdSetOneProperty(fd, options);
+ }
+
+ public:
+ VehicleHalManager* mManager;
+};
+
namespace {
using namespace std::placeholders;
@@ -57,33 +70,21 @@
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
int32_t areaId = requestedPropValue.areaId;
- switch (property) {
- case VehicleProperty::INFO_MAKE:
- pValue = getValuePool()->obtainString(kCarMake);
- break;
- case VehicleProperty::INFO_FUEL_CAPACITY:
- if (fuelCapacityAttemptsLeft-- > 0) {
- // Emulate property not ready yet.
- *outStatus = StatusCode::TRY_AGAIN;
- } else {
- pValue = getValuePool()->obtainFloat(42.42);
- }
- break;
- default:
- if (requestedPropValue.prop == kCustomComplexProperty) {
- pValue = getValuePool()->obtainComplex();
- pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
- pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
- pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
- pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
- pValue->value.stringValue = kCarMake;
- break;
- }
- auto key = makeKey(toInt(property), areaId);
- if (mValues.count(key) == 0) {
- ALOGW("");
- }
- pValue = getValuePool()->obtain(mValues[key]);
+ if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+ if (fuelCapacityAttemptsLeft-- > 0) {
+ // Emulate property not ready yet.
+ *outStatus = StatusCode::TRY_AGAIN;
+ } else {
+ pValue = getValuePool()->obtainFloat(42.42);
+ }
+ } else {
+ auto key = makeKey(requestedPropValue);
+ if (mValues.count(key) == 0) {
+ ALOGW("key not found\n");
+ *outStatus = StatusCode::INVALID_ARG;
+ return pValue;
+ }
+ pValue = getValuePool()->obtain(mValues[key]);
}
if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
&& mirrorFoldAttemptsLeft-- > 0) {
return StatusCode::TRY_AGAIN;
}
-
mValues[makeKey(propValue)] = propValue;
return StatusCode::OK;
}
@@ -181,6 +181,18 @@
actualStatusCode = refStatus;
}
+ MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+ auto pValue = objectPool->obtainComplex();
+ pValue->prop = kCustomComplexProperty;
+ pValue->areaId = 0;
+ pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+ pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+ pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+ pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+ pValue->value.stringValue = kCarMake;
+ return pValue;
+ }
+
public:
VehiclePropValue actualValue;
StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
}
TEST_F(VehicleHalManagerTest, get_Complex) {
+ ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
invokeGet(kCustomComplexProperty, 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
}
TEST_F(VehicleHalManagerTest, get_StaticString) {
+ auto pValue = objectPool->obtainString(kCarMake);
+ pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+ pValue->areaId = 0;
+ ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
ASSERT_TRUE(clients.isEmpty());
}
+TEST_F(VehicleHalManagerTest, debug) {
+ hidl_handle fd = {};
+ fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+ // Because debug function returns void, so no way to check return value.
+ manager->debug(fd, {});
+ manager->debug(fd, {"--help"});
+ manager->debug(fd, {"--list"});
+ manager->debug(fd, {"--get"});
+ manager->debug(fd, {"--set"});
+ manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+ std::string test_name;
+ const hidl_vec<hidl_string> configs;
+ bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+ public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+ const SetPropTestCase& tc = GetParam();
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ return {
+ {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
+ {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+ {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+ {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+ {"success_set_ints",
+ {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+ true},
+ {"success_set_int64",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+ true},
+ {"success_set_int64s",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+ "9223372036854775807"},
+ true},
+ {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+ {"success_set_floats",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+ true},
+ {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+ {"fail_no_options", {}, false},
+ {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+ {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+ {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+ {"fail_duplicate_string",
+ {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+ false},
+ {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+ {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+ {"fail_duplicate_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+ false},
+ {"fail_multiple_bytes",
+ {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+ false},
+ {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+ {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+ {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+ {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+ {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+ {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+ {"fail_int64_out_of_range",
+ {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+ false},
+ {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+ {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+ {"fail_float_out_of_range",
+ {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+ false},
+ {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+ {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+ {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+ {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+ {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+ };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+ testing::ValuesIn(GenSetPropParams()),
+ [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+ return info.param.test_name;
+ });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+ char infoMakeProperty[100] = {};
+ snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+ VehicleHalManagerTestHelper helper(manager.get());
+ ASSERT_TRUE(helper.cmdSetOneProperty(
+ STDERR_FILENO, {"--set", infoMakeProperty, "-s", kCarMake,
+ "-b", "0xdeadbeef", "-i", "2147483647",
+ "0", "-2147483648", "-i64", "-9223372036854775808",
+ "0", "9223372036854775807", "-f", "-3.402823466E+38",
+ "0", "3.402823466E+38", "-a", "123"}));
+ StatusCode status = StatusCode::OK;
+ VehiclePropValue requestProp;
+ requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+ requestProp.areaId = 123;
+ auto value = hal->get(requestProp, &status);
+ ASSERT_EQ(StatusCode::OK, status);
+ ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+ ASSERT_EQ(value->areaId, 123);
+ ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+ uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+ ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+ ASSERT_EQ(3u, value->value.int32Values.size());
+ ASSERT_EQ(2147483647, value->value.int32Values[0]);
+ ASSERT_EQ(0, value->value.int32Values[1]);
+ ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+ ASSERT_EQ(3u, value->value.int64Values.size());
+ // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+ // tokens and the later does not fit in unsigned long long.
+ ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+ ASSERT_EQ(0, value->value.int64Values[1]);
+ ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+ ASSERT_EQ(3u, value->value.floatValues.size());
+ ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+ ASSERT_EQ(0.0f, value->value.floatValues[1]);
+ ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
} // namespace anonymous
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
index 4e3ade1..0968166 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
@@ -58,10 +58,12 @@
TEST_F(VehicleObjectPoolTest, valuePoolBasicCorrectness) {
auto value = valuePool->obtain(VehiclePropertyType::INT32);
- // At this point, v1 should be recycled and the only object in the pool.
- ASSERT_EQ(value.get(), valuePool->obtain(VehiclePropertyType::INT32).get());
+ void* raw = value.get();
+ value.reset();
+ // At this point, value should be recycled and the only object in the pool.
+ ASSERT_EQ(raw, valuePool->obtain(VehiclePropertyType::INT32).get());
// Obtaining value of another type - should return a new object
- ASSERT_NE(value.get(), valuePool->obtain(VehiclePropertyType::FLOAT).get());
+ ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::FLOAT).get());
ASSERT_EQ(3u, stats->Obtained);
ASSERT_EQ(2u, stats->Created);
diff --git a/automotive/vehicle/aidl/Android.bp b/automotive/vehicle/aidl/Android.bp
new file mode 100644
index 0000000..477f8ed
--- /dev/null
+++ b/automotive/vehicle/aidl/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.automotive.vehicle",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/automotive/vehicle/**/*.aidl",
+ ],
+ // TODO(b/148703287) Make it stable with new APIs
+ unstable: true,
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl
new file mode 100644
index 0000000..95537dc
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserRequest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a CREATE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable CreateUserRequest {
+ /**
+ * Arbitrary id used to map the response to the request.
+ */
+ int requestId;
+ /**
+ * Basic information about Android user that was created.
+ */
+ UserInfo newUserInfo;
+ /**
+ * Name of the new Android user.
+ */
+ @utf8InCpp String newUserName;
+ /**
+ * Information about the current state of the Android system.
+ */
+ UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl
new file mode 100644
index 0000000..0588052
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserResponse.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.CreateUserStatus;
+
+/**
+ * Defines the result of a CreateUserRequest.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable CreateUserResponse {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * Status of the request.
+ */
+ CreateUserStatus status;
+ /**
+ * HAL-specific error message.
+ *
+ * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+ * used to show custom error messages to the end user.
+ */
+ @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl
new file mode 100644
index 0000000..f841ff6
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CreateUserStatus.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Status of the response to a CreateUserRequest.
+ */
+// @VintfStability
+@Backing(type="int")
+enum CreateUserStatus {
+ /**
+ * The request succeeded (for example, HAL created a new internal user, or associated the
+ * Android user to an existing internal user).
+ */
+ SUCCESS = 1,
+ /**
+ * The request failed (and Android will remove the Android user).
+ */
+ FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.aidl
new file mode 100644
index 0000000..1335eea
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/CustomInputType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Input code values for HW_CUSTOM_INPUT.
+ */
+// @VintfStability
+@Backing(type="int")
+enum CustomInputType {
+ /**
+ * Ten functions representing the custom input code to be defined and implemented by OEM
+ * partners.
+ *
+ * OEMs need to formally contact Android team if more than 10 functions are required.
+ */
+ CUSTOM_EVENT_F1 = 1001,
+ CUSTOM_EVENT_F2 = 1002,
+ CUSTOM_EVENT_F3 = 1003,
+ CUSTOM_EVENT_F4 = 1004,
+ CUSTOM_EVENT_F5 = 1005,
+ CUSTOM_EVENT_F6 = 1006,
+ CUSTOM_EVENT_F7 = 1007,
+ CUSTOM_EVENT_F8 = 1008,
+ CUSTOM_EVENT_F9 = 1009,
+ CUSTOM_EVENT_F10 = 1010,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
new file mode 100644
index 0000000..017589f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticFloatSensorIndex.aidl
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+// @VintfStability
+@Backing(type="int")
+enum DiagnosticFloatSensorIndex {
+ CALCULATED_ENGINE_LOAD = 0,
+ /*
+ * PID 0x04
+ */
+ ENGINE_COOLANT_TEMPERATURE = 1,
+ /*
+ * PID 0x05
+ */
+ SHORT_TERM_FUEL_TRIM_BANK1 = 2,
+ /*
+ * PID 0x06
+ */
+ LONG_TERM_FUEL_TRIM_BANK1 = 3,
+ /*
+ * PID 0x07
+ */
+ SHORT_TERM_FUEL_TRIM_BANK2 = 4,
+ /*
+ * PID 0x08
+ */
+ LONG_TERM_FUEL_TRIM_BANK2 = 5,
+ /*
+ * PID 0x09
+ */
+ FUEL_PRESSURE = 6,
+ /*
+ * PID 0x0A
+ */
+ INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
+ /*
+ * PID 0x0B
+ */
+ ENGINE_RPM = 8,
+ /*
+ * PID 0x0C
+ */
+ VEHICLE_SPEED = 9,
+ /*
+ * PID 0x0D
+ */
+ TIMING_ADVANCE = 10,
+ /*
+ * PID 0x0E
+ */
+ MAF_AIR_FLOW_RATE = 11,
+ /*
+ * PID 0x10
+ */
+ THROTTLE_POSITION = 12,
+ /*
+ * PID 0x11
+ */
+ OXYGEN_SENSOR1_VOLTAGE = 13,
+ /*
+ * PID 0x14
+ */
+ OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
+ /*
+ * PID 0x14
+ */
+ OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
+ /*
+ * PID 0x24
+ */
+ OXYGEN_SENSOR2_VOLTAGE = 16,
+ /*
+ * PID 0x15
+ */
+ OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
+ /*
+ * PID 0x15
+ */
+ OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
+ /*
+ * PID 0x25
+ */
+ OXYGEN_SENSOR3_VOLTAGE = 19,
+ /*
+ * PID 0x16
+ */
+ OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
+ /*
+ * PID 0x16
+ */
+ OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
+ /*
+ * PID 0x26
+ */
+ OXYGEN_SENSOR4_VOLTAGE = 22,
+ /*
+ * PID 0x17
+ */
+ OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
+ /*
+ * PID 0x17
+ */
+ OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
+ /*
+ * PID 0x27
+ */
+ OXYGEN_SENSOR5_VOLTAGE = 25,
+ /*
+ * PID 0x18
+ */
+ OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
+ /*
+ * PID 0x18
+ */
+ OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
+ /*
+ * PID 0x28
+ */
+ OXYGEN_SENSOR6_VOLTAGE = 28,
+ /*
+ * PID 0x19
+ */
+ OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
+ /*
+ * PID 0x19
+ */
+ OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
+ /*
+ * PID 0x29
+ */
+ OXYGEN_SENSOR7_VOLTAGE = 31,
+ /*
+ * PID 0x1A
+ */
+ OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
+ /*
+ * PID 0x1A
+ */
+ OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
+ /*
+ * PID 0x2A
+ */
+ OXYGEN_SENSOR8_VOLTAGE = 34,
+ /*
+ * PID 0x1B
+ */
+ OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
+ /*
+ * PID 0x1B
+ */
+ OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
+ /*
+ * PID 0x2B
+ */
+ FUEL_RAIL_PRESSURE = 37,
+ /*
+ * PID 0x22
+ */
+ FUEL_RAIL_GAUGE_PRESSURE = 38,
+ /*
+ * PID 0x23
+ */
+ COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
+ /*
+ * PID 0x2C
+ */
+ EXHAUST_GAS_RECIRCULATION_ERROR = 40,
+ /*
+ * PID 0x2D
+ */
+ COMMANDED_EVAPORATIVE_PURGE = 41,
+ /*
+ * PID 0x2E
+ */
+ FUEL_TANK_LEVEL_INPUT = 42,
+ /*
+ * PID 0x2F
+ */
+ EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
+ /*
+ * PID 0x32
+ */
+ CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
+ /*
+ * PID 0x3C
+ */
+ CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
+ /*
+ * PID 0x3D
+ */
+ CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
+ /*
+ * PID 0x3E
+ */
+ CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
+ /*
+ * PID 0x3F
+ */
+ ABSOLUTE_LOAD_VALUE = 48,
+ /*
+ * PID 0x43
+ */
+ FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
+ /*
+ * PID 0x44
+ */
+ RELATIVE_THROTTLE_POSITION = 50,
+ /*
+ * PID 0x45
+ */
+ ABSOLUTE_THROTTLE_POSITION_B = 51,
+ /*
+ * PID 0x47
+ */
+ ABSOLUTE_THROTTLE_POSITION_C = 52,
+ /*
+ * PID 0x48
+ */
+ ACCELERATOR_PEDAL_POSITION_D = 53,
+ /*
+ * PID 0x49
+ */
+ ACCELERATOR_PEDAL_POSITION_E = 54,
+ /*
+ * PID 0x4A
+ */
+ ACCELERATOR_PEDAL_POSITION_F = 55,
+ /*
+ * PID 0x4B
+ */
+ COMMANDED_THROTTLE_ACTUATOR = 56,
+ /*
+ * PID 0x4C
+ */
+ ETHANOL_FUEL_PERCENTAGE = 57,
+ /*
+ * PID 0x52
+ */
+ ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
+ /*
+ * PID 0x53
+ */
+ SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
+ /*
+ * PID 0x55
+ */
+ SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
+ /*
+ * PID 0x57
+ */
+ SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
+ /*
+ * PID 0x55
+ */
+ SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
+ /*
+ * PID 0x57
+ */
+ LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
+ /*
+ * PID 0x56
+ */
+ LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
+ /*
+ * PID 0x58
+ */
+ LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
+ /*
+ * PID 0x56
+ */
+ LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
+ /*
+ * PID 0x58
+ */
+ RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
+ /*
+ * PID 0x5A
+ */
+ HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
+ /*
+ * PID 0x5B
+ */
+ FUEL_INJECTION_TIMING = 69,
+ /*
+ * PID 0x5D
+ */
+ ENGINE_FUEL_RATE = 70,
+ /*
+ * PID 0x5E
+ */
+ // LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
new file mode 100644
index 0000000..86c8a45
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/DiagnosticIntegerSensorIndex.aidl
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+// @VintfStability
+@Backing(type="int")
+enum DiagnosticIntegerSensorIndex {
+ /**
+ * refer to FuelSystemStatus for a description of this value.
+ */
+ FUEL_SYSTEM_STATUS = 0,
+ /*
+ * PID 0x03
+ */
+ MALFUNCTION_INDICATOR_LIGHT_ON = 1,
+ /*
+ * PID 0x01
+ *
+ *
+ * refer to IgnitionMonitorKind for a description of this value.
+ */
+ IGNITION_MONITORS_SUPPORTED = 2,
+ /*
+ * PID 0x01
+ *
+ *
+ * The value of this sensor is a bitmask that specifies whether ignition-specific
+ * tests are available and whether they are complete. The semantics of the individual
+ * bits in this value are given by, respectively, SparkIgnitionMonitors and
+ * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+ */
+ IGNITION_SPECIFIC_MONITORS = 3,
+ /*
+ * PID 0x01
+ */
+ INTAKE_AIR_TEMPERATURE = 4,
+ /*
+ * PID 0x0F
+ *
+ *
+ * refer to SecondaryAirStatus for a description of this value.
+ */
+ COMMANDED_SECONDARY_AIR_STATUS = 5,
+ /*
+ * PID 0x12
+ */
+ NUM_OXYGEN_SENSORS_PRESENT = 6,
+ /*
+ * PID 0x13
+ */
+ RUNTIME_SINCE_ENGINE_START = 7,
+ /*
+ * PID 0x1F
+ */
+ DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
+ /*
+ * PID 0x21
+ */
+ WARMUPS_SINCE_CODES_CLEARED = 9,
+ /*
+ * PID 0x30
+ */
+ DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
+ /*
+ * PID 0x31
+ */
+ ABSOLUTE_BAROMETRIC_PRESSURE = 11,
+ /*
+ * PID 0x33
+ */
+ CONTROL_MODULE_VOLTAGE = 12,
+ /*
+ * PID 0x42
+ */
+ AMBIENT_AIR_TEMPERATURE = 13,
+ /*
+ * PID 0x46
+ */
+ TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
+ /*
+ * PID 0x4D
+ */
+ TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
+ /*
+ * PID 0x4E
+ */
+ MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
+ /*
+ * PID 0x4F
+ */
+ MAX_OXYGEN_SENSOR_VOLTAGE = 17,
+ /*
+ * PID 0x4F
+ */
+ MAX_OXYGEN_SENSOR_CURRENT = 18,
+ /*
+ * PID 0x4F
+ */
+ MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
+ /*
+ * PID 0x4F
+ */
+ MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
+ /*
+ * PID 0x50
+ *
+ *
+ * refer to FuelType for a description of this value.
+ */
+ FUEL_TYPE = 21,
+ /*
+ * PID 0x51
+ */
+ FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
+ /*
+ * PID 0x59
+ */
+ ENGINE_OIL_TEMPERATURE = 23,
+ /*
+ * PID 0x5C
+ */
+ DRIVER_DEMAND_PERCENT_TORQUE = 24,
+ /*
+ * PID 0x61
+ */
+ ENGINE_ACTUAL_PERCENT_TORQUE = 25,
+ /*
+ * PID 0x62
+ */
+ ENGINE_REFERENCE_PERCENT_TORQUE = 26,
+ /*
+ * PID 0x63
+ */
+ ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
+ /*
+ * PID 0x64
+ */
+ ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
+ /*
+ * PID 0x64
+ */
+ ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
+ /*
+ * PID 0x64
+ */
+ ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
+ /*
+ * PID 0x64
+ */
+ ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
+ /*
+ * PID 0x64
+ */
+ // LAST_SYSTEM_INDEX = 31,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
new file mode 100644
index 0000000..cb55ffa
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardStatus.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_STATUS.
+ */
+// @VintfStability
+@Backing(type="int")
+enum ElectronicTollCollectionCardStatus {
+ UNKNOWN = 0,
+ ELECTRONIC_TOLL_COLLECTION_CARD_VALID = 1,
+ ELECTRONIC_TOLL_COLLECTION_CARD_INVALID = 2,
+ ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
new file mode 100644
index 0000000..78254fb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ElectronicTollCollectionCardType.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_TYPE.
+ */
+// @VintfStability
+@Backing(type="int")
+enum ElectronicTollCollectionCardType {
+ UNKNOWN = 0,
+ JP_ELECTRONIC_TOLL_COLLECTION_CARD = 1,
+ JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2 = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.aidl
new file mode 100644
index 0000000..fc95bb0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvConnectorType.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by INFO_EV_CONNECTOR_TYPE to enumerate the type of connectors
+ * available to charge the vehicle.
+ */
+// @VintfStability
+@Backing(type="int")
+enum EvConnectorType {
+ /**
+ * Default type if the vehicle does not know or report the EV connector
+ * type.
+ */
+ UNKNOWN = 0,
+ IEC_TYPE_1_AC = 1,
+ IEC_TYPE_2_AC = 2,
+ IEC_TYPE_3_AC = 3,
+ IEC_TYPE_4_DC = 4,
+ IEC_TYPE_1_CCS_DC = 5,
+ IEC_TYPE_2_CCS_DC = 6,
+ TESLA_ROADSTER = 7,
+ TESLA_HPWC = 8,
+ TESLA_SUPERCHARGER = 9,
+ GBT_AC = 10,
+ GBT_DC = 11,
+ /**
+ * Connector type to use when no other types apply. Before using this
+ * value, work with Google to see if the EvConnectorType enum can be
+ * extended with an appropriate value.
+ */
+ OTHER = 101,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
new file mode 100644
index 0000000..6853ccd
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceRequestIndex.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Index in int32VAlues for VehicleProperty#EVS_SERVICE_REQUEST property.
+ */
+// @VintfStability
+@Backing(type="int")
+enum EvsServiceRequestIndex {
+ TYPE = 0,
+ STATE = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl
new file mode 100644
index 0000000..e351949
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceState.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by EVS_SERVICE_REQUEST to enumerate the service's state.
+ */
+// @VintfStability
+@Backing(type="int")
+enum EvsServiceState {
+ OFF = 0,
+ ON = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl
new file mode 100644
index 0000000..4ca241a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/EvsServiceType.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by EVS_SERVICE_REQUEST to enumerate the service's type.
+ */
+// @VintfStability
+@Backing(type="int")
+enum EvsServiceType {
+ REARVIEW = 0,
+ SURROUNDVIEW = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl
new file mode 100644
index 0000000..131ac14
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/FuelType.aidl
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by INFO_FUEL_TYPE to enumerate the type of fuels this vehicle uses.
+ * Consistent with projection protocol.
+ */
+// @VintfStability
+@Backing(type="int")
+enum FuelType {
+ /**
+ * Fuel type to use if the HU does not know on which types of fuel the vehicle
+ * runs. The use of this value is generally discouraged outside of aftermarket units.
+ */
+ FUEL_TYPE_UNKNOWN = 0,
+ /**
+ * Unleaded gasoline
+ */
+ FUEL_TYPE_UNLEADED = 1,
+ /**
+ * Leaded gasoline
+ */
+ FUEL_TYPE_LEADED = 2,
+ /**
+ * Diesel #1
+ */
+ FUEL_TYPE_DIESEL_1 = 3,
+ /**
+ * Diesel #2
+ */
+ FUEL_TYPE_DIESEL_2 = 4,
+ /**
+ * Biodiesel
+ */
+ FUEL_TYPE_BIODIESEL = 5,
+ /**
+ * 85% ethanol/gasoline blend
+ */
+ FUEL_TYPE_E85 = 6,
+ /**
+ * Liquified petroleum gas
+ */
+ FUEL_TYPE_LPG = 7,
+ /**
+ * Compressed natural gas
+ */
+ FUEL_TYPE_CNG = 8,
+ /**
+ * Liquified natural gas
+ */
+ FUEL_TYPE_LNG = 9,
+ /**
+ * Electric
+ */
+ FUEL_TYPE_ELECTRIC = 10,
+ /**
+ * Hydrogen fuel cell
+ */
+ FUEL_TYPE_HYDROGEN = 11,
+ /**
+ * Fuel type to use when no other types apply. Before using this value, work with
+ * Google to see if the FuelType enum can be extended with an appropriate value.
+ */
+ FUEL_TYPE_OTHER = 12,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
new file mode 100644
index 0000000..acb8409
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicle.aidl
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.IVehicleCallback;
+import android.hardware.automotive.vehicle.StatusCode;
+import android.hardware.automotive.vehicle.SubscribeOptions;
+import android.hardware.automotive.vehicle.VehiclePropConfig;
+import android.hardware.automotive.vehicle.VehiclePropValue;
+
+// @VintfStability
+interface IVehicle {
+ // Adding return type to method instead of out param String s since there is only one return
+ // value.
+ /**
+ * Print out debugging state for the vehicle hal.
+ *
+ * The text must be in ASCII encoding only.
+ *
+ * Performance requirements:
+ *
+ * The HAL must return from this call in less than 10ms. This call must avoid
+ * deadlocks, as it may be called at any point of operation. Any synchronization
+ * primitives used (such as mutex locks or semaphores) must be acquired
+ * with a timeout.
+ *
+ */
+ String debugDump();
+
+ /**
+ * Get a vehicle property value.
+ *
+ * For VehiclePropertyChangeMode::STATIC properties, this method must always
+ * return the same value always.
+ * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
+ * latest available value.
+ *
+ * Some properties like RADIO_PRESET requires to pass additional data in
+ * GET request in VehiclePropValue object.
+ *
+ * If there is no data available yet, which can happen during initial stage,
+ * this call must return immediately with an error code of
+ * StatusCode::TRY_AGAIN.
+ */
+ StatusCode get(in VehiclePropValue requestedPropValue, out VehiclePropValue propValue);
+
+ // Adding return type to method instead of out param VehiclePropConfig[] propConfigs since there
+ // is only one return value.
+ /**
+ * Returns a list of all property configurations supported by this vehicle
+ * HAL.
+ */
+ VehiclePropConfig[] getAllPropConfigs();
+
+ /**
+ * Returns a list of property configurations for given properties.
+ *
+ * If requested VehicleProperty wasn't found it must return
+ * StatusCode::INVALID_ARG, otherwise a list of vehicle property
+ * configurations with StatusCode::OK
+ */
+ StatusCode getPropConfigs(in int[] props, out VehiclePropConfig[] propConfigs);
+
+ // Adding return type to method instead of out param StatusCode status since there is only one
+ // return value.
+ /**
+ * Set a vehicle property value.
+ *
+ * Timestamp of data must be ignored for set operation.
+ *
+ * Setting some properties require having initial state available. If initial
+ * data is not available yet this call must return StatusCode::TRY_AGAIN.
+ * For a property with separate power control this call must return
+ * StatusCode::NOT_AVAILABLE error if property is not powered on.
+ */
+ StatusCode set(in VehiclePropValue propValue);
+
+ // Adding return type to method instead of out param StatusCode status since there is only one
+ // return value.
+ /**
+ * Subscribes to property events.
+ *
+ * Clients must be able to subscribe to multiple properties at a time
+ * depending on data provided in options argument.
+ *
+ * @param listener This client must be called on appropriate event.
+ * @param options List of options to subscribe. SubscribeOption contains
+ * information such as property Id, area Id, sample rate, etc.
+ */
+ StatusCode subscribe(in IVehicleCallback callback, in SubscribeOptions[] options);
+
+ // Adding return type to method instead of out param StatusCode status since there is only one
+ // return value.
+ /**
+ * Unsubscribes from property events.
+ *
+ * If this client wasn't subscribed to the given property, this method
+ * must return StatusCode::INVALID_ARG.
+ */
+ StatusCode unsubscribe(in IVehicleCallback callback, in int propId);
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
new file mode 100644
index 0000000..1b5a1e2
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/IVehicleCallback.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.StatusCode;
+import android.hardware.automotive.vehicle.VehiclePropValue;
+
+// @VintfStability
+interface IVehicleCallback {
+ /**
+ * Event callback happens whenever a variable that the API user has
+ * subscribed to needs to be reported. This may be based purely on
+ * threshold and frequency (a regular subscription, see subscribe call's
+ * arguments) or when the IVehicle#set method was called and the actual
+ * change needs to be reported.
+ *
+ * These callbacks are chunked.
+ *
+ * @param values that has been updated.
+ */
+ oneway void onPropertyEvent(in VehiclePropValue[] propValues);
+
+ /**
+ * This method gets called if the client was subscribed to a property using
+ * SubscribeFlags::EVENTS_FROM_ANDROID flag and IVehicle#set(...) method was called.
+ *
+ * These events must be delivered to subscriber immediately without any
+ * batching.
+ *
+ * @param value Value that was set by a client.
+ */
+ oneway void onPropertySet(in VehiclePropValue propValue);
+
+ /**
+ * Set property value is usually asynchronous operation. Thus even if
+ * client received StatusCode::OK from the IVehicle::set(...) this
+ * doesn't guarantee that the value was successfully propagated to the
+ * vehicle network. If such rare event occurs this method must be called.
+ *
+ * @param errorCode - any value from StatusCode enum.
+ * @param property - a property where error has happened.
+ * @param areaId - bitmask that specifies in which areas the problem has
+ * occurred, must be 0 for global properties
+ */
+ oneway void onPropertySetError(in StatusCode errorCode, in int propId, in int areaId);
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl
new file mode 100644
index 0000000..12746ce
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequest.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.InitialUserInfoRequestType;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a INITIAL_USER_INFO request made by the Android system.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable InitialUserInfoRequest {
+ /**
+ * Arbitrary id used to map the HAL response to the request.
+ */
+ int requestId;
+ /**
+ * Type of request.
+ */
+ InitialUserInfoRequestType requestType;
+ /**
+ * Information about the current state of the Android system.
+ */
+ UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl
new file mode 100644
index 0000000..12fec24
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoRequestType.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines when a INITIAL_USER_INFO request was made.
+ */
+// @VintfStability
+@Backing(type="int")
+enum InitialUserInfoRequestType {
+ /**
+ * At the first time Android was booted (or after a factory reset).
+ */
+ FIRST_BOOT = 1,
+ /**
+ * At the first time Android was booted after the system was updated.
+ */
+ FIRST_BOOT_AFTER_OTA = 2,
+ /**
+ * When Android was booted "from scratch".
+ */
+ COLD_BOOT = 3,
+ /**
+ * When Android was resumed after the system was suspended to memory.
+ */
+ RESUME = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
new file mode 100644
index 0000000..34d9062
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponse.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.InitialUserInfoResponseAction;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a HAL response to a INITIAL_USER_INFO request.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable InitialUserInfoResponse {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * which action the Android system should take.
+ */
+ InitialUserInfoResponseAction action;
+ /**
+ * Information about the user that should be switched to or created.
+ */
+ UserInfo userToSwitchOrCreate;
+ /**
+ * System locales of the initial user (value will be passed as-is to
+ * android.provider.Settings.System.SYSTEM_LOCALES)
+ */
+ @utf8InCpp String userLocales;
+ /**
+ * Name of the user that should be created.
+ */
+ @utf8InCpp String userNameToCreate;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
new file mode 100644
index 0000000..e35fa9a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/InitialUserInfoResponseAction.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines which action the Android system should take in an INITIAL_USER_INFO request.
+ */
+// @VintfStability
+@Backing(type="int")
+enum InitialUserInfoResponseAction {
+ /**
+ * Let the Android System decide what to do.
+ *
+ * For example, it might create a new user on first boot, and switch to the last
+ * active user afterwards.
+ */
+ DEFAULT = 0,
+ /**
+ * Switch to an existing Android user.
+ */
+ SWITCH = 1,
+ /**
+ * Create a new Android user (and switch to it).
+ */
+ CREATE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
new file mode 100644
index 0000000..775d531
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CommonIgnitionMonitors.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Ignition monitors common to both SPARK and COMPRESSION.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2CommonIgnitionMonitors {
+ COMPONENTS_AVAILABLE = 0x1 << 0,
+ COMPONENTS_INCOMPLETE = 0x1 << 1,
+ FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+ FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+ MISFIRE_AVAILABLE = 0x1 << 4,
+ MISFIRE_INCOMPLETE = 0x1 << 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
new file mode 100644
index 0000000..ab444e1
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2CompressionIgnitionMonitors.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.Obd2CommonIgnitionMonitors;
+
+/**
+ * Ignition monitors only available for COMPRESSION vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2CompressionIgnitionMonitors {
+ COMPONENTS_AVAILABLE = 0x1 << 0,
+ COMPONENTS_INCOMPLETE = 0x1 << 1,
+ FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+ FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+ MISFIRE_AVAILABLE = 0x1 << 4,
+ MISFIRE_INCOMPLETE = 0x1 << 5,
+ EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+ EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+ PM_FILTER_AVAILABLE = 0x1 << 8,
+ PM_FILTER_INCOMPLETE = 0x1 << 9,
+ EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+ EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+ BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+ BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+ NOx_SCR_AVAILABLE = 0x1 << 14,
+ NOx_SCR_INCOMPLETE = 0x1 << 15,
+ NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+ NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
new file mode 100644
index 0000000..9b4ce8f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelSystemStatus.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The status of the vehicle's fuel system.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2FuelSystemStatus {
+ OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+ CLOSED_LOOP = 2,
+ OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+ OPEN_SYSTEM_FAILURE = 8,
+ CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl
new file mode 100644
index 0000000..1428f2c
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2FuelType.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The fuel type(s) supported by a vehicle.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2FuelType {
+ NOT_AVAILABLE = 0,
+ GASOLINE = 1,
+ METHANOL = 2,
+ ETHANOL = 3,
+ DIESEL = 4,
+ LPG = 5,
+ CNG = 6,
+ PROPANE = 7,
+ ELECTRIC = 8,
+ BIFUEL_RUNNING_GASOLINE = 9,
+ BIFUEL_RUNNING_METHANOL = 10,
+ BIFUEL_RUNNING_ETHANOL = 11,
+ BIFUEL_RUNNING_LPG = 12,
+ BIFUEL_RUNNING_CNG = 13,
+ BIFUEL_RUNNING_PROPANE = 14,
+ BIFUEL_RUNNING_ELECTRIC = 15,
+ BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+ HYBRID_GASOLINE = 17,
+ HYBRID_ETHANOL = 18,
+ HYBRID_DIESEL = 19,
+ HYBRID_ELECTRIC = 20,
+ HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+ HYBRID_REGENERATIVE = 22,
+ BIFUEL_RUNNING_DIESEL = 23,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
new file mode 100644
index 0000000..477b38d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2IgnitionMonitorKind.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines which ignition monitors are available to be read.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2IgnitionMonitorKind {
+ SPARK = 0,
+ COMPRESSION = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
new file mode 100644
index 0000000..f257164
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SecondaryAirStatus.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The status of the vehicle's secondary air system.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2SecondaryAirStatus {
+ UPSTREAM = 1,
+ DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+ FROM_OUTSIDE_OR_OFF = 4,
+ PUMP_ON_FOR_DIAGNOSTICS = 8,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
new file mode 100644
index 0000000..75504df
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/Obd2SparkIgnitionMonitors.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.Obd2CommonIgnitionMonitors;
+
+/**
+ * Ignition monitors available for SPARK vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+// @VintfStability
+@Backing(type="int")
+enum Obd2SparkIgnitionMonitors {
+ COMPONENTS_AVAILABLE = 0x1 << 0,
+ COMPONENTS_INCOMPLETE = 0x1 << 1,
+ FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+ FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+ MISFIRE_AVAILABLE = 0x1 << 4,
+ MISFIRE_INCOMPLETE = 0x1 << 5,
+ EGR_AVAILABLE = 0x1 << 6,
+ EGR_INCOMPLETE = 0x1 << 7,
+ OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+ OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+ OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+ OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+ AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+ AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+ SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+ SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+ EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+ EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+ HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+ HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+ CATALYST_AVAILABLE = 0x1 << 20,
+ CATALYST_INCOMPLETE = 0x1 << 21,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.aidl
new file mode 100644
index 0000000..260dd42
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/PortLocationType.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by INFO_FUEL_DOOR_LOCATION/INFO_CHARGE_PORT_LOCATION to enumerate fuel door or
+ * ev port location.
+ */
+// @VintfStability
+@Backing(type="int")
+enum PortLocationType {
+ /**
+ * Default type if the vehicle does not know or report the Fuel door
+ * and ev port location.
+ */
+ UNKNOWN = 0,
+ FRONT_LEFT = 1,
+ FRONT_RIGHT = 2,
+ REAR_RIGHT = 3,
+ REAR_LEFT = 4,
+ FRONT = 5,
+ REAR = 6,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
new file mode 100644
index 0000000..e54a08b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/ProcessTerminationReason.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * The reason why a process is terminated by car watchdog.
+ * This is used with WATCHDOG_TERMINATED_PROCESS property.
+ */
+// @VintfStability
+@Backing(type="int")
+enum ProcessTerminationReason {
+ /**
+ * A process doesn't respond to car watchdog within the timeout.
+ */
+ NOT_RESPONDING = 1,
+ /**
+ * A process uses more IO operations than what is allowed.
+ */
+ IO_OVERUSE = 2,
+ /**
+ * A process uses more memory space than what is allowed.
+ */
+ MEMORY_OVERUSE = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.aidl
new file mode 100644
index 0000000..79a8c59
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RemoveUserRequest.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a REMOVE_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable RemoveUserRequest {
+ /**
+ * Arbitrary id used to map the response to the request.
+ */
+ int requestId;
+ /**
+ * Information about the Android user that was removed.
+ */
+ UserInfo removedUserInfo;
+ /**
+ * Information about the current state of the Android system.
+ */
+ UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl
new file mode 100644
index 0000000..eca703a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/RotaryInputType.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * A rotary control which can rotate without limits. These controls use HW_ROTARY_INPUT to report
+ * relative clockwise or counterclockwise motion. They have no absolute position.
+ */
+// @VintfStability
+@Backing(type="int")
+enum RotaryInputType {
+ /**
+ * Main rotary control, typically in the center console, used to navigate the user interface.
+ */
+ ROTARY_INPUT_TYPE_SYSTEM_NAVIGATION = 0,
+ /**
+ * Volume control for adjusting audio volume.
+ */
+ ROTARY_INPUT_TYPE_AUDIO_VOLUME = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
new file mode 100644
index 0000000..9b29229
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/StatusCode.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Error codes used in vehicle HAL interface.
+ */
+// @VintfStability
+@Backing(type="int")
+enum StatusCode {
+ OK = 0,
+ /**
+ * Try again.
+ */
+ TRY_AGAIN = 1,
+ /**
+ * Invalid argument provided.
+ */
+ INVALID_ARG = 2,
+ /**
+ * This code must be returned when device that associated with the vehicle
+ * property is not available. For example, when client tries to set HVAC
+ * temperature when the whole HVAC unit is turned OFF.
+ */
+ NOT_AVAILABLE = 3,
+ /**
+ * Access denied
+ */
+ ACCESS_DENIED = 4,
+ /**
+ * Something unexpected has happened in Vehicle HAL
+ */
+ INTERNAL_ERROR = 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeFlags.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeFlags.aidl
new file mode 100644
index 0000000..d997990
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeFlags.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum SubscribeFlags {
+ UNDEFINED = 0x0,
+
+ /**
+ * Subscribe to event that was originated in vehicle HAL
+ * (most likely this event came from the vehicle itself).
+ */
+ EVENTS_FROM_CAR = 0x1,
+
+ /**
+ * Use this flag to subscribe on events when IVehicle#set(...) was called by
+ * vehicle HAL's client (e.g. Car Service).
+ */
+ EVENTS_FROM_ANDROID = 0x2,
+
+ /**
+ * Property event for this property should be passed through shared memory with only this
+ * property's data included. This can be helpful for reducing memory copy in upper layer
+ * for data with bigger payload. If payload size is small, VHAL can send this through non-shared
+ * memory path instead.
+ */
+ EXCLUSIVE_SHARED_MEMORY = 0x4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
new file mode 100644
index 0000000..0769f28
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SubscribeOptions.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SubscribeFlags;
+
+/**
+ * Encapsulates information about subscription to vehicle property events.
+ */
+// @VintfStability
+parcelable SubscribeOptions {
+ /** Property to subscribe */
+ int propId;
+
+ /**
+ * Sample rate in Hz.
+ *
+ * Must be provided for properties with
+ * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
+ * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
+ * for a given property.
+ * This value indicates how many updates per second client wants to receive.
+ */
+ float sampleRate;
+
+ /** Flags that indicate to which event sources to listen. */
+ SubscribeFlags flags;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
new file mode 100644
index 0000000..c0b5d68
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserMessageType.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Defines the reason a SWITCH_USER call was made.
+ *
+ * The meaning of each constant is explained in that property.
+ */
+// @VintfStability
+@Backing(type="int")
+enum SwitchUserMessageType {
+ LEGACY_ANDROID_SWITCH = 1,
+ ANDROID_SWITCH = 2,
+ VEHICLE_RESPONSE = 3,
+ VEHICLE_REQUEST = 4,
+ ANDROID_POST_SWITCH = 5,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
new file mode 100644
index 0000000..9a324f4
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserRequest.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SwitchUserMessageType;
+import android.hardware.automotive.vehicle.UserInfo;
+import android.hardware.automotive.vehicle.UsersInfo;
+
+/**
+ * Defines the format of a SWITCH_USER property.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable SwitchUserRequest {
+ /**
+ * Arbitrary id used to map the response to the request.
+ */
+ int requestId;
+ /**
+ * Type of message.
+ */
+ SwitchUserMessageType messageType;
+ /**
+ * Information about the Android user being switched to.
+ *
+ * Only the user id (but not the flags) should be set when the request is made by HAL.
+ */
+ UserInfo targetUser;
+ /**
+ * Information about the current state of the Android system.
+ *
+ * Should not be set when the request is made by HAL.
+ */
+ UsersInfo usersInfo;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
new file mode 100644
index 0000000..175859d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserResponse.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.SwitchUserMessageType;
+import android.hardware.automotive.vehicle.SwitchUserStatus;
+
+/**
+ * Defines the result of a SwitchUserRequest.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable SwitchUserResponse {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * Type of message.
+ */
+ SwitchUserMessageType messageType;
+ /**
+ * Status of the request.
+ */
+ SwitchUserStatus status;
+ /**
+ * HAL-specific error message.
+ *
+ * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+ * used to show custom error messages to the end user.
+ */
+ @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
new file mode 100644
index 0000000..11dc5f2
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/SwitchUserStatus.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Status of the response to a SwitchUserRequest.
+ */
+// @VintfStability
+@Backing(type="int")
+enum SwitchUserStatus {
+ /**
+ * The request succeeded and the HAL user was switched.
+ */
+ SUCCESS = 1,
+ /**
+ * The request failed and the HAL user remained the same.
+ */
+ FAILURE = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserFlags.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserFlags.aidl
new file mode 100644
index 0000000..8daa0c1
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserFlags.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Flags used to define the characteristics of an Android user.
+ */
+// @VintfStability
+@Backing(type="int")
+enum UserFlags {
+ /**
+ * No flags.
+ */
+ NONE = 0x0,
+ /**
+ * System user.
+ * On automotive, that user is always running, although never on foreground (except during
+ * boot or exceptional circumstances).
+ */
+ SYSTEM = 0x01,
+ /**
+ * Guest users have restrictions.
+ */
+ GUEST = 0x02,
+ /**
+ * Ephemeral users have non-persistent state.
+ */
+ EPHEMERAL = 0x04,
+ /**
+ * Admin users have additional privileges such as permission to create other users.
+ */
+ ADMIN = 0x08,
+ /**
+ * Disabled users are marked for deletion.
+ */
+ DISABLED = 0x10,
+ /**
+ * Profile user is a profile of another user.
+ */
+ PROFILE = 0x20,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
new file mode 100644
index 0000000..9531bb3
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociation.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+import android.hardware.automotive.vehicle.UserIdentificationAssociationValue;
+
+/**
+ * Helper struct used when getting a user/identification association type.
+ */
+// @VintfStability
+parcelable UserIdentificationAssociation {
+ UserIdentificationAssociationType type = UserIdentificationAssociationType.INVALID;
+ UserIdentificationAssociationValue value = UserIdentificationAssociationValue.UNKNOWN;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
new file mode 100644
index 0000000..5be7f99
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationSetValue.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used to set a UserIdentificationAssociationType with an Android user.
+ */
+// @VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationSetValue {
+ INVALID = 0,
+ /**
+ * Associate the identification type with the current foreground Android user.
+ */
+ ASSOCIATE_CURRENT_USER = 1,
+ /**
+ * Disassociate the identification type from the current foreground Android user.
+ */
+ DISASSOCIATE_CURRENT_USER = 2,
+ /**
+ * Disassociate the identification type from all Android users.
+ */
+ DISASSOCIATE_ALL_USERS = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl
new file mode 100644
index 0000000..141aca8
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationType.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Types of mechanisms used to identify an Android user.
+ *
+ * See USER_IDENTIFICATION_ASSOCIATION for more details and example.
+ */
+// @VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationType {
+ INVALID = 0,
+ /**
+ * Key used to unlock the car.
+ */
+ KEY_FOB = 1,
+ /**
+ * Custom mechanism defined by the OEM.
+ */
+ CUSTOM_1 = 101,
+ /**
+ * Custom mechanism defined by the OEM.
+ */
+ CUSTOM_2 = 102,
+ /**
+ * Custom mechanism defined by the OEM.
+ */
+ CUSTOM_3 = 103,
+ /**
+ * Custom mechanism defined by the OEM.
+ */
+ CUSTOM_4 = 104,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl
new file mode 100644
index 0000000..c11ad2a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationAssociationValue.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Whether a UserIdentificationAssociationType is associate with an Android user.
+ */
+// @VintfStability
+@Backing(type="int")
+enum UserIdentificationAssociationValue {
+ /**
+ * Used when the status of an association could not be determined.
+ *
+ * For example, in a set() request, it would indicate a failure to set the given type.
+ */
+ UNKNOWN = 1,
+ /**
+ * The identification type is associated with the current foreground Android user.
+ */
+ ASSOCIATED_CURRENT_USER = 2,
+ /**
+ * The identification type is associated with another Android user.
+ */
+ ASSOCIATED_ANOTHER_USER = 3,
+ /**
+ * The identification type is not associated with any Android user.
+ */
+ NOT_ASSOCIATED_ANY_USER = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
new file mode 100644
index 0000000..cb4b8cf
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationGetRequest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a get() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable UserIdentificationGetRequest {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * Information about the current foreground Android user.
+ */
+ UserInfo userInfo;
+ /**
+ * Number of association being queried.
+ */
+ int numberAssociationTypes;
+ /**
+ * Types of association being queried.
+ */
+ UserIdentificationAssociationType[] associationTypes;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl
new file mode 100644
index 0000000..e8eb3a3
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationResponse.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociation;
+
+/**
+ * Defines the result of a USER_IDENTIFICATION_ASSOCIATION - both for get() and set().
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable UserIdentificationResponse {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * Number of associations being returned.
+ */
+ int numberAssociation;
+ /**
+ * Values associated with the user.
+ */
+ UserIdentificationAssociation[] associations;
+ /**
+ * HAL-specific error message.
+ *
+ * This argument is optional, and when defined, it's passed "as-is" to the caller. It could be
+ * used to show custom error messages to the end user.
+ */
+ @utf8InCpp String errorMessage;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
new file mode 100644
index 0000000..392ae99
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetAssociation.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationAssociationSetValue;
+import android.hardware.automotive.vehicle.UserIdentificationAssociationType;
+
+/**
+ * Helper struct used when setting a user/identification association type.
+ */
+// @VintfStability
+parcelable UserIdentificationSetAssociation {
+ UserIdentificationAssociationType type = UserIdentificationAssociationType.INVALID;
+ UserIdentificationAssociationSetValue value = UserIdentificationAssociationSetValue.INVALID;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
new file mode 100644
index 0000000..dafb1d1
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserIdentificationSetRequest.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserIdentificationSetAssociation;
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Defines the format of a set() call to USER_IDENTIFICATION_ASSOCIATION.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it must be converted to
+ * VehiclePropValue.RawValue through libraries provided by the default Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable UserIdentificationSetRequest {
+ /**
+ * Id of the request being responded.
+ */
+ int requestId;
+ /**
+ * Information about the current foreground Android user.
+ */
+ UserInfo userInfo;
+ /**
+ * Number of association being set.
+ */
+ int numberAssociations;
+ /**
+ * Associations being set.
+ */
+ UserIdentificationSetAssociation[] associations;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.aidl
new file mode 100644
index 0000000..0a84308
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UserInfo.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserFlags;
+
+/**
+ * Information about a specific Android user.
+ */
+// @VintfStability
+parcelable UserInfo {
+ int userId = 0;
+ UserFlags flags = UserFlags.NONE;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl
new file mode 100644
index 0000000..28b3f95
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/UsersInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.UserInfo;
+
+/**
+ * Information about all Android users.
+ *
+ * NOTE: this struct is not used in the HAL properties directly, it's part of other structs, which
+ * in turn are converted to a VehiclePropValue.RawValue through libraries provided by the default
+ * Vehicle HAL implementation.
+ */
+// @VintfStability
+parcelable UsersInfo {
+ /**
+ * The current foreground user.
+ */
+ UserInfo currentUser;
+ /**
+ * Number of existing users; includes the current user, recently removed users (with DISABLED
+ * flag), and profile users (with PROFILE flag).
+ */
+ int numberUsers;
+ /**
+ * List of existing users; includes the current user, recently removed users (with DISABLED
+ * flag), and profile users (with PROFILE flag).
+ */
+ UserInfo[] existingUsers;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl
new file mode 100644
index 0000000..9e593c5
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateConfigFlag.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateConfigFlag {
+ /**
+ * AP can enter deep sleep state. If not set, AP will always shutdown from
+ * VehicleApPowerState#SHUTDOWN_PREPARE power state.
+ */
+ ENABLE_DEEP_SLEEP_FLAG = 0x1,
+ /**
+ * The power controller can power on AP from off state after timeout
+ * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+ */
+ CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
new file mode 100644
index 0000000..b6cc70d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.aidl
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReport {
+ /**
+ * The device has booted. CarService has initialized and is ready to accept commands
+ * from VHAL. The user is not logged in, and vendor apps and services are expected to
+ * control the display and audio.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+ * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+ */
+ WAIT_FOR_VHAL = 0x1,
+ /**
+ * AP is ready to suspend.
+ * The AP will not send any more state reports after this.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#FINISHED.
+ * Other power state requests are ignored.
+ *
+ * int32Values[1]: Time to turn AP back on, in seconds. Power controller should turn on
+ * AP after the specified time has elapsed, so AP can run tasks like
+ * update. If this value is 0, no wake up is requested. The power
+ * controller may not necessarily support timed wake-up.
+ */
+ DEEP_SLEEP_ENTRY = 0x2,
+ /**
+ * AP is exiting from deep sleep state.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+ * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+ */
+ DEEP_SLEEP_EXIT = 0x3,
+ /**
+ * AP sends this message repeatedly while cleanup and idle tasks execute.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE
+ * requesting immediate shutdown or VehicleApPowerStateReq#CANCEL_SHUTDOWN. Other
+ * power state requests are ignored.
+ *
+ * int32Values[1]: Time to postpone shutdown in ms. Maximum value is
+ * 5000 ms.
+ * If AP needs more time, it will send another SHUTDOWN_POSTPONE
+ * message before the previous one expires.
+ */
+ SHUTDOWN_POSTPONE = 0x4,
+ /**
+ * AP is ready to shutdown.
+ * The AP will not send any more state reports after this.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#FINISHED.
+ * Other power state requests are ignored.
+ *
+ * int32Values[1]: Time to turn AP back on, in seconds. Power controller should turn on
+ * AP after the specified time has elapsed so AP can run tasks like
+ * update. If this value is 0, no wake up is specified. The power
+ * controller may not necessarily support timed wake-up.
+ */
+ SHUTDOWN_START = 0x5,
+ /**
+ * AP is entering its normal operating state.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE.
+ * Other power state requests are ignored.
+ */
+ ON = 0x6,
+ /**
+ * AP is preparing to shut down. In this state, Garage Mode is active and idle
+ * tasks are allowed to run.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#SHUTDOWN_PREPARE
+ * requesting immediate shutdown or VehicleApPowerStateReq#CANCEL_SHUTDOWN. Other
+ * power state requests are ignored.
+ */
+ SHUTDOWN_PREPARE = 0x7,
+ /**
+ * AP has stopped preparing to shut down.
+ * After reporting this state, AP will accept VehicleApPowerStateReq#ON or
+ * VehicleApPowerStateReq#SHUTDOWN_PREPARE. Other power state requests are ignored.
+ */
+ SHUTDOWN_CANCELLED = 0x8,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
new file mode 100644
index 0000000..06bc073
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReq.aidl
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReq {
+ /**
+ * This requests Android to enter its normal operating state.
+ * This may be sent after the AP has reported
+ * VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+ * VehicleApPowerStateReport#SHUTDOWN_CANCELLED, or
+ * VehicleApPowerStateReport#WAIT_FOR_VHAL.
+ */
+ ON = 0,
+ /**
+ * The power controller issues this request to shutdown the system.
+ * This may be sent after the AP has reported
+ * VehicleApPowerStateReport#DEEP_SLEEP_EXIT,
+ * VehicleApPowerStateReport#ON,
+ * VehicleApPowerStateReport#SHUTDOWN_CANCELLED,
+ * VehicleApPowerStateReport#SHUTDOWN_POSTPONE,
+ * VehicleApPowerStateReport#SHUTDOWN_PREPARE, or
+ * VehicleApPowerStateReport#WAIT_FOR_VHAL.
+ *
+ * int32Values[1] : One of VehicleApPowerStateShutdownParam.
+ * This parameter indicates if the AP should shut
+ * down fully or sleep. This parameter also
+ * indicates if the shutdown should be immediate
+ * or if it can be postponed. If the shutdown can
+ * be postponed, AP requests postponing by sending
+ * VehicleApPowerStateReport#SHUTDOWN_POSTPONE.
+ */
+ SHUTDOWN_PREPARE = 1,
+ /**
+ * Cancel the shutdown.
+ * This may be sent after the AP has reported
+ * VehicleApPowerStateReport#SHUTDOWN_POSTPONE or
+ * VehicleApPowerStateReport#SHUTDOWN_PREPARE.
+ * After receiving this request, the AP will report
+ * VehicleApPowerStateReport#WAIT_FOR_VHAL in preparation to going ON.
+ */
+ CANCEL_SHUTDOWN = 2,
+ /**
+ * Completes the shutdown process.
+ * This may be sent after the AP has reported
+ * VehicleApPowerStateReport#DEEP_SLEEP_ENTRY or
+ * VehicleApPowerStateReport#SHUTDOWN_START. The AP will not report new
+ * state information after receiving this request.
+ */
+ FINISHED = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
new file mode 100644
index 0000000..a3d6c7f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReqIndex.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Index in int32Values for VehicleProperty#AP_POWER_STATE_REQ property.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateReqIndex {
+ STATE = 0,
+ ADDITIONAL = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
new file mode 100644
index 0000000..f4ab080
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerStateShutdownParam.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleApPowerStateShutdownParam {
+ /**
+ * AP must shutdown immediately. Postponing is not allowed.
+ */
+ SHUTDOWN_IMMEDIATELY = 1,
+ /**
+ * AP can enter deep sleep instead of shutting down completely.
+ */
+ CAN_SLEEP = 2,
+ /**
+ * AP can only shutdown with postponing allowed.
+ */
+ SHUTDOWN_ONLY = 3,
+ /**
+ * AP may enter deep sleep, but must either sleep or shut down immediately.
+ * Postponing is not allowed.
+ */
+ SLEEP_IMMEDIATELY = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl
new file mode 100644
index 0000000..53b85eb
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleArea.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleArea {
+ GLOBAL = 0x01000000,
+ /** WINDOW maps to enum VehicleAreaWindow */
+ WINDOW = 0x03000000,
+ /** MIRROR maps to enum VehicleAreaMirror */
+ MIRROR = 0x04000000,
+ /** SEAT maps to enum VehicleAreaSeat */
+ SEAT = 0x05000000,
+ /** DOOR maps to enum VehicleAreaDoor */
+ DOOR = 0x06000000,
+ /** WHEEL maps to enum VehicleAreaWheel */
+ WHEEL = 0x07000000,
+
+ MASK = 0x0f000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
new file mode 100644
index 0000000..0a688c0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaConfig.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+parcelable VehicleAreaConfig {
+ /**
+ * Area id is ignored for VehiclePropertyGroup:GLOBAL properties.
+ */
+ int areaId;
+
+ /**
+ * If the property has @data_enum, leave the range to zero.
+ *
+ * Range will be ignored in the following cases:
+ * - The VehiclePropertyType is not INT32, INT64 or FLOAT.
+ * - Both of min value and max value are zero.
+ */
+
+ int minInt32Value;
+ int maxInt32Value;
+
+ long minInt64Value;
+ long maxInt64Value;
+
+ float minFloatValue;
+ float maxFloatValue;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
new file mode 100644
index 0000000..c85b171
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaDoor.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleAreaDoor {
+ ROW_1_LEFT = 0x00000001,
+ ROW_1_RIGHT = 0x00000004,
+ ROW_2_LEFT = 0x00000010,
+ ROW_2_RIGHT = 0x00000040,
+ ROW_3_LEFT = 0x00000100,
+ ROW_3_RIGHT = 0x00000400,
+ HOOD = 0x10000000,
+ REAR = 0x20000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
new file mode 100644
index 0000000..daecf0b
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaMirror.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleAreaMirror {
+ DRIVER_LEFT = 0x00000001,
+ DRIVER_RIGHT = 0x00000002,
+ DRIVER_CENTER = 0x00000004,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
new file mode 100644
index 0000000..9d16c86
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaSeat.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various Seats in the car.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleAreaSeat {
+ ROW_1_LEFT = 0x0001,
+ ROW_1_CENTER = 0x0002,
+ ROW_1_RIGHT = 0x0004,
+ ROW_2_LEFT = 0x0010,
+ ROW_2_CENTER = 0x0020,
+ ROW_2_RIGHT = 0x0040,
+ ROW_3_LEFT = 0x0100,
+ ROW_3_CENTER = 0x0200,
+ ROW_3_RIGHT = 0x0400,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
new file mode 100644
index 0000000..0e5b995
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWheel.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleAreaWheel {
+ UNKNOWN = 0x0,
+ LEFT_FRONT = 0x1,
+ RIGHT_FRONT = 0x2,
+ LEFT_REAR = 0x4,
+ RIGHT_REAR = 0x8,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
new file mode 100644
index 0000000..bab0a3f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleAreaWindow.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various windshields/windows in the car.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleAreaWindow {
+ FRONT_WINDSHIELD = 0x00000001,
+ REAR_WINDSHIELD = 0x00000002,
+ ROW_1_LEFT = 0x00000010,
+ ROW_1_RIGHT = 0x00000040,
+ ROW_2_LEFT = 0x00000100,
+ ROW_2_RIGHT = 0x00000400,
+ ROW_3_LEFT = 0x00001000,
+ ROW_3_RIGHT = 0x00004000,
+ ROOF_TOP_1 = 0x00010000,
+ ROOF_TOP_2 = 0x00020000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl
new file mode 100644
index 0000000..a7531c4
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleDisplay.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleDisplay {
+ /**
+ * The primary Android display (for example, center console)
+ */
+ MAIN = 0,
+ INSTRUMENT_CLUSTER = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl
new file mode 100644
index 0000000..8b08ff8
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleGear.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Various gears which can be selected by user and chosen in system.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleGear {
+ GEAR_UNKNOWN = 0x0000,
+ GEAR_NEUTRAL = 0x0001,
+ GEAR_REVERSE = 0x0002,
+ GEAR_PARK = 0x0004,
+ GEAR_DRIVE = 0x0008,
+ GEAR_1 = 0x0010,
+ GEAR_2 = 0x0020,
+ GEAR_3 = 0x0040,
+ GEAR_4 = 0x0080,
+ GEAR_5 = 0x0100,
+ GEAR_6 = 0x0200,
+ GEAR_7 = 0x0400,
+ GEAR_8 = 0x0800,
+ GEAR_9 = 0x1000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl
new file mode 100644
index 0000000..1967679
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHvacFanDirection.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Bit flags for fan direction
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleHvacFanDirection {
+ UNKNOWN = 0x0,
+ FACE = 0x1,
+ FLOOR = 0x2,
+ /**
+ * FACE_AND_FLOOR = FACE | FLOOR
+ */
+ FACE_AND_FLOOR = 0x3,
+ DEFROST = 0x4,
+ /**
+ * DEFROST_AND_FLOOR = DEFROST | FLOOR
+ */
+ DEFROST_AND_FLOOR = 0x06,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
new file mode 100644
index 0000000..2dfd070
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleHwKeyInputAction.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleHwKeyInputAction {
+ /**
+ * Key down
+ */
+ ACTION_DOWN = 0,
+ /**
+ * Key up
+ */
+ ACTION_UP = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
new file mode 100644
index 0000000..cf9db97
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleIgnitionState.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleIgnitionState {
+ UNDEFINED = 0,
+ /**
+ * Steering wheel is locked
+ */
+ LOCK = 1,
+ /**
+ * 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.
+ */
+ OFF,
+ /**
+ * Typically in this state accessories become available (e.g. radio).
+ * Instrument cluster and engine are turned off
+ */
+ ACC,
+ /**
+ * Ignition is in state ON. Accessories and instrument cluster available,
+ * engine might be running or ready to be started.
+ */
+ ON,
+ /**
+ * Typically in this state engine is starting (cranking).
+ */
+ START,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl
new file mode 100644
index 0000000..bfe9163
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightState.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by lights state properties to enumerate the current state of the lights.
+ *
+ * Most XXX_LIGHTS_STATE properties will only report ON and OFF states. Only
+ * the HEADLIGHTS_STATE property will report DAYTIME_RUNNING.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleLightState {
+ OFF = 0,
+ ON = 1,
+ DAYTIME_RUNNING = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
new file mode 100644
index 0000000..061f85d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleLightSwitch.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by lights switch properties to enumerate user selected switch setting.
+ *
+ * XXX_LIGHTS_SWITCH properties report the switch settings that the user
+ * selects. The switch setting may be decoupled from the state reported if the
+ * user selects AUTOMATIC.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleLightSwitch {
+ OFF = 0,
+ ON = 1,
+ /**
+ * Daytime running lights mode. Most cars automatically use DRL but some
+ * cars allow the user to activate them manually.
+ */
+ DAYTIME_RUNNING = 2,
+ /**
+ * Allows the vehicle ECU to set the lights automatically
+ */
+ AUTOMATIC = 0x100,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
new file mode 100644
index 0000000..8ea6293
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleOilLevel.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleOilLevel {
+ /**
+ * Oil level values
+ */
+ CRITICALLY_LOW = 0,
+ LOW = 1,
+ NORMAL = 2,
+ HIGH = 3,
+ ERROR = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
new file mode 100644
index 0000000..3b4e10a
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropConfig.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehicleAreaConfig;
+import android.hardware.automotive.vehicle.VehiclePropertyAccess;
+import android.hardware.automotive.vehicle.VehiclePropertyChangeMode;
+
+// @VintfStability
+parcelable VehiclePropConfig {
+ /** Property identifier */
+ int prop;
+
+ /**
+ * Defines if the property is read or write or both.
+ */
+ VehiclePropertyAccess access = VehiclePropertyAccess.NONE;
+
+ /**
+ * Defines the change mode of the property.
+ */
+ VehiclePropertyChangeMode changeMode = VehiclePropertyChangeMode.STATIC;
+
+ /**
+ * Contains per-area configuration.
+ */
+ VehicleAreaConfig[] areaConfigs;
+
+ /** Contains additional configuration parameters */
+ int[] configArray;
+
+ /**
+ * Some properties may require additional information passed over this
+ * string. Most properties do not need to set this.
+ */
+ @utf8InCpp String configString;
+
+ /**
+ * Min sample rate in Hz.
+ * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+ */
+ float minSampleRate;
+
+ /**
+ * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+ * Max sample rate in Hz.
+ */
+ float maxSampleRate;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl
new file mode 100644
index 0000000..4d403f9
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValue.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropertyStatus;
+
+/**
+ * Encapsulates the property name and the associated value. It
+ * is used across various API calls to set values, get values or to register for
+ * events.
+ */
+// @VintfStability
+parcelable VehiclePropValue {
+ /** Time is elapsed nanoseconds since boot */
+ long timestamp;
+
+ /**
+ * Area type(s) for non-global property it must be one of the value from
+ * VehicleArea* enums or 0 for global properties.
+ */
+ int areaId;
+
+ /** Property identifier */
+ int prop;
+
+ /** Status of the property */
+ VehiclePropertyStatus status;
+
+ /**
+ * This is used for properties of types VehiclePropertyType#INT
+ * and VehiclePropertyType#INT_VEC
+ */
+ int[] int32Values;
+
+ /**
+ * This is used for properties of types VehiclePropertyType#FLOAT
+ * and VehiclePropertyType#FLOAT_VEC
+ */
+ float[] floatValues;
+
+ /** This is used for properties of type VehiclePropertyType#INT64 */
+ long[] int64Values;
+
+ /** This is used for properties of type VehiclePropertyType#BYTES */
+ byte[] byteValues;
+
+ /** This is used for properties of type VehiclePropertyType#STRING */
+ @utf8InCpp String stringValue;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValueRawValue.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValueRawValue.aidl
new file mode 100644
index 0000000..325b7f0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropValueRawValue.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Contains value for a single property. Depending on property data type of
+ * this property (VehiclePropetyType) one field of this structure must be filled in.
+ */
+// @VintfStability
+parcelable VehiclePropValueRawValue {
+ /**
+ * This is used for properties of types VehiclePropertyType#INT
+ * and VehiclePropertyType#INT_VEC
+ */
+ int[] int32Values;
+ /**
+ * This is used for properties of types VehiclePropertyType#FLOAT
+ * and VehiclePropertyType#FLOAT_VEC
+ */
+ float[] floatValues;
+ /**
+ * This is used for properties of type VehiclePropertyType#INT64
+ */
+ long[] int64Values;
+ /**
+ * This is used for properties of type VehiclePropertyType#BYTES
+ */
+ byte[] bytes;
+ /**
+ * This is used for properties of type VehiclePropertyType#STRING
+ */
+ @utf8InCpp String stringValue;
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
new file mode 100644
index 0000000..a3a4b3d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -0,0 +1,2587 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VehiclePropertyType;
+/**
+ * Declares all vehicle properties. VehicleProperty has a bitwise structure.
+ * Each property must have:
+ * - a unique id from range 0x0100 - 0xffff
+ * - associated data type using VehiclePropertyType
+ * - property group (VehiclePropertyGroup)
+ * - vehicle area (VehicleArea)
+ *
+ * Vendors are allowed to extend this enum with their own properties. In this
+ * case they must use VehiclePropertyGroup:VENDOR flag when the property is
+ * declared.
+ *
+ * When a property's status field is not set to AVAILABLE:
+ * - IVehicle#set may return StatusCode::NOT_AVAILABLE.
+ * - IVehicle#get is not guaranteed to work.
+ *
+ * Properties set to values out of range must be ignored and no action taken
+ * in response to such ill formed requests.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleProperty {
+ /**
+ * Undefined property.
+ */
+ INVALID = 0x00000000,
+ /**
+ * VIN of vehicle
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_VIN = 0x0100 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Manufacturer of vehicle
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_MAKE = 0x0101 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Model of vehicle
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_MODEL = 0x0102 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Model year of vehicle.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:YEAR
+ */
+ INFO_MODEL_YEAR = 0x0103 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Fuel capacity of the vehicle in milliliters
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:MILLILITER
+ */
+ INFO_FUEL_CAPACITY = 0x0104 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * List of fuels the vehicle may use
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @data_enum FuelType
+ */
+ INFO_FUEL_TYPE = 0x0105 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Battery capacity of the vehicle, if EV or hybrid. This is the nominal
+ * battery capacity when the vehicle is new.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:WH
+ */
+ INFO_EV_BATTERY_CAPACITY = 0x0106 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * List of connectors this EV may use
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @data_enum EvConnectorType
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_EV_CONNECTOR_TYPE = 0x0107 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Fuel door location
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @data_enum PortLocationType
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_FUEL_DOOR_LOCATION = 0x0108 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * EV port location
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @data_enum PortLocationType
+ */
+ INFO_EV_PORT_LOCATION = 0x0109 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Driver's seat location
+ * VHAL implementations must ignore the areaId. Use VehicleArea:GLOBAL.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @data_enum VehicleAreaSeat
+ * @access VehiclePropertyAccess:READ
+ */
+ INFO_DRIVER_SEAT = 0x010A + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Exterior dimensions of vehicle.
+ *
+ * int32Values[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 radius
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:MILLIMETER
+ */
+ INFO_EXTERIOR_DIMENSIONS = 0x010B + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Multiple EV port locations
+ *
+ * Implement 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[0] = PortLocationType::REAR_LEFT
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @data_enum PortLocationType
+ */
+ INFO_MULTI_EV_PORT_LOCATIONS = 0x010C + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Current odometer value of the vehicle
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:KILOMETER
+ */
+ PERF_ODOMETER = 0x0204 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Speed of the vehicle
+ *
+ * The 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:METER_PER_SEC
+ */
+ PERF_VEHICLE_SPEED = 0x0207 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Speed of the vehicle for displays
+ *
+ * Some cars display a slightly slower speed than the actual speed. This is
+ * usually displayed on the speedometer.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:METER_PER_SEC
+ */
+ PERF_VEHICLE_SPEED_DISPLAY = 0x0208 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Front bicycle model steering angle for vehicle
+ *
+ * Angle is in degrees. Left is negative.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:DEGREES
+ */
+ PERF_STEERING_ANGLE = 0x0209 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Rear bicycle model steering angle for vehicle
+ *
+ * Angle is in degrees. Left is negative.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:DEGREES
+ */
+ PERF_REAR_STEERING_ANGLE = 0x0210 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Temperature of engine coolant
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:CELSIUS
+ */
+ ENGINE_COOLANT_TEMP = 0x0301 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Engine oil level
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleOilLevel
+ */
+ ENGINE_OIL_LEVEL = 0x0303 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Temperature of engine oil
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:CELSIUS
+ */
+ ENGINE_OIL_TEMP = 0x0304 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Engine rpm
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:RPM
+ */
+ ENGINE_RPM = 0x0305 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Reports wheel ticks
+ *
+ * The 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.
+ *
+ * The 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.
+ *
+ * int64Values[0] = reset count
+ * int64Values[1] = front left ticks
+ * int64Values[2] = front right ticks
+ * int64Values[3] = rear right ticks
+ * int64Values[4] = rear left ticks
+ *
+ * configArray is used to indicate the micrometers-per-wheel-tick value and
+ * which wheels are supported. configArray is set as follows:
+ *
+ * configArray[0], bits [0:3] = supported wheels. Uses enum Wheel.
+ * 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
+ *
+ * NOTE: If a wheel is not supported, its value shall always be set to 0.
+ *
+ * VehiclePropValue.timestamp must be correctly filled in.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ */
+ WHEEL_TICK = 0x0306 + 0x10000000 + 0x01000000
+ + 0x00510000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64_VEC
+ /**
+ * Fuel remaining in the vehicle, in milliliters
+ *
+ * Value may not exceed INFO_FUEL_CAPACITY
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:MILLILITER
+ */
+ FUEL_LEVEL = 0x0307 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Fuel door open
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ FUEL_DOOR_OPEN = 0x0308 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * EV battery level in WH, if EV or hybrid
+ *
+ * Value may not exceed INFO_EV_BATTERY_CAPACITY
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:WH
+ */
+ EV_BATTERY_LEVEL = 0x0309 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * EV charge port open
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ EV_CHARGE_PORT_OPEN = 0x030A + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * EV charge port connected
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ EV_CHARGE_PORT_CONNECTED = 0x030B + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * EV instantaneous charge rate in milliwatts
+ *
+ * Positive value indicates battery is being charged.
+ * Negative value indicates battery being discharged.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:MW
+ */
+ EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = 0x030C + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Range remaining
+ *
+ * Meters 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @unit VehicleUnit:METER
+ */
+ RANGE_REMAINING = 0x0308 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Tire pressure
+ *
+ * Each tires is identified by its areaConfig.areaId config and their
+ * minFloatValue/maxFloatValue are used to store OEM recommended pressure
+ * range.
+ * The Min value in the areaConfig data represents the lower bound of
+ * the recommended tire pressure.
+ * The Max value 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,
+ * }
+ * },
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:KILOPASCAL
+ */
+ TIRE_PRESSURE = 0x0309 + 0x10000000 + 0x07000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
+ /**
+ * Critically low tire pressure
+ *
+ * This 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:KILOPASCAL
+ */
+ CRITICALLY_LOW_TIRE_PRESSURE = 0x030A + 0x10000000 + 0x07000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WHEEL,VehiclePropertyType:FLOAT
+ /**
+ * Currently selected gear
+ *
+ * This is the gear selected by the user.
+ *
+ * Values in the config data must represent the list of supported gears
+ * for this vehicle. For example, config data for an automatic transmission
+ * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_DRIVE,
+ * GEAR_1, GEAR_2,...} and for manual transmission the list must be
+ * {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_1, GEAR_2,...}
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleGear
+ */
+ GEAR_SELECTION = 0x0400 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * 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.
+ *
+ * Values in the config data must represent the list of supported gears
+ * for this vehicle. For example, config data for an automatic transmission
+ * must contain {GEAR_NEUTRAL, GEAR_REVERSE, GEAR_PARK, GEAR_1, GEAR_2,...}
+ * and for manual transmission the list must be
+ * {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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleGear
+ */
+ CURRENT_GEAR = 0x0401 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Parking brake state.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ PARKING_BRAKE_ON = 0x0402 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Auto-apply parking brake.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ PARKING_BRAKE_AUTO_APPLY = 0x0403 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Warning for fuel low level.
+ *
+ * This 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:
+ *
+ * For 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ FUEL_LEVEL_LOW = 0x0405 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Night mode
+ *
+ * True 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ NIGHT_MODE = 0x0407 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * State of the vehicles turn signals
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleTurnSignal
+ */
+ TURN_SIGNAL_STATE = 0x0408 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Represents ignition state
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleIgnitionState
+ */
+ IGNITION_STATE = 0x0409 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * ABS is active
+ *
+ * Set 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ ABS_ACTIVE = 0x040A + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Traction Control is active
+ *
+ * Set 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ TRACTION_CONTROL_ACTIVE = 0x040B + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /*
+ * HVAC Properties
+ *
+ * Additional rules for mapping a zoned HVAC property (except
+ * HVAC_MAX_DEFROST_ON) to AreaIDs:
+ * - Every seat in VehicleAreaSeat that is available in the car, must be
+ * part of an AreaID in the AreaID array.
+ *
+ * Example 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). There are two
+ * temperature control units -- driver side and passenger side.
+ * - A valid mapping set of AreaIDs for HVAC_TEMPERATURE_SET would be a
+ * two element array:
+ * - ROW_1_LEFT | ROW_2_LEFT
+ * - ROW_1_RIGHT | ROW_2_CENTER | ROW_2_RIGHT
+ * - An alternative mapping for the same hardware configuration would be:
+ * - ROW_1_LEFT | ROW_2_CENTER | ROW_2_LEFT
+ * - ROW_1_RIGHT | ROW_2_RIGHT
+ * The temperature controllers are assigned to the seats which they
+ * "most influence", but every seat must be included exactly once. The
+ * assignment of the center rear seat to the left or right AreaID may seem
+ * arbitrary, but the inclusion of every seat in exactly one AreaID ensures
+ * that the seats in the car are all expressed and that a "reasonable" way
+ * to affect each seat is available.
+ *
+ * Example 2: A car has three seat rows with 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). There
+ * are three temperature control units -- driver side, passenger side, and rear.
+ * - A reasonable way to map HVAC_TEMPERATURE_SET to AreaIDs is a three
+ * 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
+ *
+ *
+ * Fan speed setting
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_FAN_SPEED = 0x0500 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Fan direction setting
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleHvacFanDirection
+ */
+ HVAC_FAN_DIRECTION = 0x0501 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * HVAC current temperature.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:CELSIUS
+ */
+ HVAC_TEMPERATURE_CURRENT = 0x0502 + 0x10000000 + 0x05000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
+ /**
+ * HVAC, target temperature set.
+ *
+ * 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 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.
+ * 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}.
+ *
+ * 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @unit VehicleUnit:CELSIUS
+ */
+ HVAC_TEMPERATURE_SET = 0x0503 + 0x10000000 + 0x05000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:FLOAT
+ /**
+ * Fan-based defrost for designated window.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_DEFROSTER = 0x0504 + 0x10000000 + 0x03000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+ /**
+ * On/off AC for designated areaId
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @config_flags Supported areaIds
+ */
+ HVAC_AC_ON = 0x0505 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * On/off max AC
+ *
+ * When 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_MAX_AC_ON = 0x0506 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * On/off max defrost
+ *
+ * When 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_MAX_DEFROST_ON = 0x0507 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Recirculation on/off
+ *
+ * Controls 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_RECIRC_ON = 0x0508 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Enable temperature coupling between areas.
+ *
+ * The 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].
+ *
+ * Example: 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]
+ *
+ * When 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).
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_DUAL_ON = 0x0509 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * On/off automatic mode
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_AUTO_ON = 0x050A + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Seat heating/cooling
+ *
+ * Negative values indicate cooling.
+ * 0 indicates off.
+ * Positive values indicate heating.
+ *
+ * Some vehicles may have multiple levels of heating and cooling. The
+ * min/max range defines the allowable range and number of steps in each
+ * direction.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_SEAT_TEMPERATURE = 0x050B + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Side Mirror Heat
+ *
+ * Increasing values denote higher heating levels for side mirrors.
+ * The Max value in the config data represents the highest heating level.
+ * The Min value in the config data MUST be zero and indicates no heating.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_SIDE_MIRROR_HEAT = 0x050C + 0x10000000 + 0x04000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+ /**
+ * Steering Wheel Heating/Cooling
+ *
+ * Sets the amount of heating/cooling for the steering wheel
+ * config data Min and Max MUST be set appropriately.
+ * Positive value indicates heating.
+ * Negative value indicates cooling.
+ * 0 indicates temperature control is off.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_STEERING_WHEEL_HEAT = 0x050D + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Temperature units for display
+ *
+ * Indicates whether the vehicle is displaying temperature to the user as
+ * Celsius or Fahrenheit.
+ * VehiclePropConfig.configArray is used to indicate the supported temperature display units.
+ * For example: configArray[0] = CELSIUS
+ * configArray[1] = FAHRENHEIT
+ *
+ * This parameter MAY be used for displaying any HVAC temperature in the system.
+ * Values must be one of VehicleUnit::CELSIUS or VehicleUnit::FAHRENHEIT
+ * Note that internally, all temperatures are represented in floating point Celsius.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ HVAC_TEMPERATURE_DISPLAY_UNITS = 0x050E + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Actual fan speed
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ HVAC_ACTUAL_FAN_SPEED_RPM = 0x050F + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * 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).
+ *
+ * [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.
+ *
+ * HvacPower_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.
+ *
+ * AreaID mapping for HVAC_POWER_ON property must contain all AreaIDs that
+ * HvacPower_DependentProperties are mapped to.
+ *
+ * Example 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].
+ *
+ * Example 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
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_POWER_ON = 0x0510 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Fan Positions Available
+ *
+ * This 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)
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleHvacFanDirection
+ */
+ HVAC_FAN_DIRECTION_AVAILABLE = 0x0511 + 0x10000000 + 0x05000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32_VEC
+ /**
+ * Automatic recirculation on/off
+ *
+ * When automatic recirculation is ON, the HVAC system may automatically
+ * switch to recirculation mode if the vehicle detects poor incoming air
+ * quality.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_AUTO_RECIRC_ON = 0x0512 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Seat ventilation
+ *
+ * 0 indicates off.
+ * Positive values indicates ventilation level.
+ *
+ * Used 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_SEAT_VENTILATION = 0x0513 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Electric defrosters' status
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_ELECTRIC_DEFROSTER_ON = 0x0514 + 0x10000000 + 0x03000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+ /**
+ * Suggested values for setting HVAC temperature.
+ *
+ * Implement the property to help applications understand the closest supported temperature
+ * value in Celsius or Fahrenheit.
+ *
+ * floatValues[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.
+ *
+ * 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.
+ *
+ * For 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.
+ *
+ * Another 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ HVAC_TEMPERATURE_VALUE_SUGGESTION = 0x0515 + 0x10000000 + 0x01000000
+ + 0x00610000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT_VEC
+ /**
+ * Distance units for display
+ *
+ * Indicates which units the car is using to display distances to the user. Eg. Mile, Meter
+ * Kilometer.
+ *
+ * Distance 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
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ DISTANCE_DISPLAY_UNITS = 0x0600 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Fuel volume units for display
+ *
+ * Indicates which units the car is using to display fuel volume to the user. Eg. Liter or
+ * Gallon.
+ *
+ * VehiclePropConfig.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
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ FUEL_VOLUME_DISPLAY_UNITS = 0x0601 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Tire pressure units for display
+ *
+ * Indicates which units the car is using to display tire pressure to the user. Eg. PSI, Bar or
+ * Kilopascal.
+ *
+ * VehiclePropConfig.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
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ TIRE_PRESSURE_DISPLAY_UNITS = 0x0602 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * EV battery units for display
+ *
+ * Indicates 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).
+ *
+ * VehiclePropConfig.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
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleUnit
+ */
+ EV_BATTERY_DISPLAY_UNITS = 0x0603 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Fuel consumption units for display
+ *
+ * Indicates 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 0x0604 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Speed units for display
+ *
+ * Indicates type of units the car is using to display speed to user. Eg. m/s, km/h, or mph.
+ *
+ * VehiclePropConfig.configArray is used to indicate the supported speed display units.
+ * Pressure units are defined in VehicleUnit.
+ * For example: configArray[0] = METER_PER_SEC
+ * configArray[1] = MILES_PER_HOUR
+ * configArray[2] = KILOMETERS_PER_HOUR
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Current date and time, encoded as Unix time (in milliseconds).
+ * This value denotes the number of milliseconds seconds that have
+ * elapsed since 1/1/1970 UTC.
+ *
+ * Reading this value will give you the system’s time. This can be
+ * useful to synchronize other vehicle systems (dash clock etc).
+ *
+ * Writing this value will update the ‘ExternalTimeSuggestion’
+ * value (if enabled). This value may be consumed by the “Time
+ * Detector Service”, if other sources do not have a higher
+ * priority. For information on how to adjust time source
+ * priorities see Time Detector Service documentation.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @unit VehicleUnit:MILLI_SECS
+ */
+ EPOCH_TIME = 0x0606 + 0x10000000 + 0x01000000
+ + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+ /**
+ * External encryption binding seed.
+ *
+ * This 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ STORAGE_ENCRYPTION_BINDING_SEED = 0x0607 + 0x10000000 + 0x01000000
+ + 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
+ /**
+ * Outside temperature
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:CELSIUS
+ */
+ ENV_OUTSIDE_TEMPERATURE = 0x0703 + 0x10000000 + 0x01000000
+ + 0x00600000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:FLOAT
+ /**
+ * Property to control power state of application processor
+ *
+ * It is assumed that AP's power state is controlled by a separate power
+ * controller.
+ *
+ * For configuration information, VehiclePropConfig.configArray can have bit flag combining
+ * values in VehicleApPowerStateConfigFlag.
+ *
+ * int32Values[0] : VehicleApPowerStateReq enum value
+ * int32Values[1] : additional parameter relevant for each state,
+ * 0 if not used.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ AP_POWER_STATE_REQ = 0x0A00 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Property to report power state of application processor
+ *
+ * It is assumed that AP's power state is controller by separate power
+ * controller.
+ *
+ * int32Values[0] : VehicleApPowerStateReport enum value
+ * int32Values[1] : Time in ms to wake up, if necessary. Otherwise 0.
+
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ AP_POWER_STATE_REPORT = 0x0A01 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * 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.
+ *
+ * int32Values[0] must be VehicleApPowerBootupReason.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ AP_POWER_BOOTUP_REASON = 0x0A02 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Property to represent brightness of the display. Some cars have single
+ * control for the brightness of all displays and this property is to share
+ * change in that control.
+ *
+ * If 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ DISPLAY_BRIGHTNESS = 0x0A03 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Property to feed H/W input events to android
+ *
+ * int32Values[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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @config_flags
+ */
+ HW_KEY_INPUT = 0x0A10 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Property to feed H/W rotary events to android
+ *
+ * int32Values[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
+ *
+ * VehiclePropValue.timestamp: when the rotation occurred. If the number of
+ * detents is > 1 or < -1, this is when the
+ * first detent of rotation occurred.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @data_enum RotaryInputType
+ * @access VehiclePropertyAccess:READ
+ */
+ HW_ROTARY_INPUT = 0x0A20 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Defines a custom OEM partner input event.
+ *
+ * This 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.
+ *
+ * The Android properties are:
+ *
+ * int32Values[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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @data_enum CustomInputType
+ * @access VehiclePropertyAccess:READ
+ */
+ HW_CUSTOM_INPUT = 0X0A30 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /***************************************************************************
+ * Most Car Cabin properties have both a POSition and MOVE parameter. These
+ * are used to control the various movements for seats, doors, and windows
+ * in a vehicle.
+ *
+ * A POS parameter allows the user to set the absolution position. For
+ * instance, for a door, 0 indicates fully closed and max value indicates
+ * fully open. Thus, a value halfway between min and max must indicate
+ * the door is halfway open.
+ *
+ * A MOVE parameter moves the device in a particular direction. The sign
+ * indicates direction, and the magnitude indicates speed (if multiple
+ * speeds are available). For a door, a move of -1 will close the door, and
+ * a move of +1 will open it. Once a door reaches the limit of open/close,
+ * the door should automatically stop moving. The user must NOT need to
+ * send a MOVE(0) command to stop the door at the end of its range.
+ **************************************************************************/
+
+ /**
+ * Door position
+ *
+ * This is an integer in case a door may be set to a particular position.
+ * Max value indicates fully open, min value (0) indicates fully closed.
+ *
+ * Some vehicles (minivans) can open the door electronically. Hence, the
+ * ability to write this property.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ DOOR_POS = 0x0B00 + 0x10000000 + 0x06000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
+ /**
+ * Door move
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ DOOR_MOVE = 0x0B01 + 0x10000000 + 0x06000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:INT32
+ /**
+ * Door lock
+ *
+ * 'true' indicates door is locked
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ DOOR_LOCK = 0x0B02 + 0x10000000 + 0x06000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:BOOLEAN
+ /**
+ * Mirror Z Position
+ *
+ * Positive value indicates tilt upwards, negative value is downwards
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_Z_POS = 0x0B40 + 0x10000000 + 0x04000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+ /**
+ * Mirror Z Move
+ *
+ * Positive value indicates tilt upwards, negative value is downwards
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_Z_MOVE = 0x0B41 + 0x10000000 + 0x04000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+ /**
+ * Mirror Y Position
+ *
+ * Positive value indicate tilt right, negative value is left
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_Y_POS = 0x0B42 + 0x10000000 + 0x04000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+ /**
+ * Mirror Y Move
+ *
+ * Positive value indicate tilt right, negative value is left
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_Y_MOVE = 0x0B43 + 0x10000000 + 0x04000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:MIRROR,VehiclePropertyType:INT32
+ /**
+ * Mirror Lock
+ *
+ * True indicates mirror positions are locked and not changeable
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_LOCK = 0x0B44 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Mirror Fold
+ *
+ * True indicates mirrors are folded
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ MIRROR_FOLD = 0x0B45 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Seat memory select
+ *
+ * This parameter selects the memory preset to use to select the seat
+ * position. The minValue is always 0, and the maxValue determines the
+ * number of seat positions available.
+ *
+ * For instance, if the driver's seat has 3 memory presets, the maxValue
+ * will be 3. When the user wants to select a preset, the desired preset
+ * number (1, 2, or 3) is set.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ SEAT_MEMORY_SELECT = 0x0B80 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat memory set
+ *
+ * This setting allows the user to save the current seat position settings
+ * into the selected preset slot. The maxValue for each seat position
+ * must match the maxValue for SEAT_MEMORY_SELECT.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ SEAT_MEMORY_SET = 0x0B81 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seatbelt buckled
+ *
+ * True indicates belt is buckled.
+ *
+ * Write access indicates automatic seat buckling capabilities. There are
+ * no known cars at this time, but you never know...
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BELT_BUCKLED = 0x0B82 + 0x10000000 + 0x05000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:BOOLEAN
+ /**
+ * Seatbelt height position
+ *
+ * Adjusts the shoulder belt anchor point.
+ * Max value indicates highest position
+ * Min value indicates lowest position
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BELT_HEIGHT_POS = 0x0B83 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seatbelt height move
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BELT_HEIGHT_MOVE = 0x0B84 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat fore/aft position
+ *
+ * Sets the seat position forward (closer to steering wheel) and backwards.
+ * Max value indicates closest to wheel, min value indicates most rearward
+ * position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_FORE_AFT_POS = 0x0B85 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat fore/aft move
+ *
+ * Moves the seat position forward and aft.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_FORE_AFT_MOVE = 0x0B86 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat backrest angle 1 position
+ *
+ * Backrest angle 1 is the actuator closest to the bottom of the seat.
+ * Max value indicates angling forward towards the steering wheel.
+ * Min value indicates full recline.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BACKREST_ANGLE_1_POS = 0x0B87 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat backrest angle 1 move
+ *
+ * Moves the backrest forward or recline.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BACKREST_ANGLE_1_MOVE = 0x0B88 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat backrest angle 2 position
+ *
+ * Backrest angle 2 is the next actuator up from the bottom of the seat.
+ * Max value indicates angling forward towards the steering wheel.
+ * Min value indicates full recline.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BACKREST_ANGLE_2_POS = 0x0B89 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat backrest angle 2 move
+ *
+ * Moves the backrest forward or recline.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_BACKREST_ANGLE_2_MOVE = 0x0B8A + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat height position
+ *
+ * Sets the seat height.
+ * Max value indicates highest position.
+ * Min value indicates lowest position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEIGHT_POS = 0x0B8B + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat height move
+ *
+ * Moves the seat height.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEIGHT_MOVE = 0x0B8C + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat depth position
+ *
+ * Sets the seat depth, distance from back rest to front edge of seat.
+ * Max value indicates longest depth position.
+ * Min value indicates shortest position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_DEPTH_POS = 0x0B8D + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat depth move
+ *
+ * Adjusts the seat depth.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_DEPTH_MOVE = 0x0B8E + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat tilt position
+ *
+ * Sets the seat tilt.
+ * Max value indicates front edge of seat higher than back edge.
+ * Min value indicates front edge of seat lower than back edge.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_TILT_POS = 0x0B8F + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat tilt move
+ *
+ * Tilts the seat.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_TILT_MOVE = 0x0B90 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Lumber fore/aft position
+ *
+ * Pushes the lumbar support forward and backwards
+ * Max value indicates most forward position.
+ * Min value indicates most rearward position.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_LUMBAR_FORE_AFT_POS = 0x0B91 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Lumbar fore/aft move
+ *
+ * Adjusts the lumbar support.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_LUMBAR_FORE_AFT_MOVE = 0x0B92 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Lumbar side support position
+ *
+ * Sets the amount of lateral lumbar support.
+ * Max value indicates widest lumbar setting (i.e. least support)
+ * Min value indicates thinnest lumbar setting.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_LUMBAR_SIDE_SUPPORT_POS = 0x0B93 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Lumbar side support move
+ *
+ * Adjusts the amount of lateral lumbar support.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Headrest height position
+ *
+ * Sets the headrest height.
+ * Max value indicates tallest setting.
+ * Min value indicates shortest setting.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_HEIGHT_POS = 0x0B95 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Headrest height move
+ *
+ * Moves the headrest up and down.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_HEIGHT_MOVE = 0x0B96 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Headrest angle position
+ *
+ * Sets the angle of the headrest.
+ * Max value indicates most upright angle.
+ * Min value indicates shallowest headrest angle.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_ANGLE_POS = 0x0B97 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Headrest angle move
+ *
+ * Adjusts the angle of the headrest
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_ANGLE_MOVE = 0x0B98 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Headrest fore/aft position
+ *
+ * Adjusts the headrest forwards and backwards.
+ * Max value indicates position closest to front of car.
+ * Min value indicates position closest to rear of car.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_FORE_AFT_POS = 0x0B99 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Headrest fore/aft move
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Seat Occupancy
+ *
+ * Indicates 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleSeatOccupancyState
+ */
+ SEAT_OCCUPANCY = 0x0BB0 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Window Position
+ *
+ * Min = window up / closed
+ * Max = window down / open
+ *
+ * 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
+ *
+ * Note that in this mode, 0 indicates the window is closed.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ WINDOW_POS = 0x0BC0 + 0x10000000 + 0x03000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
+ /**
+ * Window Move
+ *
+ * Max = Open the window as fast as possible
+ * Min = Close the window as fast as possible
+ * Magnitude denotes relative speed. I.e. +2 is faster than +1 in closing
+ * the window.
+ *
+ * For a window that may open out of plane (i.e. vent mode of sunroof) this
+ * parameter will work as follows:
+ *
+ * If sunroof is open:
+ * Max = open the sunroof further, automatically stop when fully open.
+ * Min = close the sunroof, automatically stop when sunroof is closed.
+ *
+ * If 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.
+ *
+ * If 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ WINDOW_MOVE = 0x0BC1 + 0x10000000 + 0x03000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
+ /**
+ * Window Lock
+ *
+ * True indicates windows are locked and can't be moved.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ WINDOW_LOCK = 0x0BC4 + 0x10000000 + 0x03000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
+ /**
+ * Vehicle Maps Service (VMS) message
+ *
+ * This property uses MIXED data to communicate vms messages.
+ *
+ * Its 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;
+ *
+ * IVehicle#get must always return StatusCode::NOT_AVAILABLE.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ VEHICLE_MAP_SERVICE = 0x0C00 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * OBD2 Live Sensor Data
+ *
+ * Reports a snapshot of the current (live) values of the OBD2 sensors available.
+ *
+ * The configArray is set as follows:
+ * configArray[0] = number of vendor-specific integer-valued sensors
+ * configArray[1] = number of vendor-specific float-valued sensors
+ *
+ * The 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);
+ *
+ * It 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,.
+ *
+ * bytes 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.
+ *
+ * For 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
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ OBD2_LIVE_FRAME = 0x0D00 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * OBD2 Freeze Frame Sensor Data
+ *
+ * Reports a snapshot of the value of the OBD2 sensors available at the time that a fault
+ * occurred and was detected.
+ *
+ * A configArray must be provided with the same meaning as defined for OBD2_LIVE_FRAME.
+ *
+ * The 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).
+ *
+ * A 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.
+ *
+ * Should 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ OBD2_FREEZE_FRAME = 0x0D01 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * OBD2 Freeze Frame Information
+ *
+ * This property describes the current freeze frames stored in vehicle
+ * memory and available for retrieval via OBD2_FREEZE_FRAME.
+ *
+ * The 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ OBD2_FREEZE_FRAME_INFO = 0x0D02 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * OBD2 Freeze Frame Clear
+ *
+ * This property allows deletion of any of the freeze frames stored in
+ * vehicle memory, as described by OBD2_FREEZE_FRAME_INFO.
+ *
+ * The configArray is set as follows:
+ * configArray[0] = 1 if the implementation is able to clear individual freeze frames
+ * by timestamp, 0 otherwise
+ *
+ * IVehicle#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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ OBD2_FREEZE_FRAME_CLEAR = 0x0D03 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Headlights State
+ *
+ * Return the current state of headlights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ HEADLIGHTS_STATE = 0x0E00 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * High beam lights state
+ *
+ * Return the current state of high beam lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ HIGH_BEAM_LIGHTS_STATE = 0x0E01 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Fog light state
+ *
+ * Return the current state of fog lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ FOG_LIGHTS_STATE = 0x0E02 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Hazard light status
+ *
+ * Return the current status of hazard lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ HAZARD_LIGHTS_STATE = 0x0E03 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Headlight switch
+ *
+ * The setting that the user wants.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ HEADLIGHTS_SWITCH = 0x0E10 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * High beam light switch
+ *
+ * The setting that the user wants.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ HIGH_BEAM_LIGHTS_SWITCH = 0x0E11 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Fog light switch
+ *
+ * The setting that the user wants.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ FOG_LIGHTS_SWITCH = 0x0E12 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Hazard light switch
+ *
+ * The setting that the user wants.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ HAZARD_LIGHTS_SWITCH = 0x0E13 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Cabin lights
+ *
+ * Return current status of cabin lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ CABIN_LIGHTS_STATE = 0x0F01 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Cabin lights switch
+ *
+ * The 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ CABIN_LIGHTS_SWITCH = 0x0F02 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Reading lights
+ *
+ * Return current status of reading lights.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum VehicleLightState
+ */
+ READING_LIGHTS_STATE = 0x0F03 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Reading lights switch
+ *
+ * The 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ READING_LIGHTS_SWITCH = 0x0F04 + 0x10000000 + 0x05000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
+ /**
+ * Support customize permissions for vendor properties
+ *
+ * Implement 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.
+ *
+ * For 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = 0x0F05 + 0x10000000 + 0x01000000
+ + 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+ /**
+ * Allow disabling optional featurs from vhal.
+ *
+ * This 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.
+ *
+ * Value read should include all features disabled with ',' separation.
+ * ex) "com.android.car.user.CarUserNoticeService,storage_monitoring"
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:READ
+ */
+ DISABLED_OPTIONAL_FEATURES = 0x0F06 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Defines the initial Android user to be used during initialization.
+ *
+ * This property is called by the Android system when it initializes and it lets the HAL
+ * define which Android user should be started.
+ *
+ * This 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.
+ *
+ * For example, on first boot, the request could be:
+ *
+ * int32[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)
+ *
+ * And if the HAL want to respond with the creation of an admin user called "Owner", the
+ * response would be:
+ *
+ * int32[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
+ *
+ * Notice 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.
+ *
+ * NOTE: 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).
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ INITIAL_USER_INFO = 0x0F07 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Defines a request to switch the foreground Android user.
+ *
+ * This 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
+ *
+ * When 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).
+ *
+ * The 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.
+ *
+ * 1.LEGACY_ANDROID_SWITCH
+ * -----------------------
+ *
+ * Called 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).
+ *
+ * The 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).
+ *
+ * For 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:
+ *
+ * int32[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)
+ *
+ * 2.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.
+ *
+ * The 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).
+ *
+ * For 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:
+ *
+ * int32[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)
+ *
+ * If the request succeeded, the HAL must update the property with:
+ *
+ * int32[0]: 42 // request id
+ * int32[1]: 3 // messageType = SwitchUserMessageType::VEHICLE_RESPONSE
+ * int32[2]: 1 // status = SwitchUserStatus::SUCCESS
+ *
+ * But if it failed, the response would be something like:
+ *
+ * int32[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
+ *
+ * 3.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.
+ *
+ * 4.VEHICLE_REQUEST
+ * ------------------
+ * Called by the HAL to request that the current foreground Android user is switched.
+ *
+ * This 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.
+ *
+ * The 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.
+ *
+ * For example, if the current foreground Android user is 10 and the HAL asked it to switch to
+ * 11, the request would be:
+ *
+ * int32[0]: -108 // request id
+ * int32[1]: 4 // messageType = SwitchUserMessageType::VEHICLE_REQUEST
+ * int32[2]: 11 // Android user id
+ *
+ * If the request succeeded and Android has 3 users (0, 10, 11), the response would be:
+ *
+ * int32[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)
+ *
+ * Notice 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).
+ *
+ * 5.ANDROID_POST_SWITCH
+ * ---------------------
+ * Called by the Android System after a request to switch a user was made.
+ *
+ * This 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:
+ *
+ * 1. 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.
+ *
+ * The HAL can update its internal state once it receives this request, but it doesn't need to
+ * reply back to the Android System.
+ *
+ * Request: 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).
+ *
+ * Response: none.
+ *
+ * Example: see VEHICLE_REQUEST section above.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ SWITCH_USER = 0x0F08 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Called by the Android System after an Android user was created.
+ *
+ * The HAL can use this property to create its equivalent user.
+ *
+ * This 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.
+ *
+ * The format of the request is defined by CreateUserRequest and the format of the response by
+ * CreateUserResponse.
+ *
+ * For example, if system had 2 users (0 and 10) and a 3rd one (which is an ephemeral guest) was
+ * created, the request would be:
+ *
+ * int32[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
+ *
+ * Then if the request succeeded, the HAL would return:
+ *
+ * int32[0]: 42 // request id
+ * int32[1]: 1 // CreateUserStatus::SUCCESS
+ *
+ * But if it failed:
+ *
+ * int32[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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ CREATE_USER = 0x0F09 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Called by the Android System after an Android user was removed.
+ *
+ * The HAL can use this property to remove its equivalent user.
+ *
+ * This 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.
+ *
+ * The request is made by setting the VehiclePropValue with the contents defined by
+ * RemoveUserRequest.
+ *
+ * For example, if system had 3 users (0, 10, and 11) and user 11 was removed, the request
+ * would be:
+ *
+ * int32[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)
+ *
+ * @change_mode VehiclePropertyChangeMode:STATIC
+ * @access VehiclePropertyAccess:WRITE
+ */
+ REMOVE_USER = 0x0F0A + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Property used to associate (or query the association) the current user with vehicle-specific
+ * identification mechanisms (such as key FOB).
+ *
+ * This 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.
+ *
+ * To 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.
+ *
+ * To 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.
+ *
+ * For 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:
+ *
+ * int32[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)
+ *
+ * If the user is associated with the FOB but not with the custom mechanism, the response would
+ * be:
+ *
+ * int32[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)
+ *
+ * Then to associate the user with the custom mechanism, a set request would be made:
+ *
+ * int32[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)
+ *
+ * If the request succeeded, the response would be simply:
+ *
+ * int32[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)
+ *
+ * Notice 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:
+ *
+ * int32[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)
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ USER_IDENTIFICATION_ASSOCIATION = 0x0F0B + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Enable/request an EVS service.
+ *
+ * The property provides a generalized way to trigger EVS services. VHAL
+ * should use this property to request Android to start or stop EVS service.
+ *
+ * int32Values[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.
+ *
+ * For example, to enable rear view EVS service, android side can set the property value as
+ * [EvsServiceType::REAR_VIEW, EvsServiceState::ON].
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ EVS_SERVICE_REQUEST = 0x0F10 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Defines a request to apply power policy.
+ *
+ * VHAL 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/power_policy.xml. If the given ID is not defined, car power policy
+ * service ignores the request and the current power policy is maintained.
+ *
+ * string: "sample_policy_id" // power policy ID
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ POWER_POLICY_REQ = 0x0F21 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Defines a request to set the power polic group used to decide a default power policy per
+ * power status transition.
+ *
+ * VHAL 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.
+ *
+ * string: "sample_policy_group_id" // power policy group ID
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ POWER_POLICY_GROUP_REQ = 0x0F22 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Notifies the current power policy to VHAL layer.
+ *
+ * Car power policy service sets this property when the current power policy is changed.
+ *
+ * string: "sample_policy_id" // power policy ID
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ_WRITE
+ */
+ CURRENT_POWER_POLICY = 0x0F23 + 0x10000000 + 0x01000000
+ + 0x00100000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:STRING
+ /**
+ * Defines an event that car watchdog updates to tell it's alive.
+ *
+ * Car watchdog sets this property to system uptime in milliseconds at every 3 second.
+ * During the boot, the update may take longer time.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ WATCHDOG_ALIVE = 0xF31 + 0x10000000 + 0x01000000
+ + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+ /**
+ * Defines a process terminated by car watchdog and the reason of termination.
+ *
+ * int32Values[0]: 1 // ProcessTerminationReason showing why a process is terminated.
+ * string: "/system/bin/log" // Process execution command.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ WATCHDOG_TERMINATED_PROCESS = 0x0F32 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Defines an event that VHAL signals to car watchdog as a heartbeat.
+ *
+ * If 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ VHAL_HEARTBEAT = 0x0F33 + 0x10000000 + 0x01000000
+ + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
+ /**
+ * Starts the ClusterUI in cluster display.
+ *
+ * int32: 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ CLUSTER_SWITCH_UI = 0x0F34 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Changes the state of the cluster display.
+ *
+ * Bounds: the area to render the cluster Activity.
+ * Inset: the area which Activity should avoid from placing any important
+ * information.
+ *
+ * int32[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'
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ */
+ CLUSTER_DISPLAY_STATE = 0x0F35 + 0x10000000 + 0x01000000
+ + 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ /**
+ * Reports the current display state and ClusterUI state.
+ *
+ * ClusterHome will send this message when it handles CLUSTER_SWITCH_UI, CLUSTER_DISPLAY_STATE.
+ *
+ * In 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.
+ *
+ * int32[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].
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ CLUSTER_REPORT_STATE = 0x0F36 + 0x10000000 + 0x01000000
+ + 0x00e00000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:MIXED
+ /**
+ * Requests to change the cluster display state to show some ClusterUI.
+ *
+ * When 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.
+ *
+ * int32: the type of ClusterUI to show
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ CLUSTER_REQUEST_DISPLAY = 0x0F37 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Informs the current navigation state.
+ *
+ * bytes: the serialized message of NavigationStateProto.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:WRITE
+ */
+ CLUSTER_NAVIGATION_STATE = 0x0F38 + 0x10000000 + 0x01000000
+ + 0x00700000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BYTES
+ /**
+ * Electronic Toll Collection card type.
+ *
+ * This 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum ElectronicTollCollectionCardType
+ */
+ ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = 0x0F39 + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+ /**
+ * Electronic Toll Collection card status.
+ *
+ * This 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.
+ *
+ * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+ * @access VehiclePropertyAccess:READ
+ * @data_enum ElectronicTollCollectionCardStatus
+ */
+ ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = 0x0F3A + 0x10000000 + 0x01000000
+ + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
new file mode 100644
index 0000000..055f96f
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyAccess.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Property config defines the capabilities of it. User of the API
+ * must first get the property config to understand the output from get()
+ * commands and also to ensure that set() or events commands are in sync with
+ * the expected output.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehiclePropertyAccess {
+ NONE = 0x00,
+
+ READ = 0x01,
+ WRITE = 0x02,
+ READ_WRITE = 0x03,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
new file mode 100644
index 0000000..2628730
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyChangeMode.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This describes how value of property can change.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehiclePropertyChangeMode {
+ /**
+ * Property of this type must never be changed. Subscription is not supported
+ * for these properties.
+ */
+ STATIC = 0x00,
+
+ /**
+ * Properties of this type must report when there is a change.
+ * IVehicle#get call must return the current value.
+ * Set operation for this property is assumed to be asynchronous. When the
+ * property is read (using IVehicle#get) after IVehicle#set, it may still
+ * return old value until underlying H/W backing this property has actually
+ * changed the state. Once state is changed, the property must dispatch
+ * changed value as event.
+ */
+ ON_CHANGE = 0x01,
+
+ /**
+ * Properties of this type change continuously and require a fixed rate of
+ * sampling to retrieve the data. Implementers may choose to send extra
+ * notifications on significant value changes.
+ */
+ CONTINUOUS = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
new file mode 100644
index 0000000..529a46d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyGroup.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehiclePropertyGroup {
+ /**
+ * Properties declared in AOSP must use this flag.
+ */
+ SYSTEM = 0x10000000,
+
+ /**
+ * Properties declared by vendors must use this flag.
+ */
+ VENDOR = 0x20000000,
+
+ MASK = 0xf0000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
new file mode 100644
index 0000000..6dea0d1
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Property status is a dynamic value that may change based on the vehicle state.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehiclePropertyStatus {
+ /** Property is available and behaving normally */
+ AVAILABLE = 0x00,
+ /**
+ * A property in this state is not available for reading and writing. This
+ * is a transient state that depends on the availability of the underlying
+ * implementation (e.g. hardware or driver). It MUST NOT be used to
+ * represent features that this vehicle is always incapable of. A get() of
+ * a property in this state MAY return an undefined value, but MUST
+ * correctly describe its status as UNAVAILABLE A set() of a property in
+ * this state MAY return NOT_AVAILABLE. The HAL implementation MUST ignore
+ * the value of the status field when writing a property value coming from
+ * Android.
+ */
+ UNAVAILABLE = 0x01,
+ /** There is an error with this property. */
+ ERROR = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
new file mode 100644
index 0000000..4591e92
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehiclePropertyType.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Enumerates supported data type for VehicleProperty.
+ *
+ * Used to create property ID in VehicleProperty enum.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehiclePropertyType {
+ STRING = 0x00100000,
+ BOOLEAN = 0x00200000,
+ INT32 = 0x00400000,
+ INT32_VEC = 0x00410000,
+ INT64 = 0x00500000,
+ INT64_VEC = 0x00510000,
+ FLOAT = 0x00600000,
+ FLOAT_VEC = 0x00610000,
+ BYTES = 0x00700000,
+
+ /**
+ * Any combination of scalar or vector types. The exact format must be
+ * provided in the description of the property.
+ *
+ * For vendor MIXED type properties, configArray needs to be formatted in this
+ * structure.
+ * configArray[0], 1 indicates the property has a String value
+ * configArray[1], 1 indicates the property has a Boolean value .
+ * configArray[2], 1 indicates the property has an Integer value.
+ * configArray[3], the number indicates the size of Integer[] in the property.
+ * configArray[4], 1 indicates the property has a Long value.
+ * configArray[5], the number indicates the size of Long[] in the property.
+ * configArray[6], 1 indicates the property has a Float value.
+ * configArray[7], the number indicates the size of Float[] in the property.
+ * configArray[8], the number indicates the size of byte[] in the property.
+ * For example:
+ * {@code configArray = {1, 1, 1, 3, 0, 0, 0, 0, 0}} indicates the property has
+ * a String value, a Boolean value, an Integer value and an array with 3 integers.
+ */
+ MIXED = 0x00e00000,
+
+ MASK = 0x00ff0000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
new file mode 100644
index 0000000..a17c9f0
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleSeatOccupancyState.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by seat occupancy to enumerate the current occupancy state of the seat.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleSeatOccupancyState {
+ UNKNOWN = 0,
+ VACANT = 1,
+ OCCUPIED = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
new file mode 100644
index 0000000..cec86db
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleTurnSignal.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+// @VintfStability
+@Backing(type="int")
+enum VehicleTurnSignal {
+ NONE = 0x00,
+ RIGHT = 0x01,
+ LEFT = 0x02,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.aidl
new file mode 100644
index 0000000..3fc69de
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleUnit.aidl
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Units used for int or float type with no attached enum types.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleUnit {
+ SHOULD_NOT_USE = 0x000,
+ METER_PER_SEC = 0x01,
+ RPM = 0x02,
+ HERTZ = 0x03,
+ PERCENTILE = 0x10,
+ MILLIMETER = 0x20,
+ METER = 0x21,
+ KILOMETER = 0x23,
+ MILE = 0x24,
+ CELSIUS = 0x30,
+ FAHRENHEIT = 0x31,
+ KELVIN = 0x32,
+ MILLILITER = 0x40,
+ LITER = 0x41,
+ /**
+ * deprecated. Use US_GALLON instead.
+ */
+ GALLON = 0x42,
+ US_GALLON = 0x42,
+ IMPERIAL_GALLON = 0x43,
+ NANO_SECS = 0x50,
+ SECS = 0x53,
+ YEAR = 0x59,
+ WATT_HOUR = 0x60,
+ MILLIAMPERE = 0x61,
+ MILLIVOLT = 0x62,
+ MILLIWATTS = 0x63,
+ AMPERE_HOURS = 0x64,
+ KILOWATT_HOUR = 0x65,
+ KILOPASCAL = 0x70,
+ PSI = 0x71,
+ BAR = 0x72,
+ DEGREES = 0x80,
+ MILES_PER_HOUR = 0x90,
+ KILOMETERS_PER_HOUR = 0x91,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
new file mode 100644
index 0000000..46a66e1
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleVendorPermission.aidl
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Used by SUPPORT_CUSTOMIZE_VENDOR_PERMISSION to indicate the permission of vendor properties.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VehicleVendorPermission {
+ PERMISSION_DEFAULT = 0x00000000,
+ PERMISSION_SET_VENDOR_CATEGORY_WINDOW = 0X00000001,
+ PERMISSION_GET_VENDOR_CATEGORY_WINDOW = 0x00000002,
+ PERMISSION_SET_VENDOR_CATEGORY_DOOR = 0x00000003,
+ PERMISSION_GET_VENDOR_CATEGORY_DOOR = 0x00000004,
+ PERMISSION_SET_VENDOR_CATEGORY_SEAT = 0x00000005,
+ PERMISSION_GET_VENDOR_CATEGORY_SEAT = 0x00000006,
+ PERMISSION_SET_VENDOR_CATEGORY_MIRROR = 0x00000007,
+ PERMISSION_GET_VENDOR_CATEGORY_MIRROR = 0x00000008,
+ PERMISSION_SET_VENDOR_CATEGORY_INFO = 0x00000009,
+ PERMISSION_GET_VENDOR_CATEGORY_INFO = 0x0000000A,
+ PERMISSION_SET_VENDOR_CATEGORY_ENGINE = 0x0000000B,
+ PERMISSION_GET_VENDOR_CATEGORY_ENGINE = 0x0000000C,
+ PERMISSION_SET_VENDOR_CATEGORY_HVAC = 0x0000000D,
+ PERMISSION_GET_VENDOR_CATEGORY_HVAC = 0x0000000E,
+ PERMISSION_SET_VENDOR_CATEGORY_LIGHT = 0x0000000F,
+ PERMISSION_GET_VENDOR_CATEGORY_LIGHT = 0x00000010,
+ PERMISSION_SET_VENDOR_CATEGORY_1 = 0x00010000,
+ PERMISSION_GET_VENDOR_CATEGORY_1 = 0x00011000,
+ PERMISSION_SET_VENDOR_CATEGORY_2 = 0x00020000,
+ PERMISSION_GET_VENDOR_CATEGORY_2 = 0x00021000,
+ PERMISSION_SET_VENDOR_CATEGORY_3 = 0x00030000,
+ PERMISSION_GET_VENDOR_CATEGORY_3 = 0x00031000,
+ PERMISSION_SET_VENDOR_CATEGORY_4 = 0x00040000,
+ PERMISSION_GET_VENDOR_CATEGORY_4 = 0x00041000,
+ PERMISSION_SET_VENDOR_CATEGORY_5 = 0x00050000,
+ PERMISSION_GET_VENDOR_CATEGORY_5 = 0x00051000,
+ PERMISSION_SET_VENDOR_CATEGORY_6 = 0x00060000,
+ PERMISSION_GET_VENDOR_CATEGORY_6 = 0x00061000,
+ PERMISSION_SET_VENDOR_CATEGORY_7 = 0x00070000,
+ PERMISSION_GET_VENDOR_CATEGORY_7 = 0x00071000,
+ PERMISSION_SET_VENDOR_CATEGORY_8 = 0x00080000,
+ PERMISSION_GET_VENDOR_CATEGORY_8 = 0x00081000,
+ PERMISSION_SET_VENDOR_CATEGORY_9 = 0x00090000,
+ PERMISSION_GET_VENDOR_CATEGORY_9 = 0x00091000,
+ PERMISSION_SET_VENDOR_CATEGORY_10 = 0x000A0000,
+ PERMISSION_GET_VENDOR_CATEGORY_10 = 0x000A1000,
+ PERMISSION_NOT_ACCESSIBLE = 0xF0000000,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..74e944d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsAvailabilityStateIntegerValuesIndex.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/**
+ * An availability state is sent to the subscribers in response to a change in the available
+ * layers as part of a VmsMessageType.AVAILABILITY_CHANGE message, or in response to a
+ * VmsMessageType.AVAILABILITY_REQUEST message as part of a VmsMessageType.AVAILABILITY_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber
+ * receives a smaller sequence number, it should ignore the message. An available associated layer
+ * is a layer with a list of publisher IDs:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsAvailabilityStateIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ SEQUENCE_NUMBER = 1,
+ NUMBER_OF_ASSOCIATED_LAYERS = 2,
+ LAYERS_START = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..a3a2e18
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsBaseMessageIntegerValuesIndex.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Every VMS message starts with the type of the message from the VmsMessageType enum.
+ * Messages with no parameters such as VmsMessageType.AVAILABILITY_REQUEST,
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST and VmsMessageType.DATA are also based on this enum.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsBaseMessageIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl
new file mode 100644
index 0000000..bdffde7
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageType.aidl
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * This enum lists the types of supported VMS messages. It is used as the first
+ * integer in the vehicle property integers array and determines how the rest of
+ * the message is decoded.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsMessageType {
+ /**
+ * A request from the subscribers to the VMS service to subscribe to a layer.
+ *
+ * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+ */
+ SUBSCRIBE = 1,
+ /**
+ * A request from the subscribers to the VMS service to subscribe to a layer from a specific
+ * publisher.
+ *
+ * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+ */
+ SUBSCRIBE_TO_PUBLISHER = 2,
+ /**
+ * A request from the subscribers to the VMS service to unsubscribes from a layer.
+ *
+ * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+ */
+ UNSUBSCRIBE = 3,
+ /**
+ * A request from the subscribers to the VMS service to unsubscribes from a layer from a
+ * specific publisher.
+ *
+ * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+ */
+ UNSUBSCRIBE_TO_PUBLISHER = 4,
+ /**
+ * Information from the publishers to the VMS service about the layers which the client can
+ * publish.
+ *
+ * This message type uses enum VmsOfferingMessageIntegerValuesIndex.
+ */
+ OFFERING = 5,
+ /**
+ * A request from the subscribers to the VMS service to get the available layers.
+ *
+ * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+ */
+ AVAILABILITY_REQUEST = 6,
+ /**
+ * A request from the publishers to the VMS service to get the layers with subscribers.
+ *
+ * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+ */
+ SUBSCRIPTIONS_REQUEST = 7,
+ /**
+ * A response from the VMS service to the subscribers to a VmsMessageType.AVAILABILITY_REQUEST
+ *
+ * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+ */
+ AVAILABILITY_RESPONSE = 8,
+ /**
+ * A notification from the VMS service to the subscribers on a change in the available layers.
+ *
+ * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+ */
+ AVAILABILITY_CHANGE = 9,
+ /**
+ * A response from the VMS service to the publishers to a VmsMessageType.SUBSCRIPTIONS_REQUEST
+ *
+ * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+ */
+ SUBSCRIPTIONS_RESPONSE = 10,
+ /**
+ * A notification from the VMS service to the publishers on a change in the layers with
+ * subscribers.
+ *
+ * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+ */
+ SUBSCRIPTIONS_CHANGE = 11,
+ /**
+ * A message from the VMS service to the subscribers or from the publishers to the VMS service
+ * with a serialized VMS data packet as defined in the VMS protocol.
+ *
+ * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+ */
+ DATA = 12,
+ /**
+ * A request from the publishers to the VMS service to get a Publisher ID for a serialized VMS
+ * provider description packet as defined in the VMS protocol.
+ *
+ * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+ */
+ PUBLISHER_ID_REQUEST = 13,
+ /**
+ * A response from the VMS service to the publisher that contains a provider description packet
+ * and the publisher ID assigned to it.
+ *
+ * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+ */
+ PUBLISHER_ID_RESPONSE = 14,
+ /**
+ * A request from the subscribers to the VMS service to get information for a Publisher ID.
+ *
+ * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+ */
+ PUBLISHER_INFORMATION_REQUEST = 15,
+ /**
+ * A response from the VMS service to the subscribers that contains a provider description
+ * packet and the publisher ID assigned to it.
+ *
+ * This message type uses enum VmsPublisherInformationIntegerValuesIndex.
+ */
+ PUBLISHER_INFORMATION_RESPONSE = 16,
+ /**
+ * A notification indicating that the sender has been reset.
+ *
+ * The receiving party must reset its internal state and respond to the
+ * sender with a START_SESSION message as acknowledgement.
+ *
+ * This message type uses enum VmsStartSessionMessageIntegerValuesIndex.
+ */
+ START_SESSION = 17,
+ // LAST_VMS_MESSAGE_TYPE = START_SESSION,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl
new file mode 100644
index 0000000..594ddbc
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsMessageWithLayerIntegerValuesIndex;
+
+/*
+ * A VMS message with a layer and publisher ID is sent as part of a
+ * VmsMessageType.SUBSCRIBE_TO_PUBLISHER, VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages and
+ * VmsMessageType.DATA .
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ LAYER_TYPE = 1,
+ LAYER_SUBTYPE = 2,
+ LAYER_VERSION = 3,
+ PUBLISHER_ID = 4,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
new file mode 100644
index 0000000..e3a6126
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsMessageWithLayerIntegerValuesIndex.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or
+ * VmsMessageType.UNSUBSCRIBE messages.
+ *
+ * The layer type is defined in the VMS protocol, and the subtype and version are
+ * controlled by the implementer of the publisher.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsMessageWithLayerIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ LAYER_TYPE = 1,
+ LAYER_SUBTYPE = 2,
+ LAYER_VERSION = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..9dc7a58
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsOfferingMessageIntegerValuesIndex.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * An offering can be sent by publishers as part of VmsMessageType.OFFERING in order to
+ * advertise which layers they can publish and under which constraints: e.g., I can publish Layer X
+ * if someone else will publish Layer Y.
+ * The offering contains the publisher ID which was assigned to the publisher by the VMS service.
+ * A single offering is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of dependencies (N)
+ * - N x (Layer type, Layer subtype, Layer version)
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsOfferingMessageIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ PUBLISHER_ID = 1,
+ NUMBER_OF_OFFERS = 2,
+ OFFERING_START = 3,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
new file mode 100644
index 0000000..32049cc
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsPublisherInformationIntegerValuesIndex.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * Publishers send the VMS service their information and assigned in response a publisher ID.
+ * Subscribers can request the publisher information for a publisher ID they received in other
+ * messages.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsPublisherInformationIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ PUBLISHER_ID = 1,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
new file mode 100644
index 0000000..95f2d6d
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsStartSessionMessageIntegerValuesIndex.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/*
+ * Handshake data sent as part of a VmsMessageType.START_SESSION message.
+ *
+ * A new session is initiated by sending a START_SESSION message with the
+ * sender's identifier populated and the receiver's identifier set to -1.
+ *
+ * Identifier values are independently generated, but must be non-negative, and
+ * increase monotonically between reboots.
+ *
+ * Upon receiving a START_SESSION with a mis-matching identifier, the receiver
+ * must clear any cached VMS offering or subscription state and acknowledge the
+ * new session by responding with a START_SESSION message that populates both
+ * identifier fields.
+ *
+ * Any VMS messages received between initiation and completion of the handshake
+ * must be discarded.
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsStartSessionMessageIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ /*
+ * Identifier field for the Android system service.
+ */
+ SERVICE_ID = 1,
+ /*
+ * Identifier field for the HAL client process.
+ */
+ CLIENT_ID = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
new file mode 100644
index 0000000..87d59e5
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VmsSubscriptionsStateIntegerValuesIndex.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.automotive.vehicle;
+
+import android.hardware.automotive.vehicle.VmsBaseMessageIntegerValuesIndex;
+
+/**
+ * A subscriptions state is sent to the publishers in response to a change in the subscriptions
+ * as part of a VmsMessageType.SUBSCRIPTIONS_CHANGE, or in response to a
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST message as part of VmsMessageType.SUBSCRIPTIONS_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber
+ * receives a smaller sequence number it should ignore the message. The subscriptions are sent as a
+ * list of layers followed by a list of associated layers: {Sequence number, N, M, N x layer, M x
+ * associated layer} A subscribed layer is represented as three integers:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * A subscribed associated layer is a layer with a list of publisher IDs. It is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+// @VintfStability
+@Backing(type="int")
+enum VmsSubscriptionsStateIntegerValuesIndex {
+ /*
+ * The message type as enumerated by VmsMessageType enum.
+ */
+ MESSAGE_TYPE = 0,
+ SEQUENCE_NUMBER = 1,
+ NUMBER_OF_LAYERS = 2,
+ NUMBER_OF_ASSOCIATED_LAYERS = 3,
+ SUBSCRIPTIONS_START = 4,
+}
diff --git a/automotive/vehicle/tools/translate_vehicle_props.py b/automotive/vehicle/tools/translate_vehicle_props.py
new file mode 100644
index 0000000..59eb17d
--- /dev/null
+++ b/automotive/vehicle/tools/translate_vehicle_props.py
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+
+# Copyright (C) 2021 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Tools to translate VehicleProperty from types.hal into AIDL format.
+ To store it to a file:
+ $ python translate_vehicle_props.py types.hal > VehicleProperty.aidl
+"""
+import re
+import sys
+
+ENUM_TYPE_TO_PARSE = [ "VehiclePropertyType", "VehiclePropertyGroup", "VehicleArea" ]
+VEHICLE_PROP_ENUM = "VehicleProperty"
+
+RE_COMMENT_BEGIN = re.compile("\s*\/\*\*")
+RE_COMMENT_END = re.compile("\s*\*\/")
+RE_COMMENT_SINGLE_LINE = re.compile("\s*\/\*\*.*\*\/")
+
+RE_ENUM_START = re.compile("\s*enum\s*(\w+)\s?.*\{")
+RE_ENUM_END = re.compile("\s*\}\;")
+
+RE_ENUM_ELEMENT = re.compile("\s*(\w+)\s*\=\s*(\w+),")
+
+RE_VEHICLE_PROP_ELEMENT = re.compile("\s*(\w+)\s*\=\s*\(?\s*(\w+)\s*\|?\s*(\w+\:\w+)?\s*\|?\s*(\w+:\w+)?\s*\|?\s*(\w+:\w+)?\s*\)?,")
+
+DBG_COMMENT = False
+DBG_ENUM = False
+
+class HIDLParser:
+ def __init__(self):
+ self.inEnum = False
+ self.currentEnumName = None
+ self.inVehicleProperty = False
+ self.inComment = False
+ self.recentComments = []
+ self.currentType = None
+ self.enumMap = {}
+ self.outputMsg = []
+ self.multilineFormat = []
+ self.outputMsg.append("package android.hardware.automotive.vehicle\n\n")
+
+ def addRecentCommentToMsg(self):
+ self.outputMsg.extend(self.recentComments)
+ self.recentComments = []
+
+ def addToMsg(self, msg):
+ self.outputMsg.append(msg)
+
+ def printOutputMsg(self):
+ msg = "".join(self.outputMsg)
+ print(msg)
+
+ def parseLine(self, line):
+ if self.inComment:
+ self.recentComments.append(line)
+ if RE_COMMENT_END.match(line):
+ self.inComment = False
+ if DBG_COMMENT:
+ print("Comment end:{}".format(self.recentComments))
+ return
+ elif RE_COMMENT_BEGIN.match(line):
+ self.recentComments = []
+ self.recentComments.append(line)
+ if RE_COMMENT_SINGLE_LINE.match(line):
+ if DBG_COMMENT:
+ print("Single line Comment:{}".format(self.recentComments))
+ return
+ self.inComment = True
+ if DBG_COMMENT:
+ print("Comment start")
+ return
+
+ if self.inEnum:
+ if RE_ENUM_END.match(line):
+ self.inEnum = False
+ if DBG_ENUM:
+ print("End enum {}".format(self.currentEnumName))
+ else:
+ matchElement = RE_ENUM_ELEMENT.match(line);
+ if matchElement:
+ elementName = matchElement.group(1)
+ elementValue = matchElement.group(2)
+ self.enumMap[self.currentEnumName + ':' + elementName] = elementValue
+ elif self.inVehicleProperty:
+ if RE_ENUM_END.match(line):
+ self.inVehicleProperty = False
+ self.addToMsg("}\n")
+ else:
+ text = line.strip()
+ if len(text) == 0:
+ self.multilineFormat = []
+ else:
+ self.multilineFormat.append(text)
+ textToMatch = "".join(self.multilineFormat)
+ match = RE_VEHICLE_PROP_ELEMENT.match(textToMatch)
+ if match:
+ self.multilineFormat = []
+ name = match.group(1)
+ val = match.group(2)
+ type1 = match.group(3)
+ self.addRecentCommentToMsg()
+ if type1 == None: # one line case
+ self.addToMsg(" {} = {},\n".format(name, val))
+ else:
+ type2 = match.group(4)
+ type3 = match.group(5)
+ self.addToMsg(" {} = {} + {} + {} + {}, // {},{},{}\n".\
+ format(name, val, self.enumMap[type1], self.enumMap[type3],\
+ self.enumMap[type2], type1, type3, type2))
+ else:
+ matchEnum = RE_ENUM_START.match(line)
+ if matchEnum:
+ enumName = matchEnum.group(1)
+ if enumName in ENUM_TYPE_TO_PARSE:
+ self.currentEnumName = enumName
+ self.inEnum = True
+ if DBG_ENUM:
+ print("enum {}".format(enumName))
+ elif enumName == VEHICLE_PROP_ENUM:
+ self.inVehicleProperty = True
+ self.addRecentCommentToMsg()
+ self.addToMsg("@Backing(type=\"int\")\nenum VehicleProperty {\n")
+ if DBG_ENUM:
+ print("VehicleProperty starts, all enum values {}".format(self.enumMap))
+
+
+def main():
+ if len(sys.argv) != 2:
+ print("Usage: {} types_hal_file".format(sys.argv[0]))
+ sys.exit(1)
+ file_name = sys.argv[1]
+ with open(file_name, 'r') as f:
+ parser = HIDLParser()
+ for line in f.readlines():
+ parser.parseLine(line)
+ parser.printOutputMsg()
+
+if __name__ == "__main__":
+ main()
diff --git a/biometrics/fingerprint/2.2/default/Android.bp b/biometrics/fingerprint/2.2/default/Android.bp
index f4fb57f..2d262f0 100644
--- a/biometrics/fingerprint/2.2/default/Android.bp
+++ b/biometrics/fingerprint/2.2/default/Android.bp
@@ -25,6 +25,7 @@
"libhidlbase",
"libhardware",
"libutils",
+ "android.hardware.biometrics.fingerprint@2.1",
"android.hardware.biometrics.fingerprint@2.2",
],
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 8b6e841..d4b49af 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -85,12 +85,19 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.automotive.vehicle</name>
+ <interface>
+ <name>IVehicle</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.automotive.vehicle</name>
<version>2.0</version>
<interface>
<name>IVehicle</name>
- <instance>default</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
@@ -522,12 +529,20 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.soundtrigger</name>
- <version>2.3</version>
+ <version>2.3-4</version>
<interface>
<name>ISoundTriggerHw</name>
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.soundtrigger3</name>
+ <version>1</version>
+ <interface>
+ <name>ISoundTriggerHw</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.tetheroffload.config</name>
<version>1.0</version>
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index fcc1f98..0e489c5 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -19,11 +19,13 @@
#include "GnssMeasurementInterface.h"
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
+#include "GnssReplayUtils.h"
#include "Utils.h"
namespace aidl::android::hardware::gnss {
using Utils = ::android::hardware::gnss::common::Utils;
+using ReplayUtils = ::android::hardware::gnss::common::ReplayUtils;
std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
@@ -63,9 +65,22 @@
mIsActive = true;
mThread = std::thread([this, enableCorrVecOutputs]() {
while (mIsActive == true) {
- auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
- this->reportMeasurement(measurement);
-
+ std::string rawMeasurementStr = "";
+ if (ReplayUtils::hasGnssDeviceFile() &&
+ ReplayUtils::isGnssRawMeasurement(
+ rawMeasurementStr = ReplayUtils::getDataFromDeviceFile(
+ std::string(
+ ::android::hardware::gnss::common::CMD_GET_RAWMEASUREMENT),
+ mMinIntervalMillis))) {
+ // TODO: implement rawMeasurementStr parser and report measurement.
+ ALOGD("rawMeasurementStr(size: %zu) from device file: %s", rawMeasurementStr.size(),
+ rawMeasurementStr.c_str());
+ auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+ this->reportMeasurement(measurement);
+ } else {
+ auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+ this->reportMeasurement(measurement);
+ }
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
}
});
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 43db873..f9225c2 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -41,6 +41,7 @@
"MockLocation.cpp",
"Utils.cpp",
"NmeaFixInfo.cpp",
+ "GnssReplayUtils.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
diff --git a/gnss/common/utils/default/GnssReplayUtils.cpp b/gnss/common/utils/default/GnssReplayUtils.cpp
new file mode 100644
index 0000000..fc4c477
--- /dev/null
+++ b/gnss/common/utils/default/GnssReplayUtils.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GnssReplayUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+std::string ReplayUtils::getGnssPath() {
+ char devname_value[PROPERTY_VALUE_MAX] = "";
+ if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
+ return devname_value;
+ }
+ return GNSS_PATH;
+}
+
+bool ReplayUtils::hasGnssDeviceFile() {
+ struct stat sb;
+ return stat(getGnssPath().c_str(), &sb) != -1;
+}
+
+bool ReplayUtils::isGnssRawMeasurement(const std::string& inputStr) {
+ // TODO: add more logic check to by pass invalid data.
+ return !inputStr.empty() && (inputStr.find("Raw") != std::string::npos);
+}
+
+bool ReplayUtils::isNMEA(const std::string& inputStr) {
+ return !inputStr.empty() &&
+ (inputStr.rfind("$GPRMC,", 0) == 0 || inputStr.rfind("$GPRMA,", 0) == 0);
+}
+
+std::string ReplayUtils::getDataFromDeviceFile(const std::string& command, int mMinIntervalMs) {
+ char inputBuffer[INPUT_BUFFER_SIZE];
+ int mGnssFd = open(getGnssPath().c_str(), O_RDWR | O_NONBLOCK);
+
+ if (mGnssFd == -1) {
+ return "";
+ }
+
+ int bytes_write = write(mGnssFd, command.c_str(), command.size());
+ if (bytes_write <= 0) {
+ return "";
+ }
+
+ struct epoll_event ev, events[1];
+ ev.data.fd = mGnssFd;
+ ev.events = EPOLLIN;
+ int epoll_fd = epoll_create1(0);
+ epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
+ int bytes_read = -1;
+ std::string inputStr = "";
+ int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
+
+ if (epoll_ret == -1) {
+ return "";
+ }
+ while (true) {
+ memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
+ bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
+ if (bytes_read <= 0) {
+ break;
+ }
+ inputStr += std::string(inputBuffer, bytes_read);
+ }
+
+ return inputStr;
+}
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
diff --git a/gnss/common/utils/default/include/Constants.h b/gnss/common/utils/default/include/Constants.h
index a290ed2..7581166 100644
--- a/gnss/common/utils/default/include/Constants.h
+++ b/gnss/common/utils/default/include/Constants.h
@@ -30,6 +30,18 @@
const float kMockBearingAccuracyDegrees = 90;
const int64_t kMockTimestamp = 1519930775453L;
+// Location replay constants
+constexpr char GNSS_PATH[] = "/dev/gnss0";
+constexpr int INPUT_BUFFER_SIZE = 256;
+constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
+constexpr char CMD_GET_RAWMEASUREMENT[] = "CMD_GET_RAWMEASUREMENT";
+constexpr char LINE_SEPARATOR = '\n';
+constexpr char COMMA_SEPARATOR = ',';
+constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
+constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
+constexpr double TIMESTAMP_EPSILON = 0.001;
+constexpr int MIN_COL_NUM = 13;
+
} // namespace common
} // namespace gnss
} // namespace hardware
diff --git a/gnss/common/utils/default/include/GnssReplayUtils.h b/gnss/common/utils/default/include/GnssReplayUtils.h
new file mode 100644
index 0000000..32c0e58
--- /dev/null
+++ b/gnss/common/utils/default/include/GnssReplayUtils.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_common_GnssReplayUtils_H_
+#define android_hardware_gnss_common_GnssReplayUtils_H_
+
+#include <cutils/properties.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <sys/stat.h>
+#include <chrono>
+#include <string>
+#include <thread>
+
+#include "Constants.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+struct ReplayUtils {
+ static std::string getGnssPath();
+
+ static std::string getDataFromDeviceFile(const std::string& command, int mMinIntervalMs);
+
+ static bool hasGnssDeviceFile();
+
+ static bool isGnssRawMeasurement(const std::string& inputStr);
+
+ static bool isNMEA(const std::string& inputStr);
+};
+
+} // namespace common
+} // namespace gnss
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_gnss_common_GnssReplayUtils_H_
diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h
index c96eece..5c27045 100644
--- a/gnss/common/utils/default/include/NmeaFixInfo.h
+++ b/gnss/common/utils/default/include/NmeaFixInfo.h
@@ -27,13 +27,6 @@
namespace gnss {
namespace common {
-constexpr char GPGA_RECORD_TAG[] = "$GPGGA";
-constexpr char GPRMC_RECORD_TAG[] = "$GPRMC";
-constexpr char LINE_SEPARATOR = '\n';
-constexpr char COMMA_SEPARATOR = ',';
-constexpr double TIMESTAMP_EPSILON = 0.001;
-constexpr int MIN_COL_NUM = 13;
-
/** Helper class to parse and store the GNSS fix details information. */
class NmeaFixInfo {
private:
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
index a1d6981..76024aa 100644
--- a/gnss/common/utils/default/include/v2_1/GnssTemplate.h
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -35,6 +35,7 @@
#include "GnssDebug.h"
#include "GnssMeasurement.h"
#include "GnssMeasurementCorrections.h"
+#include "GnssReplayUtils.h"
#include "MockLocation.h"
#include "NmeaFixInfo.h"
#include "Utils.h"
@@ -158,52 +159,19 @@
template <class T_IGnss>
std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
- char inputBuffer[INPUT_BUFFER_SIZE];
if (!mHardwareModeChecked) {
- // default using gnss0
- const char * gnss_dev_path = GNSS_PATH;
- char devname_value[PROPERTY_VALUE_MAX] = "";
- if (property_get("debug.location.gnss.devname", devname_value, NULL) > 0) {
- gnss_dev_path = devname_value;
- ALOGD("using %s instead of the default %s", gnss_dev_path, GNSS_PATH);
- }
+ // default using /dev/gnss0
+ std::string gnss_dev_path = ReplayUtils::getGnssPath();
- mGnssFd = open(gnss_dev_path, O_RDWR | O_NONBLOCK);
+ mGnssFd = open(gnss_dev_path.c_str(), O_RDWR | O_NONBLOCK);
if (mGnssFd == -1) {
- ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno);
+ ALOGW("Failed to open %s errno: %d", gnss_dev_path.c_str(), errno);
}
mHardwareModeChecked = true;
}
- if (mGnssFd == -1) {
- return nullptr;
- }
-
- int bytes_write = write(mGnssFd, CMD_GET_LOCATION, strlen(CMD_GET_LOCATION));
- if (bytes_write <= 0) {
- return nullptr;
- }
-
- struct epoll_event ev, events[1];
- ev.data.fd = mGnssFd;
- ev.events = EPOLLIN;
- int epoll_fd = epoll_create1(0);
- epoll_ctl(epoll_fd, EPOLL_CTL_ADD, mGnssFd, &ev);
- int bytes_read = -1;
- std::string inputStr = "";
- int epoll_ret = epoll_wait(epoll_fd, events, 1, mMinIntervalMs);
-
- if (epoll_ret == -1) {
- return nullptr;
- }
- while (true) {
- memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
- bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
- if (bytes_read <= 0) {
- break;
- }
- inputStr += std::string(inputBuffer, bytes_read);
- }
+ std::string inputStr = ::android::hardware::gnss::common::ReplayUtils::getDataFromDeviceFile(
+ CMD_GET_LOCATION, mMinIntervalMs);
return NmeaFixInfo::getLocationFromInputStr(inputStr);
}
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 7a053f1..e2a0f4d 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -97,7 +97,6 @@
renderengine::DisplaySettings clientCompositionDisplay;
clientCompositionDisplay.physicalDisplay = Rect(mDisplayWidth, mDisplayHeight);
clientCompositionDisplay.clip = clientCompositionDisplay.physicalDisplay;
- clientCompositionDisplay.clearRegion = Region(clientCompositionDisplay.physicalDisplay);
mTestRenderEngine->initGraphicBuffer(
static_cast<uint32_t>(mDisplayWidth), static_cast<uint32_t>(mDisplayHeight), 1,
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
index 4187dd1..6c90af4 100644
--- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -327,6 +327,39 @@
}
/**
+ * Test IMapper::lockYCbCr. This locks a YCbCr_P010 buffer and verifies that it's initialized.
+ */
+TEST_P(GraphicsMapperHidlTest, LockYCbCrP010) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::YCBCR_P010;
+
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, &stride));
+
+ ASSERT_NE(nullptr, bufferHandle);
+
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ int fence = -1;
+ YCbCrLayout y_cb_cr_layout{};
+ // lock buffer
+ ASSERT_NO_FATAL_FAILURE(y_cb_cr_layout =
+ mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+
+ ASSERT_NE(nullptr, &y_cb_cr_layout);
+ EXPECT_EQ(stride, info.width);
+ EXPECT_EQ(y_cb_cr_layout.yStride, info.height * 2);
+ EXPECT_EQ(y_cb_cr_layout.cStride, y_cb_cr_layout.yStride);
+ EXPECT_EQ(4, y_cb_cr_layout.chromaStep);
+
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+ if (fence >= 0) {
+ close(fence);
+ }
+}
+
+/**
* Test IMapper::lockYCbCr. This locks a YV12 buffer, and makes sure we can
* write to and read from it.
*/
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index f55a6b7..e18b1fa 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -59,6 +59,12 @@
using DecodeFunction = std::function<void(const IMapper::BufferDescriptorInfo& descriptorInfo,
const hidl_vec<uint8_t>& vec)>;
+struct YCbCr {
+ android_ycbcr yCbCr;
+ int64_t horizontalSubSampling;
+ int64_t verticalSubSampling;
+};
+
class GraphicsMapperHidlTest
: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
protected:
@@ -215,8 +221,8 @@
}
ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
- uint8_t* tmpData =
- data + planeLayout.offsetInBytes + (planeLayoutComponent.offsetInBits / 8);
+ uint8_t* tmpData = data + planeLayout.offsetInBytes +
+ bitsToBytes(planeLayoutComponent.offsetInBits);
uint64_t sampleIncrementInBytes;
auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
@@ -271,6 +277,96 @@
ASSERT_NE(nullptr, outYCbCr->cr);
}
+ YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) {
+ YCbCr yCbCr_P010;
+ hidl_vec<uint8_t> vec;
+ EXPECT_EQ(Error::NONE,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+ std::vector<PlaneLayout> planeLayouts;
+ EXPECT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+ EXPECT_EQ(2, planeLayouts.size());
+ EXPECT_EQ(1, planeLayouts[0].components.size());
+ EXPECT_EQ(2, planeLayouts[1].components.size());
+
+ yCbCr_P010.yCbCr.y = nullptr;
+ yCbCr_P010.yCbCr.cb = nullptr;
+ yCbCr_P010.yCbCr.cr = nullptr;
+ yCbCr_P010.yCbCr.ystride = 0;
+ yCbCr_P010.yCbCr.cstride = 0;
+ yCbCr_P010.yCbCr.chroma_step = 0;
+ int64_t cb_offset = 0;
+ int64_t cr_offset = 0;
+
+ for (const auto& planeLayout : planeLayouts) {
+ for (const auto& planeLayoutComponent : planeLayout.components) {
+ if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
+ continue;
+ }
+
+ uint8_t* tmpData = data + planeLayout.offsetInBytes +
+ bitsToBytes(planeLayoutComponent.offsetInBits);
+ uint64_t sampleIncrementInBytes = 0;
+ auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
+ switch (type) {
+ case PlaneLayoutComponentType::Y:
+ // For specs refer:
+ // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
+ EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y);
+ EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
+ EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
+
+ yCbCr_P010.yCbCr.y = tmpData;
+ yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes;
+ break;
+
+ case PlaneLayoutComponentType::CB:
+ case PlaneLayoutComponentType::CR:
+ sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(4, sampleIncrementInBytes);
+
+ if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) {
+ yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes;
+ yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes;
+ } else {
+ EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes);
+ EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes);
+ }
+
+ if (yCbCr_P010.horizontalSubSampling == 0 &&
+ yCbCr_P010.verticalSubSampling == 0) {
+ yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling;
+ yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling;
+ } else {
+ EXPECT_EQ(yCbCr_P010.horizontalSubSampling,
+ planeLayout.horizontalSubsampling);
+ EXPECT_EQ(yCbCr_P010.verticalSubSampling,
+ planeLayout.verticalSubsampling);
+ }
+
+ if (type == PlaneLayoutComponentType::CB) {
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb);
+ yCbCr_P010.yCbCr.cb = tmpData;
+ cb_offset = planeLayoutComponent.offsetInBits;
+ } else {
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr);
+ yCbCr_P010.yCbCr.cr = tmpData;
+ cr_offset = planeLayoutComponent.offsetInBits;
+ }
+ break;
+ default:
+ break;
+ };
+ }
+ }
+
+ EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr);
+ return yCbCr_P010;
+ }
+
void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes,
uint32_t seed = 0) {
for (uint32_t y = 0; y < height; y++) {
@@ -297,9 +393,9 @@
}
}
- void traverseYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
- int64_t hSubsampling, int64_t vSubsampling,
- std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
+ void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling,
+ std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
auto yData = static_cast<uint8_t*>(yCbCr.y);
auto cbData = static_cast<uint8_t*>(yCbCr.cb);
auto crData = static_cast<uint8_t*>(yCbCr.cr);
@@ -327,21 +423,25 @@
}
}
- void fillYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
- int64_t hSubsampling, int64_t vSubsampling) {
- traverseYCbCr888Data(yCbCr, width, height, hSubsampling, vSubsampling,
- [](auto address, auto fillingData) { *address = fillingData; });
+ void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling) {
+ traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling,
+ [](auto address, auto fillingData) { *address = fillingData; });
}
- void verifyYCbCr888Data(const android_ycbcr& yCbCr, int32_t width, int32_t height,
- int64_t hSubsampling, int64_t vSubsampling) {
- traverseYCbCr888Data(
+ void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling) {
+ traverseYCbCrData(
yCbCr, width, height, hSubsampling, vSubsampling,
[](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); });
}
bool isEqual(float a, float b) { return abs(a - b) < 0.0001; }
+ uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
+
+ uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
+
std::unique_ptr<Gralloc> mGralloc;
IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
static const std::set<StandardMetadataType> sRequiredMetadataTypes;
@@ -645,7 +745,7 @@
ASSERT_EQ(crData + 1, cbData);
ASSERT_EQ(2, yCbCr.chroma_step);
- fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
@@ -656,7 +756,7 @@
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
- verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
@@ -744,7 +844,7 @@
ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
ASSERT_EQ(1, yCbCr.chroma_step);
- fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
@@ -755,7 +855,7 @@
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
- verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
@@ -788,7 +888,7 @@
ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
- fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
@@ -799,7 +899,7 @@
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
- verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
@@ -888,6 +988,42 @@
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
+TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_P010) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::YCBCR_P010;
+
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(
+ bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ unique_fd fence;
+ uint8_t* data;
+
+ ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+ region, fence.release())));
+
+ YCbCr yCbCr;
+ ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(bufferHandle, data));
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling);
+
+ ASSERT_EQ(0, info.height % 2);
+
+ // fill the data
+ fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+ yCbCr.verticalSubSampling);
+ // verify the YCbCr data
+ verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+ yCbCr.verticalSubSampling);
+
+ ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
/**
* Test IMapper::unlock with bad access region
*/
diff --git a/soundtrigger/2.4/Android.bp b/soundtrigger/2.4/Android.bp
new file mode 100644
index 0000000..44befc3
--- /dev/null
+++ b/soundtrigger/2.4/Android.bp
@@ -0,0 +1,30 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+hidl_interface {
+ name: "android.hardware.soundtrigger@2.4",
+ root: "android.hardware",
+ srcs: [
+ "ISoundTriggerHw.hal",
+ "ISoundTriggerHwCallback.hal",
+ "ISoundTriggerHwGlobalCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@2.0",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.1",
+ "android.hardware.soundtrigger@2.2",
+ "android.hardware.soundtrigger@2.3",
+ "android.hidl.base@1.0",
+ "android.hidl.safe_union@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/soundtrigger/2.4/ISoundTriggerHw.hal b/soundtrigger/2.4/ISoundTriggerHw.hal
new file mode 100644
index 0000000..fd39303
--- /dev/null
+++ b/soundtrigger/2.4/ISoundTriggerHw.hal
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger@2.4;
+
+import @2.0::SoundModelHandle;
+import @2.1::ISoundTriggerHw.SoundModel;
+import @2.1::ISoundTriggerHw.PhraseSoundModel;
+import @2.3::ISoundTriggerHw;
+import @2.3::RecognitionConfig;
+import ISoundTriggerHwCallback;
+import ISoundTriggerHwGlobalCallback;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords
+ * and other sounds.
+ *
+ * Important notes about the threading model:
+ * ==========================================
+ * Both this interface and the corresponding callback interface use a synchronized calling
+ * convention. This model comes with some advantages, but also with some risks of deadlocks if the
+ * implementation does not handle this correctly. Please consider the following:
+ * - After stopRecognition() returns no more recognition events for that model may be sent. This
+ * implies that any queues holding such events must be flushed before the call returns and that
+ * may imply that callback from the HAL to the client are done while stopRecognition() is blocked.
+ * This is OK, and supported by the framework.
+ * - Similarly, the same relationship applies between unloadModel() and subsequent callbacks to
+ * modelUnloaded().
+ * - Other than these two cases, calls into the HAL *MAY NOT* block on callbacks from the HAL, or
+ * else deadlock conditions may result, which may be handled by rebooting of the HAL process and
+ * cause service outages.
+ *
+ * Similarly, it is expected that a single call to startRecognition() generates at most one event
+ * (the model automatically becomes stopped when the event occurs, until explicitly started again)
+ * and that after a modelUnloaded() event no more events would be sent regarding the model.
+ * Note that a getModelState() call may generate a recognition event, but this event DOES NOT modify
+ * the model state - the model remains started.
+ *
+ * The HAL is expected to correctly handle a stopRecognition() call even after it sent an event
+ * indicating that recognition is stopped and an unloadModel() call even after it sent an event
+ * indicating that it has been unloaded. This is required in order to prevent race conditions
+ * between these calls. This also implies that model handles should generally not be reused until
+ * explicitly unloaded. To avoid the rare possibility of running out of handles, the framework will
+ * call unloadModel() on models that have been preemptively unloaded by the HAL.
+ *
+ * Due to the asynchronous nature of recognition events and preemptive model unloading, the HAL must
+ * correctly handle requests that would have been valid before an event has been delivered, but
+ * became moot as result of the event. Namely:
+ * - stopRecognition() may be called on a model that has already delivered an event and became
+ * inactive as a result. The HAL must return a successful return code in this case.
+ * - Furthermore, if a model is preemptively unloaded after it triggers (typically, this would
+ * happen when it is first aborted and immediately preemptively unloaded), stopRecognition() may
+ * be called on it. The HAL must return a successful return code in this case.
+ * - startRecognition() may be called on a model that has been preemptively unloaded. In this case,
+ * the HAL must return -EBUSY to indicate that the operation is temporarily unsuccessful.
+ * - unloadSoundModel() may be called on a model that has been preemptively unloaded. The HAL must
+ * return a successful return code in this case.
+ *
+ * Important notes about resource constraints and concurrency
+ * =========================================================
+ * Up until this version, the framework would enforce concurrency constraints expressed by the
+ * Properties presented by the soundtrigger instance. These include constraints on the maximum
+ * amount of models that can be loaded at the same time and on running recognition while capturing
+ * from the microphone.
+ * This version changes the approach for how these constraints are modeled, both offering the HAL
+ * implementation more flexibility and simplifying the framework's job in enforcing these
+ * limitations. Note that there is no change for how the framework behaves with earlier versions,
+ * everything described below only applies to this version and onward.
+ * The way this is achieved is as following:
+ * - The framework will no longer enforce constraints on concurrent loading of models, as expressed
+ * in the Properties.maxSoundModels field (this property is merely a hint at this point and may be
+ * deprecated in the future.
+ * - The framework will no longer enforce constraints on concurrency of audio recording and
+ * soundtrigger operation, as expressed in the Properties.concurrentCapture field (this property
+ * is merely a hint at this point and may be deprecated in the future).
+ * - The framework will no longer enforce constraints on concurrent loading of models, as expressed
+ * in the Properties (these properties are merely hints at this point and may be deprecated in the
+ * future.
+ * - The HAL implementation is free to reject starting of any model at any time by having the
+ * respective start*() method return -EBUSY.
+ * - The HAL implementation is free to reject loading of any model at any time by having the
+ * respective load*() method return -EBUSY.
+ * - The HAL implementation is free to preemptively stop a previously started model at its own
+ * discretion (for example, if a higher priority use-case which cannot coexist with detection
+ * has been requested). The HAL must notify the framework of the preemption by sending a
+ * recognition event with an `ABORT` status. The implementation must NOT attempt to restart the
+ * recognition automatically when conditions change.
+ * - The HAL implementation is free to preemptively unload a previously loaded model at its own
+ * discretion (for example, if a higher-priority model is being loaded and the two cannot
+ * coexist). When doing so, it must first abort the detection if active (as per above) and then
+ * notify the framework of the unload using the newly added modelUnloaded callback.
+ * - When conditions change, such that a model that couldn't previously load or start or that had
+ * previously been preemptively stopped or unloaded, the HAL must notify the framework via the
+ * newly added tryAgain() callback. This callback is not a guarantee that any operation would now
+ * succeed, but merely a hint that retrying something that had previously failed, now MAY succeed.
+ * Until this callback arrives, the framework may assume that any operation that had previously
+ * failed or aborted would still fail if retried, so the implementation should not forget to
+ * deliver it. There are no guarantees regarding how the framework may respond to this event and
+ * the order in which it may choose to reload/restart its models. Typically, as result of this
+ * event the framework will make a single attempt per model to bring this model to its desired
+ * state (loaded, started).
+ */
+interface ISoundTriggerHw extends @2.3::ISoundTriggerHw {
+ /**
+ * This will get called at most once per every attachment to the service.
+ *
+ * All events not tied to a specific model should go through this callback.
+ */
+ registerGlobalCallback(ISoundTriggerHwGlobalCallback callback);
+
+ /**
+ * Load a sound model. Once loaded, recognition of this model can be
+ * started and stopped.
+ * The implementation returns a unique handle used by other functions
+ * (unloadSoundModel(), startRecognition*(), etc...
+ *
+ * Must have the exact same semantics as loadSoundModel from ISoundTriggerHw@2.3 except that the
+ * return values have changed and that there is no cookie provided (the implementation may pass
+ * any value to the callback, as it is ignored).
+ *
+ * @param soundModel A SoundModel structure describing the sound model
+ * to load.
+ * @param callback The callback interface on which the soundModelCallback*()
+ * method must be called upon completion and modelUnloaded() upon preempted unload.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EBUSY in case the operation is temporarily unavailable (but possible in general).
+ * @return modelHandle A unique handle assigned by the HAL for use by the
+ * framework when controlling activity for this sound model.
+ */
+ loadSoundModel_2_4(SoundModel soundModel, ISoundTriggerHwCallback callback)
+ generates (int32_t retval, SoundModelHandle modelHandle);
+
+ /**
+ * Load a key phrase sound model. Once loaded, recognition of this model can
+ * be started and stopped. Only one active recognition per model at a time.
+ * The SoundTrigger service must handle concurrent recognition requests by
+ * different users/applications on the same model.
+ * The implementation returns a unique handle used by other functions
+ * (unloadSoundModel(), startRecognition*(), etc...
+ *
+ * Must have the exact same semantics as loadPhraseSoundModel from ISoundTriggerHw@2.3 except
+ * that the return values have changed and that there is no cookie provided (the implementation
+ * may pass any value to the callback, as it is ignored).
+ *
+ * @param soundModel A PhraseSoundModel structure describing the sound model
+ * to load.
+ * @param callback The callback interface on which the soundModelCallback*()
+ * method must be called upon completion and modelUnloaded() upon preempted unload.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EBUSY in case the operation is temporarily unavailable (but possible in general).
+ * @return modelHandle A unique handle assigned by the HAL for use by the
+ * framework when controlling activity for this sound model.
+ */
+ loadPhraseSoundModel_2_4(PhraseSoundModel soundModel, ISoundTriggerHwCallback callback)
+ generates (int32_t retval, SoundModelHandle modelHandle);
+
+ /**
+ * Start recognition on a given model. Only one recognition active
+ * at a time per model. Once recognition succeeds or fails, the callback
+ * associated with the model handle is called.
+ *
+ * Must have the exact same semantics as startRecognition from ISoundTriggerHw@2.3 except that
+ * there are different expectations of the return value and that there is no cookie provided
+ * (the implementation may pass any value to the callback, as it is ignored).
+ *
+ * @param modelHandle the handle of the sound model to use for recognition
+ * @param config A RecognitionConfig structure containing attributes of the
+ * recognition to perform
+ * @param callback The callback interface on which the recognitionCallback()
+ * method must be called upon recognition.
+ * @return retval Operation completion status: 0 in case of success,
+ * -EBUSY in case the operation is temporarily unavailable (but possible in general), or in
+ * case model has been preemtively unloaded.
+ */
+ startRecognition_2_4(SoundModelHandle modelHandle, RecognitionConfig config)
+ generates (int32_t retval);
+};
diff --git a/soundtrigger/2.4/ISoundTriggerHwCallback.hal b/soundtrigger/2.4/ISoundTriggerHwCallback.hal
new file mode 100644
index 0000000..594deb0
--- /dev/null
+++ b/soundtrigger/2.4/ISoundTriggerHwCallback.hal
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger@2.4;
+
+import @2.0::SoundModelHandle;
+import @2.1::ISoundTriggerHwCallback;
+
+/**
+ * SoundTrigger HAL per-model Callback interface.
+ */
+interface ISoundTriggerHwCallback extends @2.1::ISoundTriggerHwCallback {
+ /**
+ * Callback method called by the HAL when a model has been unloaded at the HAL implementation's
+ * discretion. Only a stopped model may be unloaded.
+ * This event is NOT sent as part of an unload sequence initiated by the client.
+ *
+ * @param model The model handle.
+ */
+ modelUnloaded(SoundModelHandle model);
+};
diff --git a/soundtrigger/2.4/ISoundTriggerHwGlobalCallback.hal b/soundtrigger/2.4/ISoundTriggerHwGlobalCallback.hal
new file mode 100644
index 0000000..2f1a977
--- /dev/null
+++ b/soundtrigger/2.4/ISoundTriggerHwGlobalCallback.hal
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger@2.4;
+
+/**
+ * SoundTrigger HAL callback interface for events not associated with a particular model.
+ */
+interface ISoundTriggerHwGlobalCallback {
+ /**
+ * Callback method called by the HAL whenever internal conditions have been made available, such
+ * that a call that would previously have failed with an -EBUSY status may now succeed.
+ * There is no guarantee that any call would succeed following this event. It is merely a hint
+ * to the client that it may retry.
+ * Conversely, any call that have failed previously with -EBUSY is guaranteed to fail again if
+ * retried, until this callback is delivered.
+ */
+ onResourcesAvailable();
+};
diff --git a/soundtrigger/2.4/cli/Android.bp b/soundtrigger/2.4/cli/Android.bp
new file mode 100644
index 0000000..8d0979b
--- /dev/null
+++ b/soundtrigger/2.4/cli/Android.bp
@@ -0,0 +1,17 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+java_binary {
+ name: "sthal_cli_2.4",
+ wrapper: "sthal_cli_2.4",
+ srcs: ["java/**/*.java"],
+ static_libs: [
+ "android.hardware.soundtrigger-V2.4-java",
+ ],
+}
diff --git a/soundtrigger/2.4/cli/OWNERS b/soundtrigger/2.4/cli/OWNERS
new file mode 100644
index 0000000..e21b66e
--- /dev/null
+++ b/soundtrigger/2.4/cli/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/soundtrigger_middleware/OWNERS
diff --git a/soundtrigger/2.4/cli/java/android/hardware/soundtrigger/V2_4/cli/SthalCli.java b/soundtrigger/2.4/cli/java/android/hardware/soundtrigger/V2_4/cli/SthalCli.java
new file mode 100644
index 0000000..4931105
--- /dev/null
+++ b/soundtrigger/2.4/cli/java/android/hardware/soundtrigger/V2_4/cli/SthalCli.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.soundtrigger.V2_4.cli;
+
+import android.hardware.soundtrigger.V2_0.PhraseRecognitionExtra;
+import android.hardware.soundtrigger.V2_0.RecognitionMode;
+import android.hardware.soundtrigger.V2_0.SoundModelType;
+import android.hardware.soundtrigger.V2_3.OptionalModelParameterRange;
+import android.hardware.soundtrigger.V2_4.ISoundTriggerHw;
+import android.hardware.soundtrigger.V2_4.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger.V2_4.ISoundTriggerHwGlobalCallback;
+import android.os.HidlMemoryUtil;
+import android.os.HwBinder;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+
+import java.util.Scanner;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * This is a quick-and-dirty sound trigger HAL console mock.
+ *
+ * It would only work on userdebug builds.
+ *
+ * When this app is started, it will initially:
+ * - Register a ISoundTriggerHw HAL with an instance name "mock".
+ * - Set a sysprop that tells SoundTriggerMiddlewareService to try to connect to the mock instance
+ * rather than the default one.
+ * - Reboot the real (default) HAL.
+ *
+ * In response to that, SoundTriggerMiddlewareService is going to connect to the mock HAL and resume
+ * normal operation.
+ *
+ * Our mock HAL will print to stdout every call it receives as well as expose a basic set of
+ * operations for sending event callbacks to the client. This allows us to simulate the frameworks
+ * behavior in response to different HAL behaviors.
+ */
+public class SthalCli {
+ private static SoundTriggerImpl mService;
+ private static final Scanner scanner = new Scanner(System.in);
+
+ public static void main(String[] args) {
+ try {
+ System.out.println("Registering mock STHAL");
+ HwBinder.setTrebleTestingOverride(true);
+ mService = new SoundTriggerImpl();
+ mService.registerAsService("mock");
+
+ System.out.println("Rebooting STHAL");
+ SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", "2");
+ SystemProperties.set("sys.audio.restart.hal", "1");
+
+ while (processCommand()) ;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ cleanup();
+ }
+ }
+
+ private static void cleanup() {
+ System.out.println("Cleaning up.");
+ SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", null);
+ HwBinder.setTrebleTestingOverride(false);
+ }
+
+ private static boolean processCommand() {
+ String line = scanner.nextLine();
+ String[] tokens = line.split("\\s+");
+ if (tokens.length < 1) {
+ return false;
+ }
+ switch (tokens[0]) {
+ case "q":
+ return false;
+
+ case "a":
+ mService.sendOnResourcesAvailable();
+ return true;
+
+ case "u":
+ mService.sendModelUnloaded(Integer.parseInt(tokens[1]));
+ return true;
+
+ case "r":
+ mService.sendRecognitionEvent(Integer.parseInt(tokens[1]),
+ Integer.parseInt(tokens[2]));
+ return true;
+
+ case "p":
+ mService.sendPhraseRecognitionEvent(Integer.parseInt(tokens[1]),
+ Integer.parseInt(tokens[2]));
+ return true;
+
+ case "d":
+ mService.dumpModels();
+ return true;
+
+ case "h":
+ System.out.print("Available commands:\n" + "h - help\n" + "q - quit\n"
+ + "a - send onResourcesAvailable event\n"
+ + "u <model> - send modelUnloaded event\n"
+ + "r <model> <status> - send recognitionEvent\n"
+ + "p <model> <status> - send phraseRecognitionEvent\n"
+ + "d - dump models\n");
+
+ default:
+ return true;
+ }
+ }
+
+ private static class SoundTriggerImpl extends ISoundTriggerHw.Stub {
+ static class Model {
+ final ISoundTriggerHwCallback callback;
+ final SoundModel model;
+ final PhraseSoundModel phraseModel;
+ public android.hardware.soundtrigger.V2_3.RecognitionConfig config = null;
+
+ Model(ISoundTriggerHwCallback callback, SoundModel model) {
+ this.callback = callback;
+ this.model = model;
+ this.phraseModel = null;
+ }
+
+ Model(ISoundTriggerHwCallback callback, PhraseSoundModel model) {
+ this.callback = callback;
+ this.model = null;
+ this.phraseModel = model;
+ }
+ }
+
+ private ISoundTriggerHwGlobalCallback mGlobalCallback;
+ private final ConcurrentMap<Integer, Model> mLoadedModels = new ConcurrentHashMap<>();
+ private int mHandleCounter = 1;
+
+ public void dumpModels() {
+ mLoadedModels.forEach((handle, model) -> {
+ System.out.println("+++ Model " + handle);
+ System.out.println(" config = " + model.config);
+ android.hardware.soundtrigger.V2_3.RecognitionConfig recognitionConfig =
+ model.config;
+ if (recognitionConfig != null) {
+ System.out.println(" ACTIVE recognitionConfig = " + recognitionConfig);
+ } else {
+ System.out.println(" INACTIVE");
+ }
+ });
+ }
+
+ public void sendOnResourcesAvailable() {
+ if (mGlobalCallback != null) {
+ try {
+ mGlobalCallback.onResourcesAvailable();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void sendRecognitionEvent(int modelHandle, int status) {
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null && model.config != null) {
+ android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.RecognitionEvent event =
+ new android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.RecognitionEvent();
+ event.header.model = modelHandle;
+ event.header.type = SoundModelType.GENERIC;
+ event.header.status = status;
+ event.header.captureSession = model.config.base.header.captureHandle;
+ event.header.captureAvailable = true;
+ event.header.audioConfig.channelMask = 16;
+ event.header.audioConfig.format = 1;
+ event.header.audioConfig.sampleRateHz = 16000;
+ event.data = HidlMemoryUtil.byteArrayToHidlMemory(new byte[0]);
+ try {
+ model.callback.recognitionCallback_2_1(event, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ model.config = null;
+ }
+ }
+
+ public void sendPhraseRecognitionEvent(int modelHandle, int status) {
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null && model.config != null) {
+ android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.PhraseRecognitionEvent
+ event =
+ new android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback.PhraseRecognitionEvent();
+ event.common.header.model = modelHandle;
+ event.common.header.type = SoundModelType.KEYPHRASE;
+ event.common.header.status = status;
+ event.common.header.captureSession = model.config.base.header.captureHandle;
+ event.common.header.captureAvailable = true;
+ event.common.header.audioConfig.channelMask = 16;
+ event.common.header.audioConfig.format = 1;
+ event.common.header.audioConfig.sampleRateHz = 16000;
+ event.common.data = HidlMemoryUtil.byteArrayToHidlMemory(new byte[0]);
+ if (!model.phraseModel.phrases.isEmpty()) {
+ PhraseRecognitionExtra extra = new PhraseRecognitionExtra();
+ extra.id = model.phraseModel.phrases.get(0).id;
+ extra.confidenceLevel = 100;
+ extra.recognitionModes = model.phraseModel.phrases.get(0).recognitionModes;
+ event.phraseExtras.add(extra);
+ }
+ try {
+ model.callback.phraseRecognitionCallback_2_1(event, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ model.config = null;
+ }
+ }
+
+ public void sendModelUnloaded(int modelHandle) {
+ Model model = mLoadedModels.remove(modelHandle);
+ if (model != null) {
+ try {
+ model.callback.modelUnloaded(modelHandle);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void registerGlobalCallback(ISoundTriggerHwGlobalCallback callback) {
+ System.out.println("registerGlobalCallback()");
+ mGlobalCallback = callback;
+ }
+
+ @Override
+ public void loadSoundModel_2_4(SoundModel soundModel, ISoundTriggerHwCallback callback,
+ loadSoundModel_2_4Callback _hidl_cb) {
+ int handle = mHandleCounter++;
+ System.out.printf("loadSoundModel_2_4(soundModel=%s) -> %d%n", soundModel, handle);
+ mLoadedModels.put(handle, new Model(callback, soundModel));
+ _hidl_cb.onValues(0, handle);
+ }
+
+ @Override
+ public void loadPhraseSoundModel_2_4(PhraseSoundModel soundModel,
+ ISoundTriggerHwCallback callback, loadPhraseSoundModel_2_4Callback _hidl_cb) {
+ int handle = mHandleCounter++;
+ System.out.printf("loadPhraseSoundModel_2_4(soundModel=%s) -> %d%n", soundModel,
+ handle);
+ mLoadedModels.put(handle, new Model(callback, soundModel));
+ _hidl_cb.onValues(0, handle);
+ }
+
+ @Override
+ public int startRecognition_2_4(int modelHandle,
+ android.hardware.soundtrigger.V2_3.RecognitionConfig config) {
+ System.out.printf("startRecognition_2_4(modelHandle=%d)%n", modelHandle);
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null) {
+ model.config = config;
+ }
+ return 0;
+ }
+
+ @Override
+ public void getProperties_2_3(getProperties_2_3Callback _hidl_cb) {
+ System.out.println("getProperties_2_3()");
+ android.hardware.soundtrigger.V2_3.Properties properties =
+ new android.hardware.soundtrigger.V2_3.Properties();
+ properties.base.implementor = "Android";
+ properties.base.description = "Mock STHAL";
+ properties.base.maxSoundModels = 2;
+ properties.base.maxKeyPhrases = 1;
+ properties.base.recognitionModes =
+ RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER;
+ _hidl_cb.onValues(0, properties);
+ }
+
+ @Override
+ public void queryParameter(int modelHandle, int modelParam,
+ queryParameterCallback _hidl_cb) {
+ _hidl_cb.onValues(0, new OptionalModelParameterRange());
+ }
+
+ @Override
+ public int getModelState(int modelHandle) {
+ System.out.printf("getModelState(modelHandle=%d)%n", modelHandle);
+ return 0;
+ }
+
+ @Override
+ public int unloadSoundModel(int modelHandle) {
+ System.out.printf("unloadSoundModel(modelHandle=%d)%n", modelHandle);
+ return 0;
+ }
+
+ @Override
+ public int stopRecognition(int modelHandle) {
+ System.out.printf("stopRecognition(modelHandle=%d)%n", modelHandle);
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null) {
+ model.config = null;
+ }
+ return 0;
+ }
+
+ @Override
+ public void debug(android.os.NativeHandle fd, java.util.ArrayList<String> options) {
+ if (!options.isEmpty()) {
+ switch (options.get(0)) {
+ case "reboot":
+ System.out.println("Received a reboot request. Exiting.");
+ cleanup();
+ System.exit(1);
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////
+ // Everything below is not implemented and not expected to be called.
+
+ @Override
+ public int startRecognition_2_3(int modelHandle,
+ android.hardware.soundtrigger.V2_3.RecognitionConfig config) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int setParameter(int modelHandle, int modelParam, int value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getParameter(int modelHandle, int modelParam, getParameterCallback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void loadSoundModel_2_1(SoundModel soundModel,
+ android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie,
+ loadSoundModel_2_1Callback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void loadPhraseSoundModel_2_1(PhraseSoundModel soundModel,
+ android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie,
+ loadPhraseSoundModel_2_1Callback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int startRecognition_2_1(int modelHandle, RecognitionConfig config,
+ android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback callback, int cookie) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void getProperties(getPropertiesCallback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void loadSoundModel(
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHw.SoundModel soundModel,
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie,
+ loadSoundModelCallback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void loadPhraseSoundModel(
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHw.PhraseSoundModel soundModel,
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie,
+ loadPhraseSoundModelCallback _hidl_cb) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int startRecognition(int modelHandle,
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHw.RecognitionConfig config,
+ android.hardware.soundtrigger.V2_0.ISoundTriggerHwCallback callback, int cookie) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int stopAllRecognitions() {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/soundtrigger/2.4/cli/sthal_cli_2.4 b/soundtrigger/2.4/cli/sthal_cli_2.4
new file mode 100644
index 0000000..0801464
--- /dev/null
+++ b/soundtrigger/2.4/cli/sthal_cli_2.4
@@ -0,0 +1,7 @@
+#!/system/bin/sh
+# Script to start "sthal_cli_2.4" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/sthal_cli_2.4.jar
+exec app_process $base/bin android.hardware.soundtrigger.V2_4.cli.SthalCli "$@"
+
diff --git a/soundtrigger/2.4/vts/functional/Android.bp b/soundtrigger/2.4/vts/functional/Android.bp
new file mode 100644
index 0000000..4b7ae91
--- /dev/null
+++ b/soundtrigger/2.4/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalSoundtriggerV2_4TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalSoundtriggerV2_4TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.1",
+ "android.hardware.soundtrigger@2.2",
+ "android.hardware.soundtrigger@2.3",
+ "android.hardware.soundtrigger@2.4",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/soundtrigger/2.4/vts/functional/VtsHalSoundtriggerV2_4TargetTest.cpp b/soundtrigger/2.4/vts/functional/VtsHalSoundtriggerV2_4TargetTest.cpp
new file mode 100644
index 0000000..13d7005
--- /dev/null
+++ b/soundtrigger/2.4/vts/functional/VtsHalSoundtriggerV2_4TargetTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SoundTriggerHidlHalTest"
+
+#include <android-base/logging.h>
+#include <android/hardware/audio/common/2.0/types.h>
+#include <android/hardware/soundtrigger/2.4/ISoundTriggerHwGlobalCallback.h>
+#include <android/hardware/soundtrigger/2.4/ISoundTriggerHw.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::soundtrigger::V2_4::ISoundTriggerHw;
+using ::android::hardware::soundtrigger::V2_4::ISoundTriggerHwGlobalCallback;
+
+/**
+ * Test class holding the instance of the SoundTriggerHW service to test.
+ * The passed parameter is the registered name of the implementing service
+ * supplied by INSTANTIATE_TEST_SUITE_P() call.
+ */
+class SoundTriggerHidlTest : public testing::TestWithParam<std::string> {
+public:
+ void SetUp() override {
+ mSoundtrigger = ISoundTriggerHw::getService(GetParam());
+
+ ASSERT_NE(mSoundtrigger, nullptr);
+ LOG(INFO) << "Test is remote " << mSoundtrigger->isRemote();
+ }
+
+protected:
+ sp<ISoundTriggerHw> mSoundtrigger;
+};
+
+/**
+ * Empty test is in place to ensure service is initialized.
+ * Due to the nature of SoundTrigger HAL providing an interface for
+ * proprietary or vendor specific implementations, limited testing on
+ * individual APIs is possible.
+ */
+TEST_P(SoundTriggerHidlTest, ServiceIsInstantiated) {}
+
+class GlobalCallback : public ISoundTriggerHwGlobalCallback {
+ Return<void> onResourcesAvailable() override {
+ return Status::ok();
+ }
+};
+
+/**
+ * Test ISoundTriggerHw::registerGlobalCallback method
+ *
+ * Verifies that:
+ * - the implementation implements the method
+ * - the method returns no error
+ */
+TEST_P(SoundTriggerHidlTest, RegisterGlobalCallback) {
+ Return<void> hidlReturn;
+ sp<ISoundTriggerHwGlobalCallback> callback = new GlobalCallback();
+ hidlReturn = mSoundtrigger->registerGlobalCallback(callback);
+ EXPECT_TRUE(hidlReturn.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SoundTriggerHidlTest);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, SoundTriggerHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISoundTriggerHw::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/soundtrigger/aidl/Android.bp b/soundtrigger/aidl/Android.bp
new file mode 100644
index 0000000..fcccc27
--- /dev/null
+++ b/soundtrigger/aidl/Android.bp
@@ -0,0 +1,37 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.soundtrigger3",
+ vendor_available: true,
+ flags: ["-Werror", "-Weverything", ],
+ srcs: [
+ "android/hardware/soundtrigger3/ISoundTriggerHw.aidl",
+ "android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl",
+ "android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl",
+ ],
+ stability: "vintf",
+ imports: [
+ "android.media.soundtrigger.types",
+ ],
+ backend: {
+ cpp: {
+ // prefer NDK backend which can be used anywhere
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
new file mode 100644
index 0000000..bbfe7d9
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make 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.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHw {
+ android.media.soundtrigger.Properties getProperties();
+ void registerGlobalCallback(in android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback callback);
+ int loadSoundModel(in android.media.soundtrigger.SoundModel soundModel, in android.hardware.soundtrigger3.ISoundTriggerHwCallback callback);
+ int loadPhraseSoundModel(in android.media.soundtrigger.PhraseSoundModel soundModel, in android.hardware.soundtrigger3.ISoundTriggerHwCallback callback);
+ void unloadSoundModel(in int modelHandle);
+ void startRecognition(in int modelHandle, in int deviceHandle, in int ioHandle, in android.media.soundtrigger.RecognitionConfig config);
+ void stopRecognition(in int modelHandle);
+ void forceRecognitionEvent(in int modelHandle);
+ @nullable android.media.soundtrigger.ModelParameterRange queryParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam);
+ int getParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam);
+ void setParameter(in int modelHandle, in android.media.soundtrigger.ModelParameter modelParam, in int value);
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
new file mode 100644
index 0000000..152dfed
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make 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.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHwCallback {
+ void modelUnloaded(in int model);
+ void phraseRecognitionCallback(in int model, in android.media.soundtrigger.PhraseRecognitionEvent event);
+ void recognitionCallback(in int model, in android.media.soundtrigger.RecognitionEvent event);
+}
diff --git a/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
new file mode 100644
index 0000000..6dfee9f
--- /dev/null
+++ b/soundtrigger/aidl/aidl_api/android.hardware.soundtrigger3/current/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make 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.soundtrigger3;
+@VintfStability
+interface ISoundTriggerHwGlobalCallback {
+ void onResourcesAvailable();
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
new file mode 100644
index 0000000..2a3fc64
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHw.aidl
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger3;
+
+import android.hardware.soundtrigger3.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback;
+
+import android.media.soundtrigger.PhraseSoundModel;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.ModelParameter;
+import android.media.soundtrigger.ModelParameterRange;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords
+ * and other sounds.
+ *
+ * Basic usage:
+ * ============
+ * ISoundTriggerHw supports the ability to have one of more detection sessions running at a given
+ * time, and listening to acoustic events. The basic flow of setting up such a session is:
+ * - Load a model using loadSoundModel() or loadPhraseSoundModel(). The provided model object would
+ * indicate the (implementation-specific) detection algorithm (engine) to use, as well as any
+ * parameters applicable for this agorithm. Upon success, those methods would return a handle
+ * which will be used to reference this model in subsequent calls.
+ * - Once the model had been successfully loaded, detection can begin by calling startRecognition().
+ * - Recognition will continue running in the background until one of the following events occurs:
+ * - stopRecognition() has been called on this model.
+ * - A detection has occurred.
+ * - Detection was aborted, typically for resource constraints, for example, when a higher-
+ * priority use-case has been initiated.
+ * - In the latter two cases, a recognition event will be sent via a the callback interface that was
+ * registered by the client upon loading. In either case, after any of these events occur, the
+ * detection becomes inactive and no more recognition callbacks are allowed.
+ * - The same model maybe started again at a later time, and this process may repeat as many times
+ * as needed.
+ * - Finally, an inactive model that is no longer needed may be unloaded via unloadModel().
+ *
+ * Important notes about the threading model:
+ * ==========================================
+ * Both this interface and the corresponding callback interface use a synchronous calling
+ * convention. This model comes with some advantages, but also with some risks of deadlocks if the
+ * implementation does not handle this correctly. Please consider the following:
+ * - After stopRecognition() returns, no more recognition events for that model may be sent. This
+ * implies that any queues holding such events must be flushed before the call returns and that
+ * may imply that callback from the HAL to the client are done while stopRecognition() is blocked.
+ * This is OK, and supported by the framework.
+ * - Similarly, the same relationship applies between unloadModel() and subsequent callbacks to
+ * modelUnloaded().
+ * - Other than these two cases, calls into the HAL *MAY NOT* block on callbacks from the HAL, or
+ * else deadlock conditions may result, which may be handled by rebooting of the HAL process and
+ * cause service outages.
+ *
+ * Due to the asynchronous nature of recognition events and preemptive model unloading, the HAL must
+ * correctly handle requests that would have been valid before an event has been delivered, but
+ * became moot as result of the event. Namely:
+ * - stopRecognition() may be called on a model that has already delivered an event and became
+ * inactive as a result. The HAL must return a successful return code in this case.
+ * - Furthermore, if a model is preemptively unloaded after it triggers (typically, this would
+ * happen when it is first aborted and immediately preemptively unloaded), stopRecognition() may
+ * be called on it. The HAL must return successfully in this case.
+ * - startRecognition() may be called on a model that has been preemptively unloaded. In this case,
+ * the HAL must signal a ServiceSpecificException(RESOURCE_CONTENTION) to indicate that the
+ * operation is temporarily unsuccessful.
+ * - unloadSoundModel() may be called on a model that has been preemptively unloaded. The HAL must
+ * return a successful return code in this case. This also implies that model handles should
+ * generally not be reused until explicitly unloaded. To avoid the rare possibility of running out
+ * of handles, the framework may call unloadModel() on models that have been preemptively unloaded
+ * by the HAL.
+ *
+ * Important notes about resource constraints and concurrency
+ * =========================================================
+ * Up until this version, the framework would enforce concurrency constraints expressed by the
+ * Properties presented by the soundtrigger instance. These include constraints on the maximum
+ * amount of models that can be loaded at the same time and on running recognition while capturing
+ * from the microphone.
+ * This version changes the approach for how these constraints are modeled, both offering the HAL
+ * implementation more flexibility and simplifying the framework's job in enforcing these
+ * limitations. Note that there is no change for how the framework behaves with earlier versions,
+ * everything described below only applies to this version and onward.
+ * The way this is achieved is as following:
+ * - The framework will no longer enforce constraints on concurrent loading of models, as expressed
+ * in the Properties.maxSoundModels field (this property is merely a hint at this point and may be
+ * deprecated in the future), or any other implicit constraints.
+ * - The framework will no longer enforce constraints on concurrency of audio recording and
+ * soundtrigger operation, as expressed in the Properties.concurrentCapture field (this property
+ * is merely a hint at this point and may be deprecated in the future).
+ * - The HAL implementation is free to reject loading of any model at any time by having the
+ * respective load*() method signal a ServiceSpecificException(RESOURCE_CONTENTION).
+ * - The HAL implementation is free to reject starting of any model at any time by having the
+ * respective start*() method signal a ServiceSpecificException(RESOURCE_CONTENTION).
+ * - The HAL implementation is free to preemptively stop a previously started model at its own
+ * discretion (for example, if a higher priority use-case which cannot coexist with detection
+ * has been requested). The HAL must notify the framework of the preemption by sending a
+ * recognition event with an `ABORTED` status. The implementation must NOT attempt to restart the
+ * recognition automatically when conditions change.
+ * - The HAL implementation is free to preemptively unload a previously loaded model at its own
+ * discretion (for example, if a higher-priority model is being loaded and the two cannot
+ * coexist). When doing so, it must first abort the detection if active (as per above) and then
+ * notify the framework of the unload using the modelUnloaded() callback.
+ * - When conditions change, such that a model that couldn't previously load or start or that had
+ * previously been preemptively stopped or unloaded, the HAL must notify the framework via the
+ * newly added onResourcesAvailable() callback. This callback is not a guarantee that any
+ * operation would now succeed, but merely a hint that retrying something that had previously
+ * failed, now MAY succeed. Until this callback is invoked, the client may assume that any
+ * operation that had previously failed or aborted would still fail if retried, so the
+ * implementation should not forget to deliver it.
+ * There are no guarantees regarding how the framework may respond to this event and the order in
+ * which it may choose to reload/restart its models. Typically, as result of this event the
+ * framework will make a single attempt per model to bring this model to its desired state
+ * (loaded, started).
+ */
+@VintfStability
+interface ISoundTriggerHw {
+ /**
+ * Retrieve implementation properties.
+ *
+ * @return A Properties structure containing implementation description and capabilities.
+ */
+ Properties getProperties();
+
+ /**
+ * This will get called at most once per every attachment to the service.
+ *
+ * All events not tied to a specific model should go through this callback.
+ *
+ * @param callback An interface to receive global event callbacks.
+ */
+ void registerGlobalCallback(in ISoundTriggerHwGlobalCallback callback);
+
+ /**
+ * Load a sound model. Once loaded, recognition of this model can be started and stopped.
+ *
+ * @param soundModel A SoundModel structure describing the sound model to load.
+ * @param callback The callback interface on which the recognitionCallback()
+ * method will be called upon completion and modelUnloaded() upon preemptive unload.
+ * @return A unique handle assigned by the HAL for use by the client when controlling
+ * activity for this sound model.
+ * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be loaded due
+ * to resource constraints. This is typically a temporary condition and the client may
+ * retry after the onResourcesAvailable() global callback is invoked.
+ */
+ int loadSoundModel(in SoundModel soundModel, in ISoundTriggerHwCallback callback);
+
+ /**
+ * Load a key phrase sound model. Once loaded, recognition of this model can be started and
+ * stopped.
+ *
+ * @param soundModel A PhraseSoundModel structure describing the sound model to load.
+ * @param callback The callback interface on which the phraseRecognitionCallback() method will
+ * be called upon completion and modelUnloaded() upon preempted unload.
+ * @return A unique handle assigned by the HAL for use by the framework when controlling
+ * activity for this sound model.
+ * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be loaded due
+ * to resource constraints. This is typically a temporary condition and the client may
+ * retry after the onResourcesAvailable() global callback is invoked.
+ */
+ int loadPhraseSoundModel(in PhraseSoundModel soundModel, in ISoundTriggerHwCallback callback);
+
+ /**
+ * Unload a sound model. A sound model may be unloaded to free up resources and make room for a
+ * new one to overcome implementation limitations.
+ * This call is idempotent, to avoid any race conditions.
+ *
+ * @param modelHandle the handle of the sound model to unload.
+ */
+ void unloadSoundModel(in int modelHandle);
+
+ /**
+ * Start recognition on a given model.
+ * This must be called on a model that is in the stopped state.
+ * The state of this model becomes active and will remain so until explicitly stopped, or a
+ * recognition event had been delivered to the client.
+ *
+ * @param modelHandle the handle of the sound model to use for recognition
+ * @param deviceHandle The handle of the audio device to be used for recognition, as declared by
+ * the audio subsystem.
+ * @param ioHandle A handle assigned by the framework, which will later be used to retrieve
+ * an audio stream associated with this recognition session.
+ * @param config A RecognitionConfig structure containing attributes of the recognition to
+ * perform.
+ * @throws ServiceSpecificException(RESOURCE_CONTENTION) if the model cannot be started due
+ * to resource constraints. This is typically a temporary condition and the client may
+ * retry after the onResourcesAvailable() global callback is invoked.
+ */
+ void startRecognition(in int modelHandle, in int deviceHandle,
+ in int ioHandle, in RecognitionConfig config);
+
+ /**
+ * Stop recognition on a given model.
+ * This call is idempotent, to avoid any race conditions.
+ *
+ * @param modelHandle The handle of the sound model to use for recognition
+ */
+ void stopRecognition(in int modelHandle);
+
+ /**
+ * Request a recognition event to be generated.
+ * The model must be in the started state and will remain started after the event is sent.
+ * The model state is returned asynchronously as a RecognitionEvent via the callback that was
+ * registered upon loading. That event must have a RecognitionStatus.FORCED status.
+ *
+ * @param modelHandle The handle of the sound model whose state is being
+ * queried.
+ */
+ void forceRecognitionEvent(in int modelHandle);
+
+ /**
+ * Get supported parameter attributes with respect to the provided model handle.
+ * Model parameters are used to query/control model-specific detection behavior during a
+ * detection session.
+ * Along with determining the valid range, this API is also used to determine if a given
+ * parameter ID is supported at all by the modelHandle for use with getParameter() and
+ * setParameter() APIs.
+ *
+ * @param modelHandle The sound model handle indicating which model to query.
+ * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+ * @return This structure indicates supported attributes of the parameter for the given model
+ * handle. If the parameter is not supported, null is returned.
+ */
+ @nullable ModelParameterRange queryParameter(in int modelHandle, in ModelParameter modelParam);
+
+ /**
+ * Get a model specific parameter.
+ * If the value has not been set, a default value is returned. See ModelParameter for parameter
+ * default values.
+ * The caller must check if the handle supports the parameter via the queryParameter API prior
+ * to calling this method.
+ *
+ * @param modelHandle The sound model associated with given modelParam
+ * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+ * Not putting ModelParameter type directly in the definition and validating internally
+ * allows for forward compatibility.
+ * @return Value set to the requested parameter.
+ */
+ int getParameter(in int modelHandle, in ModelParameter modelParam);
+
+ /**
+ * Set a model specific parameter with the given value.
+ * This parameter will keep its value for the duration the model is loaded regardless of
+ * starting and stopping recognition. Once the model is unloaded, the value will be lost.
+ * The caller must check if the handle supports the parameter via the queryParameter API prior
+ * to calling this method.
+ *
+ * @param modelHandle The sound model handle indicating which model to modify parameters
+ * @param modelParam Parameter to set which will be validated against the ModelParameter type.
+ * Not putting ModelParameter type directly in the definition and validating internally
+ * allows for forward compatibility.
+ * @param value The value to set for the given model parameter.
+ */
+ void setParameter(in int modelHandle, in ModelParameter modelParam, in int value);
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
new file mode 100644
index 0000000..049ca65
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwCallback.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger3;
+
+import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.RecognitionEvent;
+
+/**
+ * SoundTrigger HAL per-model Callback interface.
+ */
+@VintfStability
+interface ISoundTriggerHwCallback {
+ /**
+ * Callback method called by the HAL when a model has been unloaded at the HAL implementation's
+ * discretion.
+ * This event may only be delivered when the model state is 'stopped'.
+ * This event is NOT sent as part of an unload sequence initiated by the client.
+ *
+ * @param model The model handle.
+ */
+ void modelUnloaded(in int model);
+
+ /**
+ * Callback method called by the HAL when the sound recognition triggers for a key phrase sound
+ * model.
+ * This event may only be delivered when the model state is 'started'.
+ * Unless the status of the event is RecognitionStatus.FORCED, this event indicates that the
+ * state of this model has become 'stopped'.
+ *
+ * @param event A RecognitionEvent structure containing detailed results of the recognition
+ * triggered
+ */
+ void phraseRecognitionCallback(in int model, in PhraseRecognitionEvent event);
+
+ /**
+ * Callback method called by the HAL when the sound recognition triggers.
+ * This event may only be delivered when the model state is 'started'.
+ * Unless the status of the event is RecognitionStatus.FORCED, this event indicates that the
+ * state of this model has become 'stopped'.
+ *
+ * @param event A RecognitionEvent structure containing detailed results of the recognition
+ * triggered
+ */
+ void recognitionCallback(in int model, in RecognitionEvent event);
+}
diff --git a/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
new file mode 100644
index 0000000..d6d8630
--- /dev/null
+++ b/soundtrigger/aidl/android/hardware/soundtrigger3/ISoundTriggerHwGlobalCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.soundtrigger3;
+
+/**
+ * SoundTrigger HAL callback interface for events not associated with a particular model.
+ */
+@VintfStability
+interface ISoundTriggerHwGlobalCallback {
+ /**
+ * Callback method called by the HAL whenever internal conditions have been made available, such
+ * that a call that would previously have failed with an -EBUSY status may now succeed.
+ * There is no guarantee that any call would succeed following this event. It is merely a hint
+ * to the client that it may retry.
+ * Conversely, any call that have failed previously with a
+ * ServiceSpecificException(RESOURCE_CONTENTION) is guaranteed to fail again if retried, until
+ * this callback is delivered.
+ */
+ void onResourcesAvailable();
+}
diff --git a/soundtrigger/aidl/cli/Android.bp b/soundtrigger/aidl/cli/Android.bp
new file mode 100644
index 0000000..e8999ff
--- /dev/null
+++ b/soundtrigger/aidl/cli/Android.bp
@@ -0,0 +1,17 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+java_binary {
+ name: "sthal_cli_3",
+ wrapper: "sthal_cli_3",
+ srcs: ["java/**/*.java"],
+ static_libs: [
+ "android.hardware.soundtrigger3-V1-java",
+ ],
+}
diff --git a/soundtrigger/aidl/cli/OWNERS b/soundtrigger/aidl/cli/OWNERS
new file mode 100644
index 0000000..e21b66e
--- /dev/null
+++ b/soundtrigger/aidl/cli/OWNERS
@@ -0,0 +1 @@
+include /media/java/android/media/soundtrigger_middleware/OWNERS
diff --git a/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
new file mode 100644
index 0000000..d3e1aa7
--- /dev/null
+++ b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.soundtrigger3.cli;
+
+import android.annotation.NonNull;
+import android.hardware.soundtrigger3.ISoundTriggerHw;
+import android.hardware.soundtrigger3.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger3.ISoundTriggerHwGlobalCallback;
+import android.media.audio.common.AudioConfig;
+import android.media.soundtrigger.ConfidenceLevel;
+import android.media.soundtrigger.ModelParameterRange;
+import android.media.soundtrigger.PhraseRecognitionEvent;
+import android.media.soundtrigger.PhraseRecognitionExtra;
+import android.media.soundtrigger.PhraseSoundModel;
+import android.media.soundtrigger.Properties;
+import android.media.soundtrigger.RecognitionConfig;
+import android.media.soundtrigger.RecognitionEvent;
+import android.media.soundtrigger.RecognitionMode;
+import android.media.soundtrigger.SoundModel;
+import android.media.soundtrigger.SoundModelType;
+import android.os.HwBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+
+import java.util.Scanner;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * This is a quick-and-dirty sound trigger HAL console mock.
+ *
+ * It would only work on userdebug builds.
+ *
+ * When this app is started, it will initially:
+ * - Register a ISoundTriggerHw HAL with an instance name "mock".
+ * - Set a sysprop that tells SoundTriggerMiddlewareService to try to connect to the mock instance
+ * rather than the default one.
+ * - Reboot the real (default) HAL.
+ *
+ * In response to that, SoundTriggerMiddlewareService is going to connect to the mock HAL and resume
+ * normal operation.
+ *
+ * Our mock HAL will print to stdout every call it receives as well as expose a basic set of
+ * operations for sending event callbacks to the client. This allows us to simulate the frameworks
+ * behavior in response to different HAL behaviors.
+ */
+public class SthalCli {
+ private static SoundTriggerImpl mService;
+ private static final Scanner scanner = new Scanner(System.in);
+
+ public static void main(String[] args) {
+ try {
+ printUsage();
+
+ System.out.println("Registering mock STHAL");
+ mService = new SoundTriggerImpl();
+ // This allows us to register the service, even if it is not declared in the manifest.
+ mService.forceDowngradeToSystemStability();
+ ServiceManager.addService(ISoundTriggerHw.class.getCanonicalName() + "/mock", mService);
+
+ System.out.println("Rebooting STHAL");
+ SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", "3");
+ SystemProperties.set("sys.audio.restart.hal", "1");
+
+ while (processCommand()) ;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ cleanup();
+ }
+ }
+
+ private static void cleanup() {
+ System.out.println("Cleaning up.");
+ SystemProperties.set("debug.soundtrigger_middleware.use_mock_hal", null);
+ HwBinder.setTrebleTestingOverride(false);
+ }
+
+ private static boolean processCommand() {
+ String line = scanner.nextLine();
+ String[] tokens = line.split("\\s+");
+ if (tokens.length < 1) {
+ return false;
+ }
+ switch (tokens[0]) {
+ case "q":
+ return false;
+
+ case "a":
+ mService.sendOnResourcesAvailable();
+ return true;
+
+ case "u":
+ mService.sendModelUnloaded(Integer.parseInt(tokens[1]));
+ return true;
+
+ case "r":
+ mService.sendRecognitionEvent(Integer.parseInt(tokens[1]),
+ Integer.parseInt(tokens[2]));
+ return true;
+
+ case "p":
+ mService.sendPhraseRecognitionEvent(Integer.parseInt(tokens[1]),
+ Integer.parseInt(tokens[2]));
+ return true;
+
+ case "d":
+ mService.dumpModels();
+ return true;
+
+ default:
+ printUsage();
+ return true;
+ }
+ }
+
+ private static void printUsage() {
+ System.out.print(
+ "Sound Trigger HAL v3 mock\n"
+ + "Available commands:\n"
+ + "h - help\n"
+ + "q - quit\n"
+ + "a - send onResourcesAvailable event\n"
+ + "u <model> - send modelUnloaded event\n"
+ + "r <model> <status> - send recognitionEvent\n"
+ + "p <model> <status> - send phraseRecognitionEvent\n"
+ + "d - dump models\n");
+ }
+
+ private static class SoundTriggerImpl extends ISoundTriggerHw.Stub {
+ static class Model {
+ final ISoundTriggerHwCallback callback;
+ final SoundModel model;
+ final PhraseSoundModel phraseModel;
+ public RecognitionConfig config = null;
+
+ Model(ISoundTriggerHwCallback callback, SoundModel model) {
+ this.callback = callback;
+ this.model = model;
+ this.phraseModel = null;
+ }
+
+ Model(ISoundTriggerHwCallback callback, PhraseSoundModel model) {
+ this.callback = callback;
+ this.model = null;
+ this.phraseModel = model;
+ }
+ }
+
+ private ISoundTriggerHwGlobalCallback mGlobalCallback;
+ private final ConcurrentMap<Integer, Model> mLoadedModels = new ConcurrentHashMap<>();
+ private int mHandleCounter = 1;
+
+ public void dumpModels() {
+ mLoadedModels.forEach((handle, model) -> {
+ System.out.println("+++ Model " + handle);
+ System.out.println(" config = " + model.config);
+ RecognitionConfig recognitionConfig = model.config;
+ if (recognitionConfig != null) {
+ System.out.println(" ACTIVE recognitionConfig = " + recognitionConfig);
+ } else {
+ System.out.println(" INACTIVE");
+ }
+ });
+ }
+
+ public void sendOnResourcesAvailable() {
+ if (mGlobalCallback != null) {
+ try {
+ mGlobalCallback.onResourcesAvailable();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void sendRecognitionEvent(int modelHandle, int status) {
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null && model.config != null) {
+ RecognitionEvent event = new RecognitionEvent();
+ event.type = SoundModelType.GENERIC;
+ event.status = status;
+ event.captureAvailable = true;
+ event.audioConfig.channelMask = 16;
+ event.audioConfig.format = 1;
+ event.audioConfig.sampleRateHz = 16000;
+ try {
+ model.callback.recognitionCallback(modelHandle, event);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ model.config = null;
+ }
+ }
+
+ public void sendPhraseRecognitionEvent(int modelHandle, int status) {
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null && model.config != null) {
+ PhraseRecognitionEvent event = new PhraseRecognitionEvent();
+ event.common = new RecognitionEvent();
+ event.common.type = SoundModelType.KEYPHRASE;
+ event.common.status = status;
+ event.common.captureAvailable = true;
+ event.common.audioConfig = new AudioConfig();
+ event.common.audioConfig.channelMask = 16;
+ event.common.audioConfig.format = 1;
+ event.common.audioConfig.sampleRateHz = 16000;
+ if (model.phraseModel.phrases.length > 0) {
+ PhraseRecognitionExtra extra = new PhraseRecognitionExtra();
+ extra.id = model.phraseModel.phrases[0].id;
+ extra.confidenceLevel = 100;
+ extra.recognitionModes = model.phraseModel.phrases[0].recognitionModes;
+ extra.levels = new ConfidenceLevel[0];
+ event.phraseExtras = new PhraseRecognitionExtra[]{extra};
+ } else {
+ event.phraseExtras = new PhraseRecognitionExtra[0];
+ }
+ try {
+ model.callback.phraseRecognitionCallback(modelHandle, event);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ model.config = null;
+ }
+ }
+
+ public void sendModelUnloaded(int modelHandle) {
+ Model model = mLoadedModels.remove(modelHandle);
+ if (model != null) {
+ try {
+ model.callback.modelUnloaded(modelHandle);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public void registerGlobalCallback(ISoundTriggerHwGlobalCallback callback) {
+ System.out.println("registerGlobalCallback()");
+ mGlobalCallback = callback;
+ }
+
+ @Override
+ public int loadSoundModel(SoundModel soundModel, ISoundTriggerHwCallback callback) {
+ int handle = mHandleCounter++;
+ System.out.printf("loadSoundModel(soundModel=%s) -> %d%n", soundModel, handle);
+ mLoadedModels.put(handle, new Model(callback, soundModel));
+ return handle;
+ }
+
+ @Override
+ public int loadPhraseSoundModel(PhraseSoundModel soundModel,
+ ISoundTriggerHwCallback callback) {
+ int handle = mHandleCounter++;
+ System.out.printf("loadPhraseSoundModel(soundModel=%s) -> %d%n", soundModel, handle);
+ mLoadedModels.put(handle, new Model(callback, soundModel));
+ return handle;
+ }
+
+ @Override
+ public void startRecognition(int modelHandle, int deviceHandle, int ioHandle,
+ RecognitionConfig config) {
+ System.out.printf("startRecognition(modelHandle=%d, deviceHandle=%d, ioHandle=%d)%n",
+ modelHandle, deviceHandle, ioHandle);
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null) {
+ model.config = config;
+ }
+ }
+
+ @Override
+ public Properties getProperties() {
+ System.out.println("getProperties()");
+ Properties properties = new Properties();
+ properties.implementor = "Android";
+ properties.description = "Mock STHAL";
+ properties.maxSoundModels = 2;
+ properties.maxKeyPhrases = 1;
+ properties.recognitionModes =
+ RecognitionMode.VOICE_TRIGGER | RecognitionMode.GENERIC_TRIGGER;
+ return properties;
+ }
+
+ @Override
+ public ModelParameterRange queryParameter(int modelHandle, int modelParam) {
+ System.out.printf("queryParameter(modelHandle=%d, modelParam=%d)%n", modelHandle,
+ modelParam);
+ return null;
+ }
+
+ @Override
+ public void forceRecognitionEvent(int modelHandle) {
+ System.out.printf("getModelState(modelHandle=%d)%n", modelHandle);
+ }
+
+ @Override
+ public void unloadSoundModel(int modelHandle) {
+ System.out.printf("unloadSoundModel(modelHandle=%d)%n", modelHandle);
+ }
+
+ @Override
+ public void stopRecognition(int modelHandle) {
+ System.out.printf("stopRecognition(modelHandle=%d)%n", modelHandle);
+ Model model = mLoadedModels.get(modelHandle);
+ if (model != null) {
+ model.config = null;
+ }
+ }
+
+ @Override
+ public int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ if (args.length > 0) {
+ switch (args[0]) {
+ case "reboot":
+ System.out.println("Received a reboot request. Exiting.");
+ cleanup();
+ System.exit(1);
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public void setParameter(int modelHandle, int modelParam, int value) {
+ throw new IllegalArgumentException();
+ }
+
+ @Override
+ public int getParameter(int modelHandle, int modelParam) {
+ throw new IllegalArgumentException();
+ }
+ }
+}
diff --git a/soundtrigger/aidl/cli/sthal_cli_3 b/soundtrigger/aidl/cli/sthal_cli_3
new file mode 100644
index 0000000..f157c50
--- /dev/null
+++ b/soundtrigger/aidl/cli/sthal_cli_3
@@ -0,0 +1,6 @@
+#!/system/bin/sh
+# Script to start "sthal_cli_3" on the device
+#
+base=/system
+export CLASSPATH=$base/framework/sthal_cli_3.jar
+exec app_process $base/bin android.hardware.soundtrigger3.cli.SthalCli "$@"
diff --git a/tv/cec/1.0/default/OWNERS b/tv/cec/1.0/default/OWNERS
new file mode 100644
index 0000000..c1d3f1d
--- /dev/null
+++ b/tv/cec/1.0/default/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index f470245..a7792f5 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -16,7 +16,7 @@
#include "FilterTests.h"
-void FilterCallback::startFilterEventThread(DemuxFilterEvent event) {
+void FilterCallback::startFilterEventThread(DemuxFilterEvent& event) {
struct FilterThreadArgs* threadArgs =
(struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
threadArgs->user = this;
@@ -69,9 +69,8 @@
// end thread
}
-bool FilterCallback::readFilterEventData() {
+bool FilterCallback::readFilterEventData(const DemuxFilterEvent& filterEvent) {
bool result = false;
- DemuxFilterEvent filterEvent = mFilterEvent;
ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
// todo separate filter handlers
for (auto event : filterEvent.events) {
@@ -107,7 +106,7 @@
return result;
}
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent& event) {
uint32_t length = event.dataLength;
uint64_t dataId = event.avDataId;
// read data from buffer pointed by a handle
@@ -127,7 +126,7 @@
return true;
}
-bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent event) {
+bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent& event) {
ALOGD("[vts] got DemuxFilterTsRecordEvent with pid=%d.", event.pid.tPid());
return true;
}
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 7bc4832..d37b9e1 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -77,8 +77,7 @@
android::Mutex::Autolock autoLock(mMsgLock);
// Temprarily we treat the first coming back filter data on the matching pid a success
// once all of the MQ are cleared, means we got all the expected output
- mFilterEvent = filterEvent;
- readFilterEventData();
+ readFilterEventData(filterEvent);
mPidFilterOutputCount++;
// mFilterIdToMQ.erase(filterEvent.filterId);
@@ -96,15 +95,15 @@
void testFilterDataOutput();
- void startFilterEventThread(DemuxFilterEvent event);
+ void startFilterEventThread(DemuxFilterEvent& event);
static void* __threadLoopFilter(void* threadArgs);
void filterThreadLoop(DemuxFilterEvent& event);
void updateFilterMQ(MQDesc& filterMQDescriptor);
void updateGoldenOutputMap(string goldenOutputFile);
- bool readFilterEventData();
- bool dumpAvData(DemuxFilterMediaEvent event);
- bool readRecordData(DemuxFilterTsRecordEvent event);
+ bool readFilterEventData(const DemuxFilterEvent& filterEvent);
+ bool dumpAvData(DemuxFilterMediaEvent& event);
+ bool readRecordData(DemuxFilterTsRecordEvent& event);
private:
struct FilterThreadArgs {
@@ -120,7 +119,6 @@
sp<IFilter> mFilter;
std::unique_ptr<FilterMQ> mFilterMQ;
EventFlag* mFilterMQEventFlag;
- DemuxFilterEvent mFilterEvent;
android::Mutex mMsgLock;
android::Mutex mFilterOutputLock;
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index b35d112..62ac6f7 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -370,11 +370,12 @@
mIsSoftwareFe = config.isSoftwareFe;
bool result = true;
if (mIsSoftwareFe && testWithDemux) {
- result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
- result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
- result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
- mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
- mDvrConfig.settings.playback());
+ result &=
+ getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
+ result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
+ result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
+ getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
+ mDvrConfig.settings.playback());
if (!result) {
ALOGW("[vts] Software frontend dvr configure failed.");
return failure();
@@ -397,8 +398,8 @@
Result status;
status = mFrontend->stopTune();
if (mIsSoftwareFe && testWithDemux) {
- mDvrTests.stopPlaybackThread();
- mDvrTests.closeDvrPlayback();
+ getDvrTests()->stopPlaybackThread();
+ getDvrTests()->closeDvrPlayback();
}
return AssertionResult(status == Result::SUCCESS);
}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 33ff603..c789d94 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -103,7 +103,7 @@
void setService(sp<ITuner> tuner) {
mService = tuner;
- mDvrTests.setService(tuner);
+ getDvrTests()->setService(tuner);
getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
}
@@ -124,8 +124,8 @@
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
- void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
- void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+ void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
+ void setDemux(sp<IDemux> demux) { getDvrTests()->setDemux(demux); }
void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
protected:
@@ -147,11 +147,16 @@
dvrConfig.settings.playback(playbackSettings);
}
+ DvrTests* getDvrTests() {
+ return (mExternalDvrTests != nullptr ? mExternalDvrTests : &mDvrTests);
+ }
+
sp<IFrontend> mFrontend;
FrontendInfo mFrontendInfo;
sp<FrontendCallback> mFrontendCallback;
hidl_vec<FrontendId> mFeIds;
+ DvrTests* mExternalDvrTests = nullptr;
DvrTests mDvrTests;
bool mIsSoftwareFe = false;
DvrConfig mDvrConfig;
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index b39abe3..3e3a4d4 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -177,7 +177,7 @@
mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
}
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
- mFrontendTests.setDvrTests(mDvrTests);
+ mFrontendTests.setDvrTests(&mDvrTests);
} else {
dvrSourceConfig = dvrMap[record.dvrSourceId];
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 7243a42..0b84b58 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -50,7 +50,7 @@
return true;
}
-AssertionResult filterDataOutputTestBase(FilterTests tests) {
+AssertionResult filterDataOutputTestBase(FilterTests& tests) {
// Data Verify Module
std::map<uint32_t, sp<FilterCallback>>::iterator it;
std::map<uint32_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
index 4dff853..8bdf8f6 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -64,11 +64,11 @@
ALOGW("[vts] pass and stop");
}
-void FilterCallback::readFilterEventData() {
+void FilterCallback::readFilterEventData(const DemuxFilterEvent& filterEvent) {
ALOGW("[vts] reading filter event");
// todo separate filter handlers
- for (int i = 0; i < mFilterEvent.events.size(); i++) {
- auto event = mFilterEvent.events[i];
+ for (int i = 0; i < filterEvent.events.size(); i++) {
+ auto event = filterEvent.events[i];
switch (event.getDiscriminator()) {
case DemuxFilterEvent::Event::hidl_discriminator::media:
ALOGD("[vts] Media filter event, avMemHandle numFds=%d.",
@@ -79,8 +79,13 @@
break;
}
}
- for (int i = 0; i < mFilterEventExt.events.size(); i++) {
- auto eventExt = mFilterEventExt.events[i];
+}
+
+void FilterCallback::readFilterEventExtData(const DemuxFilterEventExt& filterEventExt) {
+ ALOGW("[vts] reading filter event ext");
+ // todo separate filter handlers
+ for (int i = 0; i < filterEventExt.events.size(); i++) {
+ auto eventExt = filterEventExt.events[i];
switch (eventExt.getDiscriminator()) {
case DemuxFilterEventExt::Event::hidl_discriminator::tsRecord:
ALOGD("[vts] Extended TS record filter event, pts=%" PRIu64 ", firstMbInSlice=%d",
@@ -114,7 +119,7 @@
}
}
-bool FilterCallback::dumpAvData(DemuxFilterMediaEvent event) {
+bool FilterCallback::dumpAvData(DemuxFilterMediaEvent& event) {
uint32_t length = event.dataLength;
uint32_t offset = event.offset;
// read data from buffer pointed by a handle
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h
index 72c8129..1a1273e 100644
--- a/tv/tuner/1.1/vts/functional/FilterTests.h
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -88,9 +88,8 @@
android::Mutex::Autolock autoLock(mMsgLock);
// Temprarily we treat the first coming back filter data on the matching pid a success
// once all of the MQ are cleared, means we got all the expected output
- mFilterEvent = filterEvent;
- mFilterEventExt = filterEventExt;
- readFilterEventData();
+ readFilterEventData(filterEvent);
+ readFilterEventExtData(filterEventExt);
mPidFilterOutputCount++;
mMsgCondition.signal();
return Void();
@@ -101,8 +100,7 @@
android::Mutex::Autolock autoLock(mMsgLock);
// Temprarily we treat the first coming back filter data on the matching pid a success
// once all of the MQ are cleared, means we got all the expected output
- mFilterEvent = filterEvent;
- readFilterEventData();
+ readFilterEventData(filterEvent);
mPidFilterOutputCount++;
mMsgCondition.signal();
return Void();
@@ -115,7 +113,7 @@
void setFilterId(uint32_t filterId) { mFilterId = filterId; }
void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
- void setSharedHandle(hidl_handle sharedHandle) { mAvSharedHandle = sharedHandle; }
+ void setSharedHandle(hidl_handle& sharedHandle) { mAvSharedHandle = sharedHandle; }
void setMemSize(uint64_t size) { mAvSharedMemSize = size; }
void testFilterDataOutput();
@@ -123,15 +121,14 @@
void testFilterIpCidEvent();
void testStartIdAfterReconfigure();
- void readFilterEventData();
- bool dumpAvData(DemuxFilterMediaEvent event);
+ void readFilterEventData(const DemuxFilterEvent& filterEvent);
+ void readFilterEventExtData(const DemuxFilterEventExt& filterEventExt);
+ bool dumpAvData(DemuxFilterMediaEvent& event);
private:
uint32_t mFilterId;
sp<IFilter> mFilter;
FilterEventType mFilterEventType;
- DemuxFilterEvent mFilterEvent;
- DemuxFilterEventExt mFilterEventExt;
hidl_handle mAvSharedHandle = NULL;
uint64_t mAvSharedMemSize = -1;
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
index 9c575ff..9c0933e 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -437,11 +437,12 @@
mIsSoftwareFe = config.config1_0.isSoftwareFe;
bool result = true;
if (mIsSoftwareFe && testWithDemux) {
- result &= mDvrTests.openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
- result &= mDvrTests.configDvrPlayback(mDvrConfig.settings) == success();
- result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
- mDvrTests.startPlaybackInputThread(mDvrConfig.playbackInputFile,
- mDvrConfig.settings.playback());
+ result &=
+ getDvrTests()->openDvrInDemux(mDvrConfig.type, mDvrConfig.bufferSize) == success();
+ result &= getDvrTests()->configDvrPlayback(mDvrConfig.settings) == success();
+ result &= getDvrTests()->getDvrPlaybackMQDescriptor() == success();
+ getDvrTests()->startPlaybackInputThread(mDvrConfig.playbackInputFile,
+ mDvrConfig.settings.playback());
if (!result) {
ALOGW("[vts] Software frontend dvr configure failed.");
return failure();
@@ -456,8 +457,8 @@
Result status;
status = mFrontend->stopTune();
if (mIsSoftwareFe && testWithDemux) {
- mDvrTests.stopPlaybackThread();
- mDvrTests.closeDvrPlayback();
+ getDvrTests()->stopPlaybackThread();
+ getDvrTests()->closeDvrPlayback();
}
return AssertionResult(status == Result::SUCCESS);
}
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
index 3687389..03e5417 100644
--- a/tv/tuner/1.1/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -106,7 +106,7 @@
void setService(sp<ITuner> tuner) {
mService = tuner;
- mDvrTests.setService(tuner);
+ getDvrTests()->setService(tuner);
getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
}
@@ -131,8 +131,8 @@
void scanTest(FrontendConfig1_1 frontend, FrontendScanType type);
void getFrontendDtmbCapsTest();
- void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
- void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+ void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
+ void setDemux(sp<IDemux> demux) { getDvrTests()->setDemux(demux); }
void setSoftwareFrontendDvrConfig(DvrConfig conf) { mDvrConfig = conf; }
protected:
@@ -153,11 +153,16 @@
dvrConfig.settings.playback(playbackSettings);
}
+ DvrTests* getDvrTests() {
+ return (mExternalDvrTests != nullptr ? mExternalDvrTests : &mDvrTests);
+ }
+
sp<IFrontend> mFrontend;
FrontendInfo mFrontendInfo;
sp<FrontendCallback> mFrontendCallback;
hidl_vec<FrontendId> mFeIds;
+ DvrTests* mExternalDvrTests = nullptr;
DvrTests mDvrTests;
bool mIsSoftwareFe = false;
DvrConfig mDvrConfig;
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
index 1a9def8..41acaa1 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -147,7 +147,7 @@
mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
}
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
- mFrontendTests.setDvrTests(mDvrTests);
+ mFrontendTests.setDvrTests(&mDvrTests);
} else {
dvrSourceConfig = dvrMap[record.dvrSourceId];
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
index 13b9640..d1a9bea 100644
--- a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -39,7 +39,7 @@
return ::testing::AssertionSuccess();
}
-AssertionResult filterDataOutputTestBase(FilterTests tests) {
+AssertionResult filterDataOutputTestBase(FilterTests& tests) {
// Data Verify Module
std::map<uint64_t, sp<FilterCallback>>::iterator it;
std::map<uint64_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
diff --git a/vibrator/bench/Android.bp b/vibrator/bench/Android.bp
index e4c9cfb..73e274f 100644
--- a/vibrator/bench/Android.bp
+++ b/vibrator/bench/Android.bp
@@ -29,7 +29,7 @@
"benchmark.cpp",
],
shared_libs: [
- "android.hardware.vibrator-V1-cpp",
+ "android.hardware.vibrator-V2-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",