Merge "wifi: uprev supplicant interface to 1.4"
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index 5a1105c..083f4f0 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -34,7 +34,7 @@
static constexpr can_err_mask_t kErrMask = CAN_ERR_MASK;
base::unique_fd socket(const std::string& ifname) {
- struct sockaddr_can addr = {};
+ sockaddr_can addr = {};
addr.can_family = AF_CAN;
addr.can_ifindex = nametoindex(ifname);
if (addr.can_ifindex == 0) {
@@ -58,7 +58,7 @@
return {};
}
- if (0 != bind(sock.get(), reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) {
+ if (0 != bind(sock.get(), reinterpret_cast<sockaddr*>(&addr), sizeof(addr))) {
LOG(ERROR) << "Can't bind to CAN interface " << ifname;
return {};
}
@@ -67,26 +67,25 @@
}
bool setBitrate(std::string ifname, uint32_t bitrate) {
- struct can_bittiming bt = {};
+ can_bittiming bt = {};
bt.bitrate = bitrate;
- nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
+ nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
- const auto ifidx = nametoindex(ifname);
- if (ifidx == 0) {
+ req->ifi_index = nametoindex(ifname);
+ if (req->ifi_index == 0) {
LOG(ERROR) << "Can't find interface " << ifname;
return false;
}
- req.data().ifi_index = ifidx;
{
- auto linkinfo = req.nest(IFLA_LINKINFO);
- req.addattr(IFLA_INFO_KIND, "can");
+ auto linkinfo = req.addNested(IFLA_LINKINFO);
+ req.add(IFLA_INFO_KIND, "can");
{
- auto infodata = req.nest(IFLA_INFO_DATA);
+ auto infodata = req.addNested(IFLA_INFO_DATA);
/* For CAN FD, it would require to add IFLA_CAN_DATA_BITTIMING
* and IFLA_CAN_CTRLMODE as well. */
- req.addattr(IFLA_CAN_BITTIMING, bt);
+ req.add(IFLA_CAN_BITTIMING, bt);
}
}
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
index 9a26ff1..70cb688 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
@@ -20,6 +20,7 @@
#include <array>
#include <optional>
+#include <set>
#include <string>
namespace android::netdevice {
@@ -53,14 +54,34 @@
std::optional<bool> isUp(std::string ifname);
/**
- * Checks, if the network interface exists and is up.
- *
- * This is a convenience function to call both exists() and isUp().
- *
- * \param ifname Interface to check
- * \return true if the interface is up, false otherwise
+ * Interface condition to wait for.
*/
-bool existsAndIsUp(const std::string& ifname);
+enum class WaitCondition {
+ /**
+ * Interface is present (but not necessarily up).
+ */
+ PRESENT,
+
+ /**
+ * Interface is up.
+ */
+ PRESENT_AND_UP,
+
+ /**
+ * Interface is down or not present (disconnected) at all.
+ */
+ DOWN_OR_GONE,
+};
+
+/**
+ * Listens for interface changes until anticipated condition takes place.
+ *
+ * \param ifnames List of interfaces to watch for.
+ * \param cnd Awaited condition.
+ * \param allOf true if all interfaces need to satisfy the condition, false if only one satistying
+ * interface should stop the wait.
+ */
+void waitFor(std::set<std::string> ifnames, WaitCondition cnd, bool allOf = true);
/**
* Brings network interface up.
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index e2ba2cb..4c5b309 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -27,6 +27,8 @@
#include <linux/rtnetlink.h>
#include <net/if.h>
+#include <sstream>
+
namespace android::netdevice {
void useSocketDomain(int domain) {
@@ -37,16 +39,6 @@
return nametoindex(ifname) != 0;
}
-std::optional<bool> isUp(std::string ifname) {
- auto ifr = ifreqs::fromName(ifname);
- if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt;
- return ifr.ifr_flags & IFF_UP;
-}
-
-bool existsAndIsUp(const std::string& ifname) {
- return exists(ifname) && isUp(ifname).value_or(false);
-}
-
bool up(std::string ifname) {
auto ifr = ifreqs::fromName(ifname);
if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
@@ -62,13 +54,13 @@
}
bool add(std::string dev, std::string type) {
- nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
- req.addattr(IFLA_IFNAME, dev);
+ nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
+ NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
+ req.add(IFLA_IFNAME, dev);
{
- auto linkinfo = req.nest(IFLA_LINKINFO);
- req.addattr(IFLA_INFO_KIND, type);
+ auto linkinfo = req.addNested(IFLA_LINKINFO);
+ req.add(IFLA_INFO_KIND, type);
}
nl::Socket sock(NETLINK_ROUTE);
@@ -76,8 +68,8 @@
}
bool del(std::string dev) {
- nl::MessageFactory<struct ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
- req.addattr(IFLA_IFNAME, dev);
+ nl::MessageFactory<ifinfomsg> req(RTM_DELLINK, NLM_F_REQUEST | NLM_F_ACK);
+ req.add(IFLA_IFNAME, dev);
nl::Socket sock(NETLINK_ROUTE);
return sock.send(req) && sock.receiveAck(req);
@@ -102,6 +94,97 @@
return ifreqs::send(SIOCSIFHWADDR, ifr);
}
+std::optional<bool> isUp(std::string ifname) {
+ auto ifr = ifreqs::fromName(ifname);
+ if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt;
+ return ifr.ifr_flags & IFF_UP;
+}
+
+struct WaitState {
+ bool present;
+ bool up;
+
+ bool satisfied(WaitCondition cnd) const {
+ switch (cnd) {
+ case WaitCondition::PRESENT:
+ if (present) return true;
+ break;
+ case WaitCondition::PRESENT_AND_UP:
+ if (present && up) return true;
+ break;
+ case WaitCondition::DOWN_OR_GONE:
+ if (!present || !up) return true;
+ break;
+ }
+ return false;
+ }
+};
+
+static std::string toString(WaitCondition cnd) {
+ switch (cnd) {
+ case WaitCondition::PRESENT:
+ return "become present";
+ case WaitCondition::PRESENT_AND_UP:
+ return "come up";
+ case WaitCondition::DOWN_OR_GONE:
+ return "go down";
+ }
+}
+
+static std::string toString(const std::set<std::string>& ifnames) {
+ std::stringstream ss;
+ std::copy(ifnames.begin(), ifnames.end(), std::ostream_iterator<std::string>(ss, ","));
+ auto str = ss.str();
+ str.pop_back();
+ return str;
+}
+
+void waitFor(std::set<std::string> ifnames, WaitCondition cnd, bool allOf) {
+ nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK);
+
+ using StatesMap = std::map<std::string, WaitState>;
+ StatesMap states = {};
+ for (const auto ifname : ifnames) {
+ const auto present = exists(ifname);
+ const auto up = present && isUp(ifname).value_or(false);
+ states[ifname] = {present, up};
+ }
+
+ const auto mapConditionChecker = [cnd](const StatesMap::iterator::value_type& it) {
+ return it.second.satisfied(cnd);
+ };
+ const auto isFullySatisfied = [&states, allOf, mapConditionChecker]() {
+ if (allOf) {
+ return std::all_of(states.begin(), states.end(), mapConditionChecker);
+ } else {
+ return std::any_of(states.begin(), states.end(), mapConditionChecker);
+ }
+ };
+
+ if (isFullySatisfied()) return;
+
+ LOG(DEBUG) << "Waiting for " << (allOf ? "" : "any of ") << toString(ifnames) << " to "
+ << toString(cnd);
+ for (const auto rawMsg : sock) {
+ const auto msg = nl::Message<ifinfomsg>::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK});
+ if (!msg.has_value()) continue;
+
+ const auto ifname = msg->attributes.get<std::string>(IFLA_IFNAME);
+ if (ifnames.count(ifname) == 0) continue;
+
+ const bool present = (msg->header.nlmsg_type != RTM_DELLINK);
+ const bool up = present && (msg->data.ifi_flags & IFF_UP) != 0;
+ states[ifname] = {present, up};
+
+ if (isFullySatisfied()) {
+ LOG(DEBUG) << "Finished waiting for " << (allOf ? "" : "some of ") << toString(ifnames)
+ << " to " << toString(cnd);
+ return;
+ }
+ }
+ LOG(FATAL) << "Can't read Netlink socket";
+}
+
} // namespace android::netdevice
bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]) {
diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp
index 33dc029..ee02f7b 100644
--- a/automotive/can/1.0/default/libnetdevice/vlan.cpp
+++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp
@@ -33,18 +33,18 @@
return false;
}
- nl::MessageFactory<struct ifinfomsg> req(RTM_NEWLINK,
- NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
- req.addattr(IFLA_IFNAME, vlan);
- req.addattr<uint32_t>(IFLA_LINK, ethidx);
+ nl::MessageFactory<ifinfomsg> req(RTM_NEWLINK,
+ NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK);
+ req.add(IFLA_IFNAME, vlan);
+ req.add<uint32_t>(IFLA_LINK, ethidx);
{
- auto linkinfo = req.nest(IFLA_LINKINFO);
- req.addattr(IFLA_INFO_KIND, "vlan");
+ auto linkinfo = req.addNested(IFLA_LINKINFO);
+ req.add(IFLA_INFO_KIND, "vlan");
{
- auto linkinfo = req.nest(IFLA_INFO_DATA);
- req.addattr(IFLA_VLAN_ID, id);
+ auto linkinfo = req.addNested(IFLA_INFO_DATA);
+ req.add(IFLA_VLAN_ID, id);
}
}
diff --git a/automotive/can/1.0/default/libnl++/Attributes.cpp b/automotive/can/1.0/default/libnl++/Attributes.cpp
index c101647..620f57b 100644
--- a/automotive/can/1.0/default/libnl++/Attributes.cpp
+++ b/automotive/can/1.0/default/libnl++/Attributes.cpp
@@ -49,7 +49,11 @@
template <>
std::string Attributes::parse(Buffer<nlattr> buf) {
const auto rawString = buf.data<char>().getRaw();
- return std::string(rawString.ptr(), rawString.len());
+ std::string str(rawString.ptr(), rawString.len());
+
+ str.erase(std::find(str.begin(), str.end(), '\0'), str.end());
+
+ return str;
}
template <typename T>
diff --git a/automotive/can/1.0/default/libnl++/MessageFactory.cpp b/automotive/can/1.0/default/libnl++/MessageFactory.cpp
index 0c6a331..6f35897 100644
--- a/automotive/can/1.0/default/libnl++/MessageFactory.cpp
+++ b/automotive/can/1.0/default/libnl++/MessageFactory.cpp
@@ -17,41 +17,36 @@
#include <libnl++/MessageFactory.h>
#include <android-base/logging.h>
+#include <libnl++/bits.h>
-// for RTA_ macros missing from NLA_ definitions
-#include <linux/rtnetlink.h>
+namespace android::nl {
-namespace android::nl::impl {
-
-static struct nlattr* nlmsg_tail(struct nlmsghdr* n) {
- return reinterpret_cast<struct nlattr*>( //
- reinterpret_cast<uintptr_t>(n) + NLMSG_ALIGN(n->nlmsg_len));
+static nlattr* tail(nlmsghdr* msg) {
+ return reinterpret_cast<nlattr*>(uintptr_t(msg) + impl::align(msg->nlmsg_len));
}
-struct nlattr* addattr_l(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type, const void* data,
- size_t dataLen) {
- size_t newLen = NLMSG_ALIGN(n->nlmsg_len) + RTA_SPACE(dataLen);
+nlattr* MessageFactoryBase::add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data,
+ size_t dataLen) {
+ const auto totalAttrLen = impl::space<nlattr>(dataLen);
+ const auto newLen = impl::align(msg->nlmsg_len) + totalAttrLen;
if (newLen > maxLen) {
- LOG(ERROR) << "addattr_l failed - exceeded maxLen: " << newLen << " > " << maxLen;
+ LOG(ERROR) << "Can't add attribute of size " << dataLen //
+ << " - exceeded maxLen: " << newLen << " > " << maxLen;
return nullptr;
}
- auto attr = nlmsg_tail(n);
- attr->nla_len = RTA_SPACE(dataLen);
+ auto attr = tail(msg);
+ attr->nla_len = totalAttrLen;
attr->nla_type = type;
- if (dataLen > 0) memcpy(RTA_DATA(attr), data, dataLen);
+ if (dataLen > 0) memcpy(impl::data<nlattr, void>(attr), data, dataLen);
- n->nlmsg_len = newLen;
+ msg->nlmsg_len = newLen;
return attr;
}
-struct nlattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type) {
- return addattr_l(n, maxLen, type, nullptr, 0);
+void MessageFactoryBase::closeNested(nlmsghdr* msg, nlattr* nested) {
+ if (nested == nullptr) return;
+ nested->nla_len = uintptr_t(tail(msg)) - uintptr_t(nested);
}
-void addattr_nest_end(struct nlmsghdr* n, struct nlattr* nest) {
- size_t nestLen = reinterpret_cast<uintptr_t>(nlmsg_tail(n)) - reinterpret_cast<uintptr_t>(nest);
- nest->nla_len = nestLen;
-}
-
-} // namespace android::nl::impl
+} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/Socket.cpp b/automotive/can/1.0/default/libnl++/Socket.cpp
index 1a34df8..08683ca 100644
--- a/automotive/can/1.0/default/libnl++/Socket.cpp
+++ b/automotive/can/1.0/default/libnl++/Socket.cpp
@@ -49,8 +49,8 @@
bool Socket::send(const Buffer<nlmsghdr>& msg, const sockaddr_nl& sa) {
if constexpr (kSuperVerbose) {
- LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending Netlink message (" //
- << msg->nlmsg_pid << " -> " << sa.nl_pid << "): " << toString(msg, mProtocol);
+ LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending to " << sa.nl_pid << ": "
+ << toString(msg, mProtocol);
}
if (mFailed) return false;
@@ -68,6 +68,16 @@
return true;
}
+bool Socket::increaseReceiveBuffer(size_t maxSize) {
+ if (maxSize == 0) {
+ LOG(ERROR) << "Maximum receive size should not be zero";
+ return false;
+ }
+
+ if (mReceiveBuffer.size() < maxSize) mReceiveBuffer.resize(maxSize);
+ return true;
+}
+
std::optional<Buffer<nlmsghdr>> Socket::receive(size_t maxSize) {
return receiveFrom(maxSize).first;
}
@@ -75,11 +85,7 @@
std::pair<std::optional<Buffer<nlmsghdr>>, sockaddr_nl> Socket::receiveFrom(size_t maxSize) {
if (mFailed) return {std::nullopt, {}};
- if (maxSize == 0) {
- LOG(ERROR) << "Maximum receive size should not be zero";
- return {std::nullopt, {}};
- }
- if (mReceiveBuffer.size() < maxSize) mReceiveBuffer.resize(maxSize);
+ if (!increaseReceiveBuffer(maxSize)) return {std::nullopt, {}};
sockaddr_nl sa = {};
socklen_t saLen = sizeof(sa);
@@ -97,8 +103,7 @@
Buffer<nlmsghdr> msg(reinterpret_cast<nlmsghdr*>(mReceiveBuffer.data()), bytesReceived);
if constexpr (kSuperVerbose) {
- LOG(VERBOSE) << "received (" << sa.nl_pid << " -> " << msg->nlmsg_pid << "):" //
- << toString(msg, mProtocol);
+ LOG(VERBOSE) << "received from " << sa.nl_pid << ": " << toString(msg, mProtocol);
}
return {msg, sa};
}
@@ -121,19 +126,16 @@
std::optional<Buffer<nlmsghdr>> Socket::receive(const std::set<nlmsgtype_t>& msgtypes,
size_t maxSize) {
- while (!mFailed) {
- const auto msgBuf = receive(maxSize);
- if (!msgBuf.has_value()) return std::nullopt;
+ if (mFailed || !increaseReceiveBuffer(maxSize)) return std::nullopt;
- for (const auto rawMsg : *msgBuf) {
- if (msgtypes.count(rawMsg->nlmsg_type) == 0) {
- LOG(WARNING) << "Received (and ignored) unexpected Netlink message of type "
- << rawMsg->nlmsg_type;
- continue;
- }
-
- return rawMsg;
+ for (const auto rawMsg : *this) {
+ if (msgtypes.count(rawMsg->nlmsg_type) == 0) {
+ LOG(WARNING) << "Received (and ignored) unexpected Netlink message of type "
+ << rawMsg->nlmsg_type;
+ continue;
}
+
+ return rawMsg;
}
return std::nullopt;
@@ -151,4 +153,47 @@
return sa.nl_pid;
}
+Socket::receive_iterator::receive_iterator(Socket& socket, bool end)
+ : mSocket(socket), mIsEnd(end) {
+ if (!end) receive();
+}
+
+Socket::receive_iterator Socket::receive_iterator::operator++() {
+ CHECK(!mIsEnd) << "Trying to increment end iterator";
+ ++mCurrent;
+ if (mCurrent.isEnd()) receive();
+ return *this;
+}
+
+bool Socket::receive_iterator::operator==(const receive_iterator& other) const {
+ if (mIsEnd != other.mIsEnd) return false;
+ if (mIsEnd && other.mIsEnd) return true;
+ return mCurrent == other.mCurrent;
+}
+
+const Buffer<nlmsghdr>& Socket::receive_iterator::operator*() const {
+ CHECK(!mIsEnd) << "Trying to dereference end iterator";
+ return *mCurrent;
+}
+
+void Socket::receive_iterator::receive() {
+ CHECK(!mIsEnd) << "Trying to receive on end iterator";
+ CHECK(mCurrent.isEnd()) << "Trying to receive without draining previous read";
+
+ const auto buf = mSocket.receive();
+ if (buf.has_value()) {
+ mCurrent = buf->begin();
+ } else {
+ mIsEnd = true;
+ }
+}
+
+Socket::receive_iterator Socket::begin() {
+ return {*this, false};
+}
+
+Socket::receive_iterator Socket::end() {
+ return {*this, true};
+}
+
} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/common.cpp b/automotive/can/1.0/default/libnl++/common.cpp
index 74eee24..23c2d94 100644
--- a/automotive/can/1.0/default/libnl++/common.cpp
+++ b/automotive/can/1.0/default/libnl++/common.cpp
@@ -32,9 +32,7 @@
return 0;
}
-std::string sanitize(std::string str) {
- str.erase(std::find(str.begin(), str.end(), '\0'), str.end());
-
+std::string printableOnly(std::string str) {
const auto isInvalid = [](char c) { return !isprint(c); };
std::replace_if(str.begin(), str.end(), isInvalid, '?');
diff --git a/automotive/can/1.0/default/libnl++/common.h b/automotive/can/1.0/default/libnl++/common.h
index 1d9dbab..38263c5 100644
--- a/automotive/can/1.0/default/libnl++/common.h
+++ b/automotive/can/1.0/default/libnl++/common.h
@@ -37,11 +37,14 @@
unsigned int nametoindex(const std::string& ifname);
/**
- * Sanitize a string of unknown contents.
+ * Filter a string against non-printable characters.
*
- * Trims the string to the first '\0' character and replaces all non-printable characters with '?'.
+ * Replaces all non-printable characters with '?'.
+ *
+ * \param str String to filter.
+ * \return Filtered string.
*/
-std::string sanitize(std::string str);
+std::string printableOnly(std::string str);
/**
* Calculates a (optionally running) CRC16 checksum.
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 a6f8f7a..bf83fbc 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
@@ -17,6 +17,7 @@
#pragma once
#include <android-base/logging.h>
+#include <libnl++/bits.h>
#include <linux/netlink.h>
@@ -25,7 +26,7 @@
namespace android::nl {
/**
- * Buffer wrapper containing netlink structure (e.g. struct nlmsghdr, struct nlattr).
+ * Buffer wrapper containing netlink structure (e.g. nlmsghdr, nlattr).
*
* This is a C++-style, memory safe(r) and generic implementation of linux/netlink.h macros.
*
@@ -43,15 +44,6 @@
*/
template <typename T>
class Buffer {
- // The following definitions are C++ equivalents of NLMSG_* macros from linux/netlink.h
-
- static constexpr size_t alignto = NLMSG_ALIGNTO;
- static_assert(NLMSG_ALIGNTO == NLA_ALIGNTO);
-
- static constexpr size_t align(size_t ptr) { return (ptr + alignto - 1) & ~(alignto - 1); }
-
- static constexpr size_t hdrlen = align(sizeof(T));
-
public:
/**
* Constructs empty buffer of size 0.
@@ -96,35 +88,35 @@
template <typename D>
const Buffer<D> data(size_t offset = 0) const {
- // Equivalent to NLMSG_DATA(hdr) + NLMSG_ALIGN(offset)
- const D* dptr = reinterpret_cast<const D*>(uintptr_t(mData) + hdrlen + align(offset));
- return {dptr, dataEnd()};
+ return {impl::data<const T, const D>(mData, offset), dataEnd()};
}
class iterator {
public:
iterator() : mCurrent(nullptr, size_t(0)) {
- CHECK(!mCurrent.ok()) << "end() iterator should indicate it's beyond end";
+ CHECK(isEnd()) << "end() iterator should indicate it's beyond end";
}
iterator(const Buffer<T>& buf) : mCurrent(buf) {}
iterator operator++() {
// mBufferEnd stays the same
mCurrent.mData = reinterpret_cast<const T*>( //
- uintptr_t(mCurrent.mData) + align(mCurrent.declaredLength()));
+ uintptr_t(mCurrent.mData) + impl::align(mCurrent.declaredLength()));
return *this;
}
bool operator==(const iterator& other) const {
// all iterators beyond end are the same
- if (!mCurrent.ok() && !other.mCurrent.ok()) return true;
+ if (isEnd() && other.isEnd()) return true;
return uintptr_t(other.mCurrent.mData) == uintptr_t(mCurrent.mData);
}
const Buffer<T>& operator*() const { return mCurrent; }
+ bool isEnd() const { return !mCurrent.ok(); }
+
protected:
Buffer<T> mCurrent;
};
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
index 5272577..c3d72c5 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageFactory.h
@@ -17,6 +17,7 @@
#pragma once
#include <android-base/macros.h>
+#include <libnl++/Buffer.h>
#include <libnl++/types.h>
#include <linux/netlink.h>
@@ -25,131 +26,140 @@
namespace android::nl {
-/** Implementation details, do not use outside MessageFactory template. */
-namespace impl {
-
-struct nlattr* addattr_l(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type, const void* data,
- size_t dataLen);
-struct nlattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, nlattrtype_t type);
-void addattr_nest_end(struct nlmsghdr* n, struct nlattr* nest);
-
-} // namespace impl
+class MessageFactoryBase {
+ protected:
+ static nlattr* add(nlmsghdr* msg, size_t maxLen, nlattrtype_t type, const void* data,
+ size_t dataLen);
+ static void closeNested(nlmsghdr* msg, nlattr* nested);
+};
/**
* Wrapper around NETLINK_ROUTE messages, to build them in C++ style.
*
- * \param T specific message header (such as struct ifinfomsg)
- * \param BUFSIZE how much space to reserve for payload (not counting the header size)
+ * \param T Message payload type (such as ifinfomsg).
+ * \param BUFSIZE how much space to reserve for attributes.
*/
template <class T, unsigned int BUFSIZE = 128>
-struct MessageFactory {
- struct RequestData {
- struct nlmsghdr nlmsg;
+class MessageFactory : private MessageFactoryBase {
+ struct alignas(NLMSG_ALIGNTO) Message {
+ nlmsghdr header;
T data;
- char buf[BUFSIZE];
+ uint8_t attributesBuffer[BUFSIZE];
};
- static constexpr size_t totalLength = sizeof(RequestData);
-
+ public:
/**
* Create empty message.
*
- * \param type Message type (such as RTM_NEWLINK)
- * \param flags Message flags (such as NLM_F_REQUEST)
+ * \param type Message type (such as RTM_NEWLINK).
+ * \param flags Message flags (such as NLM_F_REQUEST).
*/
- MessageFactory(nlmsgtype_t type, uint16_t flags) {
- mRequest.nlmsg.nlmsg_len = NLMSG_LENGTH(sizeof(mRequest.data));
- mRequest.nlmsg.nlmsg_type = type;
- mRequest.nlmsg.nlmsg_flags = flags;
+ MessageFactory(nlmsgtype_t type, uint16_t flags)
+ : header(mMessage.header), data(mMessage.data) {
+ mMessage.header.nlmsg_len = offsetof(Message, attributesBuffer);
+ mMessage.header.nlmsg_type = type;
+ mMessage.header.nlmsg_flags = flags;
}
- /** \return pointer to raw netlink message header. */
- struct nlmsghdr* header() {
- return &mRequest.nlmsg;
- }
- /** Reference to message-specific header. */
- T& data() { return mRequest.data; }
-
/**
- * Adds an attribute of a simple type.
+ * Netlink message header.
*
- * If this method fails (i.e. due to insufficient space), the message will be marked
- * as bad (\see isGood).
+ * This is a generic Netlink header containing information such as message flags.
+ */
+ nlmsghdr& header;
+
+ /**
+ * Netlink message data.
+ *
+ * This is a payload specific to a given message type.
+ */
+ T& data;
+
+ T* operator->() { return &mMessage.data; }
+
+ /**
+ * Build netlink message.
+ *
+ * In fact, this operation is almost a no-op, since the factory builds the message in a single
+ * buffer, using native data structures.
+ *
+ * A likely failure case is when the BUFSIZE template parameter is too small to acommodate
+ * added attributes. In such a case, please increase this parameter.
+ *
+ * \return Netlink message or std::nullopt in case of failure.
+ */
+ std::optional<Buffer<nlmsghdr>> build() const {
+ if (!mIsGood) return std::nullopt;
+ return {{&mMessage.header, mMessage.header.nlmsg_len}};
+ }
+
+ /**
+ * Adds an attribute of a trivially copyable type.
+ *
+ * Template specializations may extend this function for other types, such as std::string.
+ *
+ * If this method fails (i.e. due to insufficient space), a warning will be printed to the log
+ * and the message will be marked as bad, causing later \see build call to fail.
*
* \param type attribute type (such as IFLA_IFNAME)
* \param attr attribute data
*/
template <class A>
- void addattr(nlattrtype_t type, const A& attr) {
- if (!mIsGood) return;
- auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, &attr, sizeof(attr));
- if (ap == nullptr) mIsGood = false;
+ void add(nlattrtype_t type, const A& attr) {
+ add(type, &attr, sizeof(attr));
}
template <>
- void addattr(nlattrtype_t type, const std::string& s) {
- if (!mIsGood) return;
- auto ap = impl::addattr_l(&mRequest.nlmsg, sizeof(mRequest), type, s.c_str(), s.size() + 1);
- if (ap == nullptr) mIsGood = false;
+ void add(nlattrtype_t type, const std::string& s) {
+ add(type, s.c_str(), s.size() + 1);
}
- /** Guard class to frame nested attributes. See nest(int). */
- struct Nest {
- Nest(MessageFactory& req, nlattrtype_t type) : mReq(req), mAttr(req.nestStart(type)) {}
- ~Nest() { mReq.nestEnd(mAttr); }
+ /** Guard class to frame nested attributes. \see addNested(nlattrtype_t). */
+ class [[nodiscard]] NestedGuard {
+ public:
+ NestedGuard(MessageFactory & req, nlattrtype_t type) : mReq(req), mAttr(req.add(type)) {}
+ ~NestedGuard() { closeNested(&mReq.mMessage.header, mAttr); }
private:
MessageFactory& mReq;
- struct nlattr* mAttr;
+ nlattr* mAttr;
- DISALLOW_COPY_AND_ASSIGN(Nest);
+ DISALLOW_COPY_AND_ASSIGN(NestedGuard);
};
/**
* Add nested attribute.
*
* The returned object is a guard for auto-nesting children inside the argument attribute.
- * When the Nest object goes out of scope, the nesting attribute is closed.
+ * When the guard object goes out of scope, the nesting attribute is closed.
*
* Example usage nesting IFLA_CAN_BITTIMING inside IFLA_INFO_DATA, which is nested
* inside IFLA_LINKINFO:
- * MessageFactory<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST);
+ * MessageFactory<ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST);
* {
- * auto linkinfo = req.nest(IFLA_LINKINFO);
- * req.addattr(IFLA_INFO_KIND, "can");
+ * auto linkinfo = req.addNested(IFLA_LINKINFO);
+ * req.add(IFLA_INFO_KIND, "can");
* {
- * auto infodata = req.nest(IFLA_INFO_DATA);
- * req.addattr(IFLA_CAN_BITTIMING, bitTimingStruct);
+ * auto infodata = req.addNested(IFLA_INFO_DATA);
+ * req.add(IFLA_CAN_BITTIMING, bitTimingStruct);
* }
* }
* // use req
*
* \param type attribute type (such as IFLA_LINKINFO)
*/
- Nest nest(int type) { return Nest(*this, type); }
-
- /**
- * Indicates, whether the message is in a good state.
- *
- * The bad state is usually a result of payload buffer being too small.
- * You can modify BUFSIZE template parameter to fix this.
- */
- bool isGood() const { return mIsGood; }
+ NestedGuard addNested(nlattrtype_t type) { return {*this, type}; }
private:
+ Message mMessage = {};
bool mIsGood = true;
- RequestData mRequest = {};
- struct nlattr* nestStart(nlattrtype_t type) {
+ nlattr* add(nlattrtype_t type, const void* data = nullptr, size_t len = 0) {
if (!mIsGood) return nullptr;
- auto attr = impl::addattr_nest(&mRequest.nlmsg, sizeof(mRequest), type);
+ auto attr = MessageFactoryBase::add(&mMessage.header, sizeof(mMessage), type, data, len);
if (attr == nullptr) mIsGood = false;
return attr;
}
-
- void nestEnd(struct nlattr* nest) {
- if (mIsGood && nest != nullptr) impl::addattr_nest_end(&mRequest.nlmsg, nest);
- }
};
} // 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 16b63f5..c69523d 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Socket.h
@@ -76,13 +76,12 @@
*/
template <typename T, unsigned BUFSIZE>
bool send(MessageFactory<T, BUFSIZE>& req, const sockaddr_nl& sa) {
- if (!req.isGood()) return false;
+ req.header.nlmsg_seq = mSeq + 1;
- const auto nlmsg = req.header();
- nlmsg->nlmsg_seq = mSeq + 1;
+ const auto msg = req.build();
+ if (!msg.has_value()) return false;
- // With MessageFactory<>, we trust nlmsg_len to be correct.
- return send({nlmsg, nlmsg->nlmsg_len}, sa);
+ return send(*msg, sa);
}
/**
@@ -156,7 +155,7 @@
*/
template <typename T, unsigned BUFSIZE>
bool receiveAck(MessageFactory<T, BUFSIZE>& req) {
- return receiveAck(req.header()->nlmsg_seq);
+ return receiveAck(req.header.nlmsg_seq);
}
/**
@@ -174,6 +173,42 @@
*/
std::optional<unsigned> getPid();
+ /**
+ * Live iterator continuously receiving messages from Netlink socket.
+ *
+ * Iteration ends when socket fails to receive a buffer.
+ *
+ * Example:
+ * ```
+ * nl::Socket sock(NETLINK_ROUTE, 0, RTMGRP_LINK);
+ * for (const auto rawMsg : sock) {
+ * const auto msg = nl::Message<ifinfomsg>::parse(rawMsg, {RTM_NEWLINK, RTM_DELLINK});
+ * if (!msg.has_value()) continue;
+ *
+ * LOG(INFO) << msg->attributes.get<std::string>(IFLA_IFNAME)
+ * << " is " << ((msg->data.ifi_flags & IFF_UP) ? "up" : "down");
+ * }
+ * LOG(FATAL) << "Failed to read from Netlink socket";
+ * ```
+ */
+ class receive_iterator {
+ public:
+ receive_iterator(Socket& socket, bool end);
+
+ receive_iterator operator++();
+ bool operator==(const receive_iterator& other) const;
+ const Buffer<nlmsghdr>& operator*() const;
+
+ private:
+ Socket& mSocket;
+ bool mIsEnd;
+ Buffer<nlmsghdr>::iterator mCurrent;
+
+ void receive();
+ };
+ receive_iterator begin();
+ receive_iterator end();
+
private:
const int mProtocol;
base::unique_fd mFd;
@@ -182,6 +217,7 @@
bool mFailed = false;
uint32_t mSeq = 0;
+ bool increaseReceiveBuffer(size_t maxSize);
std::optional<Buffer<nlmsghdr>> receive(const std::set<nlmsgtype_t>& msgtypes, size_t maxSize);
DISALLOW_COPY_AND_ASSIGN(Socket);
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/bits.h b/automotive/can/1.0/default/libnl++/include/libnl++/bits.h
new file mode 100644
index 0000000..4c8f1aa
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/bits.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <linux/netlink.h>
+
+namespace android::nl::impl {
+
+// The following definitions are C++ equivalents of NLMSG_* macros from linux/netlink.h.
+
+/**
+ * Equivalent to NLMSG_ALIGNTO.
+ */
+constexpr size_t alignto = NLMSG_ALIGNTO;
+static_assert(NLMSG_ALIGNTO == NLA_ALIGNTO);
+
+/**
+ * Equivalent to NLMSG_ALIGN(len).
+ */
+constexpr size_t align(size_t len) {
+ return (len + alignto - 1) & ~(alignto - 1);
+}
+
+/**
+ * Equivalent to NLMSG_SPACE(len).
+ */
+template <typename H>
+constexpr size_t space(size_t len) {
+ return align(align(sizeof(H)) + len);
+}
+
+/**
+ * Equivalent to NLMSG_DATA(hdr) + NLMSG_ALIGN(offset).
+ */
+template <typename H, typename D>
+constexpr D* data(H* header, size_t offset = 0) {
+ return reinterpret_cast<D*>(uintptr_t(header) + space<H>(offset));
+}
+
+} // namespace android::nl::impl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/printer.h b/automotive/can/1.0/default/libnl++/include/libnl++/printer.h
index 53a06d8..3570918 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/printer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/printer.h
@@ -32,6 +32,6 @@
* \param printPayload True will stringify message data, false will only stringify the header(s).
* \return Stringified message.
*/
-std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload = false);
+std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload = true);
} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/printer.cpp b/automotive/can/1.0/default/libnl++/printer.cpp
index 9735db1..e6cada2 100644
--- a/automotive/can/1.0/default/libnl++/printer.cpp
+++ b/automotive/can/1.0/default/libnl++/printer.cpp
@@ -28,10 +28,10 @@
namespace android::nl {
-static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {
+static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::MessageGenre genre) {
bool first = true;
auto printFlag = [&ss, &first, &nlmsg_flags](__u16 flag, const std::string& name) {
- if (!(nlmsg_flags & flag)) return;
+ if ((nlmsg_flags & flag) != flag) return;
nlmsg_flags &= ~flag;
if (first) {
@@ -42,6 +42,7 @@
ss << name;
};
+
printFlag(NLM_F_REQUEST, "REQUEST");
printFlag(NLM_F_MULTI, "MULTI");
printFlag(NLM_F_ACK, "ACK");
@@ -49,11 +50,29 @@
printFlag(NLM_F_DUMP_INTR, "DUMP_INTR");
printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED");
- // TODO(twasilczyk): print flags depending on request type
- printFlag(NLM_F_ROOT, "ROOT-REPLACE");
- printFlag(NLM_F_MATCH, "MATCH-EXCL");
- printFlag(NLM_F_ATOMIC, "ATOMIC-CREATE");
- printFlag(NLM_F_APPEND, "APPEND");
+ switch (genre) {
+ case protocols::MessageGenre::UNKNOWN:
+ break;
+ case protocols::MessageGenre::GET:
+ printFlag(NLM_F_DUMP, "DUMP"); // ROOT | MATCH
+ printFlag(NLM_F_ROOT, "ROOT");
+ printFlag(NLM_F_MATCH, "MATCH");
+ printFlag(NLM_F_ATOMIC, "ATOMIC");
+ break;
+ case protocols::MessageGenre::NEW:
+ printFlag(NLM_F_REPLACE, "REPLACE");
+ printFlag(NLM_F_EXCL, "EXCL");
+ printFlag(NLM_F_CREATE, "CREATE");
+ printFlag(NLM_F_APPEND, "APPEND");
+ break;
+ case protocols::MessageGenre::DELETE:
+ printFlag(NLM_F_NONREC, "NONREC");
+ break;
+ case protocols::MessageGenre::ACK:
+ printFlag(NLM_F_CAPPED, "CAPPED");
+ printFlag(NLM_F_ACK_TLVS, "ACK_TLVS");
+ break;
+ }
if (nlmsg_flags != 0) {
if (!first) ss << '|';
@@ -100,7 +119,7 @@
}
case DataType::String: {
const auto str = attr.data<char>().getRaw();
- ss << '"' << sanitize({str.ptr(), str.len()}) << '"';
+ ss << '"' << printableOnly({str.ptr(), str.len()}) << '"';
break;
}
case DataType::Uint:
@@ -128,27 +147,26 @@
}
protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
- auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
- const auto msgTypeName = msgDescMaybe.has_value()
- ? msgDescMaybe->get().getMessageName(hdr->nlmsg_type)
- : std::to_string(hdr->nlmsg_type);
+ const auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
+ const auto msgDetails =
+ protocols::MessageDescriptor::getMessageDetails(msgDescMaybe, hdr->nlmsg_type);
ss << "nlmsg{" << protocolDescr.getName() << " ";
ss << "hdr={";
- ss << "type=" << msgTypeName;
+ ss << "type=" << msgDetails.name;
if (hdr->nlmsg_flags != 0) {
ss << ", flags=";
- flagsToStream(ss, hdr->nlmsg_flags);
+ flagsToStream(ss, hdr->nlmsg_flags, msgDetails.genre);
}
if (hdr->nlmsg_seq != 0) ss << ", seq=" << hdr->nlmsg_seq;
if (hdr->nlmsg_pid != 0) ss << ", pid=" << hdr->nlmsg_pid;
ss << ", len=" << hdr->nlmsg_len;
-
ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
- ss << "} ";
+ ss << '}';
if (!printPayload) return ss.str();
+ ss << ' ';
if (!msgDescMaybe.has_value()) {
toStream(ss, hdr.data<uint8_t>());
diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp
index dc56643..c93d865 100644
--- a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.cpp
@@ -32,11 +32,12 @@
return find(nla_type)->second;
}
-MessageDescriptor::MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
+MessageDescriptor::MessageDescriptor(const std::string& name,
+ const MessageDetailsMap&& messageDetails,
const AttributeMap&& attrTypes, size_t contentsSize)
: mName(name),
mContentsSize(contentsSize),
- mMessageTypes(messageTypes),
+ mMessageDetails(messageDetails),
mAttributeMap(attrTypes) {}
MessageDescriptor::~MessageDescriptor() {}
@@ -45,18 +46,25 @@
return mContentsSize;
}
-const MessageDescriptor::MessageTypeMap& MessageDescriptor::getMessageTypeMap() const {
- return mMessageTypes;
+const MessageDescriptor::MessageDetailsMap& MessageDescriptor::getMessageDetailsMap() const {
+ return mMessageDetails;
}
const AttributeMap& MessageDescriptor::getAttributeMap() const {
return mAttributeMap;
}
-const std::string MessageDescriptor::getMessageName(nlmsgtype_t msgtype) const {
- const auto it = mMessageTypes.find(msgtype);
- if (it == mMessageTypes.end()) return "?";
+MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(nlmsgtype_t msgtype) const {
+ const auto it = mMessageDetails.find(msgtype);
+ if (it == mMessageDetails.end()) return {std::to_string(msgtype), MessageGenre::UNKNOWN};
return it->second;
}
+MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(
+ const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
+ nlmsgtype_t msgtype) {
+ if (msgDescMaybe.has_value()) return msgDescMaybe->get().getMessageDetails(msgtype);
+ return {std::to_string(msgtype), protocols::MessageGenre::UNKNOWN};
+}
+
} // namespace android::nl::protocols
diff --git a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h
index ef73d09..bd0e60f 100644
--- a/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h
+++ b/automotive/can/1.0/default/libnl++/protocols/MessageDefinition.h
@@ -68,30 +68,53 @@
};
/**
+ * General message type's kind.
+ *
+ * For example, RTM_NEWLINK is a NEW kind. For details, please see "Flags values"
+ * section in linux/netlink.h.
+ */
+enum class MessageGenre {
+ UNKNOWN,
+ GET,
+ NEW,
+ DELETE,
+ ACK,
+};
+
+/**
* Message family descriptor.
*
* Describes the structure of all message types with the same header and attributes.
*/
class MessageDescriptor {
- protected:
- typedef std::map<nlmsgtype_t, std::string> MessageTypeMap;
-
- MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
- const AttributeMap&& attrTypes, size_t contentsSize);
+ public:
+ struct MessageDetails {
+ std::string name;
+ MessageGenre genre;
+ };
+ typedef std::map<nlmsgtype_t, MessageDetails> MessageDetailsMap;
public:
virtual ~MessageDescriptor();
size_t getContentsSize() const;
- const MessageTypeMap& getMessageTypeMap() const;
+ const MessageDetailsMap& getMessageDetailsMap() const;
const AttributeMap& getAttributeMap() const;
- const std::string getMessageName(nlmsgtype_t msgtype) const;
+ MessageDetails getMessageDetails(nlmsgtype_t msgtype) const;
virtual void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const = 0;
+ static MessageDetails getMessageDetails(
+ const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
+ nlmsgtype_t msgtype);
+
+ protected:
+ MessageDescriptor(const std::string& name, const MessageDetailsMap&& messageDetails,
+ const AttributeMap&& attrTypes, size_t contentsSize);
+
private:
const std::string mName;
const size_t mContentsSize;
- const MessageTypeMap mMessageTypes;
+ const MessageDetailsMap mMessageDetails;
const AttributeMap mAttributeMap;
};
@@ -103,11 +126,11 @@
template <typename T>
class MessageDefinition : public MessageDescriptor {
public:
- MessageDefinition(
+ MessageDefinition( //
const std::string& name,
- const std::initializer_list<MessageDescriptor::MessageTypeMap::value_type> messageTypes,
+ const std::initializer_list<MessageDescriptor::MessageDetailsMap::value_type> msgDet,
const std::initializer_list<AttributeMap::value_type> attrTypes = {})
- : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}
+ : MessageDescriptor(name, msgDet, attrTypes, sizeof(T)) {}
void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const override {
const auto& [ok, msg] = hdr.data<T>().getFirst();
diff --git a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp
index 4b795d9..cd2e8c6 100644
--- a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.cpp
@@ -18,7 +18,7 @@
namespace android::nl::protocols {
-NetlinkProtocol::NetlinkProtocol(int protocol, const std::string name,
+NetlinkProtocol::NetlinkProtocol(int protocol, const std::string& name,
const MessageDescriptorList&& messageDescrs)
: mProtocol(protocol), mName(name), mMessageDescrs(toMap(messageDescrs, protocol)) {}
@@ -42,7 +42,7 @@
const NetlinkProtocol::MessageDescriptorList& descrs, int protocol) {
MessageDescriptorMap map;
for (const auto& descr : descrs) {
- for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
+ for (const auto& [mtype, mdet] : descr->getMessageDetailsMap()) {
map.emplace(mtype, descr);
}
}
@@ -53,7 +53,7 @@
};
for (const auto& descr : baseDescriptors) {
- for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
+ for (const auto& [mtype, mdet] : descr->getMessageDetailsMap()) {
map.emplace(mtype, descr);
}
}
diff --git a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h
index 81a0a65..c969547 100644
--- a/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h
+++ b/automotive/can/1.0/default/libnl++/protocols/NetlinkProtocol.h
@@ -46,7 +46,7 @@
protected:
typedef std::vector<std::shared_ptr<const MessageDescriptor>> MessageDescriptorList;
- NetlinkProtocol(int protocol, const std::string name,
+ NetlinkProtocol(int protocol, const std::string& name,
const MessageDescriptorList&& messageDescrs);
private:
diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp
index dbf10d4..8a672d3 100644
--- a/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/common/Empty.cpp
@@ -20,9 +20,9 @@
// clang-format off
Empty::Empty() : MessageDefinition<char>("nlmsg", {
- {NLMSG_NOOP, "NOOP"},
- {NLMSG_DONE, "DONE"},
- {NLMSG_OVERRUN, "OVERRUN"},
+ {NLMSG_NOOP, {"NOOP", MessageGenre::UNKNOWN}},
+ {NLMSG_DONE, {"DONE", MessageGenre::UNKNOWN}},
+ {NLMSG_OVERRUN, {"OVERRUN", MessageGenre::UNKNOWN}},
}) {}
// clang-format on
diff --git a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
index 1d6bd1c..44708a3 100644
--- a/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/common/Error.cpp
@@ -22,15 +22,21 @@
namespace android::nl::protocols::base {
+using DataType = AttributeDefinition::DataType;
+
// clang-format off
Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
- {NLMSG_ERROR, "ERROR"},
+ {NLMSG_ERROR, {"ERROR", MessageGenre::ACK}},
+}, {
+ {NLMSGERR_ATTR_MSG, {"MSG", DataType::String}},
+ {NLMSGERR_ATTR_OFFS, {"OFFS", DataType::Uint}},
+ {NLMSGERR_ATTR_COOKIE, {"COOKIE", DataType::Raw}},
}), mProtocol(protocol) {}
// clang-format on
void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const {
ss << "nlmsgerr{error=" << data.error
- << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol) << "}";
+ << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol, false) << "}";
}
} // namespace android::nl::protocols::base
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 5203368..134638e 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.cpp
@@ -19,13 +19,14 @@
namespace android::nl::protocols::generic {
GenericMessageBase::GenericMessageBase(
- nlmsgtype_t msgtype, std::string msgname,
+ nlmsgtype_t msgtype, const std::string&& msgname,
const std::initializer_list<GenericCommandNameMap::value_type> commandNames,
const std::initializer_list<AttributeMap::value_type> attrTypes)
- : MessageDefinition<struct genlmsghdr>(msgname, {{msgtype, msgname}}, attrTypes),
+ : MessageDefinition<genlmsghdr>(msgname, {{msgtype, {msgname, MessageGenre::UNKNOWN}}},
+ attrTypes),
mCommandNames(commandNames) {}
-void GenericMessageBase::toStream(std::stringstream& ss, const struct genlmsghdr& data) const {
+void GenericMessageBase::toStream(std::stringstream& ss, const genlmsghdr& data) const {
ss << "genlmsghdr{";
if (mCommandNames.count(data.cmd) == 0) {
ss << "cmd=" << unsigned(data.cmd);
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h
index f3b0b31..443f10c 100644
--- a/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/GenericMessageBase.h
@@ -22,16 +22,16 @@
namespace android::nl::protocols::generic {
-class GenericMessageBase : public MessageDefinition<struct genlmsghdr> {
+class GenericMessageBase : public MessageDefinition<genlmsghdr> {
public:
typedef std::map<uint8_t, std::string> GenericCommandNameMap;
GenericMessageBase(
- nlmsgtype_t msgtype, std::string msgname,
+ nlmsgtype_t msgtype, const std::string&& msgname,
const std::initializer_list<GenericCommandNameMap::value_type> commandNames = {},
const std::initializer_list<AttributeMap::value_type> attrTypes = {});
- void toStream(std::stringstream& ss, const struct genlmsghdr& data) const override;
+ void toStream(std::stringstream& ss, const genlmsghdr& data) const override;
private:
const GenericCommandNameMap mCommandNames;
diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp
index 26d3e3e..7db487a 100644
--- a/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp
+++ b/automotive/can/1.0/default/libnl++/protocols/route/Link.cpp
@@ -25,10 +25,10 @@
using DataType = AttributeDefinition::DataType;
// clang-format off
-Link::Link() : MessageDefinition<struct ifinfomsg>("link", {
- {RTM_NEWLINK, "NEWLINK"},
- {RTM_DELLINK, "DELLINK"},
- {RTM_GETLINK, "GETLINK"},
+Link::Link() : MessageDefinition<ifinfomsg>("link", {
+ {RTM_NEWLINK, {"NEWLINK", MessageGenre::NEW}},
+ {RTM_DELLINK, {"DELLINK", MessageGenre::DELETE}},
+ {RTM_GETLINK, {"GETLINK", MessageGenre::GET}},
}, {
{IFLA_ADDRESS, {"ADDRESS"}},
{IFLA_BROADCAST, {"BROADCAST"}},
@@ -107,7 +107,7 @@
}) {}
// clang-format off
-void Link::toStream(std::stringstream& ss, const struct ifinfomsg& data) const {
+void Link::toStream(std::stringstream& ss, const ifinfomsg& data) const {
ss << "ifinfomsg{"
<< "family=" << unsigned(data.ifi_family) << ", type=" << data.ifi_type
<< ", index=" << data.ifi_index << ", flags=" << data.ifi_flags
diff --git a/automotive/can/1.0/default/libnl++/protocols/route/Link.h b/automotive/can/1.0/default/libnl++/protocols/route/Link.h
index 4ea3eba..ecfefc9 100644
--- a/automotive/can/1.0/default/libnl++/protocols/route/Link.h
+++ b/automotive/can/1.0/default/libnl++/protocols/route/Link.h
@@ -22,10 +22,10 @@
namespace android::nl::protocols::route {
-class Link : public MessageDefinition<struct ifinfomsg> {
+class Link : public MessageDefinition<ifinfomsg> {
public:
Link();
- void toStream(std::stringstream& ss, const struct ifinfomsg& data) const override;
+ void toStream(std::stringstream& ss, const ifinfomsg& data) const override;
};
} // namespace android::nl::protocols::route
diff --git a/automotive/evs/1.0/default/EvsCamera.cpp b/automotive/evs/1.0/default/EvsCamera.cpp
index e0782ec..0daea5a 100644
--- a/automotive/evs/1.0/default/EvsCamera.cpp
+++ b/automotive/evs/1.0/default/EvsCamera.cpp
@@ -49,7 +49,7 @@
mDescription.cameraId = id;
- // Set up dummy data for testing
+ // Set up mock data for testing
if (mDescription.cameraId == kCameraName_Backup) {
mWidth = 640; // full NTSC/VGA
mHeight = 480; // full NTSC/VGA
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 7fe7a33..ad607d8 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -369,7 +369,7 @@
TEST_P(EvsHidlTest, CameraStreamBuffering) {
ALOGI("Starting CameraStreamBuffering test");
- // Arbitrary constant (should be > 1 and less than crazy)
+ // Arbitrary constant (should be > 1 and not too big)
static const unsigned int kBuffersToHold = 6;
// Get the camera list
@@ -381,7 +381,7 @@
sp<IEvsCamera> pCam = pEnumerator->openCamera(cam.cameraId);
ASSERT_NE(pCam, nullptr);
- // Ask for a crazy number of buffers in flight to ensure it errors correctly
+ // Ask for a very large number of buffers in flight to ensure it errors correctly
Return<EvsResult> badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF);
EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult);
diff --git a/automotive/evs/1.1/default/ConfigManager.h b/automotive/evs/1.1/default/ConfigManager.h
index 870af1c..b0b2670 100644
--- a/automotive/evs/1.1/default/ConfigManager.h
+++ b/automotive/evs/1.1/default/ConfigManager.h
@@ -76,7 +76,7 @@
}
/*
- * List of supported controls that the master client can program.
+ * List of supported controls that the primary client can program.
* Paraemters are stored with its valid range
*/
unordered_map<CameraParam,
diff --git a/automotive/evs/1.1/default/EvsEnumerator.cpp b/automotive/evs/1.1/default/EvsEnumerator.cpp
index 117ee7a..d066471 100644
--- a/automotive/evs/1.1/default/EvsEnumerator.cpp
+++ b/automotive/evs/1.1/default/EvsEnumerator.cpp
@@ -70,7 +70,7 @@
// Add ultrasonics array desc.
sUltrasonicsArrayRecordList.emplace_back(
- EvsUltrasonicsArray::GetDummyArrayDesc("front_array"));
+ EvsUltrasonicsArray::GetMockArrayDesc("front_array"));
}
diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
index bc69aa4..ebd47c6 100644
--- a/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
+++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.cpp
@@ -45,7 +45,7 @@
namespace {
-void fillDummyArrayDesc(UltrasonicsArrayDesc& arrayDesc) {
+void fillMockArrayDesc(UltrasonicsArrayDesc& arrayDesc) {
arrayDesc.maxReadingsPerSensorCount = kMaxReadingsPerSensor;
arrayDesc.maxReceiversCount = kMaxReceiversCount;
@@ -99,8 +99,8 @@
}
}
-// Fills dataFrameDesc with dummy data.
-bool fillDummyDataFrame(UltrasonicsDataFrameDesc& dataFrameDesc, sp<IMemory> pIMemory) {
+// Fills dataFrameDesc with mock data.
+bool fillMockDataFrame(UltrasonicsDataFrameDesc& dataFrameDesc, sp<IMemory> pIMemory) {
dataFrameDesc.timestampNs = elapsedRealtimeNano();
const std::vector<uint8_t> transmittersIdList = {0};
@@ -137,9 +137,9 @@
: mFramesAllowed(0), mFramesInUse(0), mStreamState(STOPPED) {
LOG(DEBUG) << "EvsUltrasonicsArray instantiated";
- // Set up dummy data for description.
+ // Set up mock data for description.
mArrayDesc.ultrasonicsArrayId = deviceName;
- fillDummyArrayDesc(mArrayDesc);
+ fillMockArrayDesc(mArrayDesc);
// Assign allocator.
mShmemAllocator = IAllocator::getService("ashmem");
@@ -182,10 +182,10 @@
mStreamState = DEAD;
}
-UltrasonicsArrayDesc EvsUltrasonicsArray::GetDummyArrayDesc(const char* deviceName) {
+UltrasonicsArrayDesc EvsUltrasonicsArray::GetMockArrayDesc(const char* deviceName) {
UltrasonicsArrayDesc ultrasonicsArrayDesc;
ultrasonicsArrayDesc.ultrasonicsArrayId = deviceName;
- fillDummyArrayDesc(ultrasonicsArrayDesc);
+ fillMockArrayDesc(ultrasonicsArrayDesc);
return ultrasonicsArrayDesc;
}
@@ -497,17 +497,17 @@
if (timeForFrame) {
// Assemble the buffer description we'll transmit below
- UltrasonicsDataFrameDesc dummyDataFrameDesc;
- dummyDataFrameDesc.dataFrameId = idx;
- dummyDataFrameDesc.waveformsData = mDataFrames[idx].sharedMemory.hidlMemory;
+ UltrasonicsDataFrameDesc mockDataFrameDesc;
+ mockDataFrameDesc.dataFrameId = idx;
+ mockDataFrameDesc.waveformsData = mDataFrames[idx].sharedMemory.hidlMemory;
- // Fill dummy waveform data.
- fillDummyDataFrame(dummyDataFrameDesc, mDataFrames[idx].sharedMemory.pIMemory);
+ // Fill mock waveform data.
+ fillMockDataFrame(mockDataFrameDesc, mDataFrames[idx].sharedMemory.pIMemory);
// Issue the (asynchronous) callback to the client -- can't be holding the lock
- auto result = mStream->deliverDataFrame(dummyDataFrameDesc);
+ auto result = mStream->deliverDataFrame(mockDataFrameDesc);
if (result.isOk()) {
- LOG(DEBUG) << "Delivered data frame id: " << dummyDataFrameDesc.dataFrameId;
+ LOG(DEBUG) << "Delivered data frame id: " << mockDataFrameDesc.dataFrameId;
} else {
// This can happen if the client dies and is likely unrecoverable.
// To avoid consuming resources generating failing calls, we stop sending
diff --git a/automotive/evs/1.1/default/EvsUltrasonicsArray.h b/automotive/evs/1.1/default/EvsUltrasonicsArray.h
index 7a41012..88aa600 100644
--- a/automotive/evs/1.1/default/EvsUltrasonicsArray.h
+++ b/automotive/evs/1.1/default/EvsUltrasonicsArray.h
@@ -58,7 +58,7 @@
static sp<EvsUltrasonicsArray> Create(const char* deviceName);
// Returns a ultrasonics array descriptor filled with sample data.
- static UltrasonicsArrayDesc GetDummyArrayDesc(const char* id);
+ static UltrasonicsArrayDesc GetMockArrayDesc(const char* id);
DISALLOW_COPY_AND_ASSIGN(EvsUltrasonicsArray);
virtual ~EvsUltrasonicsArray() override;
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 4398fb1..638ecd5 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -500,7 +500,7 @@
TEST_P(EvsHidlTest, CameraStreamBuffering) {
LOG(INFO) << "Starting CameraStreamBuffering test";
- // Arbitrary constant (should be > 1 and less than crazy)
+ // Arbitrary constant (should be > 1 and not too big)
static const unsigned int kBuffersToHold = 6;
// Get the camera list
@@ -527,7 +527,7 @@
// Store a camera handle for a clean-up
activeCameras.push_back(pCam);
- // Ask for a crazy number of buffers in flight to ensure it errors correctly
+ // Ask for a very large number of buffers in flight to ensure it errors correctly
Return<EvsResult> badResult = pCam->setMaxFramesInFlight(0xFFFFFFFF);
EXPECT_EQ(EvsResult::BUFFER_NOT_AVAILABLE, badResult);
@@ -930,12 +930,12 @@
/*
- * CameraMasterRelease
- * Verify that non-master client gets notified when the master client either
+ * CameraPrimaryClientRelease
+ * Verify that non-primary client gets notified when the primary client either
* terminates or releases a role.
*/
-TEST_P(EvsHidlTest, CameraMasterRelease) {
- LOG(INFO) << "Starting CameraMasterRelease test";
+TEST_P(EvsHidlTest, CameraPrimaryClientRelease) {
+ LOG(INFO) << "Starting CameraPrimaryClientRelease test";
if (mIsHwModule) {
// This test is not for HW module implementation.
@@ -961,57 +961,57 @@
}
// Create two camera clients.
- sp<IEvsCamera_1_1> pCamMaster =
+ sp<IEvsCamera_1_1> pCamPrimary =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
- ASSERT_NE(pCamMaster, nullptr);
+ ASSERT_NE(pCamPrimary, nullptr);
// Store a camera handle for a clean-up
- activeCameras.push_back(pCamMaster);
+ activeCameras.push_back(pCamPrimary);
- sp<IEvsCamera_1_1> pCamNonMaster =
+ sp<IEvsCamera_1_1> pCamSecondary =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
- ASSERT_NE(pCamNonMaster, nullptr);
+ ASSERT_NE(pCamSecondary, nullptr);
// Store a camera handle for a clean-up
- activeCameras.push_back(pCamNonMaster);
+ activeCameras.push_back(pCamSecondary);
// Set up per-client frame receiver objects which will fire up its own thread
- sp<FrameHandler> frameHandlerMaster =
- new FrameHandler(pCamMaster, cam,
+ sp<FrameHandler> frameHandlerPrimary =
+ new FrameHandler(pCamPrimary, cam,
nullptr,
FrameHandler::eAutoReturn);
- ASSERT_NE(frameHandlerMaster, nullptr);
- sp<FrameHandler> frameHandlerNonMaster =
- new FrameHandler(pCamNonMaster, cam,
+ ASSERT_NE(frameHandlerPrimary, nullptr);
+ sp<FrameHandler> frameHandlerSecondary =
+ new FrameHandler(pCamSecondary, cam,
nullptr,
FrameHandler::eAutoReturn);
- ASSERT_NE(frameHandlerNonMaster, nullptr);
+ ASSERT_NE(frameHandlerSecondary, nullptr);
- // Set one client as the master
- EvsResult result = pCamMaster->setMaster();
+ // Set one client as the primary client
+ EvsResult result = pCamPrimary->setMaster();
ASSERT_TRUE(result == EvsResult::OK);
- // Try to set another client as the master.
- result = pCamNonMaster->setMaster();
+ // Try to set another client as the primary client.
+ result = pCamSecondary->setMaster();
ASSERT_TRUE(result == EvsResult::OWNERSHIP_LOST);
- // Start the camera's video stream via a master client.
- bool startResult = frameHandlerMaster->startStream();
+ // Start the camera's video stream via a primary client client.
+ bool startResult = frameHandlerPrimary->startStream();
ASSERT_TRUE(startResult);
// Ensure the stream starts
- frameHandlerMaster->waitForFrameCount(1);
+ frameHandlerPrimary->waitForFrameCount(1);
// Start the camera's video stream via another client
- startResult = frameHandlerNonMaster->startStream();
+ startResult = frameHandlerSecondary->startStream();
ASSERT_TRUE(startResult);
// Ensure the stream starts
- frameHandlerNonMaster->waitForFrameCount(1);
+ frameHandlerSecondary->waitForFrameCount(1);
- // Non-master client expects to receive a master role relesed
+ // Non-primary client expects to receive a primary client role relesed
// notification.
EvsEventDesc aTargetEvent = {};
EvsEventDesc aNotification = {};
@@ -1020,14 +1020,14 @@
std::mutex eventLock;
std::condition_variable eventCond;
std::thread listener = std::thread(
- [&aNotification, &frameHandlerNonMaster, &listening, &eventCond]() {
+ [&aNotification, &frameHandlerSecondary, &listening, &eventCond]() {
// Notify that a listening thread is running.
listening = true;
eventCond.notify_all();
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
- if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification, true)) {
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification, true)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
@@ -1043,8 +1043,8 @@
}
lock.unlock();
- // Release a master role.
- pCamMaster->unsetMaster();
+ // Release a primary client role.
+ pCamPrimary->unsetMaster();
// Join a listening thread.
if (listener.joinable()) {
@@ -1055,24 +1055,24 @@
ASSERT_EQ(EvsEventType::MASTER_RELEASED,
static_cast<EvsEventType>(aNotification.aType));
- // Non-master becomes a master.
- result = pCamNonMaster->setMaster();
+ // Non-primary becomes a primary client.
+ result = pCamSecondary->setMaster();
ASSERT_TRUE(result == EvsResult::OK);
- // Previous master client fails to become a master.
- result = pCamMaster->setMaster();
+ // Previous primary client fails to become a primary client.
+ result = pCamPrimary->setMaster();
ASSERT_TRUE(result == EvsResult::OWNERSHIP_LOST);
listening = false;
listener = std::thread(
- [&aNotification, &frameHandlerMaster, &listening, &eventCond]() {
+ [&aNotification, &frameHandlerPrimary, &listening, &eventCond]() {
// Notify that a listening thread is running.
listening = true;
eventCond.notify_all();
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
- if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification, true)) {
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification, true)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
@@ -1087,8 +1087,8 @@
}
lock.unlock();
- // Closing current master client.
- frameHandlerNonMaster->shutdown();
+ // Closing current primary client.
+ frameHandlerSecondary->shutdown();
// Join a listening thread.
if (listener.joinable()) {
@@ -1100,11 +1100,11 @@
static_cast<EvsEventType>(aNotification.aType));
// Closing streams.
- frameHandlerMaster->shutdown();
+ frameHandlerPrimary->shutdown();
// Explicitly release the camera
- pEnumerator->closeCamera(pCamMaster);
- pEnumerator->closeCamera(pCamNonMaster);
+ pEnumerator->closeCamera(pCamPrimary);
+ pEnumerator->closeCamera(pCamSecondary);
activeCameras.clear();
}
}
@@ -1112,7 +1112,7 @@
/*
* MultiCameraParameter:
- * Verify that master and non-master clients behave as expected when they try to adjust
+ * Verify that primary and non-primary clients behave as expected when they try to adjust
* camera parameters.
*/
TEST_P(EvsHidlTest, MultiCameraParameter) {
@@ -1142,88 +1142,88 @@
}
// Create two camera clients.
- sp<IEvsCamera_1_1> pCamMaster =
+ sp<IEvsCamera_1_1> pCamPrimary =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
- ASSERT_NE(pCamMaster, nullptr);
+ ASSERT_NE(pCamPrimary, nullptr);
// Store a camera handle for a clean-up
- activeCameras.push_back(pCamMaster);
+ activeCameras.push_back(pCamPrimary);
- sp<IEvsCamera_1_1> pCamNonMaster =
+ sp<IEvsCamera_1_1> pCamSecondary =
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
.withDefault(nullptr);
- ASSERT_NE(pCamNonMaster, nullptr);
+ ASSERT_NE(pCamSecondary, nullptr);
// Store a camera handle for a clean-up
- activeCameras.push_back(pCamNonMaster);
+ activeCameras.push_back(pCamSecondary);
// Get the parameter list
- std::vector<CameraParam> camMasterCmds, camNonMasterCmds;
- pCamMaster->getParameterList([&camMasterCmds](hidl_vec<CameraParam> cmdList) {
- camMasterCmds.reserve(cmdList.size());
+ std::vector<CameraParam> camPrimaryCmds, camSecondaryCmds;
+ pCamPrimary->getParameterList([&camPrimaryCmds](hidl_vec<CameraParam> cmdList) {
+ camPrimaryCmds.reserve(cmdList.size());
for (auto &&cmd : cmdList) {
- camMasterCmds.push_back(cmd);
+ camPrimaryCmds.push_back(cmd);
}
}
);
- pCamNonMaster->getParameterList([&camNonMasterCmds](hidl_vec<CameraParam> cmdList) {
- camNonMasterCmds.reserve(cmdList.size());
+ pCamSecondary->getParameterList([&camSecondaryCmds](hidl_vec<CameraParam> cmdList) {
+ camSecondaryCmds.reserve(cmdList.size());
for (auto &&cmd : cmdList) {
- camNonMasterCmds.push_back(cmd);
+ camSecondaryCmds.push_back(cmd);
}
}
);
- if (camMasterCmds.size() < 1 ||
- camNonMasterCmds.size() < 1) {
+ if (camPrimaryCmds.size() < 1 ||
+ camSecondaryCmds.size() < 1) {
// Skip a camera device if it does not support any parameter.
continue;
}
// Set up per-client frame receiver objects which will fire up its own thread
- sp<FrameHandler> frameHandlerMaster =
- new FrameHandler(pCamMaster, cam,
+ sp<FrameHandler> frameHandlerPrimary =
+ new FrameHandler(pCamPrimary, cam,
nullptr,
FrameHandler::eAutoReturn);
- ASSERT_NE(frameHandlerMaster, nullptr);
- sp<FrameHandler> frameHandlerNonMaster =
- new FrameHandler(pCamNonMaster, cam,
+ ASSERT_NE(frameHandlerPrimary, nullptr);
+ sp<FrameHandler> frameHandlerSecondary =
+ new FrameHandler(pCamSecondary, cam,
nullptr,
FrameHandler::eAutoReturn);
- ASSERT_NE(frameHandlerNonMaster, nullptr);
+ ASSERT_NE(frameHandlerSecondary, nullptr);
- // Set one client as the master
- EvsResult result = pCamMaster->setMaster();
+ // Set one client as the primary client.
+ EvsResult result = pCamPrimary->setMaster();
ASSERT_EQ(EvsResult::OK, result);
- // Try to set another client as the master.
- result = pCamNonMaster->setMaster();
+ // Try to set another client as the primary client.
+ result = pCamSecondary->setMaster();
ASSERT_EQ(EvsResult::OWNERSHIP_LOST, result);
- // Start the camera's video stream via a master client.
- bool startResult = frameHandlerMaster->startStream();
+ // Start the camera's video stream via a primary client client.
+ bool startResult = frameHandlerPrimary->startStream();
ASSERT_TRUE(startResult);
// Ensure the stream starts
- frameHandlerMaster->waitForFrameCount(1);
+ frameHandlerPrimary->waitForFrameCount(1);
// Start the camera's video stream via another client
- startResult = frameHandlerNonMaster->startStream();
+ startResult = frameHandlerSecondary->startStream();
ASSERT_TRUE(startResult);
// Ensure the stream starts
- frameHandlerNonMaster->waitForFrameCount(1);
+ frameHandlerSecondary->waitForFrameCount(1);
int32_t val0 = 0;
std::vector<int32_t> values;
EvsEventDesc aNotification0 = {};
EvsEventDesc aNotification1 = {};
- for (auto &cmd : camMasterCmds) {
+ for (auto &cmd : camPrimaryCmds) {
// Get a valid parameter value range
int32_t minVal, maxVal, step;
- pCamMaster->getIntParameterRange(
+ pCamPrimary->getIntParameterRange(
cmd,
[&minVal, &maxVal, &step](int32_t val0, int32_t val1, int32_t val2) {
minVal = val0;
@@ -1236,7 +1236,7 @@
if (cmd == CameraParam::ABSOLUTE_FOCUS) {
// Try to turn off auto-focus
values.clear();
- pCamMaster->setIntParameter(CameraParam::AUTO_FOCUS, 0,
+ pCamPrimary->setIntParameter(CameraParam::AUTO_FOCUS, 0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1261,7 +1261,7 @@
std::condition_variable eventCond;
std::thread listener0 = std::thread(
[cmd, val0,
- &aNotification0, &frameHandlerMaster, &listening0, &listening1, &eventCond]() {
+ &aNotification0, &frameHandlerPrimary, &listening0, &listening1, &eventCond]() {
listening0 = true;
if (listening1) {
eventCond.notify_all();
@@ -1271,14 +1271,14 @@
aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
- if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) {
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
std::thread listener1 = std::thread(
[cmd, val0,
- &aNotification1, &frameHandlerNonMaster, &listening0, &listening1, &eventCond]() {
+ &aNotification1, &frameHandlerSecondary, &listening0, &listening1, &eventCond]() {
listening1 = true;
if (listening0) {
eventCond.notify_all();
@@ -1288,7 +1288,7 @@
aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
- if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) {
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
@@ -1305,7 +1305,7 @@
// Try to program a parameter
values.clear();
- pCamMaster->setIntParameter(cmd, val0,
+ pCamPrimary->setIntParameter(cmd, val0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1345,9 +1345,9 @@
}
// Clients expects to receive a parameter change notification
- // whenever a master client adjusts it.
+ // whenever a primary client client adjusts it.
values.clear();
- pCamMaster->getIntParameter(cmd,
+ pCamPrimary->getIntParameter(cmd,
[&result, &values](auto status, auto readValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1362,9 +1362,9 @@
}
}
- // Try to adjust a parameter via non-master client
+ // Try to adjust a parameter via non-primary client
values.clear();
- pCamNonMaster->setIntParameter(camNonMasterCmds[0], val0,
+ pCamSecondary->setIntParameter(camSecondaryCmds[0], val0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1375,21 +1375,21 @@
});
ASSERT_EQ(EvsResult::INVALID_ARG, result);
- // Non-master client attemps to be a master
- result = pCamNonMaster->setMaster();
+ // Non-primary client attempts to be a primary client
+ result = pCamSecondary->setMaster();
ASSERT_EQ(EvsResult::OWNERSHIP_LOST, result);
- // Master client retires from a master role
+ // Primary client retires from a primary client role
bool listening = false;
std::condition_variable eventCond;
std::thread listener = std::thread(
- [&aNotification0, &frameHandlerNonMaster, &listening, &eventCond]() {
+ [&aNotification0, &frameHandlerSecondary, &listening, &eventCond]() {
listening = true;
eventCond.notify_all();
EvsEventDesc aTargetEvent;
aTargetEvent.aType = EvsEventType::MASTER_RELEASED;
- if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification0, true)) {
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification0, true)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
@@ -1403,7 +1403,7 @@
}
lock.unlock();
- result = pCamMaster->unsetMaster();
+ result = pCamPrimary->unsetMaster();
ASSERT_EQ(EvsResult::OK, result);
if (listener.joinable()) {
@@ -1414,7 +1414,7 @@
// Try to adjust a parameter after being retired
values.clear();
- pCamMaster->setIntParameter(camMasterCmds[0], val0,
+ pCamPrimary->setIntParameter(camPrimaryCmds[0], val0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1425,15 +1425,15 @@
});
ASSERT_EQ(EvsResult::INVALID_ARG, result);
- // Non-master client becomes a master
- result = pCamNonMaster->setMaster();
+ // Non-primary client becomes a primary client
+ result = pCamSecondary->setMaster();
ASSERT_EQ(EvsResult::OK, result);
- // Try to adjust a parameter via new master client
- for (auto &cmd : camNonMasterCmds) {
+ // Try to adjust a parameter via new primary client
+ for (auto &cmd : camSecondaryCmds) {
// Get a valid parameter value range
int32_t minVal, maxVal, step;
- pCamNonMaster->getIntParameterRange(
+ pCamSecondary->getIntParameterRange(
cmd,
[&minVal, &maxVal, &step](int32_t val0, int32_t val1, int32_t val2) {
minVal = val0;
@@ -1447,7 +1447,7 @@
if (cmd == CameraParam::ABSOLUTE_FOCUS) {
// Try to turn off auto-focus
values.clear();
- pCamNonMaster->setIntParameter(CameraParam::AUTO_FOCUS, 0,
+ pCamSecondary->setIntParameter(CameraParam::AUTO_FOCUS, 0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1471,7 +1471,7 @@
bool listening1 = false;
std::condition_variable eventCond;
std::thread listener0 = std::thread(
- [&cmd, &val0, &aNotification0, &frameHandlerMaster, &listening0, &listening1, &eventCond]() {
+ [&]() {
listening0 = true;
if (listening1) {
eventCond.notify_all();
@@ -1481,13 +1481,13 @@
aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
- if (!frameHandlerMaster->waitForEvent(aTargetEvent, aNotification0)) {
+ if (!frameHandlerPrimary->waitForEvent(aTargetEvent, aNotification0)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
);
std::thread listener1 = std::thread(
- [&cmd, &val0, &aNotification1, &frameHandlerNonMaster, &listening0, &listening1, &eventCond]() {
+ [&]() {
listening1 = true;
if (listening0) {
eventCond.notify_all();
@@ -1497,7 +1497,7 @@
aTargetEvent.aType = EvsEventType::PARAMETER_CHANGED;
aTargetEvent.payload[0] = static_cast<uint32_t>(cmd);
aTargetEvent.payload[1] = val0;
- if (!frameHandlerNonMaster->waitForEvent(aTargetEvent, aNotification1)) {
+ if (!frameHandlerSecondary->waitForEvent(aTargetEvent, aNotification1)) {
LOG(WARNING) << "A timer is expired before a target event is fired.";
}
}
@@ -1514,7 +1514,7 @@
// Try to program a parameter
values.clear();
- pCamNonMaster->setIntParameter(cmd, val0,
+ pCamSecondary->setIntParameter(cmd, val0,
[&result, &values](auto status, auto effectiveValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1526,9 +1526,9 @@
ASSERT_EQ(EvsResult::OK, result);
// Clients expects to receive a parameter change notification
- // whenever a master client adjusts it.
+ // whenever a primary client client adjusts it.
values.clear();
- pCamNonMaster->getIntParameter(cmd,
+ pCamSecondary->getIntParameter(cmd,
[&result, &values](auto status, auto readValues) {
result = status;
if (status == EvsResult::OK) {
@@ -1567,17 +1567,17 @@
}
}
- // New master retires from a master role
- result = pCamNonMaster->unsetMaster();
+ // New primary client retires from the role
+ result = pCamSecondary->unsetMaster();
ASSERT_EQ(EvsResult::OK, result);
// Shutdown
- frameHandlerMaster->shutdown();
- frameHandlerNonMaster->shutdown();
+ frameHandlerPrimary->shutdown();
+ frameHandlerSecondary->shutdown();
// Explicitly release the camera
- pEnumerator->closeCamera(pCamMaster);
- pEnumerator->closeCamera(pCamNonMaster);
+ pEnumerator->closeCamera(pCamPrimary);
+ pEnumerator->closeCamera(pCamSecondary);
activeCameras.clear();
}
}
@@ -1586,7 +1586,7 @@
/*
* HighPriorityCameraClient:
* EVS client, which owns the display, is priortized and therefore can take over
- * a master role from other EVS clients without the display.
+ * a primary client role from other EVS clients without the display.
*/
TEST_P(EvsHidlTest, HighPriorityCameraClient) {
LOG(INFO) << "Starting HighPriorityCameraClient test";
@@ -1668,7 +1668,7 @@
frameHandler0->waitForFrameCount(1);
frameHandler1->waitForFrameCount(1);
- // Client 1 becomes a master and programs a parameter.
+ // Client 1 becomes a primary client and programs a parameter.
EvsResult result = EvsResult::OK;
// Get a valid parameter value range
int32_t minVal, maxVal, step;
@@ -1681,7 +1681,7 @@
}
);
- // Client1 becomes a master
+ // Client1 becomes a primary client
result = pCam1->setMaster();
ASSERT_EQ(EvsResult::OK, result);
@@ -1820,7 +1820,7 @@
}
lock.unlock();
- // Client 0 steals a master role
+ // Client 0 steals a primary client role
ASSERT_EQ(EvsResult::OK, pCam0->forceMaster(pDisplay));
// Join a listener
@@ -2241,7 +2241,7 @@
TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
LOG(INFO) << "Starting CameraStreamExternalBuffering test";
- // Arbitrary constant (should be > 1 and less than crazy)
+ // Arbitrary constant (should be > 1 and not too big)
static const unsigned int kBuffersToHold = 6;
// Get the camera list
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
new file mode 100644
index 0000000..e354634
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+// User HAL helper library.
+cc_library_static {
+ name: "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+ defaults: ["vhal_v2_0_defaults"],
+ vendor: true,
+ host_supported: true,
+ srcs: [
+ "UserHalHelper.cpp",
+ ],
+ export_include_dirs: [
+ ".",
+ ],
+}
+
+cc_test {
+ name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests",
+ defaults: ["vhal_v2_0_defaults"],
+ vendor: true,
+ srcs: [
+ "tests/UserHalHelper_test.cpp",
+ ],
+ static_libs: [
+ "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
+ "libgmock",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
new file mode 100644
index 0000000..33b3948
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -0,0 +1,366 @@
+/*
+ * 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 "UserHalHelper"
+
+#include "UserHalHelper.h"
+
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+namespace {
+
+using android::base::Error;
+using android::base::Result;
+
+static constexpr const char* kSeparator = "||";
+static const size_t kNumFieldsPerUserInfo = 2;
+static const size_t kNumFieldsPerSetAssociation = 2;
+
+template <typename T>
+Result<T> verifyAndCast(int32_t value) {
+ T castValue = static_cast<T>(value);
+ const auto iter = hidl_enum_range<T>();
+ if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) {
+ return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", "
+ << toString(*std::prev(iter.end())) << "]";
+ }
+ for (const auto& v : hidl_enum_range<T>()) {
+ if (castValue == v) {
+ return castValue;
+ }
+ }
+ return Error() << "Value " << value << " not in enum values";
+}
+
+Result<void> verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty,
+ size_t minInt32Values) {
+ auto prop = verifyAndCast<VehicleProperty>(propValue.prop);
+ if (!prop.ok()) {
+ return Error() << "Invalid vehicle property: " << prop.error();
+ }
+ if (*prop != vehicleProperty) {
+ return Error() << "Mismatching " << toString(vehicleProperty) << " request, received "
+ << toString(*prop) << " property";
+ }
+ if (propValue.value.int32Values.size() < minInt32Values) {
+ return Error() << "Int32Values must have at least " << minInt32Values
+ << " values, received " << propValue.value.int32Values.size();
+ }
+ return {};
+}
+
+Result<void> parseUserInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
+ UserInfo* userInfo) {
+ if (int32Values.size() < startPos + kNumFieldsPerUserInfo) {
+ return Error() << "Int32Values must have at least " << startPos + 2 << " values, received "
+ << int32Values.size();
+ }
+ userInfo->userId = int32Values[startPos];
+ auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
+ if (!userFlags.ok()) {
+ return Error() << "Invalid user flags: " << userFlags.error();
+ }
+ userInfo->flags = *userFlags;
+ return {};
+}
+
+Result<void> parseUsersInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
+ UsersInfo* usersInfo) {
+ if (int32Values.size() < startPos + 3) {
+ return Error() << "Int32Values must have at least " << startPos + 3 << " values, received "
+ << int32Values.size();
+ }
+ auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser);
+ if (!ret.ok()) {
+ return ret;
+ }
+ usersInfo->numberUsers = int32Values[startPos + 2];
+ usersInfo->existingUsers.resize(usersInfo->numberUsers);
+ for (size_t i = 0; i < static_cast<size_t>(usersInfo->numberUsers); ++i) {
+ ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i),
+ &usersInfo->existingUsers[i]);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error();
+ }
+ }
+ return {};
+}
+
+Result<void> parseUserAssociationTypes(
+ const hidl_vec<int32_t>& int32Values, size_t startPos, size_t numberAssociationTypes,
+ hidl_vec<UserIdentificationAssociationType>* associationTypes) {
+ size_t minInt32Values = startPos + numberAssociationTypes;
+ if (int32Values.size() < minInt32Values) {
+ return Error() << "Int32Values must have at least " << minInt32Values
+ << " values, received " << int32Values.size();
+ }
+ associationTypes->resize(numberAssociationTypes);
+ for (size_t i = 0; i < static_cast<size_t>(numberAssociationTypes); ++i) {
+ size_t pos = startPos + i;
+ auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+ if (!type.ok()) {
+ return Error() << "Invalid association type in query '" << i << "': " << type.error();
+ }
+ (*associationTypes)[i] = *type;
+ }
+ return {};
+}
+
+Result<void> parseUserAssociations(const hidl_vec<int32_t>& int32Values, size_t startPos,
+ size_t numberAssociations,
+ hidl_vec<UserIdentificationSetAssociation>* associations) {
+ size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation);
+ if (int32Values.size() < minInt32Values) {
+ return Error() << "Int32Values must have at least " << minInt32Values
+ << " values, received " << int32Values.size();
+ }
+ associations->resize(numberAssociations);
+ for (size_t i = 0; i < static_cast<size_t>(numberAssociations); ++i) {
+ size_t pos = startPos + (kNumFieldsPerSetAssociation * i);
+ auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+ if (!type.ok()) {
+ return Error() << "Invalid association type in request '" << i << "': " << type.error();
+ }
+ (*associations)[i].type = *type;
+ auto value = verifyAndCast<UserIdentificationAssociationSetValue>(int32Values[pos + 1]);
+ if (!value.ok()) {
+ return Error() << "Invalid association set value in request '" << i
+ << "': " << value.error();
+ }
+ (*associations)[i].value = *value;
+ }
+ return {};
+}
+
+} // namespace
+
+Result<InitialUserInfoRequest> toInitialUserInfoRequest(const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, 2);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ InitialUserInfoRequest request;
+ request.requestId = propValue.value.int32Values[0];
+ auto requestType = verifyAndCast<InitialUserInfoRequestType>(propValue.value.int32Values[1]);
+ if (!requestType.ok()) {
+ return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error();
+ }
+ request.requestType = *requestType;
+ ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse users info: " << ret.error();
+ }
+ return request;
+}
+
+Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, 2);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ SwitchUserRequest request;
+ auto messageType = verifyAndCast<SwitchUserMessageType>(propValue.value.int32Values[1]);
+ if (!messageType.ok()) {
+ return Error() << "Invalid SwitchUserMessageType: " << messageType.error();
+ }
+ if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH &&
+ *messageType != SwitchUserMessageType::ANDROID_SWITCH &&
+ *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) {
+ return Error() << "Invalid " << toString(*messageType) << " from Android System";
+ }
+ request.requestId = propValue.value.int32Values[0];
+ request.messageType = *messageType;
+ ret = parseUserInfo(propValue.value.int32Values, 2, &request.targetUser);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse target user info: " << ret.error();
+ }
+ ret = parseUsersInfo(propValue.value.int32Values, 4, &request.usersInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse users info: " << ret.error();
+ }
+ return request;
+}
+
+Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, 1);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ CreateUserRequest request;
+ request.requestId = propValue.value.int32Values[0];
+ ret = parseUserInfo(propValue.value.int32Values, 1, &request.newUserInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse new user info: " << ret.error();
+ }
+ request.newUserName = propValue.value.stringValue;
+ ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse users info: " << ret.error();
+ }
+ return request;
+}
+
+Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, 1);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ RemoveUserRequest request;
+ request.requestId = propValue.value.int32Values[0];
+ ret = parseUserInfo(propValue.value.int32Values, 1, &request.removedUserInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse removed user info: " << ret.error();
+ }
+ ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse users info: " << ret.error();
+ }
+ return request;
+}
+
+Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+ const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ UserIdentificationGetRequest request;
+ request.requestId = propValue.value.int32Values[0];
+ ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse user info: " << ret.error();
+ }
+ request.numberAssociationTypes = propValue.value.int32Values[3];
+ ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes,
+ &request.associationTypes);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error();
+ }
+ return request;
+}
+
+Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
+ const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ UserIdentificationSetRequest request;
+ request.requestId = propValue.value.int32Values[0];
+ ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse user info: " << ret.error();
+ }
+ request.numberAssociations = propValue.value.int32Values[3];
+ ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations,
+ &request.associations);
+ if (!ret.ok()) {
+ return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error();
+ }
+ return request;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request) {
+ if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) {
+ ALOGE("Invalid %s message type %s from HAL", toString(VehicleProperty::SWITCH_USER).c_str(),
+ toString(request.messageType).c_str());
+ return nullptr;
+ }
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(3);
+ propValue->value.int32Values[0] = static_cast<int32_t>(request.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(request.messageType);
+ propValue->value.int32Values[2] = static_cast<int32_t>(request.targetUser.userId);
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(4);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.action);
+ propValue->value.int32Values[2] = static_cast<int32_t>(response.userToSwitchOrCreate.userId);
+ propValue->value.int32Values[3] = static_cast<int32_t>(response.userToSwitchOrCreate.flags);
+ propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) +
+ std::string(response.userNameToCreate);
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(3);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.messageType);
+ propValue->value.int32Values[2] = static_cast<int32_t>(response.status);
+ if (response.status == SwitchUserStatus::FAILURE) {
+ propValue->value.stringValue = response.errorMessage;
+ }
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(2);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.status);
+ if (response.status == CreateUserStatus::FAILURE) {
+ propValue->value.stringValue = response.errorMessage;
+ }
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(2 + (response.numberAssociation * 2));
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.numberAssociation);
+ for (size_t i = 0; i < static_cast<size_t>(response.numberAssociation); ++i) {
+ size_t int32ValuesPos = 2 + (2 * i);
+ propValue->value.int32Values[int32ValuesPos] =
+ static_cast<int32_t>(response.associations[i].type);
+ propValue->value.int32Values[int32ValuesPos + 1] =
+ static_cast<int32_t>(response.associations[i].value);
+ }
+ if (!response.errorMessage.empty()) {
+ propValue->value.stringValue = response.errorMessage;
+ }
+ return propValue;
+}
+
+} // namespace user_hal_helper
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.h b/automotive/vehicle/2.0/utils/UserHalHelper.h
new file mode 100644
index 0000000..bee34cf
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.h
@@ -0,0 +1,62 @@
+/*
+ * 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_UserHalHelper_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_
+
+#include <android-base/result.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+#include <functional>
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+
+// Below functions parse VehiclePropValues to the respective User HAL request structs. On success,
+// these functions return the User HAL struct. Otherwise, they return the error.
+android::base::Result<InitialUserInfoRequest> toInitialUserInfoRequest(
+ const VehiclePropValue& propValue);
+android::base::Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue);
+android::base::Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue);
+android::base::Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+ const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
+ const VehiclePropValue& propValue);
+
+// Below functions convert the User HAL structs to VehiclePropValues. On success, these functions
+// return the pointer to VehiclePropValue. Otherwise, they return nullptr.
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response);
+
+} // namespace user_hal_helper
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_
diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
new file mode 100644
index 0000000..7da87a2
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp
@@ -0,0 +1,666 @@
+/*
+ * 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.
+ */
+
+#include "UserHalHelper.h"
+
+#include <gtest/gtest.h>
+
+#include <cstdint>
+
+#include "gmock/gmock.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace user_hal_helper {
+
+namespace {
+
+using testing::Eq;
+using testing::Gt;
+using testing::IsNull;
+using testing::NotNull;
+using testing::Pointee;
+
+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);
+
+constexpr int32_t FIRST_BOOT_AFTER_OTA =
+ static_cast<int32_t>(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA);
+constexpr int32_t LEGACY_ANDROID_SWITCH =
+ static_cast<int32_t>(SwitchUserMessageType::LEGACY_ANDROID_SWITCH);
+constexpr int32_t VEHICLE_REQUEST = static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST);
+
+constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
+constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
+constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+
+constexpr int32_t USER_ID_ASSOC_KEY_FOB =
+ static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
+constexpr int32_t USER_ID_ASSOC_CUSTOM_1 =
+ static_cast<int32_t>(UserIdentificationAssociationType::CUSTOM_1);
+
+constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER);
+
+constexpr int32_t USER_ID_ASSOC_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_NO_USER =
+ static_cast<int32_t>(UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER);
+
+} // namespace
+
+TEST(UserHalHelperTest, TestToInitialUserInfoRequest) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+ 10, NONE_USER}},
+ };
+ InitialUserInfoRequest expected{
+ .requestId = 23,
+ .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA,
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INT32_MAX,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+ 10, NONE_USER}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidRequestType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, INT32_MAX, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+ NONE_USER}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid request type";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidUserFlag) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER,
+ 10, INT32_MAX}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags";
+}
+
+TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithIncompleteUsersInfo) {
+ VehiclePropValue propValueMissingSecondUserInfo{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0,
+ SYSTEM_USER /*Missing 2nd UserInfo*/}},
+ };
+
+ auto actual = toInitialUserInfoRequest(propValueMissingSecondUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+ VehiclePropValue propValueMissingUsersInfo{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, /*Missing UsersInfo*/}},
+ };
+
+ actual = toInitialUserInfoRequest(propValueMissingUsersInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+}
+
+TEST(UserHalHelperTest, TestToSwitchUserRequest) {
+ VehiclePropValue propValue{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+ 0, SYSTEM_USER, 10, NONE_USER}},
+ };
+ SwitchUserRequest expected{
+ .requestId = 23,
+ .messageType = SwitchUserMessageType::LEGACY_ANDROID_SWITCH,
+ .targetUser = {0, UserFlags::SYSTEM},
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toSwitchUserRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+ 0, SYSTEM_USER, 10, NONE_USER}},
+ };
+
+ auto actual = toSwitchUserRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithInvalidMessageType) {
+ VehiclePropValue propValueIncompatibleMessageType{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, VEHICLE_REQUEST, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+ SYSTEM_USER, 10, NONE_USER}},
+ };
+
+ auto actual = toSwitchUserRequest(propValueIncompatibleMessageType);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on incompatible message type";
+
+ VehiclePropValue propValueInvalidMessageType{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, INT32_MAX, 0, SYSTEM_USER, 10, NONE_USER, 2, 0,
+ SYSTEM_USER, 10, NONE_USER}},
+ };
+
+ actual = toSwitchUserRequest(propValueInvalidMessageType);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid message type";
+}
+
+TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithIncompleteUsersInfo) {
+ VehiclePropValue propValueMissingSecondUserInfo{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2,
+ 0, SYSTEM_USER,
+ /*Missing 2nd UserInfo*/}},
+ };
+
+ auto actual = toSwitchUserRequest(propValueMissingSecondUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+ VehiclePropValue propValueMissingUsersInfo{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER,
+ /*Missing UsersInfo*/}},
+ };
+
+ actual = toSwitchUserRequest(propValueMissingUsersInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+ VehiclePropValue propValueMissingTargetUser{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, /*Missing target UserInfo*/}},
+ };
+
+ actual = toSwitchUserRequest(propValueMissingTargetUser);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing target user info";
+}
+
+TEST(UserHalHelperTest, TestToCreateUserRequest) {
+ VehiclePropValue propValue{
+ .prop = CREATE_USER,
+ .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+ NONE_USER},
+ .stringValue = "Guest11"},
+ };
+ CreateUserRequest expected{
+ .requestId = 23,
+ .newUserInfo = {11, UserFlags::GUEST},
+ .newUserName = "Guest11",
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toCreateUserRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+ NONE_USER},
+ .stringValue = "Guest11"},
+ };
+
+ auto actual = toCreateUserRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithIncompleteUsersInfo) {
+ VehiclePropValue propValueMissingSecondUserInfo{
+ .prop = CREATE_USER,
+ .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0,
+ SYSTEM_USER /*Missing 2nd UserInfo*/},
+ .stringValue = "Guest11"},
+ };
+
+ auto actual = toCreateUserRequest(propValueMissingSecondUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+ VehiclePropValue propValueMissingUsersInfo{
+ .prop = CREATE_USER,
+ .value = {.int32Values = {23, 11, GUEST_USER, /*Missing UsersInfo*/},
+ .stringValue = "Guest11"},
+ };
+
+ actual = toCreateUserRequest(propValueMissingUsersInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+ VehiclePropValue propValueMissingCreateUserInfo{
+ .prop = CREATE_USER,
+ .value = {.int32Values = {23, /*Missing create UserInfo*/}, .stringValue = "Guest11"},
+ };
+
+ actual = toCreateUserRequest(propValueMissingCreateUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing create user info";
+}
+
+TEST(UserHalHelperTest, TestToRemoveUserRequest) {
+ VehiclePropValue propValue{
+ .prop = REMOVE_USER,
+ .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+ NONE_USER}},
+ };
+ RemoveUserRequest expected{
+ .requestId = 23,
+ .removedUserInfo = {10, UserFlags::NONE},
+ .usersInfo = {{10, UserFlags::NONE},
+ 2,
+ {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}},
+ };
+
+ auto actual = toRemoveUserRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10,
+ NONE_USER}},
+ };
+
+ auto actual = toRemoveUserRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithIncompleteUsersInfo) {
+ VehiclePropValue propValueMissingSecondUserInfo{
+ .prop = REMOVE_USER,
+ .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0,
+ SYSTEM_USER /*Missing 2nd UserInfo*/}},
+ };
+
+ auto actual = toRemoveUserRequest(propValueMissingSecondUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info";
+
+ VehiclePropValue propValueMissingUsersInfo{
+ .prop = REMOVE_USER,
+ .value = {.int32Values = {23, 10, NONE_USER, /*Missing UsersInfo*/}},
+ };
+
+ actual = toRemoveUserRequest(propValueMissingUsersInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing users info";
+
+ VehiclePropValue propValueMissingRemoveUserInfo{
+ .prop = REMOVE_USER,
+ .value = {.int32Values = {23, /*Missing remove UserInfo*/}},
+ };
+
+ actual = toRemoveUserRequest(propValueMissingRemoveUserInfo);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing remove user info";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequest) {
+ VehiclePropValue propValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+ USER_ID_ASSOC_CUSTOM_1}},
+ };
+ UserIdentificationGetRequest expected{
+ .requestId = 23,
+ .userInfo = {10, UserFlags::NONE},
+ .numberAssociationTypes = 2,
+ .associationTypes = {UserIdentificationAssociationType::KEY_FOB,
+ UserIdentificationAssociationType::CUSTOM_1},
+ };
+
+ auto actual = toUserIdentificationGetRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+ USER_ID_ASSOC_CUSTOM_1}},
+ };
+
+ auto actual = toUserIdentificationGetRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithInvalidAssociationTypes) {
+ VehiclePropValue propValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX}},
+ };
+
+ auto actual = toUserIdentificationGetRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithIncompleteAssociationTypes) {
+ VehiclePropValue propValueMissingSecondAssociationType{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 2,
+ USER_ID_ASSOC_KEY_FOB /*Missing 2nd association type*/}},
+ };
+
+ auto actual = toUserIdentificationGetRequest(propValueMissingSecondAssociationType);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+ VehiclePropValue propValueMissingNumberAssociationTypes{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, /*Missing number association types*/}},
+ };
+
+ actual = toUserIdentificationGetRequest(propValueMissingNumberAssociationTypes);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMissingUserInfo) {
+ VehiclePropValue propValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, /*Missing user info*/}},
+ };
+
+ auto actual = toUserIdentificationGetRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestToUserIdentificationSetRequest) {
+ VehiclePropValue propValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+ USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+ USER_ID_ASSOC_UNSET_CURRENT_USER}},
+ };
+ UserIdentificationSetRequest expected{
+ .requestId = 23,
+ .userInfo = {10, UserFlags::NONE},
+ .numberAssociations = 2,
+ .associations = {{UserIdentificationAssociationType::KEY_FOB,
+ UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER},
+ {UserIdentificationAssociationType::CUSTOM_1,
+ UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER}},
+ };
+
+ auto actual = toUserIdentificationSetRequest(propValue);
+
+ ASSERT_TRUE(actual.ok()) << actual.error().message();
+ EXPECT_THAT(actual.value(), Eq(expected));
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMismatchingPropType) {
+ VehiclePropValue propValue{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+ USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1,
+ USER_ID_ASSOC_UNSET_CURRENT_USER}},
+ };
+
+ auto actual = toUserIdentificationSetRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithInvalidAssociations) {
+ VehiclePropValue propValueInvalidAssociationType{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX,
+ USER_ID_ASSOC_SET_CURRENT_USER}},
+ };
+
+ auto actual = toUserIdentificationSetRequest(propValueInvalidAssociationType);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type";
+
+ VehiclePropValue propValueInvalidAssociationValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, USER_ID_ASSOC_KEY_FOB, INT32_MAX}},
+ };
+
+ actual = toUserIdentificationSetRequest(propValueInvalidAssociationValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithIncompleteAssociations) {
+ VehiclePropValue propValueMissingSecondAssociationType{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB,
+ USER_ID_ASSOC_SET_CURRENT_USER,
+ /*Missing 2nd association*/}},
+ };
+
+ auto actual = toUserIdentificationSetRequest(propValueMissingSecondAssociationType);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type";
+
+ VehiclePropValue propValueMissingNumberAssociationTypes{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 10, NONE_USER, /*Missing number associations*/}},
+ };
+
+ actual = toUserIdentificationSetRequest(propValueMissingNumberAssociationTypes);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types";
+}
+
+TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMissingUserInfo) {
+ VehiclePropValue propValue{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, /*Missing user info*/}},
+ };
+
+ auto actual = toUserIdentificationSetRequest(propValue);
+
+ EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo";
+}
+
+TEST(UserHalHelperTest, TestSwitchUserRequestToVehiclePropValue) {
+ SwitchUserRequest request{
+ .requestId = 23,
+ .messageType = SwitchUserMessageType::VEHICLE_REQUEST,
+ .targetUser = {11, UserFlags::GUEST},
+ };
+ VehiclePropValue expected{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23,
+ static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST),
+ 11}},
+ };
+
+ auto actual = toVehiclePropValue(request);
+
+ ASSERT_THAT(actual, NotNull());
+ EXPECT_THAT(actual->timestamp, Gt(0));
+ // Don't rely on real timestamp in tests as the expected and actual objects won't have the same
+ // timestamps. Thus remove the timestamps before comparing them.
+ actual->timestamp = 0;
+ EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestFailsSwitchUserRequestToVehiclePropValueWithIncompatibleMessageType) {
+ SwitchUserRequest request{
+ .requestId = 23,
+ .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+ .targetUser = {11, UserFlags::GUEST},
+ };
+
+ auto actual = toVehiclePropValue(request);
+
+ EXPECT_THAT(actual, IsNull());
+}
+
+TEST(UserHalHelperTest, TestInitialUserInfoResponseToVehiclePropValue) {
+ InitialUserInfoResponse response{
+ .requestId = 23,
+ .action = InitialUserInfoResponseAction::CREATE,
+ .userToSwitchOrCreate = {11, UserFlags::GUEST},
+ .userLocales = "en-US,pt-BR",
+ .userNameToCreate = "Owner",
+ };
+ VehiclePropValue expected{
+ .prop = INITIAL_USER_INFO,
+ .value = {.int32Values = {23,
+ static_cast<int32_t>(InitialUserInfoResponseAction::CREATE),
+ 11, GUEST_USER},
+ .stringValue = "en-US,pt-BR||Owner"},
+ };
+
+ auto actual = toVehiclePropValue(response);
+
+ ASSERT_THAT(actual, NotNull());
+ EXPECT_THAT(actual->timestamp, Gt(0));
+ actual->timestamp = 0;
+ EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestSwitchUserResponseToVehiclePropValue) {
+ SwitchUserResponse response{
+ .requestId = 23,
+ .messageType = SwitchUserMessageType::VEHICLE_RESPONSE,
+ .status = SwitchUserStatus::FAILURE,
+ .errorMessage = "random error",
+ };
+ VehiclePropValue expected{
+ .prop = SWITCH_USER,
+ .value = {.int32Values = {23,
+ static_cast<int32_t>(SwitchUserMessageType::VEHICLE_RESPONSE),
+ static_cast<int32_t>(SwitchUserStatus::FAILURE)},
+ .stringValue = "random error"},
+ };
+
+ auto actual = toVehiclePropValue(response);
+
+ ASSERT_THAT(actual, NotNull());
+ EXPECT_THAT(actual->timestamp, Gt(0));
+ actual->timestamp = 0;
+ EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestCreateUserResponseToVehiclePropValue) {
+ CreateUserResponse response{
+ .requestId = 23,
+ .status = CreateUserStatus::FAILURE,
+ .errorMessage = "random error",
+ };
+ VehiclePropValue expected{
+ .prop = CREATE_USER,
+ .value = {.int32Values = {23, static_cast<int32_t>(CreateUserStatus::FAILURE)},
+ .stringValue = "random error"},
+ };
+
+ auto actual = toVehiclePropValue(response);
+
+ ASSERT_THAT(actual, NotNull());
+ EXPECT_THAT(actual->timestamp, Gt(0));
+ actual->timestamp = 0;
+ EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+TEST(UserHalHelperTest, TestUserIdentificationResponseToVehiclePropValue) {
+ UserIdentificationResponse response{
+ .requestId = 23,
+ .numberAssociation = 2,
+ .associations = {{UserIdentificationAssociationType::KEY_FOB,
+ UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER},
+ {UserIdentificationAssociationType::CUSTOM_1,
+ UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER}},
+ .errorMessage = "random error",
+ };
+ VehiclePropValue expected{
+ .prop = USER_IDENTIFICATION_ASSOCIATION,
+ .value = {.int32Values = {23, 2, USER_ID_ASSOC_KEY_FOB, USER_ID_ASSOC_CURRENT_USER,
+ USER_ID_ASSOC_CUSTOM_1, USER_ID_ASSOC_NO_USER},
+ .stringValue = "random error"},
+ };
+
+ auto actual = toVehiclePropValue(response);
+
+ ASSERT_THAT(actual, NotNull());
+ EXPECT_THAT(actual->timestamp, Gt(0));
+ actual->timestamp = 0;
+ EXPECT_THAT(actual, Pointee(Eq(expected)));
+}
+
+} // namespace user_hal_helper
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 384edf3..832c419 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -4453,9 +4453,12 @@
nullptr};
} else {
allocateGraphicBuffer(testStream.width, testStream.height,
- android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
- halStreamConfig.streams[0].consumerUsage),
- halStreamConfig.streams[0].overrideFormat, &buffer_handle);
+ /* We don't look at halStreamConfig.streams[0].consumerUsage
+ * since that is 0 for output streams
+ */
+ android_convertGralloc1To0Usage(
+ halStreamConfig.streams[0].producerUsage, bufferUsage),
+ halStreamConfig.streams[0].overrideFormat, &buffer_handle);
outputBuffer = {halStreamConfig.streams[0].id,
bufferId,
buffer_handle,
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 3ddb2b3..75d6252 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -17,7 +17,6 @@
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <hidl/HidlTransportSupport.h>
#include <wifi_system/hostapd_manager.h>
@@ -39,7 +38,6 @@
using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::ChipModeId;
using ::android::hardware::wifi::V1_0::IWifiChip;
-using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::wifi_system::HostapdManager;
using ::android::wifi_system::SupplicantManager;
@@ -68,55 +66,6 @@
}
} // namespace
-// Utility class to wait for wpa_hostapd's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
- public:
- Return<void> onRegistration(const hidl_string& fully_qualified_name,
- const hidl_string& instance_name,
- bool pre_existing) override {
- if (pre_existing) {
- return Void();
- }
- std::unique_lock<std::mutex> lock(mutex_);
- registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
- instance_name.c_str());
- lock.unlock();
- condition_.notify_one();
- return Void();
- }
-
- bool registerForHidlServiceNotifications(const std::string& instance_name) {
- if (!IHostapd::registerForNotifications(instance_name, this)) {
- return false;
- }
- configureRpcThreadpool(2, false);
- return true;
- }
-
- bool waitForHidlService(uint32_t timeout_in_millis,
- const std::string& instance_name) {
- std::unique_lock<std::mutex> lock(mutex_);
- condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
- [&]() { return registered_.size() >= 1; });
- if (registered_.size() != 1) {
- return false;
- }
- std::string expected_registered =
- std::string(IHostapd::descriptor) + "/" + instance_name;
- if (registered_[0] != expected_registered) {
- LOG(ERROR) << "Expected: " << expected_registered
- << ", Got: " << registered_[0];
- return false;
- }
- return true;
- }
-
- private:
- std::vector<std::string> registered_{};
- std::mutex mutex_;
- std::condition_variable condition_;
-};
-
void stopSupplicantIfNeeded(const std::string& instance_name) {
SupplicantManager supplicant_manager;
if (supplicant_manager.IsSupplicantRunning()) {
@@ -139,16 +88,11 @@
const std::string& hostapd_instance_name) {
initilializeDriverAndFirmware(wifi_instance_name);
- android::sp<ServiceNotificationListener> notification_listener =
- new ServiceNotificationListener();
- ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
- hostapd_instance_name));
-
HostapdManager hostapd_manager;
ASSERT_TRUE(hostapd_manager.StartHostapd());
- ASSERT_TRUE(
- notification_listener->waitForHidlService(500, hostapd_instance_name));
+ // Wait for hostapd service to come up.
+ IHostapd::getService(hostapd_instance_name);
}
bool is_1_1(const sp<IHostapd>& hostapd) {
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index addf066..5e7a371 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -18,7 +18,6 @@
#include <cutils/properties.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <hidl/HidlTransportSupport.h>
#include <wifi_system/interface_tool.h>
@@ -45,7 +44,6 @@
using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::wifi_system::InterfaceTool;
using ::android::wifi_system::SupplicantManager;
@@ -120,55 +118,6 @@
}
} // namespace
-// Utility class to wait for wpa_supplicant's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
- public:
- Return<void> onRegistration(const hidl_string& fully_qualified_name,
- const hidl_string& instance_name,
- bool pre_existing) override {
- if (pre_existing) {
- return Void();
- }
- std::unique_lock<std::mutex> lock(mutex_);
- registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
- instance_name.c_str());
- lock.unlock();
- condition_.notify_one();
- return Void();
- }
-
- bool registerForHidlServiceNotifications(const std::string& instance_name) {
- if (!ISupplicant::registerForNotifications(instance_name, this)) {
- return false;
- }
- configureRpcThreadpool(2, false);
- return true;
- }
-
- bool waitForHidlService(uint32_t timeout_in_millis,
- const std::string& instance_name) {
- std::unique_lock<std::mutex> lock(mutex_);
- condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
- [&]() { return registered_.size() >= 1; });
- if (registered_.size() != 1) {
- return false;
- }
- std::string exptected_registered =
- std::string(ISupplicant::descriptor) + "/" + instance_name;
- if (registered_[0] != exptected_registered) {
- LOG(ERROR) << "Expected: " << exptected_registered
- << ", Got: " << registered_[0];
- return false;
- }
- return true;
- }
-
- private:
- std::vector<std::string> registered_{};
- std::mutex mutex_;
- std::condition_variable condition_;
-};
-
void stopSupplicant() { stopSupplicant(""); }
void stopSupplicant(const std::string& wifi_instance_name) {
@@ -184,17 +133,12 @@
const std::string& supplicant_instance_name) {
initilializeDriverAndFirmware(wifi_instance_name);
- android::sp<ServiceNotificationListener> notification_listener =
- new ServiceNotificationListener();
- ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
- supplicant_instance_name));
-
SupplicantManager supplicant_manager;
ASSERT_TRUE(supplicant_manager.StartSupplicant());
ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
- ASSERT_TRUE(notification_listener->waitForHidlService(
- 500, supplicant_instance_name));
+ // Wait for supplicant service to come up.
+ ISupplicant::getService(supplicant_instance_name);
}
bool is_1_1(const sp<ISupplicant>& supplicant) {