Merge "Updates to VMS Utils to support HAL Client Publisher"

This commit is contained in:
TreeHugger Robot
2019-04-04 00:17:21 +00:00
committed by Android (Google) Code Review
4 changed files with 355 additions and 36 deletions

View File

@@ -19,6 +19,7 @@
#include <memory>
#include <string>
#include <unordered_set>
#include <android/hardware/automotive/vehicle/2.0/types.h>
@@ -42,6 +43,20 @@ struct VmsLayer {
int type;
int subtype;
int version;
bool operator==(const VmsLayer& layer) const {
return this->type == layer.type && this->subtype == layer.subtype &&
this->version == layer.version;
}
// Class for hash function
class VmsLayerHashFunction {
public:
// Hash of the variables is returned.
size_t operator()(const VmsLayer& layer) const {
return std::hash<int>()(layer.type) ^ std::hash<int>()(layer.type) ^
std::hash<int>()(layer.type);
}
};
};
struct VmsLayerAndPublisher {
@@ -66,6 +81,15 @@ struct VmsLayerOffering {
std::vector<VmsLayer> dependencies;
};
// A VmsOffers refers to a list of layers that can be published by the publisher
// with the specified publisher ID.
struct VmsOffers {
VmsOffers(int publisher_id, std::vector<VmsLayerOffering> offerings)
: publisher_id(publisher_id), offerings(offerings) {}
int publisher_id;
std::vector<VmsLayerOffering> offerings;
};
// A VmsSubscriptionsState is delivered in response to a
// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
@@ -81,6 +105,9 @@ struct VmsAvailabilityState {
std::vector<VmsAssociatedLayer> associated_layers;
};
// Creates an empty base VMS message with some pre-populated default fields.
std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size);
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.SUBSCRIBE, specifying to the VMS service
// which layer to subscribe to.
@@ -106,8 +133,7 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
// offered and their dependencies, if any.
std::unique_ptr<VehiclePropValue> createOfferingMessage(
const std::vector<VmsLayerOffering>& offering);
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers);
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.AVAILABILITY_REQUEST.
@@ -143,8 +169,40 @@ VmsMessageType parseMessageType(const VehiclePropValue& value);
// function to ParseFromString.
std::string parseData(const VehiclePropValue& value);
// TODO(aditin): Need to implement additional parsing functions per message
// type.
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
// Returns a nullptr if the input is empty.
std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
const std::string& vms_provider_description);
// Returns the publisher ID by parsing the VehiclePropValue containing the ID.
// Returns null if the message is invalid.
int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response);
// Returns true if the new sequence number is greater than the last seen
// sequence number.
bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
const int last_seen_sequence_number);
// Returns sequence number of the message.
int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change);
// Takes a subscription change message and returns the layers that have active
// subscriptions of the layers that are offered by your HAL client/publisher.
//
// A publisher can use this function when receiving a subscription change message
// to determine which layers to publish data on.
// The caller of this function can optionally decide to not consume these layers
// if the subscription change has the sequence number less than the last seen
// sequence number.
std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
const VmsOffers& offers);
// Takes an availability change message and returns true if the parsed message implies that
// the service has newly started or restarted.
// If the message has a sequence number 0, it means that the service
// has newly started or restarted.
bool hasServiceNewlyStarted(const VehiclePropValue& availability_change);
} // namespace vms
} // namespace V2_0

View File

@@ -27,16 +27,23 @@ namespace vms {
static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
static constexpr int kMessageTypeSize = 1;
static constexpr int kPublisherIdSize = 1;
static constexpr int kLayerNumberSize = 1;
static constexpr int kLayerSize = 3;
static constexpr int kLayerAndPublisherSize = 4;
static constexpr int kPublisherIdIndex =
toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID);
static constexpr int kSubscriptionStateSequenceNumberIndex =
toInt(VmsSubscriptionsStateIntegerValuesIndex::SEQUENCE_NUMBER);
static constexpr int kAvailabilitySequenceNumberIndex =
toInt(VmsAvailabilityStateIntegerValuesIndex::SEQUENCE_NUMBER);
// TODO(aditin): We should extend the VmsMessageType enum to include a first and
// last, which would prevent breakages in this API. However, for all of the
// functions in this module, we only need to guarantee that the message type is
// between SUBSCRIBE and DATA.
// between SUBSCRIBE and PUBLISHER_ID_RESPONSE.
static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
static constexpr int kLastMessageType = toInt(VmsMessageType::DATA);
static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE);
std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
@@ -77,17 +84,16 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
return result;
}
std::unique_ptr<VehiclePropValue> createOfferingMessage(
const std::vector<VmsLayerOffering>& offering) {
int message_size = kMessageTypeSize + kLayerNumberSize;
for (const auto& offer : offering) {
message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers) {
int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize;
for (const auto& offer : offers.offerings) {
message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize);
}
auto result = createBaseVmsMessage(message_size);
std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
static_cast<int>(offering.size())};
for (const auto& offer : offering) {
std::vector<int32_t> offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id,
static_cast<int>(offers.offerings.size())};
for (const auto& offer : offers.offerings) {
std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
offer.layer.version,
static_cast<int32_t>(offer.dependencies.size())};
@@ -97,9 +103,9 @@ std::unique_ptr<VehiclePropValue> createOfferingMessage(
layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
dependency_layer.end());
}
offers.insert(offers.end(), layer_vector.begin(), layer_vector.end());
offerings.insert(offerings.end(), layer_vector.begin(), layer_vector.end());
}
result->value.int32Values = offers;
result->value.int32Values = offerings;
return result;
}
@@ -153,6 +159,103 @@ std::string parseData(const VehiclePropValue& value) {
}
}
std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
const std::string& vms_provider_description) {
auto result = createBaseVmsMessage(kMessageTypeSize);
result->value.int32Values = hidl_vec<int32_t>{
toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
};
result->value.bytes =
std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
return result;
}
int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) {
if (isValidVmsMessage(publisher_id_response) &&
parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE &&
publisher_id_response.value.int32Values.size() > kPublisherIdIndex) {
return publisher_id_response.value.int32Values[kPublisherIdIndex];
}
return -1;
}
bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
const int last_seen_sequence_number) {
return (isValidVmsMessage(subscription_change) &&
parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
last_seen_sequence_number);
}
int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) {
if (isValidVmsMessage(subscription_change) &&
parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex];
}
return -1;
}
std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
const VmsOffers& offers) {
if (isValidVmsMessage(subscription_change) &&
parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
const int32_t num_of_layers = subscription_change.value.int32Values[toInt(
VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt(
VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];
std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
for (const auto& offer : offers.offerings) {
offered_layers.insert(offer.layer);
}
std::vector<VmsLayer> subscribed_layers;
int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
// Add all subscribed layers which are offered by the current publisher.
for (int i = 0; i < num_of_layers; i++) {
VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
subscription_change.value.int32Values[current_index + 1],
subscription_change.value.int32Values[current_index + 2]);
if (offered_layers.find(layer) != offered_layers.end()) {
subscribed_layers.push_back(layer);
}
current_index += kLayerSize;
}
// Add all subscribed associated layers which are offered by the current publisher.
// For this, we need to check if the associated layer has a publisher ID which is
// same as that of the current publisher.
for (int i = 0; i < num_of_associated_layers; i++) {
VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
subscription_change.value.int32Values[current_index + 1],
subscription_change.value.int32Values[current_index + 2]);
current_index += kLayerSize;
if (offered_layers.find(layer) != offered_layers.end()) {
int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index];
current_index++;
for (int j = 0; j < num_of_publisher_ids; j++) {
if (subscription_change.value.int32Values[current_index] ==
offers.publisher_id) {
subscribed_layers.push_back(layer);
}
current_index++;
}
}
}
return subscribed_layers;
}
return {};
}
bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) {
return (isValidVmsMessage(availability_change) &&
parseMessageType(availability_change) == VmsMessageType::AVAILABILITY_CHANGE &&
availability_change.value.int32Values.size() > kAvailabilitySequenceNumberIndex &&
availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0);
}
} // namespace vms
} // namespace V2_0
} // namespace vehicle

View File

@@ -278,7 +278,6 @@ TEST_F(VehicleHalManagerTest, subscribe) {
cb->reset();
VehiclePropValue actualValue(*subscribedValue.get());
actualValue.status = VehiclePropertyStatus::AVAILABLE;
hal->sendPropEvent(std::move(subscribedValue));
ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "

View File

@@ -60,52 +60,64 @@ TEST(VmsUtilsTest, unsubscribeMessage) {
}
TEST(VmsUtilsTest, singleOfferingMessage) {
std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
auto message = createOfferingMessage(offering);
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 2))}};
auto message = createOfferingMessage(offers);
ASSERT_NE(message, nullptr);
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
EXPECT_EQ(message->value.int32Values.size(), 0x6ul);
EXPECT_EQ(message->value.int32Values.size(), 0x7ul);
EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
// Publisher ID
EXPECT_EQ(message->value.int32Values[1], 123);
// Number of layer offerings
EXPECT_EQ(message->value.int32Values[1], 1);
EXPECT_EQ(message->value.int32Values[2], 1);
// Layer
EXPECT_EQ(message->value.int32Values[2], 1);
EXPECT_EQ(message->value.int32Values[3], 0);
EXPECT_EQ(message->value.int32Values[4], 2);
EXPECT_EQ(message->value.int32Values[3], 1);
EXPECT_EQ(message->value.int32Values[4], 0);
EXPECT_EQ(message->value.int32Values[5], 2);
// Number of dependencies
EXPECT_EQ(message->value.int32Values[5], 0);
EXPECT_EQ(message->value.int32Values[6], 0);
}
TEST(VmsUtilsTest, offeringWithDependencies) {
VmsLayer layer(1, 0, 2);
std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)};
std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)};
std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
auto message = createOfferingMessage(offering);
VmsOffers offers = {123, offering};
auto message = createOfferingMessage(offers);
ASSERT_NE(message, nullptr);
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
EXPECT_EQ(message->value.int32Values.size(), 0x9ul);
EXPECT_EQ(message->value.int32Values.size(), 0xdul);
EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
// Publisher ID
EXPECT_EQ(message->value.int32Values[1], 123);
// Number of layer offerings
EXPECT_EQ(message->value.int32Values[1], 1);
EXPECT_EQ(message->value.int32Values[2], 1);
// Layer
EXPECT_EQ(message->value.int32Values[2], 1);
EXPECT_EQ(message->value.int32Values[3], 0);
EXPECT_EQ(message->value.int32Values[4], 2);
EXPECT_EQ(message->value.int32Values[3], 1);
EXPECT_EQ(message->value.int32Values[4], 0);
EXPECT_EQ(message->value.int32Values[5], 2);
// Number of dependencies
EXPECT_EQ(message->value.int32Values[5], 1);
EXPECT_EQ(message->value.int32Values[6], 2);
// Dependency 1
EXPECT_EQ(message->value.int32Values[6], 2);
EXPECT_EQ(message->value.int32Values[7], 0);
EXPECT_EQ(message->value.int32Values[8], 2);
EXPECT_EQ(message->value.int32Values[7], 2);
EXPECT_EQ(message->value.int32Values[8], 0);
EXPECT_EQ(message->value.int32Values[9], 2);
// Dependency 2
EXPECT_EQ(message->value.int32Values[10], 3);
EXPECT_EQ(message->value.int32Values[11], 0);
EXPECT_EQ(message->value.int32Values[12], 3);
}
TEST(VmsUtilsTest, availabilityMessage) {
@@ -166,6 +178,153 @@ TEST(VmsUtilsTest, parseInvalidDataMessage) {
EXPECT_TRUE(data_str.empty());
}
TEST(VmsUtilsTest, publisherIdRequest) {
std::string bytes = "pub_id";
auto message = createPublisherIdRequest(bytes);
ASSERT_NE(message, nullptr);
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
EXPECT_EQ(parseMessageType(*message), VmsMessageType::PUBLISHER_ID_REQUEST);
EXPECT_EQ(message->value.bytes.size(), bytes.size());
EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
}
TEST(VmsUtilsTest, validPublisherIdResponse) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), 1234};
EXPECT_EQ(parsePublisherIdResponse(*message), 1234);
}
TEST(VmsUtilsTest, invalidPublisherIdResponse) {
auto message = createBaseVmsMessage(1);
EXPECT_EQ(parsePublisherIdResponse(*message), -1);
}
TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsState) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234);
}
TEST(VmsUtilsTest, invalidSubscriptionsState) {
auto message = createBaseVmsMessage(1);
EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), -1);
}
TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumber) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_TRUE(isSequenceNumberNewer(*message, 1233));
}
TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumber) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_FALSE(isSequenceNumberNewer(*message, 1235));
}
TEST(VmsUtilsTest, newSequenceNumberForSameNumber) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_FALSE(isSequenceNumberNewer(*message, 1234));
}
TEST(VmsUtilsTest, subscribedLayers) {
VmsOffers offers = {123,
{VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
VmsLayerOffering(VmsLayer(2, 0, 1))}};
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
1234, // sequence number
2, // number of layers
1, // number of associated layers
1, // layer 1
0,
1,
4, // layer 2
1,
1,
2, // associated layer
0,
1,
2, // number of publisher IDs
111, // publisher IDs
123};
EXPECT_TRUE(isValidVmsMessage(*message));
auto result = getSubscribedLayers(*message, offers);
EXPECT_EQ(static_cast<int>(result.size()), 2);
EXPECT_EQ(result.at(0), VmsLayer(1, 0, 1));
EXPECT_EQ(result.at(1), VmsLayer(2, 0, 1));
}
TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtype) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
1234, // sequence number
1, // number of layers
0, // number of associated layers
1, // layer 1
1, // different subtype
1};
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
TEST(VmsUtilsTest, subscribedLayersWithDifferentVersion) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
1234, // sequence number
1, // number of layers
0, // number of associated layers
1, // layer 1
0,
2}; // different version
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherId) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
1234, // sequence number
0, // number of layers
1, // number of associated layers
1, // associated layer 1
0,
1,
1, // number of publisher IDs
234}; // publisher ID 1
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
TEST(VmsUtilsTest, serviceNewlyStarted) {
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 0};
EXPECT_TRUE(hasServiceNewlyStarted(*message));
}
TEST(VmsUtilsTest, serviceNotNewlyStarted) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
EXPECT_FALSE(hasServiceNewlyStarted(*message));
}
TEST(VmsUtilsTest, invalidAvailabilityChange) {
auto message = createBaseVmsMessage(1);
EXPECT_FALSE(hasServiceNewlyStarted(*message));
}
} // namespace
} // namespace vms