• 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 org.junit.Assert.assertEquals;
19 import static org.mockito.Mockito.reset;
20 import static org.mockito.Mockito.verify;
21 import static org.mockito.Mockito.when;
22 
23 import android.car.vms.IVmsPublisherClient;
24 import android.car.vms.IVmsPublisherService;
25 import android.car.vms.IVmsSubscriberClient;
26 import android.car.vms.IVmsSubscriberService;
27 import android.car.vms.VmsAssociatedLayer;
28 import android.car.vms.VmsAvailableLayers;
29 import android.car.vms.VmsLayer;
30 import android.car.vms.VmsLayerDependency;
31 import android.car.vms.VmsLayersOffering;
32 import android.car.vms.VmsSubscriptionState;
33 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
34 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
35 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
36 import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
37 import android.os.Binder;
38 import android.os.IBinder;
39 
40 import org.junit.Before;
41 import org.junit.Rule;
42 import org.junit.Test;
43 import org.mockito.ArgumentCaptor;
44 import org.mockito.InOrder;
45 import org.mockito.Mock;
46 import org.mockito.Mockito;
47 import org.mockito.junit.MockitoJUnit;
48 import org.mockito.junit.MockitoRule;
49 
50 import java.util.Arrays;
51 import java.util.Collections;
52 import java.util.LinkedHashSet;
53 import java.util.List;
54 import java.util.concurrent.CountDownLatch;
55 import java.util.concurrent.TimeUnit;
56 import java.util.function.Consumer;
57 
58 public class VmsHalServiceTest {
59     private static final int LAYER_TYPE = 1;
60     private static final int LAYER_SUBTYPE = 2;
61     private static final int LAYER_VERSION = 3;
62     private static final VmsLayer LAYER = new VmsLayer(LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION);
63     private static final int PUBLISHER_ID = 12345;
64     private static final byte[] PAYLOAD = new byte[]{1, 2, 3, 4};
65     private static final List<Byte> PAYLOAD_AS_LIST = Arrays.asList(new Byte[]{1, 2, 3, 4});
66     private static final int CORE_ID = 54321;
67     private static final int CLIENT_ID = 98765;
68 
69     @Rule
70     public MockitoRule mockito = MockitoJUnit.rule();
71     @Mock
72     private VehicleHal mVehicleHal;
73     @Mock
74     private IVmsPublisherService mPublisherService;
75     @Mock
76     private IVmsSubscriberService mSubscriberService;
77     @Mock
78     private Consumer<IBinder> mPublisherOnHalConnected;
79     @Mock
80     private Runnable mPublisherOnHalDisconnected;
81     @Mock
82     private Consumer<IVmsSubscriberClient> mSubscriberOnHalDisconnected;
83 
84     private IBinder mToken;
85     private VmsHalService mHalService;
86     private IVmsPublisherClient mPublisherClient;
87     private IVmsSubscriberClient mSubscriberClient;
88 
89     @Before
setUp()90     public void setUp() throws Exception {
91         mHalService = new VmsHalService(mVehicleHal, () -> (long) CORE_ID);
92         mHalService.setPublisherConnectionCallbacks(
93                 mPublisherOnHalConnected, mPublisherOnHalDisconnected);
94         mHalService.setVmsSubscriberService(mSubscriberService, mSubscriberOnHalDisconnected);
95 
96         VehiclePropConfig propConfig = new VehiclePropConfig();
97         propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
98         mHalService.takeSupportedProperties(Collections.singleton(propConfig));
99 
100         when(mSubscriberService.getAvailableLayers()).thenReturn(
101                 new VmsAvailableLayers(Collections.emptySet(), 0));
102         mHalService.init();
103         waitForHandlerCompletion();
104 
105         // Verify START_SESSION message was sent
106         InOrder initOrder =
107                 Mockito.inOrder(mPublisherOnHalConnected, mSubscriberService, mVehicleHal);
108         initOrder.verify(mVehicleHal).subscribeProperty(mHalService,
109                 VehicleProperty.VEHICLE_MAP_SERVICE);
110         initOrder.verify(mVehicleHal).set(createHalMessage(
111                 VmsMessageType.START_SESSION, // Message type
112                 CORE_ID,                      // Core ID
113                 -1));                          // Client ID (unknown)
114 
115         // Verify no more interections until handshake received
116         initOrder.verifyNoMoreInteractions();
117 
118         // Send START_SESSION response from client
119         sendHalMessage(createHalMessage(
120                 VmsMessageType.START_SESSION,  // Message type
121                 0,                             // Core ID (unknown)
122                 CLIENT_ID                      // Client ID
123         ));
124         waitForHandlerCompletion();
125 
126         // Verify client is marked as connected
127         ArgumentCaptor<IBinder> publisherCaptor = ArgumentCaptor.forClass(IBinder.class);
128         initOrder.verify(mPublisherOnHalConnected).accept(publisherCaptor.capture());
129         mPublisherClient = IVmsPublisherClient.Stub.asInterface(publisherCaptor.getValue());
130 
131         mToken = new Binder();
132         mPublisherClient.setVmsPublisherService(mToken, mPublisherService);
133 
134         ArgumentCaptor<IVmsSubscriberClient> subscriberCaptor = ArgumentCaptor.forClass(
135                 IVmsSubscriberClient.class);
136         initOrder.verify(mSubscriberService).addVmsSubscriberToNotifications(
137                 subscriberCaptor.capture());
138         mSubscriberClient = subscriberCaptor.getValue();
139 
140         initOrder.verify(mSubscriberService).getAvailableLayers();
141         initOrder.verify(mVehicleHal).set(createHalMessage(
142                 VmsMessageType.AVAILABILITY_CHANGE, // Message type
143                 0,                                  // Sequence number
144                 0));                                // # of associated layers
145 
146         initOrder.verifyNoMoreInteractions();
147         reset(mPublisherOnHalConnected, mSubscriberService, mVehicleHal);
148     }
149 
150     @Test
testCoreId_IntegerOverflow()151     public void testCoreId_IntegerOverflow() throws Exception {
152         mHalService = new VmsHalService(mVehicleHal, () -> (long) Integer.MAX_VALUE + CORE_ID);
153 
154         VehiclePropConfig propConfig = new VehiclePropConfig();
155         propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
156         mHalService.takeSupportedProperties(Collections.singleton(propConfig));
157 
158         when(mSubscriberService.getAvailableLayers()).thenReturn(
159                 new VmsAvailableLayers(Collections.emptySet(), 0));
160         mHalService.init();
161         waitForHandlerCompletion();
162 
163         verify(mVehicleHal).set(createHalMessage(
164                 VmsMessageType.START_SESSION, // Message type
165                 CORE_ID,                      // Core ID
166                 -1));                          // Client ID (unknown)
167     }
168 
169     @Test
testTakeSupportedProperties()170     public void testTakeSupportedProperties() {
171         VehiclePropConfig vmsPropConfig = new VehiclePropConfig();
172         vmsPropConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
173 
174         VehiclePropConfig otherPropConfig = new VehiclePropConfig();
175         otherPropConfig.prop = VehicleProperty.CURRENT_GEAR;
176 
177         assertEquals(Collections.singleton(vmsPropConfig),
178                 mHalService.takeSupportedProperties(Arrays.asList(otherPropConfig, vmsPropConfig)));
179     }
180 
181     /**
182      * DATA message format:
183      * <ul>
184      * <li>Message type
185      * <li>Layer ID
186      * <li>Layer subtype
187      * <li>Layer version
188      * <li>Publisher ID
189      * <li>Payload
190      * </ul>
191      */
192     @Test
testHandleDataEvent()193     public void testHandleDataEvent() throws Exception {
194         VehiclePropValue message = createHalMessage(
195                 VmsMessageType.DATA,                       // Message type
196                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
197                 PUBLISHER_ID                               // PublisherId
198         );
199         message.value.bytes.addAll(PAYLOAD_AS_LIST);
200 
201         sendHalMessage(message);
202         verify(mPublisherService).publish(mToken, LAYER, PUBLISHER_ID, PAYLOAD);
203     }
204 
205     /**
206      * SUBSCRIBE message format:
207      * <ul>
208      * <li>Message type
209      * <li>Layer ID
210      * <li>Layer subtype
211      * <li>Layer version
212      * </ul>
213      */
214     @Test
testHandleSubscribeEvent()215     public void testHandleSubscribeEvent() throws Exception {
216         VehiclePropValue message = createHalMessage(
217                 VmsMessageType.SUBSCRIBE,                 // Message type
218                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION  // VmsLayer
219         );
220 
221         sendHalMessage(message);
222         verify(mSubscriberService).addVmsSubscriber(mSubscriberClient, LAYER);
223     }
224 
225     /**
226      * SUBSCRIBE_TO_PUBLISHER message format:
227      * <ul>
228      * <li>Message type
229      * <li>Layer ID
230      * <li>Layer subtype
231      * <li>Layer version
232      * <li>Publisher ID
233      * </ul>
234      */
235     @Test
testHandleSubscribeToPublisherEvent()236     public void testHandleSubscribeToPublisherEvent() throws Exception {
237         VehiclePropValue message = createHalMessage(
238                 VmsMessageType.SUBSCRIBE_TO_PUBLISHER,     // Message type
239                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
240                 PUBLISHER_ID                               // PublisherId
241         );
242 
243         sendHalMessage(message);
244         verify(mSubscriberService).addVmsSubscriberToPublisher(mSubscriberClient, LAYER,
245                 PUBLISHER_ID);
246     }
247 
248     /**
249      * UNSUBSCRIBE message format:
250      * <ul>
251      * <li>Message type
252      * <li>Layer ID
253      * <li>Layer subtype
254      * <li>Layer version
255      * </ul>
256      */
257     @Test
testHandleUnsubscribeEvent()258     public void testHandleUnsubscribeEvent() throws Exception {
259         VehiclePropValue message = createHalMessage(
260                 VmsMessageType.UNSUBSCRIBE,               // Message type
261                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION  // VmsLayer
262         );
263 
264         sendHalMessage(message);
265         verify(mSubscriberService).removeVmsSubscriber(mSubscriberClient, LAYER);
266     }
267 
268     /**
269      * UNSUBSCRIBE_TO_PUBLISHER message format:
270      * <ul>
271      * <li>Message type
272      * <li>Layer ID
273      * <li>Layer subtype
274      * <li>Layer version
275      * <li>Publisher ID
276      * </ul>
277      */
278     @Test
testHandleUnsubscribeFromPublisherEvent()279     public void testHandleUnsubscribeFromPublisherEvent() throws Exception {
280         VehiclePropValue message = createHalMessage(
281                 VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER,   // Message type
282                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // VmsLayer
283                 PUBLISHER_ID                               // PublisherId
284         );
285 
286         sendHalMessage(message);
287         verify(mSubscriberService).removeVmsSubscriberToPublisher(mSubscriberClient, LAYER,
288                 PUBLISHER_ID);
289     }
290 
291     /**
292      * PUBLISHER_ID_REQUEST message format:
293      * <ul>
294      * <li>Message type
295      * <li>Publisher info (bytes)
296      * </ul>
297      *
298      * PUBLISHER_ID_RESPONSE message format:
299      * <ul>
300      * <li>Message type
301      * <li>Publisher ID
302      * </ul>
303      */
304     @Test
testHandlePublisherIdRequestEvent()305     public void testHandlePublisherIdRequestEvent() throws Exception {
306         VehiclePropValue request = createHalMessage(
307                 VmsMessageType.PUBLISHER_ID_REQUEST  // Message type
308         );
309         request.value.bytes.addAll(PAYLOAD_AS_LIST);
310 
311         when(mPublisherService.getPublisherId(PAYLOAD)).thenReturn(PUBLISHER_ID);
312 
313         VehiclePropValue response = createHalMessage(
314                 VmsMessageType.PUBLISHER_ID_RESPONSE,  // Message type
315                 PUBLISHER_ID                           // Publisher ID
316         );
317 
318         sendHalMessage(request);
319         verify(mVehicleHal).set(response);
320     }
321 
322     /**
323      * PUBLISHER_INFORMATION_REQUEST message format:
324      * <ul>
325      * <li>Message type
326      * <li>Publisher ID
327      * </ul>
328      *
329      * PUBLISHER_INFORMATION_RESPONSE message format:
330      * <ul>
331      * <li>Message type
332      * <li>Publisher info (bytes)
333      * </ul>
334      */
335     @Test
testHandlePublisherInformationRequestEvent()336     public void testHandlePublisherInformationRequestEvent() throws Exception {
337         VehiclePropValue request = createHalMessage(
338                 VmsMessageType.PUBLISHER_INFORMATION_REQUEST,  // Message type
339                 PUBLISHER_ID                                   // Publisher ID
340         );
341 
342         when(mSubscriberService.getPublisherInfo(PUBLISHER_ID)).thenReturn(PAYLOAD);
343 
344         VehiclePropValue response = createHalMessage(
345                 VmsMessageType.PUBLISHER_INFORMATION_RESPONSE  // Message type
346         );
347         response.value.bytes.addAll(PAYLOAD_AS_LIST);
348 
349         sendHalMessage(request);
350         verify(mVehicleHal).set(response);
351     }
352 
353     /**
354      * OFFERING message format:
355      * <ul>
356      * <li>Message type
357      * <li>Publisher ID
358      * <li>Number of offerings.
359      * <li>Offerings (x number of offerings)
360      * <ul>
361      * <li>Layer ID
362      * <li>Layer subtype
363      * <li>Layer version
364      * <li>Number of layer dependencies.
365      * <li>Layer dependencies (x number of layer dependencies)
366      * <ul>
367      * <li>Layer ID
368      * <li>Layer subtype
369      * <li>Layer version
370      * </ul>
371      * </ul>
372      * </ul>
373      */
374     @Test
testHandleOfferingEvent_ZeroOfferings()375     public void testHandleOfferingEvent_ZeroOfferings() throws Exception {
376         VehiclePropValue message = createHalMessage(
377                 VmsMessageType.OFFERING,  // Message type
378                 PUBLISHER_ID,             // PublisherId
379                 0                         // # of offerings
380         );
381 
382         sendHalMessage(message);
383         verify(mPublisherService).setLayersOffering(
384                 mToken,
385                 new VmsLayersOffering(Collections.emptySet(), PUBLISHER_ID));
386     }
387 
388     @Test
testHandleOfferingEvent_LayerOnly()389     public void testHandleOfferingEvent_LayerOnly() throws Exception {
390         VehiclePropValue message = createHalMessage(
391                 VmsMessageType.OFFERING,                   // Message type
392                 PUBLISHER_ID,                              // PublisherId
393                 1,                                         // # of offerings
394                 // Offered layer
395                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,
396                 0                                          // # of dependencies
397         );
398 
399         sendHalMessage(message);
400         verify(mPublisherService).setLayersOffering(
401                 mToken,
402                 new VmsLayersOffering(Collections.singleton(
403                         new VmsLayerDependency(LAYER)),
404                         PUBLISHER_ID));
405     }
406 
407     @Test
testHandleOfferingEvent_LayerAndDependency()408     public void testHandleOfferingEvent_LayerAndDependency() throws Exception {
409         VehiclePropValue message = createHalMessage(
410                 VmsMessageType.OFFERING,                   // Message type
411                 PUBLISHER_ID,                              // PublisherId
412                 1,                                         // # of offerings
413                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
414                 1,                                         // # of dependencies
415                 4, 5, 6                                    // Dependency layer
416         );
417 
418         sendHalMessage(message);
419         verify(mPublisherService).setLayersOffering(
420                 mToken,
421                 new VmsLayersOffering(Collections.singleton(
422                         new VmsLayerDependency(LAYER, Collections.singleton(
423                                 new VmsLayer(4, 5, 6)))),
424                         PUBLISHER_ID));
425     }
426 
427     @Test
testHandleOfferingEvent_MultipleLayersAndDependencies()428     public void testHandleOfferingEvent_MultipleLayersAndDependencies() throws Exception {
429         VehiclePropValue message = createHalMessage(
430                 VmsMessageType.OFFERING,                   // Message type
431                 PUBLISHER_ID,                              // PublisherId
432                 3,                                         // # of offerings
433                 // Offered layer #1
434                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
435                 2,                                         // # of dependencies
436                 4, 5, 6,                                   // Dependency layer
437                 7, 8, 9,                                   // Dependency layer
438                 // Offered layer #2
439                 3, 2, 1,                                   // Layer
440                 0,                                         // # of dependencies
441                 // Offered layer #3
442                 6, 5, 4,                                   // Layer
443                 1,                                         // # of dependencies
444                 7, 8, 9                                    // Dependency layer
445         );
446 
447         sendHalMessage(message);
448         verify(mPublisherService).setLayersOffering(
449                 mToken,
450                 new VmsLayersOffering(new LinkedHashSet<>(Arrays.asList(
451                         new VmsLayerDependency(LAYER, new LinkedHashSet<>(Arrays.asList(
452                                 new VmsLayer(4, 5, 6),
453                                 new VmsLayer(7, 8, 9)
454                         ))),
455                         new VmsLayerDependency(new VmsLayer(3, 2, 1), Collections.emptySet()),
456                         new VmsLayerDependency(new VmsLayer(6, 5, 4), Collections.singleton(
457                                 new VmsLayer(7, 8, 9)
458                         )))),
459                         PUBLISHER_ID));
460     }
461 
462     /**
463      * AVAILABILITY_REQUEST message format:
464      * <ul>
465      * <li>Message type
466      * </ul>
467      *
468      * AVAILABILITY_RESPONSE message format:
469      * <ul>
470      * <li>Message type
471      * <li>Sequence number.
472      * <li>Number of associated layers.
473      * <li>Associated layers (x number of associated layers)
474      * <ul>
475      * <li>Layer ID
476      * <li>Layer subtype
477      * <li>Layer version
478      * <li>Number of publishers
479      * <li>Publisher ID (x number of publishers)
480      * </ul>
481      * </ul>
482      */
483     @Test
testHandleAvailabilityRequestEvent_ZeroLayers()484     public void testHandleAvailabilityRequestEvent_ZeroLayers() throws Exception {
485         VehiclePropValue request = createHalMessage(
486                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
487         );
488 
489         when(mSubscriberService.getAvailableLayers()).thenReturn(
490                 new VmsAvailableLayers(Collections.emptySet(), 123));
491 
492         VehiclePropValue response = createHalMessage(
493                 VmsMessageType.AVAILABILITY_RESPONSE,  // Message type
494                 123,                                   // Sequence number
495                 0                                      // # of associated layers
496         );
497 
498         sendHalMessage(request);
499         verify(mVehicleHal).set(response);
500     }
501 
502     @Test
testHandleAvailabilityRequestEvent_OneLayer()503     public void testHandleAvailabilityRequestEvent_OneLayer() throws Exception {
504         VehiclePropValue request = createHalMessage(
505                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
506         );
507 
508         when(mSubscriberService.getAvailableLayers()).thenReturn(
509                 new VmsAvailableLayers(Collections.singleton(
510                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
511 
512         VehiclePropValue response = createHalMessage(
513                 VmsMessageType.AVAILABILITY_RESPONSE,      // Message type
514                 123,                                       // Sequence number
515                 1,                                         // # of associated layers
516                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
517                 1,                                         // # of publisher IDs
518                 PUBLISHER_ID                               // Publisher ID
519         );
520 
521         sendHalMessage(request);
522         verify(mVehicleHal).set(response);
523     }
524 
525 
526     @Test
testHandleAvailabilityRequestEvent_MultipleLayers()527     public void testHandleAvailabilityRequestEvent_MultipleLayers() throws Exception {
528         VehiclePropValue request = createHalMessage(
529                 VmsMessageType.AVAILABILITY_REQUEST  // Message type
530         );
531 
532         when(mSubscriberService.getAvailableLayers()).thenReturn(
533                 new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
534                         new VmsAssociatedLayer(LAYER,
535                                 new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
536                         new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
537                                 Collections.emptySet()),
538                         new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
539                                 Collections.singleton(99999)))),
540                         123));
541 
542         VehiclePropValue response = createHalMessage(
543                 VmsMessageType.AVAILABILITY_RESPONSE,      // Message type
544                 123,                                       // Sequence number
545                 3,                                         // # of associated layers
546                 // Associated layer #1
547                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
548                 2,                                         // # of publisher IDs
549                 PUBLISHER_ID,                              // Publisher ID
550                 54321,                                     // Publisher ID #2
551                 // Associated layer #2
552                 3, 2, 1,                                   // Layer
553                 0,                                         // # of publisher IDs
554                 // Associated layer #3
555                 6, 5, 4,                                   // Layer
556                 1,                                         // # of publisher IDs
557                 99999                                      // Publisher ID
558 
559         );
560 
561         sendHalMessage(request);
562         verify(mVehicleHal).set(response);
563     }
564 
565     /**
566      * START_SESSION message format:
567      * <ul>
568      * <li>Message type
569      * <li>Core ID
570      * <li>Client ID
571      * </ul>
572      */
573     @Test
testHandleStartSessionEvent()574     public void testHandleStartSessionEvent() throws Exception {
575         when(mSubscriberService.getAvailableLayers()).thenReturn(
576                 new VmsAvailableLayers(Collections.emptySet(), 5));
577 
578         VehiclePropValue request = createHalMessage(
579                 VmsMessageType.START_SESSION,  // Message type
580                 0,                             // Core ID (unknown)
581                 CLIENT_ID                      // Client ID
582         );
583 
584         VehiclePropValue response = createHalMessage(
585                 VmsMessageType.START_SESSION,  // Message type
586                 CORE_ID,                               // Core ID
587                 CLIENT_ID                              // Client ID
588         );
589 
590         sendHalMessage(request);
591         InOrder inOrder = Mockito.inOrder(mVehicleHal);
592         inOrder.verify(mVehicleHal).set(response);
593         inOrder.verify(mVehicleHal).set(createHalMessage(
594                 VmsMessageType.AVAILABILITY_CHANGE, // Message type
595                 5,                                  // Sequence number
596                 0));                                // # of associated layers
597     }
598 
599     /**
600      * AVAILABILITY_CHANGE message format:
601      * <ul>
602      * <li>Message type
603      * <li>Sequence number.
604      * <li>Number of associated layers.
605      * <li>Associated layers (x number of associated layers)
606      * <ul>
607      * <li>Layer ID
608      * <li>Layer subtype
609      * <li>Layer version
610      * <li>Number of publishers
611      * <li>Publisher ID (x number of publishers)
612      * </ul>
613      * </ul>
614      */
615     @Test
testOnLayersAvailabilityChanged_ZeroLayers()616     public void testOnLayersAvailabilityChanged_ZeroLayers() throws Exception {
617         mSubscriberClient.onLayersAvailabilityChanged(
618                 new VmsAvailableLayers(Collections.emptySet(), 123));
619 
620         VehiclePropValue message = createHalMessage(
621                 VmsMessageType.AVAILABILITY_CHANGE,    // Message type
622                 123,                                   // Sequence number
623                 0                                      // # of associated layers
624         );
625 
626         waitForHandlerCompletion();
627         verify(mVehicleHal).set(message);
628     }
629 
630     @Test
testOnLayersAvailabilityChanged_OneLayer()631     public void testOnLayersAvailabilityChanged_OneLayer() throws Exception {
632         mSubscriberClient.onLayersAvailabilityChanged(
633                 new VmsAvailableLayers(Collections.singleton(
634                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
635 
636         VehiclePropValue message = createHalMessage(
637                 VmsMessageType.AVAILABILITY_CHANGE,        // Message type
638                 123,                                       // Sequence number
639                 1,                                         // # of associated layers
640                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
641                 1,                                         // # of publisher IDs
642                 PUBLISHER_ID                               // Publisher ID
643         );
644 
645         waitForHandlerCompletion();
646         verify(mVehicleHal).set(message);
647     }
648 
649 
650     @Test
testOnLayersAvailabilityChanged_MultipleLayers()651     public void testOnLayersAvailabilityChanged_MultipleLayers() throws Exception {
652         mSubscriberClient.onLayersAvailabilityChanged(
653                 new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
654                         new VmsAssociatedLayer(LAYER,
655                                 new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
656                         new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
657                                 Collections.emptySet()),
658                         new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
659                                 Collections.singleton(99999)))),
660                         123));
661 
662         VehiclePropValue message = createHalMessage(
663                 VmsMessageType.AVAILABILITY_CHANGE,      // Message type
664                 123,                                       // Sequence number
665                 3,                                         // # of associated layers
666                 // Associated layer #1
667                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
668                 2,                                         // # of publisher IDs
669                 PUBLISHER_ID,                              // Publisher ID
670                 54321,                                     // Publisher ID #2
671                 // Associated layer #2
672                 3, 2, 1,                                   // Layer
673                 0,                                         // # of publisher IDs
674                 // Associated layer #3
675                 6, 5, 4,                                   // Layer
676                 1,                                         // # of publisher IDs
677                 99999                                      // Publisher ID
678 
679         );
680 
681         waitForHandlerCompletion();
682         verify(mVehicleHal).set(message);
683     }
684 
685     /**
686      * SUBSCRIPTION_REQUEST message format:
687      * <ul>
688      * <li>Message type
689      * </ul>
690      *
691      * SUBSCRIPTION_RESPONSE message format:
692      * <ul>
693      * <li>Message type
694      * <li>Sequence number
695      * <li>Number of layers
696      * <li>Number of associated layers
697      * <li>Layers (x number of layers)
698      * <ul>
699      * <li>Layer ID
700      * <li>Layer subtype
701      * <li>Layer version
702      * </ul>
703      * <li>Associated layers (x number of associated layers)
704      * <ul>
705      * <li>Layer ID
706      * <li>Layer subtype
707      * <li>Layer version
708      * <li>Number of publishers
709      * <li>Publisher ID (x number of publishers)
710      * </ul>
711      * </ul>
712      */
713     @Test
testHandleSubscriptionsRequestEvent_ZeroLayers()714     public void testHandleSubscriptionsRequestEvent_ZeroLayers() throws Exception {
715         VehiclePropValue request = createHalMessage(
716                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
717         );
718 
719         when(mPublisherService.getSubscriptions()).thenReturn(
720                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
721 
722         VehiclePropValue response = createHalMessage(
723                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,  // Message type
724                 123,                                    // Sequence number
725                 0,                                      // # of layers
726                 0                                       // # of associated layers
727         );
728 
729         sendHalMessage(request);
730         verify(mVehicleHal).set(response);
731     }
732 
733     @Test
testHandleSubscriptionsRequestEvent_OneLayer_ZeroAssociatedLayers()734     public void testHandleSubscriptionsRequestEvent_OneLayer_ZeroAssociatedLayers()
735             throws Exception {
736         VehiclePropValue request = createHalMessage(
737                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
738         );
739 
740         when(mPublisherService.getSubscriptions()).thenReturn(
741                 new VmsSubscriptionState(123, Collections.singleton(LAYER),
742                         Collections.emptySet()));
743 
744         VehiclePropValue response = createHalMessage(
745                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
746                 123,                                       // Sequence number
747                 1,                                         // # of layers
748                 0,                                         // # of associated layers
749                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION   // Layer
750         );
751 
752         sendHalMessage(request);
753         verify(mVehicleHal).set(response);
754     }
755 
756     @Test
testHandleSubscriptionsRequestEvent_ZeroLayers_OneAssociatedLayer()757     public void testHandleSubscriptionsRequestEvent_ZeroLayers_OneAssociatedLayer()
758             throws Exception {
759         VehiclePropValue request = createHalMessage(
760                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
761         );
762 
763         when(mPublisherService.getSubscriptions()).thenReturn(
764                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
765                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
766 
767         VehiclePropValue response = createHalMessage(
768                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
769                 123,                                       // Sequence number
770                 0,                                         // # of layers
771                 1,                                         // # of associated layers
772                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
773                 1,                                         // # of publisher IDs
774                 PUBLISHER_ID                               // Publisher ID
775         );
776 
777         sendHalMessage(request);
778         verify(mVehicleHal).set(response);
779     }
780 
781     @Test
testHandleSubscriptionsRequestEvent_MultipleLayersAndAssociatedLayers()782     public void testHandleSubscriptionsRequestEvent_MultipleLayersAndAssociatedLayers()
783             throws Exception {
784         VehiclePropValue request = createHalMessage(
785                 VmsMessageType.SUBSCRIPTIONS_REQUEST  // Message type
786         );
787 
788         when(mPublisherService.getSubscriptions()).thenReturn(
789                 new VmsSubscriptionState(123,
790                         new LinkedHashSet<>(Arrays.asList(
791                                 LAYER,
792                                 new VmsLayer(4, 5, 6),
793                                 new VmsLayer(7, 8, 9)
794                         )),
795                         new LinkedHashSet<>(Arrays.asList(
796                                 new VmsAssociatedLayer(LAYER, Collections.emptySet()),
797                                 new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
798                                         new LinkedHashSet<>(Arrays.asList(
799                                                 PUBLISHER_ID,
800                                                 54321))))))
801         );
802 
803         VehiclePropValue response = createHalMessage(
804                 VmsMessageType.SUBSCRIPTIONS_RESPONSE,     // Message type
805                 123,                                       // Sequence number
806                 3,                                         // # of layers
807                 2,                                         // # of associated layers
808                 // Layer #1
809                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
810                 // Layer #2
811                 4, 5, 6,                                   // Layer
812                 // Layer #3
813                 7, 8, 9,                                   // Layer
814                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
815                 0,                                         // # of publisher IDs
816                 6, 5, 4,                                   // Layer
817                 2,                                         // # of publisher IDs
818                 PUBLISHER_ID,                              // Publisher ID
819                 54321                                      // Publisher ID #2
820         );
821 
822         sendHalMessage(request);
823         verify(mVehicleHal).set(response);
824     }
825 
826     /**
827      * SUBSCRIPTIONS_CHANGE message format:
828      * <ul>
829      * <li>Message type
830      * <li>Sequence number
831      * <li>Number of layers
832      * <li>Number of associated layers
833      * <li>Layers (x number of layers)
834      * <ul>
835      * <li>Layer ID
836      * <li>Layer subtype
837      * <li>Layer version
838      * </ul>
839      * <li>Associated layers (x number of associated layers)
840      * <ul>
841      * <li>Layer ID
842      * <li>Layer subtype
843      * <li>Layer version
844      * <li>Number of publishers
845      * <li>Publisher ID (x number of publishers)
846      * </ul>
847      * </ul>
848      */
849     @Test
testOnVmsSubscriptionChange_ZeroLayers()850     public void testOnVmsSubscriptionChange_ZeroLayers() throws Exception {
851         mPublisherClient.onVmsSubscriptionChange(
852                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
853 
854         VehiclePropValue response = createHalMessage(
855                 VmsMessageType.SUBSCRIPTIONS_CHANGE,    // Message type
856                 123,                                    // Sequence number
857                 0,                                      // # of layers
858                 0                                       // # of associated layers
859         );
860 
861         waitForHandlerCompletion();
862         verify(mVehicleHal).set(response);
863     }
864 
865     @Test
testOnVmsSubscriptionChange_OneLayer_ZeroAssociatedLayers()866     public void testOnVmsSubscriptionChange_OneLayer_ZeroAssociatedLayers()
867             throws Exception {
868         mPublisherClient.onVmsSubscriptionChange(
869                 new VmsSubscriptionState(123, Collections.singleton(LAYER),
870                         Collections.emptySet()));
871 
872         VehiclePropValue response = createHalMessage(
873                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
874                 123,                                       // Sequence number
875                 1,                                         // # of layers
876                 0,                                         // # of associated layers
877                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION   // Layer
878         );
879 
880         waitForHandlerCompletion();
881         verify(mVehicleHal).set(response);
882     }
883 
884     @Test
testOnVmsSubscriptionChange_ZeroLayers_OneAssociatedLayer()885     public void testOnVmsSubscriptionChange_ZeroLayers_OneAssociatedLayer()
886             throws Exception {
887         mPublisherClient.onVmsSubscriptionChange(
888                 new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
889                         new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
890 
891         VehiclePropValue response = createHalMessage(
892                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
893                 123,                                       // Sequence number
894                 0,                                         // # of layers
895                 1,                                         // # of associated layers
896                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
897                 1,                                         // # of publisher IDs
898                 PUBLISHER_ID                               // Publisher ID
899         );
900 
901         waitForHandlerCompletion();
902         verify(mVehicleHal).set(response);
903     }
904 
905     @Test
testOnVmsSubscriptionChange_MultipleLayersAndAssociatedLayers()906     public void testOnVmsSubscriptionChange_MultipleLayersAndAssociatedLayers()
907             throws Exception {
908         mPublisherClient.onVmsSubscriptionChange(
909                 new VmsSubscriptionState(123,
910                         new LinkedHashSet<>(Arrays.asList(
911                                 LAYER,
912                                 new VmsLayer(4, 5, 6),
913                                 new VmsLayer(7, 8, 9)
914                         )),
915                         new LinkedHashSet<>(Arrays.asList(
916                                 new VmsAssociatedLayer(LAYER, Collections.emptySet()),
917                                 new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
918                                         new LinkedHashSet<>(Arrays.asList(
919                                                 PUBLISHER_ID,
920                                                 54321))))))
921         );
922 
923         VehiclePropValue response = createHalMessage(
924                 VmsMessageType.SUBSCRIPTIONS_CHANGE,       // Message type
925                 123,                                       // Sequence number
926                 3,                                         // # of layers
927                 2,                                         // # of associated layers
928                 // Layer #1
929                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
930                 // Layer #2
931                 4, 5, 6,                                   // Layer
932                 // Layer #3
933                 7, 8, 9,                                   // Layer
934                 LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,  // Layer
935                 0,                                         // # of publisher IDs
936                 6, 5, 4,                                   // Layer
937                 2,                                         // # of publisher IDs
938                 PUBLISHER_ID,                              // Publisher ID
939                 54321                                      // Publisher ID #2
940         );
941 
942         waitForHandlerCompletion();
943         verify(mVehicleHal).set(response);
944     }
945 
createHalMessage(Integer... message)946     private static VehiclePropValue createHalMessage(Integer... message) {
947         VehiclePropValue result = new VehiclePropValue();
948         result.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
949         result.value.int32Values.addAll(Arrays.asList(message));
950         return result;
951     }
952 
sendHalMessage(VehiclePropValue message)953     private void sendHalMessage(VehiclePropValue message) {
954         mHalService.handleHalEvents(Collections.singletonList(message));
955     }
956 
waitForHandlerCompletion()957     private void waitForHandlerCompletion() throws Exception {
958         final CountDownLatch latch = new CountDownLatch(1);
959         mHalService.getHandler().post(latch::countDown);
960         latch.await(5, TimeUnit.SECONDS);
961     }
962 }
963