Loading automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +62 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <memory> #include <string> #include <unordered_set> #include <android/hardware/automotive/vehicle/2.0/types.h> Loading @@ -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 { Loading @@ -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 Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +115 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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())}; Loading @@ -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; } Loading Loading @@ -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 Loading automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -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: " Loading automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +178 −19 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading Loading
automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h +62 −4 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <memory> #include <string> #include <unordered_set> #include <android/hardware/automotive/vehicle/2.0/types.h> Loading @@ -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 { Loading @@ -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 Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading
automotive/vehicle/2.0/default/common/src/VmsUtils.cpp +115 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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())}; Loading @@ -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; } Loading Loading @@ -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 Loading
automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -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: " Loading
automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp +178 −19 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading