Loading automotive/vehicle/2.0/default/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ cc_library_static { "common/src/VehicleObjectPool.cpp", "common/src/VehicleObjectPool.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", "common/src/VehicleUtils.cpp", "common/src/VmsUtils.cpp", ], ], local_include_dirs: ["common/include/vhal_v2_0"], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["common/include"], export_include_dirs: ["common/include"], Loading Loading @@ -93,6 +94,7 @@ cc_test { "tests/VehicleHalManager_test.cpp", "tests/VehicleHalManager_test.cpp", "tests/VehicleObjectPool_test.cpp", "tests/VehicleObjectPool_test.cpp", "tests/VehiclePropConfigIndex_test.cpp", "tests/VehiclePropConfigIndex_test.cpp", "tests/VmsUtils_test.cpp", ], ], header_libs: ["libbase_headers"], header_libs: ["libbase_headers"], } } Loading automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h 0 → 100644 +156 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_VmsUtils_H_ #define android_hardware_automotive_vehicle_V2_0_VmsUtils_H_ #include <memory> #include <string> #include <android/hardware/automotive/vehicle/2.0/types.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { // VmsUtils are a set of abstractions for creating and parsing Vehicle Property // updates to VehicleProperty::VEHICLE_MAP_SERVICE. The format for parsing a // VehiclePropValue update with a VMS message is specified in the Vehicle HIDL. // // This interface is meant for use by HAL clients of VMS; corresponding // functionality is also provided by VMS in the embedded car service. // A VmsLayer is comprised of a type, subtype, and version. struct VmsLayer { VmsLayer(int type, int subtype, int version) : type(type), subtype(subtype), version(version) {} int type; int subtype; int version; }; struct VmsLayerAndPublisher { VmsLayer layer; int publisher_id; }; // A VmsAssociatedLayer is used by subscribers to specify which publisher IDs // are acceptable for a given layer. struct VmsAssociatedLayer { VmsLayer layer; std::vector<int> publisher_ids; }; // A VmsLayerOffering refers to a single layer that can be published, along with // its dependencies. Dependencies can be empty. struct VmsLayerOffering { VmsLayerOffering(VmsLayer layer, std::vector<VmsLayer> dependencies) : layer(layer), dependencies(dependencies) {} VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {} VmsLayer layer; std::vector<VmsLayer> dependencies; }; // 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 // currently being subscribed to in the system. struct VmsSubscriptionsState { int sequence_number; std::vector<VmsLayer> layers; std::vector<VmsAssociatedLayer> associated_layers; }; struct VmsAvailabilityState { int sequence_number; std::vector<VmsAssociatedLayer> associated_layers; }; // Creates a VehiclePropValue containing a message of type // VmsMessageType.SUBSCRIBE, specifying to the VMS service // which layer to subscribe to. std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.SUBSCRIBE_TO_PUBLISHER, specifying to the VMS service // which layer and publisher_id to subscribe to. std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage( const VmsLayerAndPublisher& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.UNSUBSCRIBE, specifying to the VMS service // which layer to unsubscribe from. std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, specifying to the VMS service // which layer and publisher_id to unsubscribe from. std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage( const VmsLayerAndPublisher& layer); // 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); // Creates a VehiclePropValue containing a message of type // VmsMessageType.AVAILABILITY_REQUEST. std::unique_ptr<VehiclePropValue> createAvailabilityRequest(); // Creates a VehiclePropValue containing a message of type // VmsMessageType.AVAILABILITY_REQUEST. std::unique_ptr<VehiclePropValue> createSubscriptionsRequest(); // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA. // Returns a nullptr if the byte string in bytes is empty. // // For example, to build a VehiclePropMessage containing a proto, the caller // should convert the proto to a byte string using the SerializeToString proto // API, then use this inteface to build the VehicleProperty. std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes); // Returns true if the VehiclePropValue pointed to by value contains a valid Vms // message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all // valid. Note: If the VmsMessageType enum is extended, this function will // return false for any new message types added. bool isValidVmsMessage(const VehiclePropValue& value); // Returns the message type. Expects that the VehiclePropValue contains a valid // Vms message, as verified by isValidVmsMessage. VmsMessageType parseMessageType(const VehiclePropValue& value); // Constructs a string byte array from a message of type VmsMessageType.DATA. // Returns an empty string if the message type doesn't match or if the // VehiclePropValue does not contain a byte array. // // A proto message can then be constructed by passing the result of this // function to ParseFromString. std::string parseData(const VehiclePropValue& value); // TODO(aditin): Need to implement additional parsing functions per message // type. } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_VmsUtils_H_ automotive/vehicle/2.0/default/common/src/VmsUtils.cpp 0 → 100644 +162 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VmsUtils.h" #include <common/include/vhal_v2_0/VehicleUtils.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE); static constexpr int kMessageTypeSize = 1; static constexpr int kLayerNumberSize = 1; static constexpr int kLayerSize = 3; static constexpr int kLayerAndPublisherSize = 4; // 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. static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE); static constexpr int kLastMessageType = toInt(VmsMessageType::DATA); std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) { auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size); result->prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE); result->areaId = toInt(VehicleArea::GLOBAL); return result; } std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIBE), layer.type, layer.subtype, layer.version}; return result; } std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage( const VmsLayerAndPublisher& layer_publisher) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::SUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type, layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id}; return result; } std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::UNSUBSCRIBE), layer.type, layer.subtype, layer.version}; return result; } std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage( const VmsLayerAndPublisher& layer_publisher) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::UNSUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type, layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id}; 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; } 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> layer_vector = {offer.layer.type, offer.layer.subtype, offer.layer.version, static_cast<int32_t>(offer.dependencies.size())}; for (const auto& dependency : offer.dependencies) { std::vector<int32_t> dependency_layer = {dependency.type, dependency.subtype, dependency.version}; layer_vector.insert(layer_vector.end(), dependency_layer.begin(), dependency_layer.end()); } offers.insert(offers.end(), layer_vector.begin(), layer_vector.end()); } result->value.int32Values = offers; return result; } std::unique_ptr<VehiclePropValue> createAvailabilityRequest() { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::AVAILABILITY_REQUEST), }; return result; } std::unique_ptr<VehiclePropValue> createSubscriptionsRequest() { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::SUBSCRIPTIONS_REQUEST), }; return result; } std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes) { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::DATA)}; result->value.bytes = std::vector<uint8_t>(bytes.begin(), bytes.end()); return result; } bool verifyPropertyAndArea(const VehiclePropValue& value) { return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE) && value.areaId == toInt(VehicleArea::GLOBAL)); } bool verifyMessageType(const VehiclePropValue& value) { return (value.value.int32Values.size() > 0 && value.value.int32Values[kMessageIndex] >= kFirstMessageType && value.value.int32Values[kMessageIndex] <= kLastMessageType); } bool isValidVmsMessage(const VehiclePropValue& value) { return (verifyPropertyAndArea(value) && verifyMessageType(value)); } VmsMessageType parseMessageType(const VehiclePropValue& value) { return static_cast<VmsMessageType>(value.value.int32Values[kMessageIndex]); } std::string parseData(const VehiclePropValue& value) { if (isValidVmsMessage(value) && parseMessageType(value) == VmsMessageType::DATA && value.value.bytes.size() > 0) { return std::string(value.value.bytes.begin(), value.value.bytes.end()); } else { return std::string(); } } } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp 0 → 100644 +183 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <gtest/gtest.h> #include "VehicleHalTestUtils.h" #include "vhal_v2_0/VmsUtils.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { namespace { TEST(VmsUtilsTest, subscribeMessage) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x4ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIBE); // Layer EXPECT_EQ(message->value.int32Values[1], 1); EXPECT_EQ(message->value.int32Values[2], 0); EXPECT_EQ(message->value.int32Values[3], 2); } TEST(VmsUtilsTest, unsubscribeMessage) { VmsLayer layer(1, 0, 2); auto message = createUnsubscribeMessage(layer); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x4ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::UNSUBSCRIBE); // Layer EXPECT_EQ(message->value.int32Values[1], 1); EXPECT_EQ(message->value.int32Values[2], 0); EXPECT_EQ(message->value.int32Values[3], 2); } TEST(VmsUtilsTest, singleOfferingMessage) { std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))}; auto message = createOfferingMessage(offering); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x6ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); // Number of layer offerings EXPECT_EQ(message->value.int32Values[1], 1); // Layer EXPECT_EQ(message->value.int32Values[2], 1); EXPECT_EQ(message->value.int32Values[3], 0); EXPECT_EQ(message->value.int32Values[4], 2); // Number of dependencies EXPECT_EQ(message->value.int32Values[5], 0); } TEST(VmsUtilsTest, offeringWithDependencies) { VmsLayer layer(1, 0, 2); std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)}; std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)}; auto message = createOfferingMessage(offering); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x9ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); // Number of layer offerings EXPECT_EQ(message->value.int32Values[1], 1); // Layer EXPECT_EQ(message->value.int32Values[2], 1); EXPECT_EQ(message->value.int32Values[3], 0); EXPECT_EQ(message->value.int32Values[4], 2); // Number of dependencies EXPECT_EQ(message->value.int32Values[5], 1); // Dependency 1 EXPECT_EQ(message->value.int32Values[6], 2); EXPECT_EQ(message->value.int32Values[7], 0); EXPECT_EQ(message->value.int32Values[8], 2); } TEST(VmsUtilsTest, availabilityMessage) { auto message = createAvailabilityRequest(); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::AVAILABILITY_REQUEST); } TEST(VmsUtilsTest, subscriptionsMessage) { auto message = createSubscriptionsRequest(); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIPTIONS_REQUEST); } TEST(VmsUtilsTest, dataMessage) { std::string bytes = "aaa"; auto message = createDataMessage(bytes); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA); EXPECT_EQ(message->value.bytes.size(), bytes.size()); EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0); } TEST(VmsUtilsTest, emptyMessageInvalid) { VehiclePropValue empty_prop; EXPECT_FALSE(isValidVmsMessage(empty_prop)); } TEST(VmsUtilsTest, invalidMessageType) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); message->value.int32Values[0] = 0; EXPECT_FALSE(isValidVmsMessage(*message)); } TEST(VmsUtilsTest, parseDataMessage) { std::string bytes = "aaa"; auto message = createDataMessage(bytes); auto data_str = parseData(*message); ASSERT_FALSE(data_str.empty()); EXPECT_EQ(data_str, bytes); } TEST(VmsUtilsTest, parseInvalidDataMessage) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); auto data_str = parseData(*message); EXPECT_TRUE(data_str.empty()); } } // namespace } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android Loading
automotive/vehicle/2.0/default/Android.bp +2 −0 Original line number Original line Diff line number Diff line Loading @@ -46,6 +46,7 @@ cc_library_static { "common/src/VehicleObjectPool.cpp", "common/src/VehicleObjectPool.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehiclePropertyStore.cpp", "common/src/VehicleUtils.cpp", "common/src/VehicleUtils.cpp", "common/src/VmsUtils.cpp", ], ], local_include_dirs: ["common/include/vhal_v2_0"], local_include_dirs: ["common/include/vhal_v2_0"], export_include_dirs: ["common/include"], export_include_dirs: ["common/include"], Loading Loading @@ -93,6 +94,7 @@ cc_test { "tests/VehicleHalManager_test.cpp", "tests/VehicleHalManager_test.cpp", "tests/VehicleObjectPool_test.cpp", "tests/VehicleObjectPool_test.cpp", "tests/VehiclePropConfigIndex_test.cpp", "tests/VehiclePropConfigIndex_test.cpp", "tests/VmsUtils_test.cpp", ], ], header_libs: ["libbase_headers"], header_libs: ["libbase_headers"], } } Loading
automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h 0 → 100644 +156 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef android_hardware_automotive_vehicle_V2_0_VmsUtils_H_ #define android_hardware_automotive_vehicle_V2_0_VmsUtils_H_ #include <memory> #include <string> #include <android/hardware/automotive/vehicle/2.0/types.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { // VmsUtils are a set of abstractions for creating and parsing Vehicle Property // updates to VehicleProperty::VEHICLE_MAP_SERVICE. The format for parsing a // VehiclePropValue update with a VMS message is specified in the Vehicle HIDL. // // This interface is meant for use by HAL clients of VMS; corresponding // functionality is also provided by VMS in the embedded car service. // A VmsLayer is comprised of a type, subtype, and version. struct VmsLayer { VmsLayer(int type, int subtype, int version) : type(type), subtype(subtype), version(version) {} int type; int subtype; int version; }; struct VmsLayerAndPublisher { VmsLayer layer; int publisher_id; }; // A VmsAssociatedLayer is used by subscribers to specify which publisher IDs // are acceptable for a given layer. struct VmsAssociatedLayer { VmsLayer layer; std::vector<int> publisher_ids; }; // A VmsLayerOffering refers to a single layer that can be published, along with // its dependencies. Dependencies can be empty. struct VmsLayerOffering { VmsLayerOffering(VmsLayer layer, std::vector<VmsLayer> dependencies) : layer(layer), dependencies(dependencies) {} VmsLayerOffering(VmsLayer layer) : layer(layer), dependencies() {} VmsLayer layer; std::vector<VmsLayer> dependencies; }; // 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 // currently being subscribed to in the system. struct VmsSubscriptionsState { int sequence_number; std::vector<VmsLayer> layers; std::vector<VmsAssociatedLayer> associated_layers; }; struct VmsAvailabilityState { int sequence_number; std::vector<VmsAssociatedLayer> associated_layers; }; // Creates a VehiclePropValue containing a message of type // VmsMessageType.SUBSCRIBE, specifying to the VMS service // which layer to subscribe to. std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.SUBSCRIBE_TO_PUBLISHER, specifying to the VMS service // which layer and publisher_id to subscribe to. std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage( const VmsLayerAndPublisher& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.UNSUBSCRIBE, specifying to the VMS service // which layer to unsubscribe from. std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer); // Creates a VehiclePropValue containing a message of type // VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, specifying to the VMS service // which layer and publisher_id to unsubscribe from. std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage( const VmsLayerAndPublisher& layer); // 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); // Creates a VehiclePropValue containing a message of type // VmsMessageType.AVAILABILITY_REQUEST. std::unique_ptr<VehiclePropValue> createAvailabilityRequest(); // Creates a VehiclePropValue containing a message of type // VmsMessageType.AVAILABILITY_REQUEST. std::unique_ptr<VehiclePropValue> createSubscriptionsRequest(); // Creates a VehiclePropValue containing a message of type VmsMessageType.DATA. // Returns a nullptr if the byte string in bytes is empty. // // For example, to build a VehiclePropMessage containing a proto, the caller // should convert the proto to a byte string using the SerializeToString proto // API, then use this inteface to build the VehicleProperty. std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes); // Returns true if the VehiclePropValue pointed to by value contains a valid Vms // message, i.e. the VehicleProperty, VehicleArea, and VmsMessageType are all // valid. Note: If the VmsMessageType enum is extended, this function will // return false for any new message types added. bool isValidVmsMessage(const VehiclePropValue& value); // Returns the message type. Expects that the VehiclePropValue contains a valid // Vms message, as verified by isValidVmsMessage. VmsMessageType parseMessageType(const VehiclePropValue& value); // Constructs a string byte array from a message of type VmsMessageType.DATA. // Returns an empty string if the message type doesn't match or if the // VehiclePropValue does not contain a byte array. // // A proto message can then be constructed by passing the result of this // function to ParseFromString. std::string parseData(const VehiclePropValue& value); // TODO(aditin): Need to implement additional parsing functions per message // type. } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_VmsUtils_H_
automotive/vehicle/2.0/default/common/src/VmsUtils.cpp 0 → 100644 +162 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "VmsUtils.h" #include <common/include/vhal_v2_0/VehicleUtils.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE); static constexpr int kMessageTypeSize = 1; static constexpr int kLayerNumberSize = 1; static constexpr int kLayerSize = 3; static constexpr int kLayerAndPublisherSize = 4; // 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. static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE); static constexpr int kLastMessageType = toInt(VmsMessageType::DATA); std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) { auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size); result->prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE); result->areaId = toInt(VehicleArea::GLOBAL); return result; } std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIBE), layer.type, layer.subtype, layer.version}; return result; } std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage( const VmsLayerAndPublisher& layer_publisher) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::SUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type, layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id}; return result; } std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::UNSUBSCRIBE), layer.type, layer.subtype, layer.version}; return result; } std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage( const VmsLayerAndPublisher& layer_publisher) { auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::UNSUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type, layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id}; 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; } 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> layer_vector = {offer.layer.type, offer.layer.subtype, offer.layer.version, static_cast<int32_t>(offer.dependencies.size())}; for (const auto& dependency : offer.dependencies) { std::vector<int32_t> dependency_layer = {dependency.type, dependency.subtype, dependency.version}; layer_vector.insert(layer_vector.end(), dependency_layer.begin(), dependency_layer.end()); } offers.insert(offers.end(), layer_vector.begin(), layer_vector.end()); } result->value.int32Values = offers; return result; } std::unique_ptr<VehiclePropValue> createAvailabilityRequest() { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::AVAILABILITY_REQUEST), }; return result; } std::unique_ptr<VehiclePropValue> createSubscriptionsRequest() { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{ toInt(VmsMessageType::SUBSCRIPTIONS_REQUEST), }; return result; } std::unique_ptr<VehiclePropValue> createDataMessage(const std::string& bytes) { auto result = createBaseVmsMessage(kMessageTypeSize); result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::DATA)}; result->value.bytes = std::vector<uint8_t>(bytes.begin(), bytes.end()); return result; } bool verifyPropertyAndArea(const VehiclePropValue& value) { return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE) && value.areaId == toInt(VehicleArea::GLOBAL)); } bool verifyMessageType(const VehiclePropValue& value) { return (value.value.int32Values.size() > 0 && value.value.int32Values[kMessageIndex] >= kFirstMessageType && value.value.int32Values[kMessageIndex] <= kLastMessageType); } bool isValidVmsMessage(const VehiclePropValue& value) { return (verifyPropertyAndArea(value) && verifyMessageType(value)); } VmsMessageType parseMessageType(const VehiclePropValue& value) { return static_cast<VmsMessageType>(value.value.int32Values[kMessageIndex]); } std::string parseData(const VehiclePropValue& value) { if (isValidVmsMessage(value) && parseMessageType(value) == VmsMessageType::DATA && value.value.bytes.size() > 0) { return std::string(value.value.bytes.begin(), value.value.bytes.end()); } else { return std::string(); } } } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android
automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp 0 → 100644 +183 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <gtest/gtest.h> #include "VehicleHalTestUtils.h" #include "vhal_v2_0/VmsUtils.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace vms { namespace { TEST(VmsUtilsTest, subscribeMessage) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x4ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIBE); // Layer EXPECT_EQ(message->value.int32Values[1], 1); EXPECT_EQ(message->value.int32Values[2], 0); EXPECT_EQ(message->value.int32Values[3], 2); } TEST(VmsUtilsTest, unsubscribeMessage) { VmsLayer layer(1, 0, 2); auto message = createUnsubscribeMessage(layer); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x4ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::UNSUBSCRIBE); // Layer EXPECT_EQ(message->value.int32Values[1], 1); EXPECT_EQ(message->value.int32Values[2], 0); EXPECT_EQ(message->value.int32Values[3], 2); } TEST(VmsUtilsTest, singleOfferingMessage) { std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))}; auto message = createOfferingMessage(offering); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x6ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); // Number of layer offerings EXPECT_EQ(message->value.int32Values[1], 1); // Layer EXPECT_EQ(message->value.int32Values[2], 1); EXPECT_EQ(message->value.int32Values[3], 0); EXPECT_EQ(message->value.int32Values[4], 2); // Number of dependencies EXPECT_EQ(message->value.int32Values[5], 0); } TEST(VmsUtilsTest, offeringWithDependencies) { VmsLayer layer(1, 0, 2); std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)}; std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)}; auto message = createOfferingMessage(offering); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x9ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING); // Number of layer offerings EXPECT_EQ(message->value.int32Values[1], 1); // Layer EXPECT_EQ(message->value.int32Values[2], 1); EXPECT_EQ(message->value.int32Values[3], 0); EXPECT_EQ(message->value.int32Values[4], 2); // Number of dependencies EXPECT_EQ(message->value.int32Values[5], 1); // Dependency 1 EXPECT_EQ(message->value.int32Values[6], 2); EXPECT_EQ(message->value.int32Values[7], 0); EXPECT_EQ(message->value.int32Values[8], 2); } TEST(VmsUtilsTest, availabilityMessage) { auto message = createAvailabilityRequest(); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::AVAILABILITY_REQUEST); } TEST(VmsUtilsTest, subscriptionsMessage) { auto message = createSubscriptionsRequest(); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::SUBSCRIPTIONS_REQUEST); } TEST(VmsUtilsTest, dataMessage) { std::string bytes = "aaa"; auto message = createDataMessage(bytes); ASSERT_NE(message, nullptr); EXPECT_TRUE(isValidVmsMessage(*message)); EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE)); EXPECT_EQ(message->areaId, toInt(VehicleArea::GLOBAL)); EXPECT_EQ(message->value.int32Values.size(), 0x1ul); EXPECT_EQ(parseMessageType(*message), VmsMessageType::DATA); EXPECT_EQ(message->value.bytes.size(), bytes.size()); EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0); } TEST(VmsUtilsTest, emptyMessageInvalid) { VehiclePropValue empty_prop; EXPECT_FALSE(isValidVmsMessage(empty_prop)); } TEST(VmsUtilsTest, invalidMessageType) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); message->value.int32Values[0] = 0; EXPECT_FALSE(isValidVmsMessage(*message)); } TEST(VmsUtilsTest, parseDataMessage) { std::string bytes = "aaa"; auto message = createDataMessage(bytes); auto data_str = parseData(*message); ASSERT_FALSE(data_str.empty()); EXPECT_EQ(data_str, bytes); } TEST(VmsUtilsTest, parseInvalidDataMessage) { VmsLayer layer(1, 0, 2); auto message = createSubscribeMessage(layer); auto data_str = parseData(*message); EXPECT_TRUE(data_str.empty()); } } // namespace } // namespace vms } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android