blob: adcc336a532083088f03d41fbe40184426db6ac6 [file] [log] [blame]
/*
* Copyright (C) 2016 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.vehiclenetwork.haltest;
import static java.lang.Integer.toHexString;
import android.car.VehicleZoneUtil;
import android.os.HandlerThread;
import android.test.AndroidTestCase;
import android.util.Log;
import com.android.car.vehiclenetwork.VehicleNetwork;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
import java.util.HashMap;
import java.util.Map;
/**
* Base class for testing vehicle HAL using vehicle network service (VNS).
*/
public class VnsHalBaseTestCase extends AndroidTestCase {
protected static final String TAG = "VnsHalTest";
protected static final int PROP_TIMEOUT_MS = 5000;
protected static final int NO_ZONE = -1;
private final HandlerThread mHandlerThread =
new HandlerThread(VnsHalBaseTestCase.class.getSimpleName());
protected VehicleNetwork mVehicleNetwork;
protected RecordingVehicleNetworkListener mListener;
protected Map<Integer, VehiclePropConfig> mConfigsMap;
@Override
protected void setUp() throws Exception {
super.setUp();
mHandlerThread.start();
mListener = new RecordingVehicleNetworkListener();
mVehicleNetwork = VehicleNetwork.createVehicleNetwork(mListener,
mHandlerThread.getLooper());
setupConfigsMap();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
mHandlerThread.quit();
}
private void setupConfigsMap() {
mConfigsMap = new HashMap<>();
for (VehiclePropConfig config : mVehicleNetwork.listProperties().getConfigsList()) {
mConfigsMap.put(config.getProp(), config);
}
assertTrue(mConfigsMap.size() > 0);
}
protected boolean isPropertyAvailable(int... properties) {
assertTrue(properties.length > 0);
for (int propertyId : properties) {
if (!mConfigsMap.containsKey(propertyId)) {
// Property is not supported by vehicle HAL, nothing to test.
Log.w(TAG, "Property: 0x" + Integer.toHexString(propertyId)
+ " is not available, ignoring...");
return false;
}
}
return true;
}
protected void setPropertyAndVerify(int propertyId, boolean switchOn) {
setPropertyAndVerify(propertyId, NO_ZONE, switchOn);
}
protected void setPropertyAndVerify(int propertyId, int zone, boolean switchOn) {
int val = switchOn ? 1 : 0;
if (zone == NO_ZONE) {
mVehicleNetwork.setBooleanProperty(propertyId, switchOn);
} else {
mVehicleNetwork.setZonedBooleanProperty(propertyId, zone, switchOn);
}
verifyValue(propertyId, zone, val);
}
protected void setPropertyAndVerify(String message, int propertyId, int zone, int value) {
if (zone == NO_ZONE) {
mVehicleNetwork.setIntProperty(propertyId, value);
} else {
mVehicleNetwork.setZonedIntProperty(propertyId, zone, value);
}
verifyValue(message, propertyId, zone, value);
}
protected void verifyValue(int propertyId, boolean val) {
verifyValue(propertyId, NO_ZONE, val);
}
protected void verifyValue(int propertyId, int zone, boolean val) {
int intVal = val ? 1 : 0;
assertEquals(intVal, waitForIntValue(propertyId, zone, intVal));
}
protected void verifyValue(int propertyId, int zone, int val) {
assertEquals(val, waitForIntValue(propertyId, zone, val));
}
protected void verifyValue(String message, int propertyId, int zone, int val) {
assertEquals(message, val, waitForIntValue(propertyId, zone, val));
}
protected int getFirstZoneForProperty(int propertyId) {
return VehicleZoneUtil.getFirstZone(mConfigsMap.get(propertyId).getZones());
}
protected void verifyIntZonedProperty(int propertyId) throws InterruptedException {
if (!isPropertyAvailable(propertyId)) {
return;
}
VehiclePropConfig config = mConfigsMap.get(propertyId);
// Assert setting edge-case values.
iterateOnZones(config, (message, zone, minValue, maxValue) -> {
setPropertyAndVerify(message, propertyId, zone, minValue);
setPropertyAndVerify(message, propertyId, zone, maxValue);
});
// Setting out of the range values.
iterateOnZones(config, ((message, zone, minValue, maxValue) -> {
mVehicleNetwork.setZonedIntProperty(propertyId, zone, minValue - 1);
verifyValue(message, propertyId, zone, minValue);
mVehicleNetwork.setZonedIntProperty(propertyId, zone, maxValue + 20);
verifyValue(message, propertyId, zone, maxValue);
}));
// Verify that subsequent SET calls will result in correct value at the end.
mVehicleNetwork.subscribe(propertyId, 0f, config.getZones());
int zone = VehicleZoneUtil.getFirstZone(config.getZones());
int minValue = config.getInt32Mins(0);
int maxValue = config.getInt32Maxs(0);
int finalValue = (minValue + maxValue) / 2;
mListener.reset();
// We can only expect to see finalValue in the events as vehicle HAL may batch
// set commands and use only last value.
mListener.addExpectedValues(propertyId, zone, finalValue);
mVehicleNetwork.setZonedIntProperty(propertyId, zone, minValue);
mVehicleNetwork.setZonedIntProperty(propertyId, zone, maxValue);
mVehicleNetwork.setZonedIntProperty(propertyId, zone, finalValue);
verifyValue(propertyId, zone, finalValue);
mListener.waitAndVerifyValues();
mVehicleNetwork.unsubscribe(propertyId);
}
protected int waitForIntValue(int propertyId, int zone, int expectedValue) {
int actualValue = mVehicleNetwork.getZonedIntProperty(propertyId, zone);
long deadline = System.currentTimeMillis() + PROP_TIMEOUT_MS;
while (System.currentTimeMillis() <= deadline && actualValue != expectedValue) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
actualValue = mVehicleNetwork.getZonedIntProperty(propertyId, zone);
}
return actualValue;
}
protected void iterateOnZones(VehiclePropConfig config, IntZonesFunctor f) {
int[] zones = VehicleZoneUtil.listAllZones(config.getZones());
int zoneIndex = 0;
boolean isBooleanType = config.getValueType() ==
VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN;
for (int zone : zones) {
int minValue = isBooleanType ? 0 : config.getInt32Mins(zoneIndex);
int maxValue = isBooleanType ? 1 : config.getInt32Maxs(zoneIndex);
String message = "PropertyId: 0x" + toHexString(config.getProp())
+ ", zone[" + zoneIndex + "]: 0x" + toHexString(zone);
f.func(message, zone, minValue, maxValue);
zoneIndex++;
}
}
protected interface IntZonesFunctor {
void func(String message, int zone, int minValue, int maxValue);
}
}