From dbce8697bd270b7144e9c43db44b0bca7b3eec16 Mon Sep 17 00:00:00 2001 From: Prachi Hande Date: Thu, 14 Nov 2019 17:57:44 -0800 Subject: [PATCH] VmsUtils: Add new methods to parse availability state messages These methods are needed in the HAL client to parse sequence number and associated layers when the availablity of the VMS layers change. HAL client relies on these messages by either explicitly requesting the availability or through availability change message sent by the Car service. Bug: 144434783 Fixes: 144434783 Test: Added new tests for the new methods. Ran the tests on Hawk. Change-Id: I09497640367a894e1dfb6143ac3bbdb63d64b53e --- .../common/include/vhal_v2_0/VmsUtils.h | 26 +++- .../2.0/default/common/src/VmsUtils.cpp | 114 ++++++++++++--- .../2.0/default/tests/VmsUtils_test.cpp | 134 +++++++++++++++++- 3 files changed, 247 insertions(+), 27 deletions(-) diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h index 8ee3c545dc..f8b10cacf8 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h @@ -61,7 +61,7 @@ struct VmsLayer { struct VmsLayerAndPublisher { VmsLayerAndPublisher(VmsLayer layer, int publisher_id) - : layer(layer), publisher_id(publisher_id) {} + : layer(std::move(layer)), publisher_id(publisher_id) {} VmsLayer layer; int publisher_id; }; @@ -69,6 +69,8 @@ struct VmsLayerAndPublisher { // A VmsAssociatedLayer is used by subscribers to specify which publisher IDs // are acceptable for a given layer. struct VmsAssociatedLayer { + VmsAssociatedLayer(VmsLayer layer, std::vector publisher_ids) + : layer(std::move(layer)), publisher_ids(std::move(publisher_ids)) {} VmsLayer layer; std::vector publisher_ids; }; @@ -77,7 +79,7 @@ struct VmsAssociatedLayer { // its dependencies. Dependencies can be empty. struct VmsLayerOffering { VmsLayerOffering(VmsLayer layer, std::vector dependencies) - : layer(layer), dependencies(dependencies) {} + : layer(std::move(layer)), dependencies(std::move(dependencies)) {} VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {} VmsLayer layer; std::vector dependencies; @@ -87,7 +89,7 @@ struct VmsLayerOffering { // with the specified publisher ID. struct VmsOffers { VmsOffers(int publisher_id, std::vector offerings) - : publisher_id(publisher_id), offerings(offerings) {} + : publisher_id(publisher_id), offerings(std::move(offerings)) {} int publisher_id; std::vector offerings; }; @@ -231,6 +233,24 @@ VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, const int current_service_id, const int current_client_id, int* new_service_id); +// Returns true if the new sequence number of the availability state message is greater than +// the last seen availability sequence number. +bool isAvailabilitySequenceNumberNewer(const VehiclePropValue& availability_state, + const int last_seen_availability_sequence_number); + +// Returns sequence number of the availability state message. +int32_t getSequenceNumberForAvailabilityState(const VehiclePropValue& availability_state); + +// Takes a availability state message and returns the associated layers that are +// available to publish data. +// +// A subscriber can use this function when receiving an availability response or availability +// change message to determine which associated layers are ready to publish data. +// The caller of this function can optionally decide to not consume these layers +// if the availability change has the sequence number less than the last seen +// sequence number. +std::vector getAvailableLayers(const VehiclePropValue& availability_state); + } // namespace vms } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp index 9eba905901..a65cded261 100644 --- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp @@ -219,12 +219,9 @@ std::vector getSubscribedLayers(const VehiclePropValue& subscriptions_ if (isValidVmsMessage(subscriptions_state) && (parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_CHANGE || parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_RESPONSE) && - subscriptions_state.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) { - const int32_t num_of_layers = subscriptions_state.value.int32Values[toInt( - VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)]; - const int32_t num_of_associated_layers = subscriptions_state.value.int32Values[toInt( - VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)]; - + subscriptions_state.value.int32Values.size() > + toInt(VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)) { + int subscriptions_state_int_size = subscriptions_state.value.int32Values.size(); std::unordered_set offered_layers; for (const auto& offer : offers.offerings) { offered_layers.insert(offer.layer); @@ -232,33 +229,52 @@ std::vector getSubscribedLayers(const VehiclePropValue& subscriptions_ std::vector subscribed_layers; int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START); + // Add all subscribed layers which are offered by the current publisher. + const int32_t num_of_layers = subscriptions_state.value.int32Values[toInt( + VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)]; for (int i = 0; i < num_of_layers; i++) { + if (subscriptions_state_int_size < current_index + kLayerSize) { + return {}; + } VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index], subscriptions_state.value.int32Values[current_index + 1], subscriptions_state.value.int32Values[current_index + 2]); if (offered_layers.find(layer) != offered_layers.end()) { - subscribed_layers.push_back(layer); + subscribed_layers.push_back(std::move(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(subscriptions_state.value.int32Values[current_index], - subscriptions_state.value.int32Values[current_index + 1], - subscriptions_state.value.int32Values[current_index + 2]); - current_index += kLayerSize; - if (offered_layers.find(layer) != offered_layers.end()) { - int32_t num_of_publisher_ids = subscriptions_state.value.int32Values[current_index]; - current_index++; - for (int j = 0; j < num_of_publisher_ids; j++) { - if (subscriptions_state.value.int32Values[current_index] == - offers.publisher_id) { - subscribed_layers.push_back(layer); - } + if (subscriptions_state_int_size > + toInt(VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)) { + const int32_t num_of_associated_layers = subscriptions_state.value.int32Values[toInt( + VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)]; + + for (int i = 0; i < num_of_associated_layers; i++) { + if (subscriptions_state_int_size < current_index + kLayerSize) { + return {}; + } + VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index], + subscriptions_state.value.int32Values[current_index + 1], + subscriptions_state.value.int32Values[current_index + 2]); + current_index += kLayerSize; + if (offered_layers.find(layer) != offered_layers.end() && + subscriptions_state_int_size > current_index) { + int32_t num_of_publisher_ids = + subscriptions_state.value.int32Values[current_index]; current_index++; + for (int j = 0; j < num_of_publisher_ids; j++) { + if (subscriptions_state_int_size > current_index && + subscriptions_state.value.int32Values[current_index] == + offers.publisher_id) { + subscribed_layers.push_back(std::move(layer)); + } + current_index++; + } } } } @@ -300,6 +316,64 @@ VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session, return VmsSessionStatus::kInvalidMessage; } +bool isAvailabilitySequenceNumberNewer(const VehiclePropValue& availability_state, + const int last_seen_availability_sequence_number) { + return (isValidVmsMessage(availability_state) && + (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE || + parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) && + availability_state.value.int32Values.size() > kAvailabilitySequenceNumberIndex && + availability_state.value.int32Values[kAvailabilitySequenceNumberIndex] > + last_seen_availability_sequence_number); +} + +int32_t getSequenceNumberForAvailabilityState(const VehiclePropValue& availability_state) { + if (isValidVmsMessage(availability_state) && + (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE || + parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) && + availability_state.value.int32Values.size() > kAvailabilitySequenceNumberIndex) { + return availability_state.value.int32Values[kAvailabilitySequenceNumberIndex]; + } + return -1; +} + +std::vector getAvailableLayers(const VehiclePropValue& availability_state) { + if (isValidVmsMessage(availability_state) && + (parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_CHANGE || + parseMessageType(availability_state) == VmsMessageType::AVAILABILITY_RESPONSE) && + availability_state.value.int32Values.size() > + toInt(VmsAvailabilityStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)) { + int availability_state_int_size = availability_state.value.int32Values.size(); + const int32_t num_of_associated_layers = availability_state.value.int32Values[toInt( + VmsAvailabilityStateIntegerValuesIndex::NUMBER_OF_ASSOCIATED_LAYERS)]; + int current_index = toInt(VmsAvailabilityStateIntegerValuesIndex::LAYERS_START); + std::vector available_layers; + for (int i = 0; i < num_of_associated_layers; i++) { + if (availability_state_int_size < current_index + kLayerSize) { + return {}; + } + VmsLayer layer = VmsLayer(availability_state.value.int32Values[current_index], + availability_state.value.int32Values[current_index + 1], + availability_state.value.int32Values[current_index + 2]); + current_index += kLayerSize; + std::vector publisher_ids; + if (availability_state_int_size > current_index) { + int32_t num_of_publisher_ids = availability_state.value.int32Values[current_index]; + current_index++; + for (int j = 0; j < num_of_publisher_ids; j++) { + if (availability_state_int_size > current_index) { + publisher_ids.push_back( + availability_state.value.int32Values[current_index]); + current_index++; + } + } + } + available_layers.emplace_back(layer, std::move(publisher_ids)); + } + return available_layers; + } + return {}; +} + } // namespace vms } // namespace V2_0 } // namespace vehicle diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp index 8b547f1733..a48d19ca58 100644 --- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp @@ -279,7 +279,7 @@ void testSubscribedLayers(VmsMessageType type) { VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}), VmsLayerOffering(VmsLayer(2, 0, 1))}}; - auto message = createBaseVmsMessage(2); + auto message = createBaseVmsMessage(16); message->value.int32Values = hidl_vec{toInt(type), 1234, // sequence number 2, // number of layers @@ -308,9 +308,28 @@ TEST(VmsUtilsTest, subscribedLayersForResponse) { testSubscribedLayers(VmsMessageType::SUBSCRIPTIONS_RESPONSE); } +void testGetSubscribedLayersMalformedData(VmsMessageType type) { + 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{toInt(type), 1234}; // sequence number + EXPECT_TRUE(isValidVmsMessage(*message)); + auto result = getSubscribedLayers(*message, offers); + EXPECT_EQ(static_cast(result.size()), 0); +} + +TEST(VmsUtilsTest, subscribedLayersForMalformedChange) { + testGetSubscribedLayersMalformedData(VmsMessageType::SUBSCRIPTIONS_CHANGE); +} + +TEST(VmsUtilsTest, subscribedLayersForMalformedResponse) { + testGetSubscribedLayersMalformedData(VmsMessageType::SUBSCRIPTIONS_RESPONSE); +} + void testSubscribedLayersWithDifferentSubtype(VmsMessageType type) { VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; - auto message = createBaseVmsMessage(2); + auto message = createBaseVmsMessage(7); message->value.int32Values = hidl_vec{toInt(type), 1234, // sequence number 1, // number of layers @@ -332,7 +351,7 @@ TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtypeForResponse) { void subscribedLayersWithDifferentVersion(VmsMessageType type) { VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; - auto message = createBaseVmsMessage(2); + auto message = createBaseVmsMessage(7); message->value.int32Values = hidl_vec{toInt(type), 1234, // sequence number 1, // number of layers @@ -353,7 +372,7 @@ TEST(VmsUtilsTest, subscribedLayersWithDifferentVersionForResponse) { void subscribedLayersWithDifferentPublisherId(VmsMessageType type) { VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}}; - auto message = createBaseVmsMessage(2); + auto message = createBaseVmsMessage(9); message->value.int32Values = hidl_vec{toInt(type), 1234, // sequence number 0, // number of layers @@ -475,6 +494,113 @@ TEST(VmsUtilsTest, startSessionInvalidMessageFormat) { EXPECT_EQ(new_service_id, 123); } +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingSmallerNumberForChange) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234}; + EXPECT_TRUE(isAvailabilitySequenceNumberNewer(*message, 1233)); +} + +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingSmallerNumberForResponse) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234}; + EXPECT_TRUE(isAvailabilitySequenceNumberNewer(*message, 1233)); +} + +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingGreaterNumberForChange) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234}; + EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1235)); +} + +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForExistingGreaterNumberForResponse) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234}; + EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1235)); +} + +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForSameNumberForChange) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234}; + EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1234)); +} + +TEST(VmsUtilsTest, newAvailabilitySequenceNumberForSameNumberForResponse) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234}; + EXPECT_FALSE(isAvailabilitySequenceNumberNewer(*message, 1234)); +} + +TEST(VmsUtilsTest, validSequenceNumberForAvailabilityChange) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234}; + EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), 1234); +} + +TEST(VmsUtilsTest, validSequenceNumberForAvailabilityResponse) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec{toInt(VmsMessageType::AVAILABILITY_RESPONSE), 1234}; + EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), 1234); +} + +TEST(VmsUtilsTest, invalidAvailabilityState) { + auto message = createBaseVmsMessage(1); + EXPECT_EQ(getSequenceNumberForAvailabilityState(*message), -1); +} + +void testGetAvailableLayers(VmsMessageType type) { + auto message = createBaseVmsMessage(13); + message->value.int32Values = hidl_vec{toInt(type), + 1234, // sequence number + 2, // number of associated layers + 1, // associated layer 1 + 0, 1, + 2, // number of publisher IDs + 111, // publisher IDs + 123, + 2, // associated layer 2 + 0, 1, 0}; // number of publisher IDs + EXPECT_TRUE(isValidVmsMessage(*message)); + auto result = getAvailableLayers(*message); + EXPECT_EQ(static_cast(result.size()), 2); + EXPECT_EQ(result.at(0).layer, VmsLayer(1, 0, 1)); + EXPECT_EQ(result.at(0).publisher_ids.at(0), 111); + EXPECT_EQ(result.at(0).publisher_ids.at(1), 123); + EXPECT_EQ(result.at(1).layer, VmsLayer(2, 0, 1)); + EXPECT_EQ(static_cast(result.at(1).publisher_ids.size()), 0); +} + +TEST(VmsUtilsTest, availableLayersForChange) { + testGetAvailableLayers(VmsMessageType::AVAILABILITY_CHANGE); +} + +TEST(VmsUtilsTest, availableLayersForResponse) { + testGetAvailableLayers(VmsMessageType::AVAILABILITY_RESPONSE); +} + +void testGetAvailableLayersMalformedData(VmsMessageType type) { + auto message = createBaseVmsMessage(2); + message->value.int32Values = hidl_vec{toInt(type), 1234}; // sequence number + EXPECT_TRUE(isValidVmsMessage(*message)); + auto result = getAvailableLayers(*message); + EXPECT_EQ(static_cast(result.size()), 0); +} + +TEST(VmsUtilsTest, availableLayersForMalformedChange) { + testGetAvailableLayersMalformedData(VmsMessageType::AVAILABILITY_CHANGE); +} + +TEST(VmsUtilsTest, availableLayersForMalformedResponse) { + testGetAvailableLayersMalformedData(VmsMessageType::AVAILABILITY_RESPONSE); +} + } // namespace } // namespace vms