blob: 487ec1f016b372215f3db1b66cfde59aa2f9b19a [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;
Anna Linetsky5c45fca2018-04-26 14:29:16 -070019
Antonio Cortes734010a2017-01-19 20:09:22 -080020import static java.lang.Integer.toHexString;
21
Antonio Cortes734010a2017-01-19 20:09:22 -080022import android.car.VehicleAreaType;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080023import android.car.vms.IVmsPublisherClient;
24import android.car.vms.IVmsPublisherService;
Asaf Rosenfeld2ca6f8c2017-03-20 12:59:33 -070025import android.car.vms.IVmsSubscriberClient;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080026import android.car.vms.IVmsSubscriberService;
Asaf Rosenfeld43900532017-06-16 11:16:55 -070027import android.car.vms.VmsAssociatedLayer;
Asaf Rosenfeld908811e2018-01-22 09:13:47 -080028import android.car.vms.VmsAvailableLayers;
Anna Linetsky5c45fca2018-04-26 14:29:16 -070029import android.car.vms.VmsLayer;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070030import android.car.vms.VmsLayerDependency;
31import android.car.vms.VmsLayersOffering;
Demyn Plantenberg3ca12892017-06-20 21:01:34 -070032import android.car.vms.VmsOperationRecorder;
Antonio Cortes2febe9f2017-03-24 09:42:17 -070033import android.car.vms.VmsSubscriptionState;
Pavel Maltsevcfe93102017-02-02 12:38:08 -080034import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
35import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
Pavel Maltsev99e1a752017-08-24 15:15:05 -070036import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
37import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
38import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
39import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex;
Pavel Maltsev99e1a752017-08-24 15:15:05 -070040import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerIntegerValuesIndex;
Anna Linetsky5c45fca2018-04-26 14:29:16 -070041import android.hardware.automotive.vehicle.V2_0.VmsOfferingMessageIntegerValuesIndex;
Mark Tabry786dacd2019-02-26 14:23:48 -080042import android.hardware.automotive.vehicle.V2_0.VmsPublisherInformationIntegerValuesIndex;
Mark Tabry9abdf102019-04-26 13:36:22 -070043import android.hardware.automotive.vehicle.V2_0.VmsStartSessionMessageIntegerValuesIndex;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080044import android.os.Handler;
45import android.os.HandlerThread;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070046import android.os.IBinder;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080047import android.os.Message;
48import android.os.RemoteException;
Mark Tabry9abdf102019-04-26 13:36:22 -070049import android.os.SystemClock;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080050import android.util.ArraySet;
Antonio Cortes734010a2017-01-19 20:09:22 -080051import android.util.Log;
Anna Linetsky5c45fca2018-04-26 14:29:16 -070052
Mark Tabry76cfaaa2019-02-01 14:28:30 -080053import androidx.annotation.VisibleForTesting;
54
Antonio Cortes734010a2017-01-19 20:09:22 -080055import com.android.car.CarLog;
Asaf Rosenfeld43900532017-06-16 11:16:55 -070056
Antonio Cortes734010a2017-01-19 20:09:22 -080057import java.io.PrintWriter;
Antonio Cortes40b90262017-02-06 11:43:57 -080058import java.util.ArrayList;
Mark Tabry9abdf102019-04-26 13:36:22 -070059import java.util.Arrays;
Antonio Cortes734010a2017-01-19 20:09:22 -080060import java.util.Collection;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070061import java.util.Collections;
asafro99e4f082017-02-09 13:11:42 -080062import java.util.HashSet;
Antonio Cortes734010a2017-01-19 20:09:22 -080063import java.util.List;
asafro99e4f082017-02-09 13:11:42 -080064import java.util.Set;
Mark Tabry9abdf102019-04-26 13:36:22 -070065import java.util.function.Consumer;
66import java.util.function.Supplier;
Antonio Cortes734010a2017-01-19 20:09:22 -080067
68/**
Mark Tabry76cfaaa2019-02-01 14:28:30 -080069 * VMS client implementation that proxies VmsPublisher/VmsSubscriber API calls to the Vehicle HAL
70 * using HAL-specific message encodings.
71 *
72 * @see android.hardware.automotive.vehicle.V2_0
Antonio Cortes734010a2017-01-19 20:09:22 -080073 */
Antonio Cortes734010a2017-01-19 20:09:22 -080074public class VmsHalService extends HalServiceBase {
75 private static final boolean DBG = true;
Antonio Cortes734010a2017-01-19 20:09:22 -080076 private static final String TAG = "VmsHalService";
Mark Tabry76cfaaa2019-02-01 14:28:30 -080077 private static final int HAL_PROPERTY_ID = VehicleProperty.VEHICLE_MAP_SERVICE;
78 private static final int NUM_INTEGERS_IN_VMS_LAYER = 3;
Mark Tabry9abdf102019-04-26 13:36:22 -070079 private static final int UNKNOWN_CLIENT_ID = -1;
Antonio Cortes734010a2017-01-19 20:09:22 -080080
Antonio Cortes734010a2017-01-19 20:09:22 -080081 private final VehicleHal mVehicleHal;
Mark Tabry9abdf102019-04-26 13:36:22 -070082 private final int mCoreId;
83 private final MessageQueue mMessageQueue;
Mark Tabry76cfaaa2019-02-01 14:28:30 -080084 private volatile boolean mIsSupported = false;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070085
Mark Tabry76cfaaa2019-02-01 14:28:30 -080086 private IVmsPublisherService mPublisherService;
Mark Tabry9abdf102019-04-26 13:36:22 -070087 private Consumer<IBinder> mPublisherOnHalConnected;
88 private Runnable mPublisherOnHalDisconnected;
89 private IBinder mPublisherToken;
Antonio Cortes734010a2017-01-19 20:09:22 -080090
Mark Tabry9abdf102019-04-26 13:36:22 -070091 private IVmsSubscriberService mSubscriberService;
92 private Consumer<IVmsSubscriberClient> mSuscriberOnHalDisconnected;
asafro99e4f082017-02-09 13:11:42 -080093
Mark Tabry76cfaaa2019-02-01 14:28:30 -080094 private int mSubscriptionStateSequence = -1;
95 private int mAvailableLayersSequence = -1;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -070096
Mark Tabry76cfaaa2019-02-01 14:28:30 -080097 private final IVmsPublisherClient.Stub mPublisherClient = new IVmsPublisherClient.Stub() {
98 @Override
99 public void setVmsPublisherService(IBinder token, IVmsPublisherService service) {
100 mPublisherToken = token;
101 mPublisherService = service;
Antonio Cortes734010a2017-01-19 20:09:22 -0800102 }
Antonio Cortes734010a2017-01-19 20:09:22 -0800103
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800104 @Override
105 public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
Mark Tabry9abdf102019-04-26 13:36:22 -0700106 if (DBG) Log.d(TAG, "Handling a subscription state change");
107 // Drop out-of-order notifications
108 if (subscriptionState.getSequenceNumber() <= mSubscriptionStateSequence) {
109 Log.w(TAG,
110 String.format("Out of order subscription state received: %d (expecting %d)",
111 subscriptionState.getSequenceNumber(),
112 mSubscriptionStateSequence + 1));
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800113 return;
114 }
Mark Tabry9abdf102019-04-26 13:36:22 -0700115 mSubscriptionStateSequence = subscriptionState.getSequenceNumber();
116 mMessageQueue.enqueue(VmsMessageType.SUBSCRIPTIONS_CHANGE,
117 createSubscriptionStateMessage(VmsMessageType.SUBSCRIPTIONS_CHANGE,
118 subscriptionState));
Anna Linetsky5c45fca2018-04-26 14:29:16 -0700119 }
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800120 };
asafro25a87402017-02-28 16:08:17 -0800121
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800122 private final IVmsSubscriberClient.Stub mSubscriberClient = new IVmsSubscriberClient.Stub() {
123 @Override
124 public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
125 if (DBG) Log.d(TAG, "Handling a data message for Layer: " + layer);
Mark Tabry9abdf102019-04-26 13:36:22 -0700126 mMessageQueue.enqueue(VmsMessageType.DATA, createDataMessage(layer, payload));
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700127 }
asafro25a87402017-02-28 16:08:17 -0800128
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800129 @Override
130 public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
131 if (DBG) Log.d(TAG, "Handling a layer availability change");
Mark Tabry9abdf102019-04-26 13:36:22 -0700132 // Drop out-of-order notifications
133 if (availableLayers.getSequence() <= mAvailableLayersSequence) {
134 Log.w(TAG,
135 String.format("Out of order layer availability received: %d (expecting %d)",
136 availableLayers.getSequence(),
137 mAvailableLayersSequence + 1));
138 return;
139 }
140 mAvailableLayersSequence = availableLayers.getSequence();
141 mMessageQueue.enqueue(VmsMessageType.AVAILABILITY_CHANGE,
142 createAvailableLayersMessage(VmsMessageType.AVAILABILITY_CHANGE,
143 availableLayers));
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800144 }
145 };
146
Mark Tabry9abdf102019-04-26 13:36:22 -0700147 private class MessageQueue implements Handler.Callback {
148 private final Set<Integer> mSupportedMessageTypes = new ArraySet<>(Arrays.asList(
149 VmsMessageType.DATA,
150 VmsMessageType.START_SESSION,
151 VmsMessageType.AVAILABILITY_CHANGE,
152 VmsMessageType.SUBSCRIPTIONS_CHANGE
153 ));
154 private HandlerThread mHandlerThread;
155 private Handler mHandler;
156
157 synchronized void init() {
158 mHandlerThread = new HandlerThread(TAG);
159 mHandlerThread.start();
160 mHandler = new Handler(mHandlerThread.getLooper(), this);
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800161 }
Mark Tabry9abdf102019-04-26 13:36:22 -0700162
163 synchronized void release() {
164 if (mHandlerThread != null) {
165 mHandlerThread.quitSafely();
166 }
167 }
168
169 synchronized void enqueue(int messageType, Object message) {
170 if (mSupportedMessageTypes.contains(messageType)) {
171 Message.obtain(mHandler, messageType, message).sendToTarget();
172 } else {
173 Log.e(TAG, "Unexpected message type: " + VmsMessageType.toString(messageType));
174 }
175 }
176
177 synchronized void clear() {
178 mSupportedMessageTypes.forEach(mHandler::removeMessages);
179 }
180
181 @Override
182 public boolean handleMessage(Message msg) {
183 int messageType = msg.what;
184 VehiclePropValue vehicleProp = (VehiclePropValue) msg.obj;
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800185 if (DBG) Log.d(TAG, "Sending " + VmsMessageType.toString(messageType) + " message");
186 try {
187 setPropertyValue(vehicleProp);
188 } catch (RemoteException e) {
189 Log.e(TAG, "While sending " + VmsMessageType.toString(messageType));
asafro25a87402017-02-28 16:08:17 -0800190 }
Mark Tabry9abdf102019-04-26 13:36:22 -0700191 return true;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700192 }
Mark Tabry9abdf102019-04-26 13:36:22 -0700193 }
asafro25a87402017-02-28 16:08:17 -0800194
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800195 /**
196 * Constructor used by {@link VehicleHal}
197 */
198 VmsHalService(VehicleHal vehicleHal) {
Mark Tabry9abdf102019-04-26 13:36:22 -0700199 this(vehicleHal, SystemClock::uptimeMillis);
200 }
201
202 @VisibleForTesting
203 VmsHalService(VehicleHal vehicleHal, Supplier<Long> getCoreId) {
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800204 mVehicleHal = vehicleHal;
Mark Tabry9abdf102019-04-26 13:36:22 -0700205 mCoreId = (int) (getCoreId.get() % Integer.MAX_VALUE);
206 mMessageQueue = new MessageQueue();
asafro25a87402017-02-28 16:08:17 -0800207 }
208
Asaf Rosenfeld60284892017-05-19 12:59:56 -0700209 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800210 * Retrieves the callback message handler for use by unit tests.
Asaf Rosenfeld60284892017-05-19 12:59:56 -0700211 */
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800212 @VisibleForTesting
213 Handler getHandler() {
Mark Tabry9abdf102019-04-26 13:36:22 -0700214 return mMessageQueue.mHandler;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700215 }
216
asafro25a87402017-02-28 16:08:17 -0800217 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800218 * Gets the {@link IVmsPublisherClient} implementation for the HAL's publisher callback.
asafro25a87402017-02-28 16:08:17 -0800219 */
Mark Tabry9abdf102019-04-26 13:36:22 -0700220 public void setPublisherConnectionCallbacks(Consumer<IBinder> onHalConnected,
221 Runnable onHalDisconnected) {
222 mPublisherOnHalConnected = onHalConnected;
223 mPublisherOnHalDisconnected = onHalDisconnected;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700224 }
225
226 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800227 * Sets a reference to the {@link IVmsSubscriberService} implementation for use by the HAL.
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700228 */
Mark Tabry9abdf102019-04-26 13:36:22 -0700229 public void setVmsSubscriberService(IVmsSubscriberService service,
230 Consumer<IVmsSubscriberClient> onHalDisconnected) {
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800231 mSubscriberService = service;
Mark Tabry9abdf102019-04-26 13:36:22 -0700232 mSuscriberOnHalDisconnected = onHalDisconnected;
Antonio Cortes734010a2017-01-19 20:09:22 -0800233 }
234
235 @Override
236 public Collection<VehiclePropConfig> takeSupportedProperties(
237 Collection<VehiclePropConfig> allProperties) {
Antonio Cortes734010a2017-01-19 20:09:22 -0800238 for (VehiclePropConfig p : allProperties) {
239 if (p.prop == HAL_PROPERTY_ID) {
Antonio Cortes734010a2017-01-19 20:09:22 -0800240 mIsSupported = true;
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800241 return Collections.singleton(p);
Antonio Cortes734010a2017-01-19 20:09:22 -0800242 }
243 }
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800244 return Collections.emptySet();
Antonio Cortes734010a2017-01-19 20:09:22 -0800245 }
246
247 @Override
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800248 public void init() {
249 if (mIsSupported) {
250 if (DBG) Log.d(TAG, "Initializing VmsHalService VHAL property");
251 mVehicleHal.subscribeProperty(this, HAL_PROPERTY_ID);
252 } else {
253 if (DBG) Log.d(TAG, "VmsHalService VHAL property not supported");
254 return; // Do not continue initialization
asafro25a87402017-02-28 16:08:17 -0800255 }
asafro99e4f082017-02-09 13:11:42 -0800256
Mark Tabry9abdf102019-04-26 13:36:22 -0700257 mMessageQueue.init();
258 mMessageQueue.enqueue(VmsMessageType.START_SESSION,
259 createStartSessionMessage(mCoreId, UNKNOWN_CLIENT_ID));
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800260 }
261
262 @Override
263 public void release() {
Mark Tabry9abdf102019-04-26 13:36:22 -0700264 mMessageQueue.release();
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800265 mSubscriptionStateSequence = -1;
266 mAvailableLayersSequence = -1;
Asaf Rosenfeldbcf7df12017-06-02 18:31:28 -0700267
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800268 if (mIsSupported) {
269 if (DBG) Log.d(TAG, "Releasing VmsHalService VHAL property");
270 mVehicleHal.unsubscribeProperty(this, HAL_PROPERTY_ID);
271 } else {
272 return;
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700273 }
274
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800275 if (mSubscriberService != null) {
276 try {
277 mSubscriberService.removeVmsSubscriberToNotifications(mSubscriberClient);
278 } catch (RemoteException e) {
279 Log.e(TAG, "While removing subscriber callback", e);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700280 }
281 }
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700282 }
283
Antonio Cortes734010a2017-01-19 20:09:22 -0800284 @Override
285 public void dump(PrintWriter writer) {
286 writer.println(TAG);
287 writer.println("VmsProperty " + (mIsSupported ? "" : "not") + " supported.");
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800288
289 writer.println(
290 "VmsPublisherService " + (mPublisherService != null ? "" : "not") + " registered.");
291 writer.println("mSubscriptionStateSequence: " + mSubscriptionStateSequence);
292
293 writer.println("VmsSubscriberService " + (mSubscriberService != null ? "" : "not")
294 + " registered.");
295 writer.println("mAvailableLayersSequence: " + mAvailableLayersSequence);
Antonio Cortes734010a2017-01-19 20:09:22 -0800296 }
297
asafro99e4f082017-02-09 13:11:42 -0800298 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800299 * Consumes/produces HAL messages.
asafro99e4f082017-02-09 13:11:42 -0800300 *
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800301 * The format of these messages is defined in:
302 * hardware/interfaces/automotive/vehicle/2.0/types.hal
asafro99e4f082017-02-09 13:11:42 -0800303 */
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800304 @Override
305 public void handleHalEvents(List<VehiclePropValue> values) {
306 if (DBG) Log.d(TAG, "Handling a VMS property change");
307 for (VehiclePropValue v : values) {
308 ArrayList<Integer> vec = v.value.int32Values;
309 int messageType = vec.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
asafro99e4f082017-02-09 13:11:42 -0800310
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800311 if (DBG) Log.d(TAG, "Received " + VmsMessageType.toString(messageType) + " message");
Asaf Rosenfeld4d473f42018-08-14 12:13:21 -0700312 try {
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800313 switch (messageType) {
314 case VmsMessageType.DATA:
315 handleDataEvent(vec, toByteArray(v.value.bytes));
316 break;
317 case VmsMessageType.SUBSCRIBE:
318 handleSubscribeEvent(vec);
319 break;
320 case VmsMessageType.UNSUBSCRIBE:
321 handleUnsubscribeEvent(vec);
322 break;
323 case VmsMessageType.SUBSCRIBE_TO_PUBLISHER:
324 handleSubscribeToPublisherEvent(vec);
325 break;
326 case VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER:
327 handleUnsubscribeFromPublisherEvent(vec);
328 break;
Mark Tabry786dacd2019-02-26 14:23:48 -0800329 case VmsMessageType.PUBLISHER_ID_REQUEST:
330 handlePublisherIdRequest(toByteArray(v.value.bytes));
331 break;
332 case VmsMessageType.PUBLISHER_INFORMATION_REQUEST:
333 handlePublisherInfoRequest(vec);
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800334 case VmsMessageType.OFFERING:
335 handleOfferingEvent(vec);
336 break;
337 case VmsMessageType.AVAILABILITY_REQUEST:
338 handleAvailabilityRequestEvent();
339 break;
340 case VmsMessageType.SUBSCRIPTIONS_REQUEST:
341 handleSubscriptionsRequestEvent();
342 break;
Mark Tabry9abdf102019-04-26 13:36:22 -0700343 case VmsMessageType.START_SESSION:
344 handleStartSessionEvent(vec);
345 break;
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800346 default:
347 Log.e(TAG, "Unexpected message type: " + messageType);
348 }
349 } catch (IndexOutOfBoundsException | RemoteException e) {
350 Log.e(TAG, "While handling: " + messageType, e);
Asaf Rosenfeld4d473f42018-08-14 12:13:21 -0700351 }
asafro99e4f082017-02-09 13:11:42 -0800352 }
asafro99e4f082017-02-09 13:11:42 -0800353 }
354
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800355 /**
Mark Tabry9abdf102019-04-26 13:36:22 -0700356 * SESSION_START message format:
357 * <ul>
358 * <li>Message type
359 * <li>Core ID
360 * <li>Client ID
361 * </ul>
362 */
363 private void handleStartSessionEvent(List<Integer> message) {
364 int coreId = message.get(VmsStartSessionMessageIntegerValuesIndex.SERVICE_ID);
365 int clientId = message.get(VmsStartSessionMessageIntegerValuesIndex.CLIENT_ID);
366 if (DBG) {
367 Log.d(TAG,
368 "Handling a session start event with coreId: " + coreId + " client: "
369 + clientId);
370 }
371
372 if (coreId != mCoreId) {
373 if (mPublisherOnHalDisconnected != null) {
374 mPublisherOnHalDisconnected.run();
375 } else {
376 Log.w(TAG, "Publisher disconnect callback not registered");
377 }
378 if (mSuscriberOnHalDisconnected != null) {
379 mSuscriberOnHalDisconnected.accept(mSubscriberClient);
380 } else {
381 Log.w(TAG, "Subscriber disconnect callback not registered");
382 }
383
384 // Drop all queued messages and client state
385 mMessageQueue.clear();
386 mSubscriptionStateSequence = -1;
387 mAvailableLayersSequence = -1;
388
389 // Enqueue an acknowledgement message
390 mMessageQueue.enqueue(VmsMessageType.START_SESSION,
391 createStartSessionMessage(mCoreId, clientId));
392 }
393
394 // Notify client manager of connection
395 if (mPublisherOnHalConnected != null) {
396 mPublisherOnHalConnected.accept(mPublisherClient);
397 } else {
398 Log.w(TAG, "Publisher connect callback not registered");
399 }
400
401 // Notify subscriber service of connection
402 if (mSubscriberService != null) {
403 try {
404 mSubscriberService.addVmsSubscriberToNotifications(mSubscriberClient);
405 } catch (RemoteException e) {
406 Log.e(TAG, "While adding subscriber callback", e);
407 }
408
409 // Publish layer availability to HAL clients (this triggers HAL client initialization)
410 try {
411 mSubscriberClient.onLayersAvailabilityChanged(
412 mSubscriberService.getAvailableLayers());
413 } catch (RemoteException e) {
414 Log.e(TAG, "While publishing layer availability", e);
415 }
416 } else {
417 Log.w(TAG, "Subscriber connect callback not registered");
418 }
419 }
420
421 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800422 * DATA message format:
423 * <ul>
424 * <li>Message type
425 * <li>Layer ID
426 * <li>Layer subtype
427 * <li>Layer version
428 * <li>Publisher ID
429 * <li>Payload
430 * </ul>
431 */
432 private void handleDataEvent(List<Integer> message, byte[] payload)
433 throws RemoteException {
434 VmsLayer vmsLayer = parseVmsLayerFromMessage(message);
435 int publisherId = parsePublisherIdFromMessage(message);
436 if (DBG) {
437 Log.d(TAG,
438 "Handling a data event for Layer: " + vmsLayer + " Publisher: " + publisherId);
439 }
440 mPublisherService.publish(mPublisherToken, vmsLayer, publisherId, payload);
441 }
442
443 /**
444 * SUBSCRIBE message format:
445 * <ul>
446 * <li>Message type
447 * <li>Layer ID
448 * <li>Layer subtype
449 * <li>Layer version
450 * </ul>
451 */
452 private void handleSubscribeEvent(List<Integer> message) throws RemoteException {
453 VmsLayer vmsLayer = parseVmsLayerFromMessage(message);
454 if (DBG) Log.d(TAG, "Handling a subscribe event for Layer: " + vmsLayer);
455 mSubscriberService.addVmsSubscriber(mSubscriberClient, vmsLayer);
456 }
457
458 /**
459 * SUBSCRIBE_TO_PUBLISHER message format:
460 * <ul>
461 * <li>Message type
462 * <li>Layer ID
463 * <li>Layer subtype
464 * <li>Layer version
465 * <li>Publisher ID
466 * </ul>
467 */
468 private void handleSubscribeToPublisherEvent(List<Integer> message)
469 throws RemoteException {
470 VmsLayer vmsLayer = parseVmsLayerFromMessage(message);
471 int publisherId = parsePublisherIdFromMessage(message);
472 if (DBG) {
473 Log.d(TAG,
474 "Handling a subscribe event for Layer: " + vmsLayer + " Publisher: "
475 + publisherId);
476 }
477 mSubscriberService.addVmsSubscriberToPublisher(mSubscriberClient, vmsLayer, publisherId);
478 }
479
480 /**
481 * UNSUBSCRIBE message format:
482 * <ul>
483 * <li>Message type
484 * <li>Layer ID
485 * <li>Layer subtype
486 * <li>Layer version
487 * </ul>
488 */
489 private void handleUnsubscribeEvent(List<Integer> message) throws RemoteException {
490 VmsLayer vmsLayer = parseVmsLayerFromMessage(message);
491 if (DBG) Log.d(TAG, "Handling an unsubscribe event for Layer: " + vmsLayer);
492 mSubscriberService.removeVmsSubscriber(mSubscriberClient, vmsLayer);
493 }
494
495 /**
496 * UNSUBSCRIBE_TO_PUBLISHER message format:
497 * <ul>
498 * <li>Message type
499 * <li>Layer ID
500 * <li>Layer subtype
501 * <li>Layer version
502 * <li>Publisher ID
503 * </ul>
504 */
505 private void handleUnsubscribeFromPublisherEvent(List<Integer> message)
506 throws RemoteException {
507 VmsLayer vmsLayer = parseVmsLayerFromMessage(message);
508 int publisherId = parsePublisherIdFromMessage(message);
509 if (DBG) {
510 Log.d(TAG, "Handling an unsubscribe event for Layer: " + vmsLayer + " Publisher: "
511 + publisherId);
512 }
513 mSubscriberService.removeVmsSubscriberToPublisher(mSubscriberClient, vmsLayer, publisherId);
514 }
515
516 /**
Mark Tabry786dacd2019-02-26 14:23:48 -0800517 * PUBLISHER_ID_REQUEST message format:
518 * <ul>
519 * <li>Message type
520 * <li>Publisher info (bytes)
521 * </ul>
522 *
523 * PUBLISHER_ID_RESPONSE message format:
524 * <ul>
525 * <li>Message type
526 * <li>Publisher ID
527 * </ul>
528 */
529 private void handlePublisherIdRequest(byte[] payload)
530 throws RemoteException {
531 if (DBG) Log.d(TAG, "Handling a publisher id request event");
532
533 VehiclePropValue vehicleProp = createVmsMessage(VmsMessageType.PUBLISHER_ID_RESPONSE);
534 // Publisher ID
535 vehicleProp.value.int32Values.add(mPublisherService.getPublisherId(payload));
536
537 setPropertyValue(vehicleProp);
538 }
539
540
541 /**
542 * PUBLISHER_INFORMATION_REQUEST message format:
543 * <ul>
544 * <li>Message type
545 * <li>Publisher ID
546 * </ul>
547 *
548 * PUBLISHER_INFORMATION_RESPONSE message format:
549 * <ul>
550 * <li>Message type
551 * <li>Publisher info (bytes)
552 * </ul>
553 */
554 private void handlePublisherInfoRequest(List<Integer> message)
555 throws RemoteException {
556 if (DBG) Log.d(TAG, "Handling a publisher info request event");
557 int publisherId = message.get(VmsPublisherInformationIntegerValuesIndex.PUBLISHER_ID);
558
559 VehiclePropValue vehicleProp =
560 createVmsMessage(VmsMessageType.PUBLISHER_INFORMATION_RESPONSE);
561 // Publisher Info
562 appendBytes(vehicleProp.value.bytes, mSubscriberService.getPublisherInfo(publisherId));
563
564 setPropertyValue(vehicleProp);
565 }
566
567 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800568 * OFFERING message format:
569 * <ul>
570 * <li>Message type
571 * <li>Publisher ID
572 * <li>Number of offerings.
573 * <li>Offerings (x number of offerings)
574 * <ul>
575 * <li>Layer ID
576 * <li>Layer subtype
577 * <li>Layer version
578 * <li>Number of layer dependencies.
579 * <li>Layer dependencies (x number of layer dependencies)
580 * <ul>
581 * <li>Layer ID
582 * <li>Layer subtype
583 * <li>Layer version
584 * </ul>
585 * </ul>
586 * </ul>
587 */
588 private void handleOfferingEvent(List<Integer> message) throws RemoteException {
589 // Publisher ID for OFFERING is stored at a different index than in other message types
590 int publisherId = message.get(VmsOfferingMessageIntegerValuesIndex.PUBLISHER_ID);
591 int numLayerDependencies =
592 message.get(
593 VmsOfferingMessageIntegerValuesIndex.NUMBER_OF_OFFERS);
594 if (DBG) {
595 Log.d(TAG, "Handling an offering event of " + numLayerDependencies
596 + " layers for Publisher: " + publisherId);
597 }
598
599 Set<VmsLayerDependency> offeredLayers = new ArraySet<>(numLayerDependencies);
600 int idx = VmsOfferingMessageIntegerValuesIndex.OFFERING_START;
601 for (int i = 0; i < numLayerDependencies; i++) {
602 VmsLayer offeredLayer = parseVmsLayerAtIndex(message, idx);
603 idx += NUM_INTEGERS_IN_VMS_LAYER;
604
605 int numDependenciesForLayer = message.get(idx++);
606 if (numDependenciesForLayer == 0) {
607 offeredLayers.add(new VmsLayerDependency(offeredLayer));
608 } else {
609 Set<VmsLayer> dependencies = new HashSet<>();
610
611 for (int j = 0; j < numDependenciesForLayer; j++) {
612 VmsLayer dependantLayer = parseVmsLayerAtIndex(message, idx);
613 idx += NUM_INTEGERS_IN_VMS_LAYER;
614 dependencies.add(dependantLayer);
615 }
616 offeredLayers.add(new VmsLayerDependency(offeredLayer, dependencies));
617 }
618 }
619
620 VmsLayersOffering offering = new VmsLayersOffering(offeredLayers, publisherId);
621 VmsOperationRecorder.get().setHalPublisherLayersOffering(offering);
622 mPublisherService.setLayersOffering(mPublisherToken, offering);
623 }
624
625 /**
626 * AVAILABILITY_REQUEST message format:
627 * <ul>
628 * <li>Message type
629 * </ul>
630 */
631 private void handleAvailabilityRequestEvent() throws RemoteException {
632 setPropertyValue(
633 createAvailableLayersMessage(VmsMessageType.AVAILABILITY_RESPONSE,
634 mSubscriberService.getAvailableLayers()));
635 }
636
637 /**
638 * SUBSCRIPTION_REQUEST message format:
639 * <ul>
640 * <li>Message type
641 * </ul>
642 */
643 private void handleSubscriptionsRequestEvent() throws RemoteException {
644 setPropertyValue(
645 createSubscriptionStateMessage(VmsMessageType.SUBSCRIPTIONS_RESPONSE,
646 mPublisherService.getSubscriptions()));
647 }
648
649 private void setPropertyValue(VehiclePropValue vehicleProp) throws RemoteException {
650 int messageType = vehicleProp.value.int32Values.get(
651 VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE);
652
653 if (!mIsSupported) {
654 Log.w(TAG, "HAL unsupported while attempting to send "
655 + VmsMessageType.toString(messageType));
656 return;
657 }
658
659 try {
660 mVehicleHal.set(vehicleProp);
661 } catch (PropertyTimeoutException e) {
662 Log.e(CarLog.TAG_PROPERTY,
663 "set, property not ready 0x" + toHexString(HAL_PROPERTY_ID));
664 throw new RemoteException(
665 "Timeout while sending " + VmsMessageType.toString(messageType));
666 }
667 }
668
669 /**
Mark Tabry9abdf102019-04-26 13:36:22 -0700670 * Creates a SESSION_START type {@link VehiclePropValue}.
671 *
672 * SESSION_START message format:
673 * <ul>
674 * <li>Message type
675 * <li>Core ID
676 * <li>Client ID
677 * </ul>
678 */
679 private static VehiclePropValue createStartSessionMessage(int coreId, int clientId) {
680 // Message type + layer
681 VehiclePropValue vehicleProp = createVmsMessage(VmsMessageType.START_SESSION);
682 List<Integer> message = vehicleProp.value.int32Values;
683
684 // Core ID
685 message.add(coreId);
686
687 // Client ID
688 message.add(clientId);
689
690 return vehicleProp;
691 }
692
693 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800694 * Creates a DATA type {@link VehiclePropValue}.
695 *
696 * DATA message format:
697 * <ul>
698 * <li>Message type
699 * <li>Layer ID
700 * <li>Layer subtype
701 * <li>Layer version
702 * <li>Publisher ID
703 * <li>Payload
704 * </ul>
705 *
706 * @param layer Layer for which message was published.
707 */
Mark Tabry9abdf102019-04-26 13:36:22 -0700708 private static VehiclePropValue createDataMessage(VmsLayer layer, byte[] payload) {
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800709 // Message type + layer
Mark Tabry9abdf102019-04-26 13:36:22 -0700710 VehiclePropValue vehicleProp = createVmsMessage(VmsMessageType.DATA);
711 appendLayer(vehicleProp.value.int32Values, layer);
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800712 List<Integer> message = vehicleProp.value.int32Values;
713
714 // Publisher ID
Mark Tabry9abdf102019-04-26 13:36:22 -0700715 // TODO(b/124130256): Set publisher ID of data message
716 message.add(0);
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800717
718 // Payload
Mark Tabry786dacd2019-02-26 14:23:48 -0800719 appendBytes(vehicleProp.value.bytes, payload);
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800720 return vehicleProp;
721 }
722
723 /**
724 * Creates a SUBSCRIPTION_CHANGE or SUBSCRIPTION_RESPONSE type {@link VehiclePropValue}.
725 *
726 * Both message types have the same format:
727 * <ul>
728 * <li>Message type
729 * <li>Sequence number
730 * <li>Number of layers
731 * <li>Number of associated layers
732 * <li>Layers (x number of layers) (see {@link #appendLayer})
733 * <li>Associated layers (x number of associated layers) (see {@link #appendAssociatedLayer})
734 * </ul>
735 *
736 * @param messageType Either SUBSCRIPTIONS_CHANGE or SUBSCRIPTIONS_RESPONSE.
737 * @param subscriptionState The subscription state to encode in the message.
738 */
739 private static VehiclePropValue createSubscriptionStateMessage(int messageType,
740 VmsSubscriptionState subscriptionState) {
741 // Message type
742 VehiclePropValue vehicleProp = createVmsMessage(messageType);
743 List<Integer> message = vehicleProp.value.int32Values;
744
745 // Sequence number
746 message.add(subscriptionState.getSequenceNumber());
747
748 Set<VmsLayer> layers = subscriptionState.getLayers();
749 Set<VmsAssociatedLayer> associatedLayers = subscriptionState.getAssociatedLayers();
750
751 // Number of layers
752 message.add(layers.size());
753 // Number of associated layers
754 message.add(associatedLayers.size());
755
756 // Layers
757 for (VmsLayer layer : layers) {
758 appendLayer(message, layer);
759 }
760
761 // Associated layers
762 for (VmsAssociatedLayer layer : associatedLayers) {
763 appendAssociatedLayer(message, layer);
764 }
765 return vehicleProp;
766 }
767
768 /**
769 * Creates an AVAILABILITY_CHANGE or AVAILABILITY_RESPONSE type {@link VehiclePropValue}.
770 *
771 * Both message types have the same format:
772 * <ul>
773 * <li>Message type
774 * <li>Sequence number.
775 * <li>Number of associated layers.
776 * <li>Associated layers (x number of associated layers) (see {@link #appendAssociatedLayer})
777 * </ul>
778 *
779 * @param messageType Either AVAILABILITY_CHANGE or AVAILABILITY_RESPONSE.
780 * @param availableLayers The available layers to encode in the message.
781 */
782 private static VehiclePropValue createAvailableLayersMessage(int messageType,
783 VmsAvailableLayers availableLayers) {
784 // Message type
785 VehiclePropValue vehicleProp = createVmsMessage(messageType);
786 List<Integer> message = vehicleProp.value.int32Values;
787
788 // Sequence number
789 message.add(availableLayers.getSequence());
790
791 // Number of associated layers
792 message.add(availableLayers.getAssociatedLayers().size());
793
794 // Associated layers
795 for (VmsAssociatedLayer layer : availableLayers.getAssociatedLayers()) {
796 appendAssociatedLayer(message, layer);
797 }
798 return vehicleProp;
799 }
800
801 /**
802 * Creates a base {@link VehiclePropValue} of the requested message type, with no message fields
803 * populated.
804 *
805 * @param messageType Type of message, from {@link VmsMessageType}
806 */
807 private static VehiclePropValue createVmsMessage(int messageType) {
Antonio Cortes734010a2017-01-19 20:09:22 -0800808 VehiclePropValue vehicleProp = new VehiclePropValue();
809 vehicleProp.prop = HAL_PROPERTY_ID;
Steve Paik419f5ef2018-06-04 14:53:47 -0700810 vehicleProp.areaId = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL;
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800811 vehicleProp.value.int32Values.add(messageType);
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700812 return vehicleProp;
813 }
814
Asaf Rosenfeld43900532017-06-16 11:16:55 -0700815 /**
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800816 * Appends a {@link VmsLayer} to an encoded VMS message.
817 *
818 * Layer format:
819 * <ul>
820 * <li>Layer ID
821 * <li>Layer subtype
822 * <li>Layer version
823 * </ul>
824 *
825 * @param message Message to append to.
826 * @param layer Layer to append.
827 */
828 private static void appendLayer(List<Integer> message, VmsLayer layer) {
829 message.add(layer.getType());
830 message.add(layer.getSubtype());
831 message.add(layer.getVersion());
Antonio Cortes734010a2017-01-19 20:09:22 -0800832 }
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700833
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800834 /**
835 * Appends a {@link VmsAssociatedLayer} to an encoded VMS message.
836 *
837 * AssociatedLayer format:
838 * <ul>
839 * <li>Layer ID
840 * <li>Layer subtype
841 * <li>Layer version
842 * <li>Number of publishers
843 * <li>Publisher ID (x number of publishers)
844 * </ul>
845 *
846 * @param message Message to append to.
847 * @param layer Layer to append.
848 */
849 private static void appendAssociatedLayer(List<Integer> message, VmsAssociatedLayer layer) {
850 message.add(layer.getVmsLayer().getType());
851 message.add(layer.getVmsLayer().getSubtype());
852 message.add(layer.getVmsLayer().getVersion());
853 message.add(layer.getPublisherIds().size());
Mark Tabry9abdf102019-04-26 13:36:22 -0700854 message.addAll(layer.getPublisherIds());
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700855 }
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800856
Mark Tabry786dacd2019-02-26 14:23:48 -0800857 private static void appendBytes(ArrayList<Byte> dst, byte[] src) {
858 dst.ensureCapacity(src.length);
859 for (byte b : src) {
860 dst.add(b);
861 }
862 }
863
Mark Tabry76cfaaa2019-02-01 14:28:30 -0800864 private static VmsLayer parseVmsLayerFromMessage(List<Integer> message) {
865 return parseVmsLayerAtIndex(message,
866 VmsMessageWithLayerIntegerValuesIndex.LAYER_TYPE);
867 }
868
869 private static VmsLayer parseVmsLayerAtIndex(List<Integer> message, int index) {
870 List<Integer> layerValues = message.subList(index, index + NUM_INTEGERS_IN_VMS_LAYER);
871 return new VmsLayer(layerValues.get(0), layerValues.get(1), layerValues.get(2));
872 }
873
874 private static int parsePublisherIdFromMessage(List<Integer> message) {
875 return message.get(VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.PUBLISHER_ID);
876 }
Asaf Rosenfeldeb541d42017-03-31 14:32:10 -0700877}