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