CarVendorExtensionManagerTest.java revision 52d7da59a5445b9e139527a75b795625c174a948
1/* 2 * Copyright (C) 2016 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 17package com.android.car.test; 18 19import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePermissionModel.VEHICLE_PERMISSION_NO_RESTRICTION; 20import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE; 21import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE; 22import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BYTES; 23import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32; 24import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_STRING; 25import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT; 26import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleZone.VEHICLE_ZONE_ROW_1_LEFT; 27import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleZone.VEHICLE_ZONE_ROW_1_RIGHT; 28import static com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue.newBuilder; 29import static java.util.Collections.singletonList; 30 31import android.car.Car; 32import android.car.hardware.CarPropertyConfig; 33import android.car.hardware.CarVendorExtensionManager; 34import android.car.test.CarTestManager; 35import android.car.test.CarTestManagerBinderWrapper; 36import android.os.SystemClock; 37import android.util.Log; 38import android.util.SparseArray; 39 40import com.google.android.collect.Lists; 41import com.google.protobuf.ByteString; 42 43import com.android.car.vehiclenetwork.VehicleNetwork.VehicleNetworkHalMock; 44import com.android.car.vehiclenetwork.VehicleNetworkConsts; 45import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig; 46import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs; 47import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 48import com.android.car.vehiclenetwork.VehiclePropValueUtil; 49 50import org.junit.Assert; 51 52import java.util.Arrays; 53import java.util.List; 54import java.util.Random; 55 56/** 57 * Tests for {@link CarVendorExtensionManager} 58 */ 59public class CarVendorExtensionManagerTest extends MockedCarTestBase { 60 61 private static final String TAG = CarVendorExtensionManager.class.getSimpleName(); 62 63 private static final int CUSTOM_GLOBAL_INT_PROP_ID = 64 VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START; 65 private static final int CUSTOM_ZONED_FLOAT_PROP_ID = 66 VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 1; 67 private static final int CUSTOM_BYTES_PROP_ID_1 = 68 VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 2; 69 private static final int CUSTOM_BYTES_PROP_ID_2 = 70 VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 3; 71 private static final int CUSTOM_STRING_PROP_ID = 72 VehicleNetworkConsts.VEHICLE_PROPERTY_CUSTOM_START + 4; 73 74 private static final float EPS = 1e-9f; 75 private static final int MILLION = 1000 * 1000; 76 77 private static final int MIN_PROP_INT32 = 0x0000005; 78 private static final int MAX_PROP_INT32 = 0xDeadBee; 79 80 private static final float MIN_PROP_FLOAT = 10.42f; 81 private static final float MAX_PROP_FLOAT = 42.10f; 82 83 private static final MockedVehicleHal mVehicleHal = new MockedVehicleHal(); 84 85 private static final VehiclePropConfigs VEHICLE_HAL_CONFIGS = VehiclePropConfigs.newBuilder() 86 .addConfigs(VehiclePropConfig.newBuilder() 87 .setProp(CUSTOM_GLOBAL_INT_PROP_ID) 88 .setAccess(VEHICLE_PROP_ACCESS_READ_WRITE) 89 .setChangeMode(VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) 90 .setValueType(VEHICLE_VALUE_TYPE_INT32) 91 .setPermissionModel(VEHICLE_PERMISSION_NO_RESTRICTION) 92 .addConfigArray(0) 93 .setSampleRateMin(0f) 94 .setSampleRateMax(0f) 95 .addAllInt32Mins(singletonList(MIN_PROP_INT32)) 96 .addAllInt32Maxs(singletonList(MAX_PROP_INT32)) 97 .build()) 98 .addConfigs(VehiclePropConfig.newBuilder() 99 .setProp(CUSTOM_ZONED_FLOAT_PROP_ID) 100 .setAccess(VEHICLE_PROP_ACCESS_READ_WRITE) 101 .setChangeMode(VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) 102 .setValueType(VEHICLE_VALUE_TYPE_ZONED_FLOAT) 103 .setPermissionModel(VEHICLE_PERMISSION_NO_RESTRICTION) 104 .setZones(VEHICLE_ZONE_ROW_1_LEFT | VEHICLE_ZONE_ROW_1_RIGHT) 105 .addConfigArray(0) 106 .setSampleRateMin(0f) 107 .setSampleRateMax(0f) 108 .addAllFloatMins(Lists.newArrayList(MIN_PROP_FLOAT, MIN_PROP_FLOAT)) 109 .addAllFloatMaxs(Lists.newArrayList(MAX_PROP_FLOAT, MAX_PROP_FLOAT)) 110 .build()) 111 .addConfigs(VehiclePropConfig.newBuilder() 112 .setProp(CUSTOM_BYTES_PROP_ID_1) 113 .setAccess(VEHICLE_PROP_ACCESS_READ_WRITE) 114 .setChangeMode(VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) 115 .setValueType(VEHICLE_VALUE_TYPE_BYTES) 116 .setPermissionModel(VEHICLE_PERMISSION_NO_RESTRICTION) 117 .setZones(VEHICLE_ZONE_ROW_1_LEFT | VEHICLE_ZONE_ROW_1_RIGHT) 118 .addConfigArray(0) 119 .setSampleRateMin(0f) 120 .setSampleRateMax(0f) 121 .build()) 122 .addConfigs(VehiclePropConfig.newBuilder() 123 .setProp(CUSTOM_BYTES_PROP_ID_2) 124 .setAccess(VEHICLE_PROP_ACCESS_READ_WRITE) 125 .setChangeMode(VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) 126 .setValueType(VEHICLE_VALUE_TYPE_BYTES) 127 .setPermissionModel(VEHICLE_PERMISSION_NO_RESTRICTION) 128 .addConfigArray(0) 129 .setSampleRateMin(0f) 130 .setSampleRateMax(0f) 131 .build()) 132 .addConfigs(VehiclePropConfig.newBuilder() 133 .setProp(CUSTOM_STRING_PROP_ID) 134 .setAccess(VEHICLE_PROP_ACCESS_READ_WRITE) 135 .setChangeMode(VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) 136 .setValueType(VEHICLE_VALUE_TYPE_STRING) 137 .setPermissionModel(VEHICLE_PERMISSION_NO_RESTRICTION) 138 .addConfigArray(0) 139 .setSampleRateMin(0f) 140 .setSampleRateMax(0f) 141 .build()) 142 .build(); 143 144 private CarVendorExtensionManager mManager; 145 private CarTestManager mCarTestManager; 146 147 @Override 148 protected void setUp() throws Exception { 149 super.setUp(); 150 151 CarTestManagerBinderWrapper testManagerWrapper = 152 (CarTestManagerBinderWrapper) getCar().getCarManager(Car.TEST_SERVICE); 153 154 mCarTestManager = new CarTestManager(testManagerWrapper); 155 mCarTestManager.startMocking(mVehicleHal, 0); 156 157 mManager = (CarVendorExtensionManager) getCar().getCarManager(Car.VENDOR_EXTENSION_SERVICE); 158 assertNotNull(mManager); 159 } 160 161 @Override 162 protected void tearDown() throws Exception { 163 super.tearDown(); 164 mCarTestManager.stopMocking(); 165 } 166 167 public void testPropertyList() throws Exception { 168 List<CarPropertyConfig> configs = mManager.getProperties(); 169 assertEquals(VEHICLE_HAL_CONFIGS.getConfigsCount(), configs.size()); 170 171 SparseArray<CarPropertyConfig> configById = new SparseArray<>(configs.size()); 172 for (CarPropertyConfig config : configs) { 173 configById.put(config.getPropertyId(), config); 174 } 175 176 CarPropertyConfig prop1 = configById.get(CUSTOM_GLOBAL_INT_PROP_ID); 177 assertNotNull(prop1); 178 assertEquals(Integer.class, prop1.getPropertyType()); 179 assertEquals(MIN_PROP_INT32, prop1.getMinValue()); 180 assertEquals(MAX_PROP_INT32, prop1.getMaxValue()); 181 } 182 183 public void testIntGlobalProperty() throws Exception { 184 final int value = 0xbeef; 185 mManager.setGlobalProperty(Integer.class, CUSTOM_GLOBAL_INT_PROP_ID, value); 186 int actualValue = mManager.getGlobalProperty(Integer.class, CUSTOM_GLOBAL_INT_PROP_ID); 187 assertEquals(value, actualValue); 188 } 189 190 public void testFloatZonedProperty() throws Exception { 191 final float value = MIN_PROP_FLOAT + 1; 192 mManager.setProperty( 193 Float.class, 194 CUSTOM_ZONED_FLOAT_PROP_ID, 195 VEHICLE_ZONE_ROW_1_RIGHT, 196 value); 197 198 float actualValue = mManager.getProperty( 199 Float.class, CUSTOM_ZONED_FLOAT_PROP_ID, VEHICLE_ZONE_ROW_1_RIGHT); 200 assertEquals(value, actualValue, EPS); 201 } 202 203 public void testByteArrayProperty() throws Exception { 204 final byte[] expectedData = new byte[] { 1, 2, 3, 4, -1, 127, -127, 0 }; 205 206 // Write to CUSTOM_BYTES_PROP_ID_1 and read this value from CUSTOM_BYTES_PROP_ID_2 207 mManager.setGlobalProperty( 208 byte[].class, 209 CUSTOM_BYTES_PROP_ID_1, 210 expectedData); 211 212 byte[] actualData = mManager.getGlobalProperty( 213 byte[].class, 214 CUSTOM_BYTES_PROP_ID_2); 215 216 assertEquals(Arrays.toString(expectedData), Arrays.toString(actualData)); 217 } 218 219 public void testLargeByteArrayProperty() throws Exception { 220 // Allocate array of byte which is greater than binder transaction buffer limitation. 221 byte[] expectedData = new byte[3 * MILLION]; 222 223 new Random(SystemClock.elapsedRealtimeNanos()) 224 .nextBytes(expectedData); 225 226 // Write to CUSTOM_BYTES_PROP_ID_1 and read this value from CUSTOM_BYTES_PROP_ID_2 227 mManager.setGlobalProperty( 228 byte[].class, 229 CUSTOM_BYTES_PROP_ID_1, 230 expectedData); 231 232 byte[] actualData = mManager.getGlobalProperty( 233 byte[].class, 234 CUSTOM_BYTES_PROP_ID_2); 235 236 Assert.assertArrayEquals(expectedData, actualData); 237 } 238 239 public void testLargeStringProperty() throws Exception { 240 // Allocate string which is greater than binder transaction buffer limitation. 241 String expectedString = generateRandomString(2 * MILLION, 242 "abcdefghijKLMNεὕρηκα!@#$%^&*()[]{}:\"\t\n\r!'"); 243 244 mManager.setGlobalProperty( 245 String.class, 246 CUSTOM_STRING_PROP_ID, 247 expectedString); 248 249 String actualString = mManager.getGlobalProperty( 250 String.class, 251 CUSTOM_STRING_PROP_ID); 252 253 assertEquals(expectedString, actualString); 254 } 255 256 public void testStringProperty() throws Exception { 257 final String expectedString = "εὕρηκα!"; // Test some utf as well. 258 259 mManager.setGlobalProperty( 260 String.class, 261 CUSTOM_STRING_PROP_ID, 262 expectedString); 263 264 String actualString = mManager.getGlobalProperty( 265 String.class, 266 CUSTOM_STRING_PROP_ID); 267 268 assertEquals(expectedString, actualString); 269 } 270 271 private static String generateRandomString(int length, String allowedSymbols) { 272 Random r = new Random(SystemClock.elapsedRealtimeNanos()); 273 StringBuilder sb = new StringBuilder(length); 274 char[] chars = allowedSymbols.toCharArray(); 275 for (int i = 0; i < length; i++) { 276 sb.append(chars[r.nextInt(chars.length)]); 277 } 278 return sb.toString(); 279 } 280 281 private static class MockedVehicleHal implements VehicleNetworkHalMock { 282 private final SparseArray<VehiclePropValue> mValues = new SparseArray<>(); 283 284 private byte[] mBytes = null; 285 286 @Override 287 public VehiclePropConfigs onListProperties() { 288 return VEHICLE_HAL_CONFIGS; 289 } 290 291 @Override 292 public void onPropertySet(VehiclePropValue value) { 293 if (value.getProp() == CUSTOM_BYTES_PROP_ID_1) { 294 mBytes = value.getBytesValue().toByteArray(); 295 } 296 297 mValues.put(value.getProp(), newBuilder(value).build()); 298 } 299 300 @Override 301 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 302 Log.d(TAG, "onPropertyGet: 0x" + Integer.toHexString(value.getProp()) + ", " 303 + VehiclePropValueUtil.toString(value)); 304 305 if (value.getProp() == CUSTOM_BYTES_PROP_ID_2 && mBytes != null) { 306 Log.d(TAG, "Returning byte array property, value: " + Arrays.toString(mBytes)); 307 return VehiclePropValue 308 .newBuilder(value) 309 .setBytesValue(ByteString.copyFrom(mBytes)) 310 .build(); 311 } 312 313 VehiclePropValue existingValue = mValues.get(value.getProp()); 314 if (existingValue != null) { 315 return existingValue; 316 } 317 318 int type = value.getValueType(); 319 320 // VehicleNetwork will fail if we do not set empty data for these properties. 321 if (type == VEHICLE_VALUE_TYPE_BYTES && !value.hasBytesValue()) { 322 return VehiclePropValue.newBuilder(value).setBytesValue(ByteString.EMPTY).build(); 323 } else if (type == VEHICLE_VALUE_TYPE_STRING && !value.hasStringValue()) { 324 return VehiclePropValue.newBuilder(value).setStringValue("").build(); 325 } else { 326 return value; 327 } 328 } 329 330 @Override 331 public void onPropertySubscribe(int property, float sampleRate, int zones) { } 332 333 @Override 334 public void onPropertyUnsubscribe(int property) { } 335 } 336} 337