blob: 9516c7cb24f4fefc3fadf6e1458f760460089e65 [file] [log] [blame]
/*
* Copyright (C) 2019 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.car.Car;
import android.car.VehicleAreaType;
import android.car.vms.VmsAvailableLayers;
import android.car.vms.VmsLayer;
import android.car.vms.VmsPublisherClientService;
import android.car.vms.VmsSubscriberManager;
import android.car.vms.VmsSubscriptionState;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
import android.hardware.automotive.vehicle.V2_0.VmsAvailabilityStateIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.hardware.automotive.vehicle.V2_0.VmsStartSessionMessageIntegerValuesIndex;
import android.util.Log;
import android.util.Pair;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.HidlMockedVehicleHal;
import org.junit.Before;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class MockedVmsTestBase extends MockedCarTestBase {
public static final long PUBLISHER_CLIENT_TIMEOUT = 500L;
public static final long MESSAGE_RECEIVE_TIMEOUT = 500L;
private static final String TAG = "MockedVmsTestBase";
private MockPublisherClient mPublisherClient;
private CountDownLatch mPublisherIsReady = new CountDownLatch(1);
private VmsSubscriberManager mVmsSubscriberManager;
private MockSubscriberClient mSubscriberClient;
private MockHalClient mHalClient;
@Override
protected synchronized void configureMockedHal() {
mHalClient = new MockHalClient();
addProperty(VehicleProperty.VEHICLE_MAP_SERVICE, mHalClient)
.setChangeMode(VehiclePropertyChangeMode.ON_CHANGE)
.setAccess(VehiclePropertyAccess.READ_WRITE)
.addAreaConfig(VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, 0, 0);
}
@Before
public void setUpVms() throws Exception {
mPublisherClient = new MockPublisherClient();
mPublisherClient.setMockCar(getCar());
mVmsSubscriberManager = (VmsSubscriberManager) getCar().getCarManager(
Car.VMS_SUBSCRIBER_SERVICE);
mSubscriberClient = new MockSubscriberClient();
mVmsSubscriberManager.setVmsSubscriberClientCallback(Executors.newSingleThreadExecutor(),
mSubscriberClient);
assertTrue(
"Timeout while waiting for publisher client to be ready",
mPublisherIsReady.await(PUBLISHER_CLIENT_TIMEOUT, TimeUnit.MILLISECONDS));
// Validate session handshake
List<Integer> v = mHalClient.receiveMessage().value.int32Values;
assertEquals(VmsMessageType.START_SESSION,
(int) v.get(VmsBaseMessageIntegerValuesIndex.MESSAGE_TYPE));
int coreId = v.get(VmsStartSessionMessageIntegerValuesIndex.SERVICE_ID);
assertTrue(coreId > 0);
assertEquals(-1, (int) v.get(VmsStartSessionMessageIntegerValuesIndex.CLIENT_ID));
// Send handshake acknowledgement
mHalClient.sendMessage(
VmsMessageType.START_SESSION,
coreId,
12345 // Client ID
);
// Validate layer availability sent to HAL
v = mHalClient.receiveMessage().value.int32Values;
assertEquals(VmsMessageType.AVAILABILITY_CHANGE,
(int) v.get(VmsAvailabilityStateIntegerValuesIndex.MESSAGE_TYPE));
assertEquals(0,
(int) v.get(VmsAvailabilityStateIntegerValuesIndex.SEQUENCE_NUMBER));
assertEquals(0,
(int) v.get(VmsAvailabilityStateIntegerValuesIndex.NUMBER_OF_ASSOCIATED_LAYERS));
}
VmsSubscriberManager getSubscriberManager() {
return mVmsSubscriberManager;
}
MockPublisherClient getMockPublisherClient() {
return mPublisherClient;
}
MockSubscriberClient getMockSubscriberClient() {
return mSubscriberClient;
}
MockHalClient getMockHalClient() {
return mHalClient;
}
class MockPublisherClient extends VmsPublisherClientService {
private BlockingQueue<VmsSubscriptionState> mSubscriptionState =
new LinkedBlockingQueue<>();
void setMockCar(Car car) {
onCarLifecycleChanged(car, true);
}
@Override
protected void onVmsPublisherServiceReady() {
Log.d(TAG, "MockPublisherClient.onVmsPublisherServiceReady");
mPublisherIsReady.countDown();
}
@Override
public void onVmsSubscriptionChange(VmsSubscriptionState subscriptionState) {
Log.d(TAG, "MockPublisherClient.onVmsSubscriptionChange: "
+ subscriptionState.getSequenceNumber());
mSubscriptionState.add(subscriptionState);
}
VmsSubscriptionState receiveSubscriptionState() {
return receiveWithTimeout(mSubscriptionState);
}
}
class MockSubscriberClient implements VmsSubscriberManager.VmsSubscriberClientCallback {
private BlockingQueue<Pair<VmsLayer, byte[]>> mMessages = new LinkedBlockingQueue<>();
private BlockingQueue<VmsAvailableLayers> mAvailableLayers = new LinkedBlockingQueue<>();
@Override
public void onVmsMessageReceived(VmsLayer layer, byte[] payload) {
Log.d(TAG, "MockSubscriberClient.onVmsMessageReceived");
mMessages.add(Pair.create(layer, payload));
}
@Override
public void onLayersAvailabilityChanged(VmsAvailableLayers availableLayers) {
Log.d(TAG, "MockSubscriberClient.onVmsMessageReceived");
mAvailableLayers.add(availableLayers);
}
Pair<VmsLayer, byte[]> receiveMessage() {
return receiveWithTimeout(mMessages);
}
VmsAvailableLayers receiveLayerAvailability() {
return receiveWithTimeout(mAvailableLayers);
}
}
class MockHalClient implements HidlMockedVehicleHal.VehicleHalPropertyHandler {
private BlockingQueue<VehiclePropValue> mMessages = new LinkedBlockingQueue<>();
@Override
public void onPropertySet(VehiclePropValue value) {
Log.d(TAG, "MockHalClient.onPropertySet");
if (value.prop == VehicleProperty.VEHICLE_MAP_SERVICE) {
mMessages.add(value);
}
}
void sendMessage(int... message) {
getHidlMockedVehicleHal().injectEvent(
VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
.addIntValue(message)
.build());
}
void sendMessage(int[] message, byte[] payload) {
getHidlMockedVehicleHal().injectEvent(
VehiclePropValueBuilder.newBuilder(VehicleProperty.VEHICLE_MAP_SERVICE)
.addIntValue(message)
.addByteValue(payload)
.build());
}
VehiclePropValue receiveMessage() {
return receiveWithTimeout(mMessages);
}
}
private static <T> T receiveWithTimeout(BlockingQueue<T> queue) {
try {
return queue.poll(MESSAGE_RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}