summaryrefslogtreecommitdiffstats
path: root/automotive/vehicle
diff options
context:
space:
mode:
authorPrachi Hande <prachihande@google.com>2019-03-28 12:19:43 -0700
committerPrachi Hande <prachihande@google.com>2019-04-02 17:51:21 -0700
commitcde1aa96177cc896268d61cd591b2e205721ebfd (patch)
tree11ec311957259a948b918293f1507d070f359a58 /automotive/vehicle
parent1b3049e56c4910bc4417dac810e563fc52f6bbb6 (diff)
downloadandroid_hardware_interfaces-cde1aa96177cc896268d61cd591b2e205721ebfd.tar.gz
android_hardware_interfaces-cde1aa96177cc896268d61cd591b2e205721ebfd.tar.bz2
android_hardware_interfaces-cde1aa96177cc896268d61cd591b2e205721ebfd.zip
Updates to VMS Utils to support HAL Client Publisher
1. Added new API/utility functions to support publishing VMS messages from HAL client. 2. Fixed creation of offering message by adding publisher ID 3. Fixed an existing failing test from VmsHalManager_test.cpp Bug: 129475485 Bug: 129163926 Fixes: 129475485 Fixes: 129163926 Test: Added tests for all the new and updated functions in VmsUtilsTest. Ran the tests on Hawk. Change-Id: Ie561dafb86d137a4fdf3042e033f8cb133b4aca7
Diffstat (limited to 'automotive/vehicle')
-rw-r--r--automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h66
-rw-r--r--automotive/vehicle/2.0/default/common/src/VmsUtils.cpp127
-rw-r--r--automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp1
-rw-r--r--automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp197
4 files changed, 355 insertions, 36 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 9e32bb5a8..258dbd97a 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
@@ -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
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index f001a3236..1863191ed 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -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
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index f64eab55a..09750718a 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -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: "
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 414c5c2a4..5ea5bd45c 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -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