blob: 093ab9bb34aa0fa1cf5b09d1c551a7cf9a5b0b95 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.hal;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.car.vms.IVmsPublisherClient;
import android.car.vms.IVmsPublisherService;
import android.car.vms.IVmsSubscriberClient;
import android.car.vms.IVmsSubscriberService;
import android.car.vms.VmsAssociatedLayer;
import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsLayerDependency;
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsSubscriptionState;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.os.Binder;
import android.os.IBinder;
import com.android.car.R;
import com.android.car.test.utils.TemporaryFile;
import com.android.car.vms.VmsClientManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class VmsHalServiceTest {
private static final int LAYER_TYPE = 1;
private static final int LAYER_SUBTYPE = 2;
private static final int LAYER_VERSION = 3;
private static final VmsLayer LAYER = new VmsLayer(LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION);
private static final int PUBLISHER_ID = 12345;
private static final byte[] PAYLOAD = new byte[]{1, 2, 3, 4};
private static final List<Byte> PAYLOAD_AS_LIST = Arrays.asList(new Byte[]{1, 2, 3, 4});
private static final int CORE_ID = 54321;
private static final int CLIENT_ID = 98765;
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Mock
private Context mContext;
@Mock
private Resources mResources;
@Mock
private VehicleHal mVehicleHal;
@Mock
private VmsClientManager mClientManager;
@Mock
private IVmsPublisherService mPublisherService;
@Mock
private IVmsSubscriberService mSubscriberService;
private IBinder mToken;
private VmsHalService mHalService;
private IVmsPublisherClient mPublisherClient;
private IVmsSubscriberClient mSubscriberClient;
@Before
public void setUp() throws Exception {
initHalService(true);
}
private void initHalService(boolean propagatePropertyException) throws Exception {
when(mContext.getResources()).thenReturn(mResources);
mHalService = new VmsHalService(mContext, mVehicleHal, () -> (long) CORE_ID,
propagatePropertyException);
mHalService.setClientManager(mClientManager);
mHalService.setVmsSubscriberService(mSubscriberService);
VehiclePropConfig propConfig = new VehiclePropConfig();
propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
mHalService.takeSupportedProperties(Collections.singleton(propConfig));
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.emptySet(), 0));
mHalService.init();
waitForHandlerCompletion();
// Verify START_SESSION message was sent
InOrder initOrder =
Mockito.inOrder(mClientManager, mSubscriberService, mVehicleHal);
initOrder.verify(mVehicleHal).subscribeProperty(mHalService,
VehicleProperty.VEHICLE_MAP_SERVICE);
initOrder.verify(mVehicleHal).set(createHalMessage(
VmsMessageType.START_SESSION, // Message type
CORE_ID, // Core ID
-1)); // Client ID (unknown)
// Verify no more interections until handshake received
initOrder.verifyNoMoreInteractions();
// Send START_SESSION response from client
sendHalMessage(createHalMessage(
VmsMessageType.START_SESSION, // Message type
CORE_ID, // Core ID
CLIENT_ID // Client ID
));
waitForHandlerCompletion();
// Verify client is marked as connected
ArgumentCaptor<IVmsPublisherClient> publisherCaptor =
ArgumentCaptor.forClass(IVmsPublisherClient.class);
ArgumentCaptor<IVmsSubscriberClient> subscriberCaptor =
ArgumentCaptor.forClass(IVmsSubscriberClient.class);
initOrder.verify(mClientManager, never()).onHalDisconnected();
initOrder.verify(mClientManager)
.onHalConnected(publisherCaptor.capture(), subscriberCaptor.capture());
mPublisherClient = publisherCaptor.getValue();
mSubscriberClient = subscriberCaptor.getValue();
mToken = new Binder();
mPublisherClient.setVmsPublisherService(mToken, mPublisherService);
initOrder.verify(mSubscriberService).getAvailableLayers();
initOrder.verify(mVehicleHal).set(createHalMessage(
VmsMessageType.AVAILABILITY_CHANGE, // Message type
0, // Sequence number
0)); // # of associated layers
waitForHandlerCompletion();
initOrder.verifyNoMoreInteractions();
reset(mClientManager, mSubscriberService, mVehicleHal);
}
@Test
public void testCoreId_IntegerOverflow() throws Exception {
mHalService = new VmsHalService(mContext, mVehicleHal,
() -> (long) Integer.MAX_VALUE + CORE_ID, true);
VehiclePropConfig propConfig = new VehiclePropConfig();
propConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
mHalService.takeSupportedProperties(Collections.singleton(propConfig));
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.emptySet(), 0));
mHalService.init();
waitForHandlerCompletion();
verify(mVehicleHal).set(createHalMessage(
VmsMessageType.START_SESSION, // Message type
CORE_ID, // Core ID
-1)); // Client ID (unknown)
}
@Test
public void testTakeSupportedProperties() {
VehiclePropConfig vmsPropConfig = new VehiclePropConfig();
vmsPropConfig.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
VehiclePropConfig otherPropConfig = new VehiclePropConfig();
otherPropConfig.prop = VehicleProperty.CURRENT_GEAR;
assertEquals(Collections.singleton(vmsPropConfig),
mHalService.takeSupportedProperties(Arrays.asList(otherPropConfig, vmsPropConfig)));
}
/**
* DATA message format:
* <ul>
* <li>Message type
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Publisher ID
* <li>Payload
* </ul>
*/
@Test
public void testHandleDataEvent() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.DATA, // Message type
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // VmsLayer
PUBLISHER_ID // PublisherId
);
message.value.bytes.addAll(PAYLOAD_AS_LIST);
sendHalMessage(message);
verify(mPublisherService).publish(mToken, LAYER, PUBLISHER_ID, PAYLOAD);
}
/**
* SUBSCRIBE message format:
* <ul>
* <li>Message type
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* </ul>
*/
@Test
public void testHandleSubscribeEvent() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.SUBSCRIBE, // Message type
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION // VmsLayer
);
sendHalMessage(message);
verify(mSubscriberService).addVmsSubscriber(mSubscriberClient, LAYER);
}
/**
* SUBSCRIBE_TO_PUBLISHER message format:
* <ul>
* <li>Message type
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Publisher ID
* </ul>
*/
@Test
public void testHandleSubscribeToPublisherEvent() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.SUBSCRIBE_TO_PUBLISHER, // Message type
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // VmsLayer
PUBLISHER_ID // PublisherId
);
sendHalMessage(message);
verify(mSubscriberService).addVmsSubscriberToPublisher(mSubscriberClient, LAYER,
PUBLISHER_ID);
}
/**
* UNSUBSCRIBE message format:
* <ul>
* <li>Message type
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* </ul>
*/
@Test
public void testHandleUnsubscribeEvent() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.UNSUBSCRIBE, // Message type
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION // VmsLayer
);
sendHalMessage(message);
verify(mSubscriberService).removeVmsSubscriber(mSubscriberClient, LAYER);
}
/**
* UNSUBSCRIBE_TO_PUBLISHER message format:
* <ul>
* <li>Message type
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Publisher ID
* </ul>
*/
@Test
public void testHandleUnsubscribeFromPublisherEvent() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER, // Message type
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // VmsLayer
PUBLISHER_ID // PublisherId
);
sendHalMessage(message);
verify(mSubscriberService).removeVmsSubscriberToPublisher(mSubscriberClient, LAYER,
PUBLISHER_ID);
}
/**
* PUBLISHER_ID_REQUEST message format:
* <ul>
* <li>Message type
* <li>Publisher info (bytes)
* </ul>
*
* PUBLISHER_ID_RESPONSE message format:
* <ul>
* <li>Message type
* <li>Publisher ID
* </ul>
*/
@Test
public void testHandlePublisherIdRequestEvent() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.PUBLISHER_ID_REQUEST // Message type
);
request.value.bytes.addAll(PAYLOAD_AS_LIST);
when(mPublisherService.getPublisherId(PAYLOAD)).thenReturn(PUBLISHER_ID);
VehiclePropValue response = createHalMessage(
VmsMessageType.PUBLISHER_ID_RESPONSE, // Message type
PUBLISHER_ID // Publisher ID
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
/**
* PUBLISHER_INFORMATION_REQUEST message format:
* <ul>
* <li>Message type
* <li>Publisher ID
* </ul>
*
* PUBLISHER_INFORMATION_RESPONSE message format:
* <ul>
* <li>Message type
* <li>Publisher info (bytes)
* </ul>
*/
@Test
public void testHandlePublisherInformationRequestEvent() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.PUBLISHER_INFORMATION_REQUEST, // Message type
PUBLISHER_ID // Publisher ID
);
when(mSubscriberService.getPublisherInfo(PUBLISHER_ID)).thenReturn(PAYLOAD);
VehiclePropValue response = createHalMessage(
VmsMessageType.PUBLISHER_INFORMATION_RESPONSE // Message type
);
response.value.bytes.addAll(PAYLOAD_AS_LIST);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
/**
* OFFERING message format:
* <ul>
* <li>Message type
* <li>Publisher ID
* <li>Number of offerings.
* <li>Offerings (x number of offerings)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Number of layer dependencies.
* <li>Layer dependencies (x number of layer dependencies)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* </ul>
* </ul>
* </ul>
*/
@Test
public void testHandleOfferingEvent_ZeroOfferings() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.OFFERING, // Message type
PUBLISHER_ID, // PublisherId
0 // # of offerings
);
sendHalMessage(message);
verify(mPublisherService).setLayersOffering(
mToken,
new VmsLayersOffering(Collections.emptySet(), PUBLISHER_ID));
}
@Test
public void testHandleOfferingEvent_LayerOnly() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.OFFERING, // Message type
PUBLISHER_ID, // PublisherId
1, // # of offerings
// Offered layer
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION,
0 // # of dependencies
);
sendHalMessage(message);
verify(mPublisherService).setLayersOffering(
mToken,
new VmsLayersOffering(Collections.singleton(
new VmsLayerDependency(LAYER)),
PUBLISHER_ID));
}
@Test
public void testHandleOfferingEvent_LayerAndDependency() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.OFFERING, // Message type
PUBLISHER_ID, // PublisherId
1, // # of offerings
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
1, // # of dependencies
4, 5, 6 // Dependency layer
);
sendHalMessage(message);
verify(mPublisherService).setLayersOffering(
mToken,
new VmsLayersOffering(Collections.singleton(
new VmsLayerDependency(LAYER, Collections.singleton(
new VmsLayer(4, 5, 6)))),
PUBLISHER_ID));
}
@Test
public void testHandleOfferingEvent_MultipleLayersAndDependencies() throws Exception {
VehiclePropValue message = createHalMessage(
VmsMessageType.OFFERING, // Message type
PUBLISHER_ID, // PublisherId
3, // # of offerings
// Offered layer #1
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
2, // # of dependencies
4, 5, 6, // Dependency layer
7, 8, 9, // Dependency layer
// Offered layer #2
3, 2, 1, // Layer
0, // # of dependencies
// Offered layer #3
6, 5, 4, // Layer
1, // # of dependencies
7, 8, 9 // Dependency layer
);
sendHalMessage(message);
verify(mPublisherService).setLayersOffering(
mToken,
new VmsLayersOffering(new LinkedHashSet<>(Arrays.asList(
new VmsLayerDependency(LAYER, new LinkedHashSet<>(Arrays.asList(
new VmsLayer(4, 5, 6),
new VmsLayer(7, 8, 9)
))),
new VmsLayerDependency(new VmsLayer(3, 2, 1), Collections.emptySet()),
new VmsLayerDependency(new VmsLayer(6, 5, 4), Collections.singleton(
new VmsLayer(7, 8, 9)
)))),
PUBLISHER_ID));
}
/**
* AVAILABILITY_REQUEST message format:
* <ul>
* <li>Message type
* </ul>
*
* AVAILABILITY_RESPONSE message format:
* <ul>
* <li>Message type
* <li>Sequence number.
* <li>Number of associated layers.
* <li>Associated layers (x number of associated layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Number of publishers
* <li>Publisher ID (x number of publishers)
* </ul>
* </ul>
*/
@Test
public void testHandleAvailabilityRequestEvent_ZeroLayers() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.AVAILABILITY_REQUEST // Message type
);
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.emptySet(), 123));
VehiclePropValue response = createHalMessage(
VmsMessageType.AVAILABILITY_RESPONSE, // Message type
123, // Sequence number
0 // # of associated layers
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
@Test
public void testHandleAvailabilityRequestEvent_OneLayer() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.AVAILABILITY_REQUEST // Message type
);
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.singleton(
new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
VehiclePropValue response = createHalMessage(
VmsMessageType.AVAILABILITY_RESPONSE, // Message type
123, // Sequence number
1, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
1, // # of publisher IDs
PUBLISHER_ID // Publisher ID
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
@Test
public void testHandleAvailabilityRequestEvent_MultipleLayers() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.AVAILABILITY_REQUEST // Message type
);
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
new VmsAssociatedLayer(LAYER,
new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
Collections.emptySet()),
new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
Collections.singleton(99999)))),
123));
VehiclePropValue response = createHalMessage(
VmsMessageType.AVAILABILITY_RESPONSE, // Message type
123, // Sequence number
3, // # of associated layers
// Associated layer #1
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
2, // # of publisher IDs
PUBLISHER_ID, // Publisher ID
54321, // Publisher ID #2
// Associated layer #2
3, 2, 1, // Layer
0, // # of publisher IDs
// Associated layer #3
6, 5, 4, // Layer
1, // # of publisher IDs
99999 // Publisher ID
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
/**
* START_SESSION message format:
* <ul>
* <li>Message type
* <li>Core ID
* <li>Client ID
* </ul>
*/
@Test
public void testHandleStartSessionEvent() throws Exception {
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.emptySet(), 5));
VehiclePropValue request = createHalMessage(
VmsMessageType.START_SESSION, // Message type
-1, // Core ID (unknown)
CLIENT_ID // Client ID
);
VehiclePropValue response = createHalMessage(
VmsMessageType.START_SESSION, // Message type
CORE_ID, // Core ID
CLIENT_ID // Client ID
);
sendHalMessage(request);
InOrder inOrder = Mockito.inOrder(mClientManager, mVehicleHal);
inOrder.verify(mClientManager).onHalDisconnected();
inOrder.verify(mVehicleHal).set(response);
inOrder.verify(mClientManager).onHalConnected(mPublisherClient, mSubscriberClient);
waitForHandlerCompletion();
inOrder.verify(mVehicleHal).set(createHalMessage(
VmsMessageType.AVAILABILITY_CHANGE, // Message type
5, // Sequence number
0)); // # of associated layers
}
/**
* AVAILABILITY_CHANGE message format:
* <ul>
* <li>Message type
* <li>Sequence number.
* <li>Number of associated layers.
* <li>Associated layers (x number of associated layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Number of publishers
* <li>Publisher ID (x number of publishers)
* </ul>
* </ul>
*/
@Test
public void testOnLayersAvailabilityChanged_ZeroLayers() throws Exception {
mSubscriberClient.onLayersAvailabilityChanged(
new VmsAvailableLayers(Collections.emptySet(), 123));
VehiclePropValue message = createHalMessage(
VmsMessageType.AVAILABILITY_CHANGE, // Message type
123, // Sequence number
0 // # of associated layers
);
waitForHandlerCompletion();
verify(mVehicleHal).set(message);
}
@Test
public void testOnLayersAvailabilityChanged_OneLayer() throws Exception {
mSubscriberClient.onLayersAvailabilityChanged(
new VmsAvailableLayers(Collections.singleton(
new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID))), 123));
VehiclePropValue message = createHalMessage(
VmsMessageType.AVAILABILITY_CHANGE, // Message type
123, // Sequence number
1, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
1, // # of publisher IDs
PUBLISHER_ID // Publisher ID
);
waitForHandlerCompletion();
verify(mVehicleHal).set(message);
}
@Test
public void testOnLayersAvailabilityChanged_MultipleLayers() throws Exception {
mSubscriberClient.onLayersAvailabilityChanged(
new VmsAvailableLayers(new LinkedHashSet<>(Arrays.asList(
new VmsAssociatedLayer(LAYER,
new LinkedHashSet<>(Arrays.asList(PUBLISHER_ID, 54321))),
new VmsAssociatedLayer(new VmsLayer(3, 2, 1),
Collections.emptySet()),
new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
Collections.singleton(99999)))),
123));
VehiclePropValue message = createHalMessage(
VmsMessageType.AVAILABILITY_CHANGE, // Message type
123, // Sequence number
3, // # of associated layers
// Associated layer #1
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
2, // # of publisher IDs
PUBLISHER_ID, // Publisher ID
54321, // Publisher ID #2
// Associated layer #2
3, 2, 1, // Layer
0, // # of publisher IDs
// Associated layer #3
6, 5, 4, // Layer
1, // # of publisher IDs
99999 // Publisher ID
);
waitForHandlerCompletion();
verify(mVehicleHal).set(message);
}
/**
* SUBSCRIPTION_REQUEST message format:
* <ul>
* <li>Message type
* </ul>
*
* SUBSCRIPTION_RESPONSE message format:
* <ul>
* <li>Message type
* <li>Sequence number
* <li>Number of layers
* <li>Number of associated layers
* <li>Layers (x number of layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* </ul>
* <li>Associated layers (x number of associated layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Number of publishers
* <li>Publisher ID (x number of publishers)
* </ul>
* </ul>
*/
@Test
public void testHandleSubscriptionsRequestEvent_ZeroLayers() throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_REQUEST // Message type
);
when(mPublisherService.getSubscriptions()).thenReturn(
new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_RESPONSE, // Message type
123, // Sequence number
0, // # of layers
0 // # of associated layers
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
@Test
public void testHandleSubscriptionsRequestEvent_OneLayer_ZeroAssociatedLayers()
throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_REQUEST // Message type
);
when(mPublisherService.getSubscriptions()).thenReturn(
new VmsSubscriptionState(123, Collections.singleton(LAYER),
Collections.emptySet()));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_RESPONSE, // Message type
123, // Sequence number
1, // # of layers
0, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION // Layer
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
@Test
public void testHandleSubscriptionsRequestEvent_ZeroLayers_OneAssociatedLayer()
throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_REQUEST // Message type
);
when(mPublisherService.getSubscriptions()).thenReturn(
new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_RESPONSE, // Message type
123, // Sequence number
0, // # of layers
1, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
1, // # of publisher IDs
PUBLISHER_ID // Publisher ID
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
@Test
public void testHandleSubscriptionsRequestEvent_MultipleLayersAndAssociatedLayers()
throws Exception {
VehiclePropValue request = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_REQUEST // Message type
);
when(mPublisherService.getSubscriptions()).thenReturn(
new VmsSubscriptionState(123,
new LinkedHashSet<>(Arrays.asList(
LAYER,
new VmsLayer(4, 5, 6),
new VmsLayer(7, 8, 9)
)),
new LinkedHashSet<>(Arrays.asList(
new VmsAssociatedLayer(LAYER, Collections.emptySet()),
new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
new LinkedHashSet<>(Arrays.asList(
PUBLISHER_ID,
54321))))))
);
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_RESPONSE, // Message type
123, // Sequence number
3, // # of layers
2, // # of associated layers
// Layer #1
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
// Layer #2
4, 5, 6, // Layer
// Layer #3
7, 8, 9, // Layer
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
0, // # of publisher IDs
6, 5, 4, // Layer
2, // # of publisher IDs
PUBLISHER_ID, // Publisher ID
54321 // Publisher ID #2
);
sendHalMessage(request);
verify(mVehicleHal).set(response);
}
/**
* SUBSCRIPTIONS_CHANGE message format:
* <ul>
* <li>Message type
* <li>Sequence number
* <li>Number of layers
* <li>Number of associated layers
* <li>Layers (x number of layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* </ul>
* <li>Associated layers (x number of associated layers)
* <ul>
* <li>Layer ID
* <li>Layer subtype
* <li>Layer version
* <li>Number of publishers
* <li>Publisher ID (x number of publishers)
* </ul>
* </ul>
*/
@Test
public void testOnVmsSubscriptionChange_ZeroLayers() throws Exception {
mPublisherClient.onVmsSubscriptionChange(
new VmsSubscriptionState(123, Collections.emptySet(), Collections.emptySet()));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_CHANGE, // Message type
123, // Sequence number
0, // # of layers
0 // # of associated layers
);
waitForHandlerCompletion();
verify(mVehicleHal).set(response);
}
@Test
public void testOnVmsSubscriptionChange_OneLayer_ZeroAssociatedLayers()
throws Exception {
mPublisherClient.onVmsSubscriptionChange(
new VmsSubscriptionState(123, Collections.singleton(LAYER),
Collections.emptySet()));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_CHANGE, // Message type
123, // Sequence number
1, // # of layers
0, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION // Layer
);
waitForHandlerCompletion();
verify(mVehicleHal).set(response);
}
@Test
public void testOnVmsSubscriptionChange_ZeroLayers_OneAssociatedLayer()
throws Exception {
mPublisherClient.onVmsSubscriptionChange(
new VmsSubscriptionState(123, Collections.emptySet(), Collections.singleton(
new VmsAssociatedLayer(LAYER, Collections.singleton(PUBLISHER_ID)))));
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_CHANGE, // Message type
123, // Sequence number
0, // # of layers
1, // # of associated layers
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
1, // # of publisher IDs
PUBLISHER_ID // Publisher ID
);
waitForHandlerCompletion();
verify(mVehicleHal).set(response);
}
@Test
public void testOnVmsSubscriptionChange_MultipleLayersAndAssociatedLayers()
throws Exception {
mPublisherClient.onVmsSubscriptionChange(
new VmsSubscriptionState(123,
new LinkedHashSet<>(Arrays.asList(
LAYER,
new VmsLayer(4, 5, 6),
new VmsLayer(7, 8, 9)
)),
new LinkedHashSet<>(Arrays.asList(
new VmsAssociatedLayer(LAYER, Collections.emptySet()),
new VmsAssociatedLayer(new VmsLayer(6, 5, 4),
new LinkedHashSet<>(Arrays.asList(
PUBLISHER_ID,
54321))))))
);
VehiclePropValue response = createHalMessage(
VmsMessageType.SUBSCRIPTIONS_CHANGE, // Message type
123, // Sequence number
3, // # of layers
2, // # of associated layers
// Layer #1
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
// Layer #2
4, 5, 6, // Layer
// Layer #3
7, 8, 9, // Layer
LAYER_TYPE, LAYER_SUBTYPE, LAYER_VERSION, // Layer
0, // # of publisher IDs
6, 5, 4, // Layer
2, // # of publisher IDs
PUBLISHER_ID, // Publisher ID
54321 // Publisher ID #2
);
waitForHandlerCompletion();
verify(mVehicleHal).set(response);
}
@Test
public void testPropertySetExceptionNotPropagated_CoreStartSession() throws Exception {
doThrow(new RuntimeException()).when(mVehicleHal).set(any());
initHalService(false);
mHalService.init();
waitForHandlerCompletion();
}
@Test
public void testPropertySetExceptionNotPropagated_ClientStartSession() throws Exception {
initHalService(false);
when(mSubscriberService.getAvailableLayers()).thenReturn(
new VmsAvailableLayers(Collections.emptySet(), 0));
doThrow(new RuntimeException()).when(mVehicleHal).set(any());
VehiclePropValue request = createHalMessage(
VmsMessageType.START_SESSION, // Message type
-1, // Core ID (unknown)
CLIENT_ID // Client ID
);
sendHalMessage(request);
waitForHandlerCompletion();
}
@Test
public void testDumpMetrics_DefaultConfig() {
mHalService.dumpMetrics(new FileDescriptor());
verifyZeroInteractions(mVehicleHal);
}
@Test
public void testDumpMetrics_NonVendorProperty() throws Exception {
VehiclePropValue vehicleProp = new VehiclePropValue();
vehicleProp.value.bytes.addAll(PAYLOAD_AS_LIST);
when(mVehicleHal.get(anyInt())).thenReturn(vehicleProp);
when(mResources.getInteger(
R.integer.vmsHalClientMetricsProperty)).thenReturn(
VehicleProperty.VEHICLE_MAP_SERVICE);
setUp();
mHalService.dumpMetrics(new FileDescriptor());
verifyZeroInteractions(mVehicleHal);
}
@Test
public void testDumpMetrics_VendorProperty() throws Exception {
int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
when(mResources.getInteger(
R.integer.vmsHalClientMetricsProperty)).thenReturn(
metricsPropertyId);
setUp();
VehiclePropValue metricsProperty = new VehiclePropValue();
metricsProperty.value.bytes.addAll(PAYLOAD_AS_LIST);
when(mVehicleHal.get(metricsPropertyId)).thenReturn(metricsProperty);
try (TemporaryFile dumpsysFile = new TemporaryFile("VmsHalServiceTest")) {
FileOutputStream outputStream = new FileOutputStream(dumpsysFile.getFile());
mHalService.dumpMetrics(outputStream.getFD());
verify(mVehicleHal).get(metricsPropertyId);
FileInputStream inputStream = new FileInputStream(dumpsysFile.getFile());
byte[] dumpsysOutput = new byte[PAYLOAD.length];
assertEquals(PAYLOAD.length, inputStream.read(dumpsysOutput));
assertArrayEquals(PAYLOAD, dumpsysOutput);
}
}
@Test
public void testDumpMetrics_VendorProperty_Timeout() throws Exception {
int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
when(mResources.getInteger(
R.integer.vmsHalClientMetricsProperty)).thenReturn(
metricsPropertyId);
setUp();
when(mVehicleHal.get(metricsPropertyId))
.thenThrow(new PropertyTimeoutException(metricsPropertyId));
mHalService.dumpMetrics(new FileDescriptor());
verify(mVehicleHal).get(metricsPropertyId);
}
@Test
public void testDumpMetrics_VendorProperty_Unavailable() throws Exception {
int metricsPropertyId = VehiclePropertyGroup.VENDOR | 1;
when(mResources.getInteger(
R.integer.vmsHalClientMetricsProperty)).thenReturn(
metricsPropertyId);
setUp();
when(mVehicleHal.get(metricsPropertyId)).thenReturn(null);
mHalService.dumpMetrics(new FileDescriptor());
verify(mVehicleHal).get(metricsPropertyId);
}
private static VehiclePropValue createHalMessage(Integer... message) {
VehiclePropValue result = new VehiclePropValue();
result.prop = VehicleProperty.VEHICLE_MAP_SERVICE;
result.value.int32Values.addAll(Arrays.asList(message));
return result;
}
private void sendHalMessage(VehiclePropValue message) {
mHalService.handleHalEvents(Collections.singletonList(message));
}
private void waitForHandlerCompletion() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
mHalService.getHandler().post(latch::countDown);
latch.await(5, TimeUnit.SECONDS);
}
}