1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "VmsUtils.h"
18
19 #include <common/include/vhal_v2_0/VehicleUtils.h>
20
21 namespace android {
22 namespace hardware {
23 namespace automotive {
24 namespace vehicle {
25 namespace V2_0 {
26 namespace vms {
27
28 static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
29 static constexpr int kMessageTypeSize = 1;
30 static constexpr int kPublisherIdSize = 1;
31 static constexpr int kLayerNumberSize = 1;
32 static constexpr int kLayerSize = 3;
33 static constexpr int kLayerAndPublisherSize = 4;
34 static constexpr int kSessionIdsSize = 2;
35 static constexpr int kPublisherIdIndex =
36 toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID);
37 static constexpr int kSubscriptionStateSequenceNumberIndex =
38 toInt(VmsSubscriptionsStateIntegerValuesIndex::SEQUENCE_NUMBER);
39 static constexpr int kAvailabilitySequenceNumberIndex =
40 toInt(VmsAvailabilityStateIntegerValuesIndex::SEQUENCE_NUMBER);
41
42 // TODO(aditin): We should extend the VmsMessageType enum to include a first and
43 // last, which would prevent breakages in this API. However, for all of the
44 // functions in this module, we only need to guarantee that the message type is
45 // between SUBSCRIBE and START_SESSION.
46 static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
47 static constexpr int kLastMessageType = toInt(VmsMessageType::START_SESSION);
48
createBaseVmsMessage(size_t message_size)49 std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
50 auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
51 result->prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE);
52 result->areaId = toInt(VehicleArea::GLOBAL);
53 return result;
54 }
55
createSubscribeMessage(const VmsLayer & layer)56 std::unique_ptr<VehiclePropValue> createSubscribeMessage(const VmsLayer& layer) {
57 auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
58 result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIBE), layer.type,
59 layer.subtype, layer.version};
60 return result;
61 }
62
createSubscribeToPublisherMessage(const VmsLayerAndPublisher & layer_publisher)63 std::unique_ptr<VehiclePropValue> createSubscribeToPublisherMessage(
64 const VmsLayerAndPublisher& layer_publisher) {
65 auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
66 result->value.int32Values = hidl_vec<int32_t>{
67 toInt(VmsMessageType::SUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
68 layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
69 return result;
70 }
71
createUnsubscribeMessage(const VmsLayer & layer)72 std::unique_ptr<VehiclePropValue> createUnsubscribeMessage(const VmsLayer& layer) {
73 auto result = createBaseVmsMessage(kMessageTypeSize + kLayerSize);
74 result->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::UNSUBSCRIBE), layer.type,
75 layer.subtype, layer.version};
76 return result;
77 }
78
createUnsubscribeToPublisherMessage(const VmsLayerAndPublisher & layer_publisher)79 std::unique_ptr<VehiclePropValue> createUnsubscribeToPublisherMessage(
80 const VmsLayerAndPublisher& layer_publisher) {
81 auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
82 result->value.int32Values = hidl_vec<int32_t>{
83 toInt(VmsMessageType::UNSUBSCRIBE_TO_PUBLISHER), layer_publisher.layer.type,
84 layer_publisher.layer.subtype, layer_publisher.layer.version, layer_publisher.publisher_id};
85 return result;
86 }
87
createOfferingMessage(const VmsOffers & offers)88 std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers) {
89 int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize;
90 for (const auto& offer : offers.offerings) {
91 message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize);
92 }
93 auto result = createBaseVmsMessage(message_size);
94
95 std::vector<int32_t> offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id,
96 static_cast<int>(offers.offerings.size())};
97 for (const auto& offer : offers.offerings) {
98 std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
99 offer.layer.version,
100 static_cast<int32_t>(offer.dependencies.size())};
101 for (const auto& dependency : offer.dependencies) {
102 std::vector<int32_t> dependency_layer = {dependency.type, dependency.subtype,
103 dependency.version};
104 layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
105 dependency_layer.end());
106 }
107 offerings.insert(offerings.end(), layer_vector.begin(), layer_vector.end());
108 }
109 result->value.int32Values = offerings;
110 return result;
111 }
112
createAvailabilityRequest()113 std::unique_ptr<VehiclePropValue> createAvailabilityRequest() {
114 auto result = createBaseVmsMessage(kMessageTypeSize);
115 result->value.int32Values = hidl_vec<int32_t>{
116 toInt(VmsMessageType::AVAILABILITY_REQUEST),
117 };
118 return result;
119 }
120
createSubscriptionsRequest()121 std::unique_ptr<VehiclePropValue> createSubscriptionsRequest() {
122 auto result = createBaseVmsMessage(kMessageTypeSize);
123 result->value.int32Values = hidl_vec<int32_t>{
124 toInt(VmsMessageType::SUBSCRIPTIONS_REQUEST),
125 };
126 return result;
127 }
128
createDataMessageWithLayerPublisherInfo(const VmsLayerAndPublisher & layer_publisher,const std::string & vms_packet)129 std::unique_ptr<VehiclePropValue> createDataMessageWithLayerPublisherInfo(
130 const VmsLayerAndPublisher& layer_publisher, const std::string& vms_packet) {
131 auto result = createBaseVmsMessage(kMessageTypeSize + kLayerAndPublisherSize);
132 result->value.int32Values = hidl_vec<int32_t>{
133 toInt(VmsMessageType::DATA), layer_publisher.layer.type, layer_publisher.layer.subtype,
134 layer_publisher.layer.version, layer_publisher.publisher_id};
135 result->value.bytes = std::vector<uint8_t>(vms_packet.begin(), vms_packet.end());
136 return result;
137 }
138
createPublisherIdRequest(const std::string & vms_provider_description)139 std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
140 const std::string& vms_provider_description) {
141 auto result = createBaseVmsMessage(kMessageTypeSize);
142 result->value.int32Values = hidl_vec<int32_t>{
143 toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
144 };
145 result->value.bytes =
146 std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
147 return result;
148 }
149
createStartSessionMessage(const int service_id,const int client_id)150 std::unique_ptr<VehiclePropValue> createStartSessionMessage(const int service_id,
151 const int client_id) {
152 auto result = createBaseVmsMessage(kMessageTypeSize + kSessionIdsSize);
153 result->value.int32Values = hidl_vec<int32_t>{
154 toInt(VmsMessageType::START_SESSION),
155 service_id,
156 client_id,
157 };
158 return result;
159 }
160
isValidVmsProperty(const VehiclePropValue & value)161 bool isValidVmsProperty(const VehiclePropValue& value) {
162 return (value.prop == toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
163 }
164
isValidVmsMessageType(const VehiclePropValue & value)165 bool isValidVmsMessageType(const VehiclePropValue& value) {
166 return (value.value.int32Values.size() > 0 &&
167 value.value.int32Values[kMessageIndex] >= kFirstMessageType &&
168 value.value.int32Values[kMessageIndex] <= kLastMessageType);
169 }
170
isValidVmsMessage(const VehiclePropValue & value)171 bool isValidVmsMessage(const VehiclePropValue& value) {
172 return (isValidVmsProperty(value) && isValidVmsMessageType(value));
173 }
174
parseMessageType(const VehiclePropValue & value)175 VmsMessageType parseMessageType(const VehiclePropValue& value) {
176 return static_cast<VmsMessageType>(value.value.int32Values[kMessageIndex]);
177 }
178
parseData(const VehiclePropValue & value)179 std::string parseData(const VehiclePropValue& value) {
180 if (isValidVmsMessage(value) && parseMessageType(value) == VmsMessageType::DATA &&
181 value.value.bytes.size() > 0) {
182 return std::string(value.value.bytes.begin(), value.value.bytes.end());
183 } else {
184 return std::string();
185 }
186 }
187
parsePublisherIdResponse(const VehiclePropValue & publisher_id_response)188 int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) {
189 if (isValidVmsMessage(publisher_id_response) &&
190 parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE &&
191 publisher_id_response.value.int32Values.size() > kPublisherIdIndex) {
192 return publisher_id_response.value.int32Values[kPublisherIdIndex];
193 }
194 return -1;
195 }
196
isSequenceNumberNewer(const VehiclePropValue & subscription_change,const int last_seen_sequence_number)197 bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
198 const int last_seen_sequence_number) {
199 return (isValidVmsMessage(subscription_change) &&
200 parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
201 subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
202 subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
203 last_seen_sequence_number);
204 }
205
getSequenceNumberForSubscriptionsState(const VehiclePropValue & subscription_change)206 int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) {
207 if (isValidVmsMessage(subscription_change) &&
208 parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
209 subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
210 return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex];
211 }
212 return -1;
213 }
214
getSubscribedLayers(const VehiclePropValue & subscription_change,const VmsOffers & offers)215 std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
216 const VmsOffers& offers) {
217 if (isValidVmsMessage(subscription_change) &&
218 parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
219 subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
220 const int32_t num_of_layers = subscription_change.value.int32Values[toInt(
221 VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
222 const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt(
223 VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];
224
225 std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
226 for (const auto& offer : offers.offerings) {
227 offered_layers.insert(offer.layer);
228 }
229 std::vector<VmsLayer> subscribed_layers;
230
231 int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
232 // Add all subscribed layers which are offered by the current publisher.
233 for (int i = 0; i < num_of_layers; i++) {
234 VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
235 subscription_change.value.int32Values[current_index + 1],
236 subscription_change.value.int32Values[current_index + 2]);
237 if (offered_layers.find(layer) != offered_layers.end()) {
238 subscribed_layers.push_back(layer);
239 }
240 current_index += kLayerSize;
241 }
242 // Add all subscribed associated layers which are offered by the current publisher.
243 // For this, we need to check if the associated layer has a publisher ID which is
244 // same as that of the current publisher.
245 for (int i = 0; i < num_of_associated_layers; i++) {
246 VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
247 subscription_change.value.int32Values[current_index + 1],
248 subscription_change.value.int32Values[current_index + 2]);
249 current_index += kLayerSize;
250 if (offered_layers.find(layer) != offered_layers.end()) {
251 int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index];
252 current_index++;
253 for (int j = 0; j < num_of_publisher_ids; j++) {
254 if (subscription_change.value.int32Values[current_index] ==
255 offers.publisher_id) {
256 subscribed_layers.push_back(layer);
257 }
258 current_index++;
259 }
260 }
261 }
262 return subscribed_layers;
263 }
264 return {};
265 }
266
hasServiceNewlyStarted(const VehiclePropValue & availability_change)267 bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) {
268 return (isValidVmsMessage(availability_change) &&
269 parseMessageType(availability_change) == VmsMessageType::AVAILABILITY_CHANGE &&
270 availability_change.value.int32Values.size() > kAvailabilitySequenceNumberIndex &&
271 availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0);
272 }
273
parseStartSessionMessage(const VehiclePropValue & start_session,const int current_service_id,const int current_client_id,int * new_service_id)274 VmsSessionStatus parseStartSessionMessage(const VehiclePropValue& start_session,
275 const int current_service_id, const int current_client_id,
276 int* new_service_id) {
277 if (isValidVmsMessage(start_session) &&
278 parseMessageType(start_session) == VmsMessageType::START_SESSION &&
279 start_session.value.int32Values.size() == kSessionIdsSize + 1) {
280 *new_service_id = start_session.value.int32Values[1];
281 const int new_client_id = start_session.value.int32Values[2];
282 if (new_client_id != current_client_id) {
283 // If the new_client_id = -1, it means the service has newly started.
284 // But if it is not -1 and is different than the current client ID, then
285 // it means that the service did not have the correct client ID. In
286 // both these cases, the client should acknowledge with a START_SESSION
287 // message containing the correct client ID. So here, the status is returned as
288 // kNewServerSession.
289 return VmsSessionStatus::kNewServerSession;
290 } else {
291 // kAckToCurrentSession is returned if the new client ID is same as the current one.
292 return VmsSessionStatus::kAckToCurrentSession;
293 }
294 }
295 // If the message is invalid then persist the old service ID.
296 *new_service_id = current_service_id;
297 return VmsSessionStatus::kInvalidMessage;
298 }
299
300 } // namespace vms
301 } // namespace V2_0
302 } // namespace vehicle
303 } // namespace automotive
304 } // namespace hardware
305 } // namespace android
306