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