blob: b29498500b0ada7d7c3d8e6e8e64d834537b7092 [file] [log] [blame]
Antonio Cortes734010a2017-01-19 20:09:22 -08001/*
2 * Copyright (C) 2017 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 */
16package com.android.car.hal;
17
asafro99e4f082017-02-09 13:11:42 -080018import static com.android.car.CarServiceUtils.toByteArray;
Antonio Cortes734010a2017-01-19 20:09:22 -080019import static java.lang.Integer.toHexString;
20
Antonio Cortes734010a2017-01-19 20:09:22 -080021import android.car.VehicleAreaType;
Antonio Cortesa6845c32017-02-06 09:22:26 -080022import android.car.annotation.FutureFeature;
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -070023import android.car.vms.IVmsSubscriberClient;
Antonio Cortes0bd67c32017-03-13 08:02:40 -070024import android.car.vms.VmsLayer;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070025import android.car.vms.VmsLayerDependency;
26import android.car.vms.VmsLayersOffering;
Antonio Cortes2febe9f2017-03-24 09:42:17 -070027import android.car.vms.VmsSubscriptionState;
Pavel Maltsevcfe93102017-02-02 12:38:08 -080028import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
29import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
Antonio Cortes747364a2017-02-28 10:37:24 -080030import android.hardware.automotive.vehicle.V2_1.VehicleProperty;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070031import android.hardware.automotive.vehicle.V2_1.VmsBaseMessageIntegerValuesIndex;
Antonio Cortes747364a2017-02-28 10:37:24 -080032import android.hardware.automotive.vehicle.V2_1.VmsMessageType;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070033import android.hardware.automotive.vehicle.V2_1.VmsOfferingMessageIntegerValuesIndex;
34import android.hardware.automotive.vehicle.V2_1.VmsSimpleMessageIntegerValuesIndex;
35import android.os.Binder;
36import android.os.IBinder;
Antonio Cortes734010a2017-01-19 20:09:22 -080037import android.util.Log;
Antonio Cortes734010a2017-01-19 20:09:22 -080038import com.android.car.CarLog;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070039import com.android.car.VmsLayersAvailability;
asafro25a87402017-02-28 16:08:17 -080040import com.android.car.VmsRouting;
Antonio Cortes734010a2017-01-19 20:09:22 -080041import com.android.internal.annotations.GuardedBy;
Antonio Cortes734010a2017-01-19 20:09:22 -080042import java.io.PrintWriter;
Antonio Cortes40b90262017-02-06 11:43:57 -080043import java.util.ArrayList;
Antonio Cortes734010a2017-01-19 20:09:22 -080044import java.util.Collection;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070045import java.util.Collections;
46import java.util.HashMap;
asafro99e4f082017-02-09 13:11:42 -080047import java.util.HashSet;
Antonio Cortes734010a2017-01-19 20:09:22 -080048import java.util.LinkedList;
49import java.util.List;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070050import java.util.Map;
asafro99e4f082017-02-09 13:11:42 -080051import java.util.Set;
asafro99e4f082017-02-09 13:11:42 -080052import java.util.concurrent.CopyOnWriteArrayList;
Antonio Cortes734010a2017-01-19 20:09:22 -080053
54/**
55 * This is a glue layer between the VehicleHal and the VmsService. It sends VMS properties back and
56 * forth.
57 */
Antonio Cortesa6845c32017-02-06 09:22:26 -080058@FutureFeature
Antonio Cortes734010a2017-01-19 20:09:22 -080059public class VmsHalService extends HalServiceBase {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070060
Antonio Cortes734010a2017-01-19 20:09:22 -080061 private static final boolean DBG = true;
62 private static final int HAL_PROPERTY_ID = VehicleProperty.VEHICLE_MAP_SERVICE;
63 private static final String TAG = "VmsHalService";
64
65 private boolean mIsSupported = false;
asafro99e4f082017-02-09 13:11:42 -080066 private CopyOnWriteArrayList<VmsHalPublisherListener> mPublisherListeners =
67 new CopyOnWriteArrayList<>();
68 private CopyOnWriteArrayList<VmsHalSubscriberListener> mSubscriberListeners =
69 new CopyOnWriteArrayList<>();
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070070
71 private final IBinder mHalPublisherToken = new Binder();
Antonio Cortes734010a2017-01-19 20:09:22 -080072 private final VehicleHal mVehicleHal;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070073
74 private final Object mRoutingLock = new Object();
75 private final VmsRouting mRouting = new VmsRouting();
76 private final Object mAvailabilityLock = new Object();
77 @GuardedBy("mAvailabilityLock")
78 private final Map<IBinder, VmsLayersOffering> mOfferings = new HashMap<>();
79 @GuardedBy("mAvailabilityLock")
80 private final VmsLayersAvailability mAvailableLayers = new VmsLayersAvailability();
Antonio Cortes734010a2017-01-19 20:09:22 -080081
82 /**
asafro99e4f082017-02-09 13:11:42 -080083 * The VmsPublisherService implements this interface to receive data from the HAL.
84 */
85 public interface VmsHalPublisherListener {
Antonio Cortes2febe9f2017-03-24 09:42:17 -070086 void onChange(VmsSubscriptionState subscriptionState);
asafro99e4f082017-02-09 13:11:42 -080087 }
88
89 /**
90 * The VmsSubscriberService implements this interface to receive data from the HAL.
91 */
92 public interface VmsHalSubscriberListener {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070093 // Notify listener on a data Message.
94 void onDataMessage(VmsLayer layer, byte[] payload);
95
96 // Notify listener on a change in available layers.
97 void onLayersAvaiabilityChange(List<VmsLayer> availableLayers);
asafro99e4f082017-02-09 13:11:42 -080098 }
99
100 /**
Antonio Cortes734010a2017-01-19 20:09:22 -0800101 * The VmsService implements this interface to receive data from the HAL.
102 */
Antonio Cortes734010a2017-01-19 20:09:22 -0800103 protected VmsHalService(VehicleHal vehicleHal) {
104 mVehicleHal = vehicleHal;
105 if (DBG) {
106 Log.d(TAG, "started VmsHalService!");
107 }
108 }
109
asafro99e4f082017-02-09 13:11:42 -0800110 public void addPublisherListener(VmsHalPublisherListener listener) {
111 mPublisherListeners.add(listener);
Antonio Cortes40b90262017-02-06 11:43:57 -0800112 }
113
asafro99e4f082017-02-09 13:11:42 -0800114 public void addSubscriberListener(VmsHalSubscriberListener listener) {
115 mSubscriberListeners.add(listener);
Antonio Cortes734010a2017-01-19 20:09:22 -0800116 }
117
asafro99e4f082017-02-09 13:11:42 -0800118 public void removePublisherListener(VmsHalPublisherListener listener) {
119 mPublisherListeners.remove(listener);
Antonio Cortes734010a2017-01-19 20:09:22 -0800120 }
121
asafro99e4f082017-02-09 13:11:42 -0800122 public void removeSubscriberListener(VmsHalSubscriberListener listener) {
123 mSubscriberListeners.remove(listener);
Antonio Cortes734010a2017-01-19 20:09:22 -0800124 }
125
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700126 public void addSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700127 boolean firstSubscriptionForLayer = false;
128 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800129 // Check if publishers need to be notified about this change in subscriptions.
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700130 firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
asafro25a87402017-02-28 16:08:17 -0800131
132 // Add the listeners subscription to the layer
133 mRouting.addSubscription(listener, layer);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700134 }
135 if (firstSubscriptionForLayer) {
136 notifyPublishers(layer, true);
asafro25a87402017-02-28 16:08:17 -0800137 }
138 }
139
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700140 public void removeSubscription(IVmsSubscriberClient listener, VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700141 boolean layerHasSubscribers = true;
142 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800143 if (!mRouting.hasLayerSubscriptions(layer)) {
144 Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
145 return;
146 }
147
148 // Remove the listeners subscription to the layer
149 mRouting.removeSubscription(listener, layer);
150
151 // Check if publishers need to be notified about this change in subscriptions.
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700152 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
153 }
154 if (!layerHasSubscribers) {
155 notifyPublishers(layer, false);
asafro25a87402017-02-28 16:08:17 -0800156 }
157 }
158
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700159 public void addSubscription(IVmsSubscriberClient listener) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700160 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800161 mRouting.addSubscription(listener);
162 }
163 }
164
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700165 public void removeSubscription(IVmsSubscriberClient listener) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700166 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800167 mRouting.removeSubscription(listener);
168 }
169 }
170
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700171 public void removeDeadListener(IVmsSubscriberClient listener) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700172 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800173 mRouting.removeDeadListener(listener);
174 }
175 }
176
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700177 public Set<IVmsSubscriberClient> getListeners(VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700178 synchronized (mRoutingLock) {
Antonio Cortes8b350092017-03-16 16:02:51 -0700179 return mRouting.getListeners(layer);
180 }
asafro25a87402017-02-28 16:08:17 -0800181 }
182
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700183 public Set<IVmsSubscriberClient> getAllListeners() {
184 synchronized (mRoutingLock) {
185 return mRouting.getAllListeners();
186 }
187 }
188
asafro25a87402017-02-28 16:08:17 -0800189 public boolean isHalSubscribed(VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700190 synchronized (mRoutingLock) {
Antonio Cortes8b350092017-03-16 16:02:51 -0700191 return mRouting.isHalSubscribed(layer);
192 }
asafro25a87402017-02-28 16:08:17 -0800193 }
194
Antonio Cortes2febe9f2017-03-24 09:42:17 -0700195 public VmsSubscriptionState getSubscriptionState() {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700196 synchronized (mRoutingLock) {
Antonio Cortes2febe9f2017-03-24 09:42:17 -0700197 return mRouting.getSubscriptionState();
Antonio Cortes8b350092017-03-16 16:02:51 -0700198 }
asafro25a87402017-02-28 16:08:17 -0800199 }
200
201 public void addHalSubscription(VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700202 boolean firstSubscriptionForLayer = true;
203 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800204 // Check if publishers need to be notified about this change in subscriptions.
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700205 firstSubscriptionForLayer = !mRouting.hasLayerSubscriptions(layer);
asafro25a87402017-02-28 16:08:17 -0800206
207 // Add the listeners subscription to the layer
208 mRouting.addHalSubscription(layer);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700209 }
210 if (firstSubscriptionForLayer) {
211 notifyPublishers(layer, true);
asafro25a87402017-02-28 16:08:17 -0800212 }
213 }
214
215 public void removeHalSubscription(VmsLayer layer) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700216 boolean layerHasSubscribers = true;
217 synchronized (mRoutingLock) {
asafro25a87402017-02-28 16:08:17 -0800218 if (!mRouting.hasLayerSubscriptions(layer)) {
219 Log.i(TAG, "Trying to remove a layer with no subscription: " + layer);
220 return;
221 }
222
223 // Remove the listeners subscription to the layer
224 mRouting.removeHalSubscription(layer);
225
226 // Check if publishers need to be notified about this change in subscriptions.
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700227 layerHasSubscribers = mRouting.hasLayerSubscriptions(layer);
228 }
229 if (!layerHasSubscribers) {
230 notifyPublishers(layer, false);
asafro25a87402017-02-28 16:08:17 -0800231 }
232 }
233
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -0700234 public boolean containsListener(IVmsSubscriberClient listener) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700235 synchronized (mRoutingLock) {
Antonio Cortes8b350092017-03-16 16:02:51 -0700236 return mRouting.containsListener(listener);
237 }
asafro25a87402017-02-28 16:08:17 -0800238 }
239
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700240 public void setPublisherLayersOffering(IBinder publisherToken, VmsLayersOffering offering){
241 Set<VmsLayer> availableLayers = Collections.EMPTY_SET;
242 synchronized (mAvailabilityLock) {
243 updateOffering(publisherToken, offering);
244 availableLayers = mAvailableLayers.getAvailableLayers();
245 }
246 notifySubscribers(availableLayers);
247 }
248
249 public Set<VmsLayer> getAvailableLayers() {
250 //TODO(b/36872877): wrap available layers in VmsAvailabilityState similar to VmsSubscriptionState.
251 synchronized (mAvailabilityLock) {
252 return mAvailableLayers.getAvailableLayers();
253 }
254 }
255
asafro25a87402017-02-28 16:08:17 -0800256 /**
257 * Notify all the publishers and the HAL on subscription changes regardless of who triggered
258 * the change.
259 *
Antonio Cortes9db963a2017-03-10 15:15:28 -0800260 * @param layer layer which is being subscribed to or unsubscribed from.
261 * @param hasSubscribers indicates if the notification is for subscription or unsubscription.
asafro25a87402017-02-28 16:08:17 -0800262 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700263 private void notifyPublishers(VmsLayer layer, boolean hasSubscribers) {
264 // notify the HAL
265 setSubscriptionRequest(layer, hasSubscribers);
asafro25a87402017-02-28 16:08:17 -0800266
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700267 // Notify the App publishers
268 for (VmsHalPublisherListener listener : mPublisherListeners) {
269 // Besides the list of layers, also a timestamp is provided to the clients.
270 // They should ignore any notification with a timestamp that is older than the most
271 // recent timestamp they have seen.
272 listener.onChange(getSubscriptionState());
273 }
274 }
275
276 /**
277 * Notify all the subscribers and the HAL on layers availability change.
278 *
279 * @param availableLayers the layers which publishers claim they made publish.
280 */
281 private void notifySubscribers(Set<VmsLayer> availableLayers) {
282 // notify the HAL
283 setAvailableLayers(availableLayers);
284
285 // Notify the App subscribers
286 for (VmsHalSubscriberListener listener : mSubscriberListeners) {
287 listener.onLayersAvaiabilityChange(new ArrayList<>(availableLayers));
asafro25a87402017-02-28 16:08:17 -0800288 }
289 }
290
Antonio Cortes734010a2017-01-19 20:09:22 -0800291 @Override
292 public void init() {
293 if (DBG) {
294 Log.d(TAG, "init()");
295 }
296 if (mIsSupported) {
Pavel Maltsev79d5e122017-03-24 12:46:40 -0700297 mVehicleHal.subscribeProperty(this, HAL_PROPERTY_ID);
Antonio Cortes734010a2017-01-19 20:09:22 -0800298 }
299 }
300
301 @Override
302 public void release() {
303 if (DBG) {
304 Log.d(TAG, "release()");
305 }
306 if (mIsSupported) {
307 mVehicleHal.unsubscribeProperty(this, HAL_PROPERTY_ID);
308 }
asafro99e4f082017-02-09 13:11:42 -0800309 mPublisherListeners.clear();
310 mSubscriberListeners.clear();
Antonio Cortes734010a2017-01-19 20:09:22 -0800311 }
312
313 @Override
314 public Collection<VehiclePropConfig> takeSupportedProperties(
315 Collection<VehiclePropConfig> allProperties) {
316 List<VehiclePropConfig> taken = new LinkedList<>();
317 for (VehiclePropConfig p : allProperties) {
318 if (p.prop == HAL_PROPERTY_ID) {
319 taken.add(p);
320 mIsSupported = true;
321 if (DBG) {
322 Log.d(TAG, "takeSupportedProperties: " + toHexString(p.prop));
323 }
324 break;
325 }
326 }
327 return taken;
328 }
329
Antonio Cortese0824d72017-04-06 11:13:35 -0700330 /**
331 * Consumes/produces HAL messages. The format of these messages is defined in:
332 * hardware/interfaces/automotive/vehicle/2.1/types.hal
333 */
Antonio Cortes734010a2017-01-19 20:09:22 -0800334 @Override
335 public void handleHalEvents(List<VehiclePropValue> values) {
asafro25a87402017-02-28 16:08:17 -0800336 if (DBG) {
337 Log.d(TAG, "Handling a VMS property change");
338 }
asafro99e4f082017-02-09 13:11:42 -0800339 for (VehiclePropValue v : values) {
340 ArrayList<Integer> vec = v.value.int32Values;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700341 int messageType = vec.get(VmsBaseMessageIntegerValuesIndex.VMS_MESSAGE_TYPE);
asafro99e4f082017-02-09 13:11:42 -0800342
asafro25a87402017-02-28 16:08:17 -0800343 if (DBG) {
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700344 Log.d(TAG, "Handling VMS message type: " + messageType);
asafro25a87402017-02-28 16:08:17 -0800345 }
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700346 switch(messageType) {
347 case VmsMessageType.DATA:
348 handleDataEvent(vec, toByteArray(v.value.bytes));
349 break;
350 case VmsMessageType.SUBSCRIBE:
351 handleSubscribeEvent(vec);
352 break;
353 case VmsMessageType.UNSUBSCRIBE:
354 handleUnsubscribeEvent(vec);
355 break;
356 case VmsMessageType.OFFERING:
357 handleOfferingEvent(vec);
358 break;
Asaf Rosenfeld1ab389c2017-04-25 11:24:17 -0700359 case VmsMessageType.AVAILABILITY_REQUEST:
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700360 handleAvailabilityEvent();
361 break;
Antonio Cortese0824d72017-04-06 11:13:35 -0700362 case VmsMessageType.SUBSCRIPTION_REQUEST:
363 handleSubscriptionRequestEvent();
364 break;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700365 default:
366 throw new IllegalArgumentException("Unexpected message type: " + messageType);
Antonio Cortes734010a2017-01-19 20:09:22 -0800367 }
368 }
369 }
370
Antonio Cortese0824d72017-04-06 11:13:35 -0700371 /**
372 * Data message format:
373 * <ul>
374 * <li>Message type.
375 * <li>Layer id.
376 * <li>Layer version.
377 * <li>Payload.
378 * </ul>
379 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700380 private void handleDataEvent(List<Integer> integerValues, byte[] payload) {
381 int layerId = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_ID);
382 int layerVersion = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_VERSION);
383 if (DBG) {
384 Log.d(TAG,
385 "Handling a data event for Layer Id: " + layerId +
386 " Version: " + layerVersion);
387 }
388
389 // Send the message.
390 for (VmsHalSubscriberListener listener : mSubscriberListeners) {
391 listener.onDataMessage(new VmsLayer(layerId, layerVersion), payload);
392 }
393 }
394
Antonio Cortese0824d72017-04-06 11:13:35 -0700395 /**
396 * Subscribe message format:
397 * <ul>
398 * <li>Message type.
399 * <li>Layer id.
400 * <li>Layer version.
401 * </ul>
402 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700403 private void handleSubscribeEvent(List<Integer> integerValues) {
404 int layerId = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_ID);
405 int layerVersion = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_VERSION);
406 if (DBG) {
407 Log.d(TAG,
408 "Handling a subscribe event for Layer Id: " + layerId +
409 " Version: " + layerVersion);
410 }
411 addHalSubscription(new VmsLayer(layerId, layerVersion));
412 }
413
Antonio Cortese0824d72017-04-06 11:13:35 -0700414 /**
415 * Unsubscribe message format:
416 * <ul>
417 * <li>Message type.
418 * <li>Layer id.
419 * <li>Layer version.
420 * </ul>
421 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700422 private void handleUnsubscribeEvent(List<Integer> integerValues) {
423 int layerId = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_ID);
424 int layerVersion = integerValues.get(VmsSimpleMessageIntegerValuesIndex.VMS_LAYER_VERSION);
425 if (DBG) {
426 Log.d(TAG,
427 "Handling an unsubscribe event for Layer Id: " + layerId +
428 " Version: " + layerVersion);
429 }
430 removeHalSubscription(new VmsLayer(layerId, layerVersion));
431 }
432
Antonio Cortese0824d72017-04-06 11:13:35 -0700433 /**
434 * Offering message format:
435 * <ul>
436 * <li>Message type.
437 * <li>Number of offerings.
438 * <li>Each offering consists of:
439 * <ul>
440 * <li>Layer id.
441 * <li>Layer version.
442 * <li>Number of layer dependencies.
443 * <li>Layer type/version pairs.
444 * </ul>
445 * </ul>
446 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700447 private void handleOfferingEvent(List<Integer> integerValues) {
448 int numLayersDependencies =
449 integerValues.get(VmsOfferingMessageIntegerValuesIndex.VMS_NUMBER_OF_LAYERS_DEPENDENCIES);
450 int idx = VmsOfferingMessageIntegerValuesIndex.FIRST_DEPENDENCIES_INDEX;
451
452 List<VmsLayerDependency> offeredLayers = new ArrayList<>();
453
454 // An offering is layerId, LayerVersion, NumDeps, <LayerId, LayerVersion> X NumDeps.
455 for (int i = 0; i < numLayersDependencies; i++) {
456 int layerId = integerValues.get(idx++);
457 int layerVersion = integerValues.get(idx++);
458 VmsLayer offeredLayer = new VmsLayer(layerId, layerVersion);
459
460 int numDependenciesForLayer = integerValues.get(idx++);
461 if (numDependenciesForLayer == 0) {
462 offeredLayers.add(new VmsLayerDependency(offeredLayer));
463 } else {
464 Set<VmsLayer> dependencies = new HashSet<>();
465
466 for (int j = 0; j < numDependenciesForLayer; j++) {
467 int dependantLayerId = integerValues.get(idx++);
468 int dependantLayerVersion = integerValues.get(idx++);
469
470 VmsLayer dependantLayer = new VmsLayer(dependantLayerId, dependantLayerVersion);
471 dependencies.add(dependantLayer);
472 }
473 offeredLayers.add(new VmsLayerDependency(offeredLayer, dependencies));
474 }
475 }
476 // Store the HAL offering.
477 VmsLayersOffering offering = new VmsLayersOffering(offeredLayers);
478 synchronized (mAvailabilityLock) {
479 updateOffering(mHalPublisherToken, offering);
480 }
481 }
482
Antonio Cortese0824d72017-04-06 11:13:35 -0700483 /**
484 * Availability message format:
485 * <ul>
486 * <li>Message type.
487 * <li>Number of layers.
488 * <li>Layer type/version pairs.
489 * </ul>
490 */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700491 private void handleAvailabilityEvent() {
492 synchronized (mAvailabilityLock) {
493 Collection<VmsLayer> availableLayers = mAvailableLayers.getAvailableLayers();
494 VehiclePropValue vehiclePropertyValue = toVehiclePropValue(
Asaf Rosenfeld1ab389c2017-04-25 11:24:17 -0700495 VmsMessageType.AVAILABILITY_RESPONSE, availableLayers);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700496 setPropertyValue(vehiclePropertyValue);
497 }
498 }
499
Antonio Cortese0824d72017-04-06 11:13:35 -0700500 /**
501 * VmsSubscriptionRequestFormat:
502 * <ul>
503 * <li>Message type.
504 * </ul>
505 *
506 * VmsSubscriptionResponseFormat:
507 * <ul>
508 * <li>Message type.
509 * <li>Sequence number.
510 * <li>Number of layers.
511 * <li>Layer type/version pairs.
512 * </ul>
513 */
514 private void handleSubscriptionRequestEvent() {
515 VmsSubscriptionState subscription = getSubscriptionState();
516 VehiclePropValue vehicleProp = toVehiclePropValue(VmsMessageType.SUBSCRIPTION_RESPONSE);
517 VehiclePropValue.RawValue v = vehicleProp.value;
518 v.int32Values.add(subscription.getSequenceNumber());
519 List<VmsLayer> layers = subscription.getLayers();
520 v.int32Values.add(layers.size());
521 for (VmsLayer layer : layers) {
522 v.int32Values.add(layer.getId());
523 v.int32Values.add(layer.getVersion());
524 }
525 setPropertyValue(vehicleProp);
526 }
527
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700528 private void updateOffering(IBinder publisherToken, VmsLayersOffering offering) {
529 Set<VmsLayer> availableLayers = Collections.EMPTY_SET;
530 synchronized (mAvailabilityLock) {
531 mOfferings.put(publisherToken, offering);
532
533 // Update layers availability.
534 mAvailableLayers.setPublishersOffering(mOfferings.values());
535
536 availableLayers = mAvailableLayers.getAvailableLayers();
537 }
538 notifySubscribers(availableLayers);
539 }
540
Antonio Cortes734010a2017-01-19 20:09:22 -0800541 @Override
542 public void dump(PrintWriter writer) {
543 writer.println(TAG);
544 writer.println("VmsProperty " + (mIsSupported ? "" : "not") + " supported.");
545 }
546
asafro99e4f082017-02-09 13:11:42 -0800547 /**
548 * Updates the VMS HAL property with the given value.
549 *
Antonio Cortes01a60392017-03-22 13:00:02 -0700550 * @param layer layer data to update the hal property.
551 * @param hasSubscribers if it is a subscribe or unsubscribe message.
552 * @return true if the call to the HAL to update the property was successful.
asafro99e4f082017-02-09 13:11:42 -0800553 */
Antonio Cortes01a60392017-03-22 13:00:02 -0700554 public boolean setSubscriptionRequest(VmsLayer layer, boolean hasSubscribers) {
asafro25a87402017-02-28 16:08:17 -0800555 VehiclePropValue vehiclePropertyValue = toVehiclePropValue(
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700556 hasSubscribers ? VmsMessageType.SUBSCRIBE : VmsMessageType.UNSUBSCRIBE, layer);
asafro99e4f082017-02-09 13:11:42 -0800557 return setPropertyValue(vehiclePropertyValue);
558 }
559
Antonio Cortes01a60392017-03-22 13:00:02 -0700560 public boolean setDataMessage(VmsLayer layer, byte[] payload) {
asafro99e4f082017-02-09 13:11:42 -0800561 VehiclePropValue vehiclePropertyValue = toVehiclePropValue(VmsMessageType.DATA,
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700562 layer,
563 payload);
564 return setPropertyValue(vehiclePropertyValue);
565 }
566
567 public boolean setAvailableLayers(Collection<VmsLayer> availableLayers) {
Asaf Rosenfeld1ab389c2017-04-25 11:24:17 -0700568 VehiclePropValue vehiclePropertyValue =
569 toVehiclePropValue(VmsMessageType.AVAILABILITY_RESPONSE,
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700570 availableLayers);
571
asafro99e4f082017-02-09 13:11:42 -0800572 return setPropertyValue(vehiclePropertyValue);
573 }
574
575 public boolean setPropertyValue(VehiclePropValue vehiclePropertyValue) {
576 try {
577 mVehicleHal.set(vehiclePropertyValue);
578 return true;
579 } catch (PropertyTimeoutException e) {
580 Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(HAL_PROPERTY_ID));
581 }
582 return false;
583 }
584
585 /** Creates a {@link VehiclePropValue} */
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700586 private static VehiclePropValue toVehiclePropValue(int messageType) {
Antonio Cortes734010a2017-01-19 20:09:22 -0800587 VehiclePropValue vehicleProp = new VehiclePropValue();
588 vehicleProp.prop = HAL_PROPERTY_ID;
589 vehicleProp.areaId = VehicleAreaType.VEHICLE_AREA_TYPE_NONE;
590 VehiclePropValue.RawValue v = vehicleProp.value;
asafro99e4f082017-02-09 13:11:42 -0800591
592 v.int32Values.add(messageType);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700593 return vehicleProp;
594 }
595
596 /** Creates a {@link VehiclePropValue} */
597 private static VehiclePropValue toVehiclePropValue(int messageType, VmsLayer layer) {
598 VehiclePropValue vehicleProp = toVehiclePropValue(messageType);
599 VehiclePropValue.RawValue v = vehicleProp.value;
Antonio Cortes01a60392017-03-22 13:00:02 -0700600 v.int32Values.add(layer.getId());
601 v.int32Values.add(layer.getVersion());
asafro99e4f082017-02-09 13:11:42 -0800602 return vehicleProp;
603 }
604
Antonio Cortes01a60392017-03-22 13:00:02 -0700605 /** Creates a {@link VehiclePropValue} with payload */
606 private static VehiclePropValue toVehiclePropValue(int messageType,
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700607 VmsLayer layer,
608 byte[] payload) {
Antonio Cortes01a60392017-03-22 13:00:02 -0700609 VehiclePropValue vehicleProp = toVehiclePropValue(messageType, layer);
asafro99e4f082017-02-09 13:11:42 -0800610 VehiclePropValue.RawValue v = vehicleProp.value;
611 v.bytes.ensureCapacity(payload.length);
612 for (byte b : payload) {
613 v.bytes.add(b);
614 }
Antonio Cortes734010a2017-01-19 20:09:22 -0800615 return vehicleProp;
616 }
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700617
618 /** Creates a {@link VehiclePropValue} with payload */
619 private static VehiclePropValue toVehiclePropValue(int messageType,
620 Collection<VmsLayer> layers) {
621 VehiclePropValue vehicleProp = toVehiclePropValue(messageType);
622 VehiclePropValue.RawValue v = vehicleProp.value;
623 int numLayers = layers.size();
624 v.int32Values.add(numLayers);
625 for (VmsLayer layer : layers) {
626 v.int32Values.add(layer.getId());
627 v.int32Values.add(layer.getVersion());
628 }
629 return vehicleProp;
630 }
631}