• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.car.hal;
17 
18 import static com.android.car.CarServiceUtils.toByteArray;
19 import static com.android.car.CarServiceUtils.toIntArray;
20 
21 import static org.junit.Assert.assertArrayEquals;
22 import static org.junit.Assert.assertEquals;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.Mockito.doThrow;
26 import static org.mockito.Mockito.reset;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.verifyNoMoreInteractions;
29 import static org.mockito.Mockito.when;
30 
31 import android.car.hardware.property.VehicleHalStatusCode;
32 import android.car.test.util.TemporaryFile;
33 import android.car.vms.VmsAssociatedLayer;
34 import android.car.vms.VmsAvailableLayers;
35 import android.car.vms.VmsClient;
36 import android.car.vms.VmsClientManager.VmsClientCallback;
37 import android.car.vms.VmsLayer;
38 import android.car.vms.VmsLayerDependency;
39 import android.car.vms.VmsSubscriptionState;
40 import android.content.Context;
41 import android.content.res.Resources;
42 import android.hardware.automotive.vehicle.VehiclePropConfig;
43 import android.hardware.automotive.vehicle.VehicleProperty;
44 import android.hardware.automotive.vehicle.VehiclePropertyGroup;
45 import android.hardware.automotive.vehicle.VmsMessageType;
46 import android.os.Handler;
47 import android.os.ServiceSpecificException;
48 
49 import com.android.car.R;
50 
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.InOrder;
55 import org.mockito.Mock;
56 import org.mockito.Mockito;
57 import org.mockito.junit.MockitoJUnitRunner;
58 
59 import java.io.FileDescriptor;
60 import java.io.FileInputStream;
61 import java.io.FileOutputStream;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.HashSet;
66 import java.util.LinkedHashSet;
67 import java.util.List;
68 import java.util.Set;
69 import java.util.concurrent.CountDownLatch;
70 import java.util.concurrent.TimeUnit;
71 
72 @RunWith(MockitoJUnitRunner.class)
73 public class VmsHalServiceTest {
74     private static final int LAYER_TYPE = 1;
75     private static final int LAYER_SUBTYPE = 2;
76     private static final int LAYER_VERSION = 3;
77     private static final VmsLayer LAYER = new VmsLayer(LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION);
78     private static final int PUBLISHER_ID = 12345;
79     private static final byte[] PAYLOAD = new byte[]{1, 2, 3, 4};
80     private static final List<Byte> PAYLOAD_AS_LIST = Arrays.asList(new Byte[]{1, 2, 3, 4});
81     private static final int CORE_ID = 54321;
82     private static final int CLIENT_ID = 98765;
83 
84     private final HalPropValueBuilder mPropValueBuilder = new HalPropValueBuilder(/*isAidl=*/true);
85 
86     @Mock
87     private Context mContext;
88     @Mock
89     private Resources mResources;
90     @Mock
91     private VehicleHal mVehicleHal;
92     @Mock
93     private VmsClient mVmsClient;
94 
95     private VmsHalService mHalService;
96     private VmsClientCallback mEventCallback;
97     private int mVmsInitCount;
98 
99     @Before
setUp()100     public void setUp() throws Exception {
101         initHalService(true);
102     }
103 
initHalService(boolean propagatePropertyException)104     private void initHalService(boolean propagatePropertyException) throws Exception {
105         mVmsInitCount = 0;
106         when(mContext.getResources()).thenReturn(mResources);
107         when(mVehicleHal.getHalPropValueBuilder()).thenReturn(mPropValueBuilder);
108         mHalService = new VmsHalService(mContext, mVehicleHal, () -> (long) CORE_ID,
109                 this::initVmsClient, propagatePropertyException);
110 
111         VehiclePropConfig propConfig = new VehiclePropConfig();
112         propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
113         HalPropConfig halPropConfig = new AidlHalPropConfig(propConfig);
114         mHalService.takeProperties(Collections.singleton(halPropConfig));
115 
116         when(mVmsClient.getAvailableLayers()).thenReturn(
117                 new VmsAvailableLayers(Collections.emptySet(), 0));
118         mHalService.init();
119         waitForHandlerCompletion();
120 
121         // Verify START_SESSION message was sent
122         InOrder initOrder = Mockito.inOrder(mVehicleHal);
123         initOrder.verify(mVehicleHal).subscribePropertySafe(mHalService,
124                 VehicleProperty.VEHICLE_MAP_SERVICE);
125         initOrder.verify(mVehicleHal).set(createHalMessage(
126                 VmsMessageType.START_SESSION, // Message type
127                 CORE_ID,                      // Core ID
128                 -1));                          // Client ID (unknown)
129 
130         // Verify no more interections until handshake received
131         initOrder.verifyNoMoreInteractions();
132 
133         // Send START_SESSION response from client
134         sendHalMessage(createHalMessage(
135                 VmsMessageType.START_SESSION,  // Message type
136                 CORE_ID,                       // Core ID
137                 CLIENT_ID                      // Client ID
138         ));
139         waitForHandlerCompletion();
140 
141         initOrder.verify(mVehicleHal).set(createHalMessage(
142                 VmsMessageType.AVAILABILITY_CHANGE, // Message type
143                 0,                                  // Sequence number
144                 0));                                // # of associated layers
145 
146 
147         waitForHandlerCompletion();
148         initOrder.verifyNoMoreInteractions();
149         assertEquals(1, mVmsInitCount);
150         reset(mVmsClient, mVehicleHal);
151     }
152 
initVmsClient(Handler handler, VmsClientCallback callback)153     private VmsClient initVmsClient(Handler handler, VmsClientCallback callback) {
154         mEventCallback = callback;
155         mVmsInitCount++;
156         return mVmsClient;
157     }
158 
159     @Test
testCoreId_IntegerOverflow()160     public void testCoreId_IntegerOverflow() throws Exception {
161         when(mVehicleHal.getHalPropValueBuilder()).thenReturn(mPropValueBuilder);
162         mHalService = new VmsHalService(mContext, mVehicleHal,
163                 () -> (long) Integer.MAX_VALUE + CORE_ID, this::initVmsClient, true);
164 
165         VehiclePropConfig propConfig = new VehiclePropConfig();
166         propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
167         HalPropConfig halPropConfig = new AidlHalPropConfig(propConfig);
168         mHalService.takeProperties(Collections.singleton(halPropConfig));
169 
170         when(mVmsClient.getAvailableLayers()).thenReturn(
171                 new VmsAvailableLayers(Collections.emptySet(), 0));
172         mHalService.init();
173         waitForHandlerCompletion();
174 
175         verify(mVehicleHal).set(createHalMessage(
176                 VmsMessageType.START_SESSION, // Message type
177                 CORE_ID,                      // Core ID
178                 -1));                          // Client ID (unknown)
179     }
180 
181     @Test
testTakeSupportedProperties()182     public void testTakeSupportedProperties() {
183         VehiclePropConfig vmsPropConfig = new VehiclePropConfig();
184         vmsPropConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
185         HalPropConfig vmsHalPropConfig = new AidlHalPropConfig(vmsPropConfig);
186 
187         VehiclePropConfig otherPropConfig = new VehiclePropConfig();
188         otherPropConfig.prop = VehicleProperty.CURRENT_GEAR;
189         HalPropConfig otherHalPropConfig = new AidlHalPropConfig(otherPropConfig);
190 
191         mHalService.takeProperties(Arrays.asList(vmsHalPropConfig, otherHalPropConfig));
192     }
193 
194     /**
195      * DATA message format:
196      * <ul>
197      * <li>Message type
198      * <li>Layer ID
199      * <li>Layer subtype
200      * <li>Layer version
201      * <li>Publisher ID
202      * <li>Payload
203      * </ul>
204      */
205     @Test
testHandleDataEvent()206     public void testHandleDataEvent() {
207         HalPropValue message = createHalMessage(
208                 toByteArray(PAYLOAD_AS_LIST),
209                 VmsMessageType.DATA,                       // Message type
210                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
211                 PUBLISHER_ID                               // PublisherId
212         );
213 
214         sendHalMessage(message);
215         verify(mVmsClient).publishPacket(PUBLISHER_ID, LAYER, PAYLOAD);
216     }
217 
218     @Test
testHandleInvalidEvent()219     public void testHandleInvalidEvent() {
220         // Invalid message with no message type.
221         HalPropValue message =  mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
222                 /*areaId=*/0, "1234");
223 
224         sendHalMessage(message);
225         verify(mVmsClient, Mockito.never()).publishPacket(
226                 Mockito.anyInt(), Mockito.any(), Mockito.any());
227 
228         // Incomplete VmsLayer.
229         ArrayList<Integer> int32Values =
230                 new ArrayList<Integer>(
231                         Arrays.asList(VmsMessageType.DATA, LAYER_TYPE, LAYER_SUBTYPE));
232         message = mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
233                 /*areaId=*/0, /*timestamp=*/0, /*status=*/0,
234                 /*int32Values=*/toIntArray(int32Values), /*floatValues=*/new float[0],
235                 /*int64Values=*/new long[0], "1234", /*byteValues=*/new byte[0]);
236 
237         sendHalMessage(message);
238         verify(mVmsClient, Mockito.never()).publishPacket(
239                 Mockito.anyInt(), Mockito.any(), Mockito.any());
240 
241         // No publisher ID.
242         int32Values.add(LAYER_VERSION);
243         message = mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
244                 /*areaId=*/0, /*timestamp=*/0, /*status=*/0,
245                 /*int32Values=*/toIntArray(int32Values), /*floatValues=*/new float[0],
246                 /*int64Values=*/new long[0], "1234", /*byteValues=*/new byte[0]);
247 
248         sendHalMessage(message);
249         verify(mVmsClient, Mockito.never()).publishPacket(
250                 Mockito.anyInt(), Mockito.any(), Mockito.any());
251 
252         // No payload.
253         int32Values.add(PUBLISHER_ID);
254         message = mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
255                 /*areaId=*/0, /*timestamp=*/0, /*status=*/0,
256                 /*int32Values=*/toIntArray(int32Values), /*floatValues=*/new float[0],
257                 /*int64Values=*/new long[0], "1234", /*byteValues=*/new byte[0]);
258 
259         sendHalMessage(message);
260         verify(mVmsClient, Mockito.never()).publishPacket(
261                 Mockito.anyInt(), Mockito.any(), Mockito.any());
262 
263         // No payload for publisherID event.
264         int32Values.set(0, VmsMessageType.PUBLISHER_ID_REQUEST);
265         message = mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
266                 /*areaId=*/0, /*timestamp=*/0, /*status=*/0,
267                 /*int32Values=*/toIntArray(int32Values), /*floatValues=*/new float[0],
268                 /*int64Values=*/new long[0], "1234", /*byteValues=*/new byte[0]);
269 
270         sendHalMessage(message);
271         verify(mVmsClient, Mockito.never()).publishPacket(
272                 Mockito.anyInt(), Mockito.any(), Mockito.any());
273     }
274 
275     @Test
testOnPacketReceivedEvent()276     public void testOnPacketReceivedEvent() throws Exception {
277         HalPropValue message = createHalMessage(
278                 toByteArray(PAYLOAD_AS_LIST),
279                 VmsMessageType.DATA,                       // Message type
280                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
281                 PUBLISHER_ID                               // PublisherId
282         );
283 
284         mEventCallback.onPacketReceived(PUBLISHER_ID, LAYER, PAYLOAD);
285         verify(mVehicleHal).set(message);
286     }
287 
288     /**
289      * SUBSCRIBE message format:
290      * <ul>
291      * <li>Message type
292      * <li>Layer ID
293      * <li>Layer subtype
294      * <li>Layer version
295      * </ul>
296      */
297     @Test
testHandleSubscribeEvent()298     public void testHandleSubscribeEvent() {
299         HalPropValue message = createHalMessage(
300                 VmsMessageType.SUBSCRIBE,                 // Message type
301                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION  // VmsLayer
302         );
303 
304         sendHalMessage(message);
305         verify(mVmsClient).setSubscriptions(asSet(new VmsAssociatedLayer(LAYER, asSet())));
306     }
307 
308     /**
309      * SUBSCRIBE_TO_PUBLISHER message format:
310      * <ul>
311      * <li>Message type
312      * <li>Layer ID
313      * <li>Layer subtype
314      * <li>Layer version
315      * <li>Publisher ID
316      * </ul>
317      */
318     @Test
testHandleSubscribeToPublisherEvent()319     public void testHandleSubscribeToPublisherEvent() {
320         HalPropValue message = createHalMessage(
321                 VmsMessageType.SUBSCRIBE_TO_PUBLISHER,     // Message type
322                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
323                 PUBLISHER_ID                               // PublisherId
324         );
325 
326         sendHalMessage(message);
327         verify(mVmsClient).setSubscriptions(asSet(
328                 new VmsAssociatedLayer(LAYER, asSet(PUBLISHER_ID))));
329     }
330 
331     /**
332      * UNSUBSCRIBE message format:
333      * <ul>
334      * <li>Message type
335      * <li>Layer ID
336      * <li>Layer subtype
337      * <li>Layer version
338      * </ul>
339      */
340     @Test
testHandleUnsubscribeEvent()341     public void testHandleUnsubscribeEvent() {
342         testHandleSubscribeEvent();
343 
344         HalPropValue message = createHalMessage(
345                 VmsMessageType.UNSUBSCRIBE,               // Message type
346                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION  // VmsLayer
347         );
348 
349         sendHalMessage(message);
350         verify(mVmsClient).setSubscriptions(asSet());
351     }
352 
353     /**
354      * UNSUBSCRIBE_TO_PUBLISHER message format:
355      * <ul>
356      * <li>Message type
357      * <li>Layer ID
358      * <li>Layer subtype
359      * <li>Layer version
360      * <li>Publisher ID
361      * </ul>
362      */
363     @Test
testHandleUnsubscribeFromPublisherEvent()364     public void testHandleUnsubscribeFromPublisherEvent() {
365         testHandleSubscribeToPublisherEvent();
366 
367         HalPropValue message = createHalMessage(
368                 VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER,   // Message type
369                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
370                 PUBLISHER_ID                               // PublisherId
371         );
372 
373         sendHalMessage(message);
374         verify(mVmsClient).setSubscriptions(asSet());
375     }
376 
377     /**
378      * PUBLISHER_ID_REQUEST message format:
379      * <ul>
380      * <li>Message type
381      * <li>Publisher info (bytes)
382      * </ul>
383      *
384      * PUBLISHER_ID_RESPONSE message format:
385      * <ul>
386      * <li>Message type
387      * <li>Publisher ID
388      * </ul>
389      */
390     @Test
testHandlePublisherIdRequestEvent()391     public void testHandlePublisherIdRequestEvent() throws Exception {
392         HalPropValue request = createHalMessage(
393                 toByteArray(PAYLOAD_AS_LIST),
394                 VmsMessageType.PUBLISHER_ID_REQUEST  // Message type
395         );
396 
397         when(mVmsClient.registerProvider(PAYLOAD)).thenReturn(PUBLISHER_ID);
398 
399         HalPropValue response = createHalMessage(
400                 VmsMessageType.PUBLISHER_ID_RESPONSE,  // Message type
401                 PUBLISHER_ID                           // Publisher ID
402         );
403 
404         sendHalMessage(request);
405         verify(mVehicleHal).set(response);
406     }
407 
408     /**
409      * PUBLISHER_INFORMATION_REQUEST message format:
410      * <ul>
411      * <li>Message type
412      * <li>Publisher ID
413      * </ul>
414      *
415      * PUBLISHER_INFORMATION_RESPONSE message format:
416      * <ul>
417      * <li>Message type
418      * <li>Publisher info (bytes)
419      * </ul>
420      */
421     @Test
testHandlePublisherInformationRequestEvent()422     public void testHandlePublisherInformationRequestEvent() throws Exception {
423         HalPropValue request = createHalMessage(
424                 VmsMessageType.PUBLISHER_INFORMATION_REQUEST,  // Message type
425                 PUBLISHER_ID                                   // Publisher ID
426         );
427 
428         when(mVmsClient.getProviderDescription(PUBLISHER_ID)).thenReturn(PAYLOAD);
429 
430         HalPropValue response = createHalMessage(
431                 toByteArray(PAYLOAD_AS_LIST),
432                 VmsMessageType.PUBLISHER_INFORMATION_RESPONSE  // Message type
433         );
434 
435         sendHalMessage(request);
436         verify(mVehicleHal).set(response);
437     }
438 
439     /**
440      * OFFERING message format:
441      * <ul>
442      * <li>Message type
443      * <li>Publisher ID
444      * <li>Number of offerings.
445      * <li>Offerings (x number of offerings)
446      * <ul>
447      * <li>Layer ID
448      * <li>Layer subtype
449      * <li>Layer version
450      * <li>Number of layer dependencies.
451      * <li>Layer dependencies (x number of layer dependencies)
452      * <ul>
453      * <li>Layer ID
454      * <li>Layer subtype
455      * <li>Layer version
456      * </ul>
457      * </ul>
458      * </ul>
459      */
460     @Test
testHandleOfferingEvent_ZeroOfferings()461     public void testHandleOfferingEvent_ZeroOfferings() {
462         HalPropValue message = createHalMessage(
463                 VmsMessageType.OFFERING,  // Message type
464                 PUBLISHER_ID,             // PublisherId
465                 0                         // # of offerings
466         );
467 
468         sendHalMessage(message);
469         verify(mVmsClient).setProviderOfferings(PUBLISHER_ID, asSet());
470     }
471 
472     @Test
testHandleOfferingEvent_LayerOnly()473     public void testHandleOfferingEvent_LayerOnly() {
474         HalPropValue message = createHalMessage(
475                 VmsMessageType.OFFERING,                   // Message type
476                 PUBLISHER_ID,                              // PublisherId
477                 1,                                         // # of offerings
478                 // Offered layer
479                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,
480                 0                                          // # of dependencies
481         );
482 
483         sendHalMessage(message);
484         verify(mVmsClient).setProviderOfferings(
485                 PUBLISHER_ID,
486                 asSet(new VmsLayerDependency(LAYER)));
487     }
488 
489     @Test
testHandleOfferingEvent_LayerAndDependency()490     public void testHandleOfferingEvent_LayerAndDependency() {
491         HalPropValue message = createHalMessage(
492                 VmsMessageType.OFFERING,                   // Message type
493                 PUBLISHER_ID,                              // PublisherId
494                 1,                                         // # of offerings
495                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
496                 1,                                         // # of dependencies
497                 4, 5, 6                                    // Dependency layer
498         );
499 
500         sendHalMessage(message);
501         verify(mVmsClient).setProviderOfferings(
502                 PUBLISHER_ID,
503                 asSet(
504                         new VmsLayerDependency(LAYER, Collections.singleton(
505                                 new VmsLayer(4, 5, 6)))));
506     }
507 
508     @Test
testHandleOfferingEvent_MultipleLayersAndDependencies()509     public void testHandleOfferingEvent_MultipleLayersAndDependencies() {
510         HalPropValue message = createHalMessage(
511                 VmsMessageType.OFFERING,                   // Message type
512                 PUBLISHER_ID,                              // PublisherId
513                 3,                                         // # of offerings
514                 // Offered layer #1
515                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
516                 2,                                         // # of dependencies
517                 4, 5, 6,                                   // Dependency layer
518                 7, 8, 9,                                   // Dependency layer
519                 // Offered layer #2
520                 3, 2, 1,                                   // Layer
521                 0,                                         // # of dependencies
522                 // Offered layer #3
523                 6, 5, 4,                                   // Layer
524                 1,                                         // # of dependencies
525                 7, 8, 9                                    // Dependency layer
526         );
527 
528         sendHalMessage(message);
529         verify(mVmsClient).setProviderOfferings(
530                 PUBLISHER_ID,
531                 asSet(
532                         new VmsLayerDependency(LAYER, new LinkedHashSet<>(Arrays.asList(
533                                 new VmsLayer(4, 5, 6),
534                                 new VmsLayer(7, 8, 9)
535                         ))),
536                         new VmsLayerDependency(new VmsLayer(3, 2, 1), Collections.emptySet()),
537                         new VmsLayerDependency(new VmsLayer(6, 5, 4), Collections.singleton(
538                                 new VmsLayer(7, 8, 9)
539                         ))));
540     }
541 
542     /**
543      * AVAILABILITY_REQUEST message format:
544      * <ul>
545      * <li>Message type
546      * </ul>
547      *
548      * AVAILABILITY_RESPONSE message format:
549      * <ul>
550      * <li>Message type
551      * <li>Sequence number.
552      * <li>Number of associated layers.
553      * <li>Associated layers (x number of associated layers)
554      * <ul>
555      * <li>Layer ID
556      * <li>Layer subtype
557      * <li>Layer version
558      * <li>Number of publishers
559      * <li>Publisher ID (x number of publishers)
560      * </ul>
561      * </ul>
562      */
563     @Test
testHandleAvailabilityRequestEvent_ZeroLayers()564     public void testHandleAvailabilityRequestEvent_ZeroLayers() throws Exception {
565         HalPropValue request = createHalMessage(
566                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
567         );
568 
569         when(mVmsClient.getAvailableLayers()).thenReturn(
570                 new VmsAvailableLayers(Collections.emptySet(), 123));
571 
572         HalPropValue response = createHalMessage(
573                 VmsMessageType.AVAILABILITY_RESPONSE,  // Message type
574                 123,                                   // Sequence number
575                 0                                      // # of associated layers
576         );
577 
578         sendHalMessage(request);
579         verify(mVehicleHal).set(response);
580     }
581 
582     @Test
testHandleAvailabilityRequestEvent_OneLayer()583     public void testHandleAvailabilityRequestEvent_OneLayer() throws Exception {
584         HalPropValue request = createHalMessage(
585                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
586         );
587 
588         when(mVmsClient.getAvailableLayers()).thenReturn(
589                 new VmsAvailableLayers(Collections.singleton(
590                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
591 
592         HalPropValue response = createHalMessage(
593                 VmsMessageType.AVAILABILITY_RESPONSE,      // Message type
594                 123,                                       // Sequence number
595                 1,                                         // # of associated layers
596                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
597                 1,                                         // # of publisher IDs
598                 PUBLISHER_ID                               // Publisher ID
599         );
600 
601         sendHalMessage(request);
602         verify(mVehicleHal).set(response);
603     }
604 
605 
606     @Test
testHandleAvailabilityRequestEvent_MultipleLayers()607     public void testHandleAvailabilityRequestEvent_MultipleLayers() throws Exception {
608         HalPropValue request = createHalMessage(
609                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
610         );
611 
612         when(mVmsClient.getAvailableLayers()).thenReturn(
613                 new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
614                         new VmsAssociatedLayer(LAYER,
615                                 new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
616                         new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
617                                 Collections.emptySet()),
618                         new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
619                                 Collections.singleton(99999)))),
620                         123));
621 
622         HalPropValue response = createHalMessage(
623                 VmsMessageType.AVAILABILITY_RESPONSE,      // Message type
624                 123,                                       // Sequence number
625                 3,                                         // # of associated layers
626                 // Associated layer #1
627                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
628                 2,                                         // # of publisher IDs
629                 PUBLISHER_ID,                              // Publisher ID
630                 54321,                                     // Publisher ID #2
631                 // Associated layer #2
632                 3, 2, 1,                                   // Layer
633                 0,                                         // # of publisher IDs
634                 // Associated layer #3
635                 6, 5, 4,                                   // Layer
636                 1,                                         // # of publisher IDs
637                 99999                                      // Publisher ID
638 
639         );
640 
641         sendHalMessage(request);
642         verify(mVehicleHal).set(response);
643     }
644 
645     /**
646      * START_SESSION message format:
647      * <ul>
648      * <li>Message type
649      * <li>Core ID
650      * <li>Client ID
651      * </ul>
652      */
653     @Test
testHandleStartSessionEvent()654     public void testHandleStartSessionEvent() throws Exception {
655         when(mVmsClient.getAvailableLayers()).thenReturn(
656                 new VmsAvailableLayers(Collections.emptySet(), 5));
657 
658         HalPropValue request = createHalMessage(
659                 VmsMessageType.START_SESSION,  // Message type
660                 -1,                            // Core ID (unknown)
661                 CLIENT_ID                      // Client ID
662         );
663 
664         HalPropValue response = createHalMessage(
665                 VmsMessageType.START_SESSION,  // Message type
666                 CORE_ID,                               // Core ID
667                 CLIENT_ID                              // Client ID
668         );
669 
670         sendHalMessage(request);
671 
672         InOrder inOrder = Mockito.inOrder(mVehicleHal, mVmsClient);
673         inOrder.verify(mVmsClient).unregister();
674         inOrder.verify(mVehicleHal).set(response);
675         assertEquals(2, mVmsInitCount);
676 
677         waitForHandlerCompletion();
678         inOrder.verify(mVehicleHal).set(createHalMessage(
679                 VmsMessageType.AVAILABILITY_CHANGE, // Message type
680                 5,                                  // Sequence number
681                 0));                                // # of associated layers
682 
683     }
684 
685     /**
686      * AVAILABILITY_CHANGE message format:
687      * <ul>
688      * <li>Message type
689      * <li>Sequence number.
690      * <li>Number of associated layers.
691      * <li>Associated layers (x number of associated layers)
692      * <ul>
693      * <li>Layer ID
694      * <li>Layer subtype
695      * <li>Layer version
696      * <li>Number of publishers
697      * <li>Publisher ID (x number of publishers)
698      * </ul>
699      * </ul>
700      */
701     @Test
testOnLayersAvailabilityChanged_ZeroLayers()702     public void testOnLayersAvailabilityChanged_ZeroLayers() throws Exception {
703         mEventCallback.onLayerAvailabilityChanged(
704                 new VmsAvailableLayers(Collections.emptySet(), 123));
705 
706         HalPropValue message = createHalMessage(
707                 VmsMessageType.AVAILABILITY_CHANGE,    // Message type
708                 123,                                   // Sequence number
709                 0                                      // # of associated layers
710         );
711 
712         waitForHandlerCompletion();
713         verify(mVehicleHal).set(message);
714     }
715 
716     @Test
testOnLayersAvailabilityChanged_OneLayer()717     public void testOnLayersAvailabilityChanged_OneLayer() throws Exception {
718         mEventCallback.onLayerAvailabilityChanged(
719                 new VmsAvailableLayers(Collections.singleton(
720                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
721 
722         HalPropValue message = createHalMessage(
723                 VmsMessageType.AVAILABILITY_CHANGE,        // Message type
724                 123,                                       // Sequence number
725                 1,                                         // # of associated layers
726                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
727                 1,                                         // # of publisher IDs
728                 PUBLISHER_ID                               // Publisher ID
729         );
730 
731         waitForHandlerCompletion();
732         verify(mVehicleHal).set(message);
733     }
734 
735 
736     @Test
testOnLayersAvailabilityChanged_MultipleLayers()737     public void testOnLayersAvailabilityChanged_MultipleLayers() throws Exception {
738         mEventCallback.onLayerAvailabilityChanged(
739                 new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
740                         new VmsAssociatedLayer(LAYER,
741                                 new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
742                         new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
743                                 Collections.emptySet()),
744                         new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
745                                 Collections.singleton(99999)))),
746                         123));
747 
748         HalPropValue message = createHalMessage(
749                 VmsMessageType.AVAILABILITY_CHANGE,      // Message type
750                 123,                                       // Sequence number
751                 3,                                         // # of associated layers
752                 // Associated layer #1
753                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
754                 2,                                         // # of publisher IDs
755                 PUBLISHER_ID,                              // Publisher ID
756                 54321,                                     // Publisher ID #2
757                 // Associated layer #2
758                 3, 2, 1,                                   // Layer
759                 0,                                         // # of publisher IDs
760                 // Associated layer #3
761                 6, 5, 4,                                   // Layer
762                 1,                                         // # of publisher IDs
763                 99999                                      // Publisher ID
764 
765         );
766 
767         waitForHandlerCompletion();
768         verify(mVehicleHal).set(message);
769     }
770 
771     /**
772      * SUBSCRIPTION_REQUEST message format:
773      * <ul>
774      * <li>Message type
775      * </ul>
776      *
777      * SUBSCRIPTION_RESPONSE message format:
778      * <ul>
779      * <li>Message type
780      * <li>Sequence number
781      * <li>Number of layers
782      * <li>Number of associated layers
783      * <li>Layers (x number of layers)
784      * <ul>
785      * <li>Layer ID
786      * <li>Layer subtype
787      * <li>Layer version
788      * </ul>
789      * <li>Associated layers (x number of associated layers)
790      * <ul>
791      * <li>Layer ID
792      * <li>Layer subtype
793      * <li>Layer version
794      * <li>Number of publishers
795      * <li>Publisher ID (x number of publishers)
796      * </ul>
797      * </ul>
798      */
799     @Test
testHandleSubscriptionsRequestEvent_ZeroLayers()800     public void testHandleSubscriptionsRequestEvent_ZeroLayers() throws Exception {
801         HalPropValue request = createHalMessage(
802                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
803         );
804 
805         when(mVmsClient.getSubscriptionState()).thenReturn(
806                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
807 
808         HalPropValue response = createHalMessage(
809                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,  // Message type
810                 123,                                    // Sequence number
811                 0,                                      // # of layers
812                 0                                       // # of associated layers
813         );
814 
815         sendHalMessage(request);
816         verify(mVehicleHal).set(response);
817     }
818 
819     @Test
testHandleSubscriptionsRequestEvent_OneLayer_ZeroAssociatedLayers()820     public void testHandleSubscriptionsRequestEvent_OneLayer_ZeroAssociatedLayers()
821             throws Exception {
822         HalPropValue request = createHalMessage(
823                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
824         );
825 
826         when(mVmsClient.getSubscriptionState()).thenReturn(
827                 new VmsSubscriptionState(123, Collections.singleton(LAYER),
828                         Collections.emptySet()));
829 
830         HalPropValue response = createHalMessage(
831                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
832                 123,                                       // Sequence number
833                 1,                                         // # of layers
834                 0,                                         // # of associated layers
835                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION   // Layer
836         );
837 
838         sendHalMessage(request);
839         verify(mVehicleHal).set(response);
840     }
841 
842     @Test
testHandleSubscriptionsRequestEvent_ZeroLayers_OneAssociatedLayer()843     public void testHandleSubscriptionsRequestEvent_ZeroLayers_OneAssociatedLayer()
844             throws Exception {
845         HalPropValue request = createHalMessage(
846                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
847         );
848 
849         when(mVmsClient.getSubscriptionState()).thenReturn(
850                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
851                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
852 
853         HalPropValue response = createHalMessage(
854                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
855                 123,                                       // Sequence number
856                 0,                                         // # of layers
857                 1,                                         // # of associated layers
858                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
859                 1,                                         // # of publisher IDs
860                 PUBLISHER_ID                               // Publisher ID
861         );
862 
863         sendHalMessage(request);
864         verify(mVehicleHal).set(response);
865     }
866 
867     @Test
testHandleSubscriptionsRequestEvent_MultipleLayersAndAssociatedLayers()868     public void testHandleSubscriptionsRequestEvent_MultipleLayersAndAssociatedLayers()
869             throws Exception {
870         HalPropValue request = createHalMessage(
871                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
872         );
873 
874         when(mVmsClient.getSubscriptionState()).thenReturn(
875                 new VmsSubscriptionState(123,
876                         new LinkedHashSet<>(Arrays.asList(
877                                 LAYER,
878                                 new VmsLayer(4, 5, 6),
879                                 new VmsLayer(7, 8, 9)
880                         )),
881                         new LinkedHashSet<>(Arrays.asList(
882                                 new VmsAssociatedLayer(LAYER, Collections.emptySet()),
883                                 new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
884                                         new LinkedHashSet<>(Arrays.asList(
885                                                 PUBLISHER_ID,
886                                                 54321))))))
887         );
888 
889         HalPropValue response = createHalMessage(
890                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
891                 123,                                       // Sequence number
892                 3,                                         // # of layers
893                 2,                                         // # of associated layers
894                 // Layer #1
895                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
896                 // Layer #2
897                 4, 5, 6,                                   // Layer
898                 // Layer #3
899                 7, 8, 9,                                   // Layer
900                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
901                 0,                                         // # of publisher IDs
902                 6, 5, 4,                                   // Layer
903                 2,                                         // # of publisher IDs
904                 PUBLISHER_ID,                              // Publisher ID
905                 54321                                      // Publisher ID #2
906         );
907 
908         sendHalMessage(request);
909         verify(mVehicleHal).set(response);
910     }
911 
912     /**
913      * SUBSCRIPTIONS_CHANGE message format:
914      * <ul>
915      * <li>Message type
916      * <li>Sequence number
917      * <li>Number of layers
918      * <li>Number of associated layers
919      * <li>Layers (x number of layers)
920      * <ul>
921      * <li>Layer ID
922      * <li>Layer subtype
923      * <li>Layer version
924      * </ul>
925      * <li>Associated layers (x number of associated layers)
926      * <ul>
927      * <li>Layer ID
928      * <li>Layer subtype
929      * <li>Layer version
930      * <li>Number of publishers
931      * <li>Publisher ID (x number of publishers)
932      * </ul>
933      * </ul>
934      */
935     @Test
testOnVmsSubscriptionChange_ZeroLayers()936     public void testOnVmsSubscriptionChange_ZeroLayers() throws Exception {
937         mEventCallback.onSubscriptionStateChanged(
938                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
939 
940         HalPropValue response = createHalMessage(
941                 VmsMessageType.SUBSCRIPTIONS_CHANGE,    // Message type
942                 123,                                    // Sequence number
943                 0,                                      // # of layers
944                 0                                       // # of associated layers
945         );
946 
947         waitForHandlerCompletion();
948         verify(mVehicleHal).set(response);
949     }
950 
951     @Test
testOnVmsSubscriptionChange_OneLayer_ZeroAssociatedLayers()952     public void testOnVmsSubscriptionChange_OneLayer_ZeroAssociatedLayers()
953             throws Exception {
954         mEventCallback.onSubscriptionStateChanged(
955                 new VmsSubscriptionState(123, Collections.singleton(LAYER),
956                         Collections.emptySet()));
957 
958         HalPropValue response = createHalMessage(
959                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
960                 123,                                       // Sequence number
961                 1,                                         // # of layers
962                 0,                                         // # of associated layers
963                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION   // Layer
964         );
965 
966         waitForHandlerCompletion();
967         verify(mVehicleHal).set(response);
968     }
969 
970     @Test
testOnVmsSubscriptionChange_ZeroLayers_OneAssociatedLayer()971     public void testOnVmsSubscriptionChange_ZeroLayers_OneAssociatedLayer()
972             throws Exception {
973         mEventCallback.onSubscriptionStateChanged(
974                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
975                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
976 
977         HalPropValue response = createHalMessage(
978                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
979                 123,                                       // Sequence number
980                 0,                                         // # of layers
981                 1,                                         // # of associated layers
982                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
983                 1,                                         // # of publisher IDs
984                 PUBLISHER_ID                               // Publisher ID
985         );
986 
987         waitForHandlerCompletion();
988         verify(mVehicleHal).set(response);
989     }
990 
991     @Test
testOnVmsSubscriptionChange_MultipleLayersAndAssociatedLayers()992     public void testOnVmsSubscriptionChange_MultipleLayersAndAssociatedLayers()
993             throws Exception {
994         mEventCallback.onSubscriptionStateChanged(
995                 new VmsSubscriptionState(123,
996                         new LinkedHashSet<>(Arrays.asList(
997                                 LAYER,
998                                 new VmsLayer(4, 5, 6),
999                                 new VmsLayer(7, 8, 9)
1000                         )),
1001                         new LinkedHashSet<>(Arrays.asList(
1002                                 new VmsAssociatedLayer(LAYER, Collections.emptySet()),
1003                                 new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
1004                                         new LinkedHashSet<>(Arrays.asList(
1005                                                 PUBLISHER_ID,
1006                                                 54321))))))
1007         );
1008 
1009         HalPropValue response = createHalMessage(
1010                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
1011                 123,                                       // Sequence number
1012                 3,                                         // # of layers
1013                 2,                                         // # of associated layers
1014                 // Layer #1
1015                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
1016                 // Layer #2
1017                 4, 5, 6,                                   // Layer
1018                 // Layer #3
1019                 7, 8, 9,                                   // Layer
1020                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
1021                 0,                                         // # of publisher IDs
1022                 6, 5, 4,                                   // Layer
1023                 2,                                         // # of publisher IDs
1024                 PUBLISHER_ID,                              // Publisher ID
1025                 54321                                      // Publisher ID #2
1026         );
1027 
1028         waitForHandlerCompletion();
1029         verify(mVehicleHal).set(response);
1030     }
1031 
1032     @Test
testPropertySetExceptionNotPropagated_CoreStartSession()1033     public void testPropertySetExceptionNotPropagated_CoreStartSession() throws Exception {
1034         doThrow(new RuntimeException()).when(mVehicleHal).set(any());
1035         initHalService(false);
1036 
1037         waitForHandlerCompletion();
1038     }
1039 
1040     @Test
testPropertySetExceptionNotPropagated_ClientStartSession()1041     public void testPropertySetExceptionNotPropagated_ClientStartSession() throws Exception {
1042         initHalService(false);
1043 
1044         when(mVmsClient.getAvailableLayers()).thenReturn(
1045                 new VmsAvailableLayers(Collections.emptySet(), 0));
1046         doThrow(new RuntimeException()).when(mVehicleHal).set(any());
1047 
1048         HalPropValue request = createHalMessage(
1049                 VmsMessageType.START_SESSION,  // Message type
1050                 -1,                            // Core ID (unknown)
1051                 CLIENT_ID                      // Client ID
1052         );
1053 
1054         sendHalMessage(request);
1055         waitForHandlerCompletion();
1056     }
1057 
1058     @Test
testDumpMetrics_DefaultConfig()1059     public void testDumpMetrics_DefaultConfig() {
1060         mHalService.dumpMetrics(new FileDescriptor());
1061         verifyNoMoreInteractions(mVehicleHal);
1062     }
1063 
1064     @Test
testDumpMetrics_NonVendorProperty()1065     public void testDumpMetrics_NonVendorProperty() throws Exception {
1066         HalPropValue vehicleProp = mPropValueBuilder.build(/* prop= */ 0, /* areaId= */ 0,
1067                 toByteArray(PAYLOAD_AS_LIST));
1068         when(mVehicleHal.get(anyInt())).thenReturn(vehicleProp);
1069 
1070         when(mResources.getInteger(
1071                 R.integer.vmsHalClientMetricsProperty)).thenReturn(
1072                 VehicleProperty.VEHICLE_MAP_SERVICE);
1073         setUp();
1074 
1075         mHalService.dumpMetrics(new FileDescriptor());
1076         verifyNoMoreInteractions(mVehicleHal);
1077     }
1078 
1079     @Test
testDumpMetrics_VendorProperty()1080     public void testDumpMetrics_VendorProperty() throws Exception {
1081         int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
1082         when(mResources.getInteger(
1083                 R.integer.vmsHalClientMetricsProperty)).thenReturn(
1084                 metricsPropertyId);
1085         setUp();
1086 
1087         HalPropValue metricsProperty = mPropValueBuilder.build(/* prop= */ 0, /* areaId= */ 0,
1088                 toByteArray(PAYLOAD_AS_LIST));
1089         when(mVehicleHal.get(metricsPropertyId)).thenReturn(metricsProperty);
1090 
1091         try (TemporaryFile dumpsysFile = new TemporaryFile("VmsHalServiceTest")) {
1092             try (FileOutputStream outputStream = new FileOutputStream(dumpsysFile.getFile())) {
1093                 mHalService.dumpMetrics(outputStream.getFD());
1094                 verify(mVehicleHal).get(metricsPropertyId);
1095             }
1096 
1097             try (FileInputStream inputStream = new FileInputStream(dumpsysFile.getFile())) {
1098                 byte[] dumpsysOutput = new byte[PAYLOAD.length];
1099                 assertEquals(PAYLOAD.length, inputStream.read(dumpsysOutput));
1100                 assertArrayEquals(PAYLOAD, dumpsysOutput);
1101             }
1102         }
1103     }
1104 
1105     @Test
testDumpMetrics_VendorProperty_Timeout()1106     public void testDumpMetrics_VendorProperty_Timeout() throws Exception {
1107         int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
1108         when(mResources.getInteger(
1109                 R.integer.vmsHalClientMetricsProperty)).thenReturn(
1110                 metricsPropertyId);
1111         setUp();
1112 
1113         when(mVehicleHal.get(metricsPropertyId))
1114                 .thenThrow(new ServiceSpecificException(VehicleHalStatusCode.STATUS_TRY_AGAIN,
1115                         "propertyId: 0x" + Integer.toHexString(metricsPropertyId)));
1116 
1117         mHalService.dumpMetrics(new FileDescriptor());
1118         verify(mVehicleHal).get(metricsPropertyId);
1119     }
1120 
1121     @Test
testDumpMetrics_VendorProperty_Unavailable()1122     public void testDumpMetrics_VendorProperty_Unavailable() throws Exception {
1123         int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
1124         when(mResources.getInteger(
1125                 R.integer.vmsHalClientMetricsProperty)).thenReturn(
1126                 metricsPropertyId);
1127         setUp();
1128 
1129         when(mVehicleHal.get(metricsPropertyId)).thenReturn(null);
1130 
1131         mHalService.dumpMetrics(new FileDescriptor());
1132         verify(mVehicleHal).get(metricsPropertyId);
1133     }
1134 
createHalMessage(Integer... message)1135     private HalPropValue createHalMessage(Integer... message) {
1136         HalPropValue result = mPropValueBuilder.build(VehicleProperty.VEHICLE_MAP_SERVICE,
1137                 /*areaId=*/0, toIntArray(Arrays.asList(message)));
1138         return result;
1139     }
1140 
createHalMessage(byte[] payload, Integer... message)1141     private HalPropValue createHalMessage(byte[] payload, Integer... message) {
1142         HalPropValue result = mPropValueBuilder.build(
1143                 VehicleProperty.VEHICLE_MAP_SERVICE,
1144                 /*areaId=*/0, /*timestamp=*/0, /*status=*/0,
1145                 /*int32Values=*/toIntArray(Arrays.asList(message)), /*floatValues=*/new float[0],
1146                 /*int64Values=*/new long[0], /*stringValue=*/new String(), /*byteValues=*/payload);
1147         return result;
1148     }
1149 
sendHalMessage(HalPropValue message)1150     private void sendHalMessage(HalPropValue message) {
1151         mHalService.onHalEvents(Collections.singletonList(message));
1152     }
1153 
waitForHandlerCompletion()1154     private void waitForHandlerCompletion() throws Exception {
1155         final CountDownLatch latch = new CountDownLatch(1);
1156         mHalService.getHandler().post(latch::countDown);
1157         latch.await(5, TimeUnit.SECONDS);
1158     }
1159 
1160     @SafeVarargs
asSet(T... values)1161     private static <T> Set<T> asSet(T... values) {
1162         return new HashSet<>(Arrays.asList(values));
1163     }
1164 }
1165