Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cde1aa96 authored by Prachi Hande's avatar Prachi Hande
Browse files

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
parent 1b3049e5
Loading
Loading
Loading
Loading
+62 −4
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@


#include <memory>
#include <memory>
#include <string>
#include <string>
#include <unordered_set>


#include <android/hardware/automotive/vehicle/2.0/types.h>
#include <android/hardware/automotive/vehicle/2.0/types.h>


@@ -42,6 +43,20 @@ struct VmsLayer {
    int type;
    int type;
    int subtype;
    int subtype;
    int version;
    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 {
struct VmsLayerAndPublisher {
@@ -66,6 +81,15 @@ struct VmsLayerOffering {
    std::vector<VmsLayer> dependencies;
    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
// A VmsSubscriptionsState is delivered in response to a
// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
@@ -81,6 +105,9 @@ struct VmsAvailabilityState {
    std::vector<VmsAssociatedLayer> associated_layers;
    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
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.SUBSCRIBE, specifying to the VMS service
// VmsMessageType.SUBSCRIBE, specifying to the VMS service
// which layer to subscribe to.
// which layer to subscribe to.
@@ -106,8 +133,7 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
// Creates a VehiclePropValue containing a message of type
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
// offered and their dependencies, if any.
// offered and their dependencies, if any.
std::unique_ptr<VehiclePropValue> createOfferingMessage(
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers);
    const std::vector<VmsLayerOffering>& offering);


// Creates a VehiclePropValue containing a message of type
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.AVAILABILITY_REQUEST.
// VmsMessageType.AVAILABILITY_REQUEST.
@@ -143,8 +169,40 @@ VmsMessageType parseMessageType(const VehiclePropValue& value);
// function to ParseFromString.
// function to ParseFromString.
std::string parseData(const VehiclePropValue& value);
std::string parseData(const VehiclePropValue& value);


// TODO(aditin): Need to implement additional parsing functions per message
// Creates a VehiclePropValue containing a message of type
// 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 vms
}  // namespace V2_0
}  // namespace V2_0
+115 −12
Original line number Original line Diff line number Diff line
@@ -27,16 +27,23 @@ namespace vms {


static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
static constexpr int kMessageTypeSize = 1;
static constexpr int kMessageTypeSize = 1;
static constexpr int kPublisherIdSize = 1;
static constexpr int kLayerNumberSize = 1;
static constexpr int kLayerNumberSize = 1;
static constexpr int kLayerSize = 3;
static constexpr int kLayerSize = 3;
static constexpr int kLayerAndPublisherSize = 4;
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
// 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
// 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
// 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 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) {
std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
    auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
    auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
@@ -77,17 +84,16 @@ std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
    return result;
    return result;
}
}


std::unique_ptr<VehiclePropValue> createOfferingMessage(
std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers) {
    const std::vector<VmsLayerOffering>& offering) {
    int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize;
    int message_size = kMessageTypeSize + kLayerNumberSize;
    for (const auto& offer : offers.offerings) {
    for (const auto& offer : offering) {
        message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize);
        message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
    }
    }
    auto result = createBaseVmsMessage(message_size);
    auto result = createBaseVmsMessage(message_size);


    std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
    std::vector<int32_t> offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id,
                                   static_cast<int>(offering.size())};
                                      static_cast<int>(offers.offerings.size())};
    for (const auto& offer : offering) {
    for (const auto& offer : offers.offerings) {
        std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
        std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
                                             offer.layer.version,
                                             offer.layer.version,
                                             static_cast<int32_t>(offer.dependencies.size())};
                                             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(),
            layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
                                dependency_layer.end());
                                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;
    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 vms
}  // namespace V2_0
}  // namespace V2_0
}  // namespace vehicle
}  // namespace vehicle
+0 −1
Original line number Original line Diff line number Diff line
@@ -278,7 +278,6 @@ TEST_F(VehicleHalManagerTest, subscribe) {


    cb->reset();
    cb->reset();
    VehiclePropValue actualValue(*subscribedValue.get());
    VehiclePropValue actualValue(*subscribedValue.get());
    actualValue.status = VehiclePropertyStatus::AVAILABLE;
    hal->sendPropEvent(std::move(subscribedValue));
    hal->sendPropEvent(std::move(subscribedValue));


    ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
    ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
+178 −19
Original line number Original line Diff line number Diff line
@@ -60,52 +60,64 @@ TEST(VmsUtilsTest, unsubscribeMessage) {
}
}


TEST(VmsUtilsTest, singleOfferingMessage) {
TEST(VmsUtilsTest, singleOfferingMessage) {
    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
    VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 2))}};
    auto message = createOfferingMessage(offering);
    auto message = createOfferingMessage(offers);
    ASSERT_NE(message, nullptr);
    ASSERT_NE(message, nullptr);
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
    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);
    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);


    // Publisher ID
    EXPECT_EQ(message->value.int32Values[1], 123);

    // Number of layer offerings
    // Number of layer offerings
    EXPECT_EQ(message->value.int32Values[1], 1);
    EXPECT_EQ(message->value.int32Values[2], 1);


    // Layer
    // Layer
    EXPECT_EQ(message->value.int32Values[2], 1);
    EXPECT_EQ(message->value.int32Values[3], 1);
    EXPECT_EQ(message->value.int32Values[3], 0);
    EXPECT_EQ(message->value.int32Values[4], 0);
    EXPECT_EQ(message->value.int32Values[4], 2);
    EXPECT_EQ(message->value.int32Values[5], 2);


    // Number of dependencies
    // Number of dependencies
    EXPECT_EQ(message->value.int32Values[5], 0);
    EXPECT_EQ(message->value.int32Values[6], 0);
}
}


TEST(VmsUtilsTest, offeringWithDependencies) {
TEST(VmsUtilsTest, offeringWithDependencies) {
    VmsLayer layer(1, 0, 2);
    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)};
    std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
    auto message = createOfferingMessage(offering);
    VmsOffers offers = {123, offering};
    auto message = createOfferingMessage(offers);
    ASSERT_NE(message, nullptr);
    ASSERT_NE(message, nullptr);
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_TRUE(isValidVmsMessage(*message));
    EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
    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);
    EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);


    // Publisher ID
    EXPECT_EQ(message->value.int32Values[1], 123);

    // Number of layer offerings
    // Number of layer offerings
    EXPECT_EQ(message->value.int32Values[1], 1);
    EXPECT_EQ(message->value.int32Values[2], 1);


    // Layer
    // Layer
    EXPECT_EQ(message->value.int32Values[2], 1);
    EXPECT_EQ(message->value.int32Values[3], 1);
    EXPECT_EQ(message->value.int32Values[3], 0);
    EXPECT_EQ(message->value.int32Values[4], 0);
    EXPECT_EQ(message->value.int32Values[4], 2);
    EXPECT_EQ(message->value.int32Values[5], 2);


    // Number of dependencies
    // Number of dependencies
    EXPECT_EQ(message->value.int32Values[5], 1);
    EXPECT_EQ(message->value.int32Values[6], 2);


    // Dependency 1
    // Dependency 1
    EXPECT_EQ(message->value.int32Values[6], 2);
    EXPECT_EQ(message->value.int32Values[7], 2);
    EXPECT_EQ(message->value.int32Values[7], 0);
    EXPECT_EQ(message->value.int32Values[8], 0);
    EXPECT_EQ(message->value.int32Values[8], 2);
    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) {
TEST(VmsUtilsTest, availabilityMessage) {
@@ -166,6 +178,153 @@ TEST(VmsUtilsTest, parseInvalidDataMessage) {
    EXPECT_TRUE(data_str.empty());
    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


}  // namespace vms
}  // namespace vms