1 /* 2 * Copyright (C) 2022 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 17 package com.android.car.hal.fakevhal; 18 19 import static org.junit.Assert.assertThrows; 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.after; 23 import static org.mockito.Mockito.atLeastOnce; 24 import static org.mockito.Mockito.atMost; 25 import static org.mockito.Mockito.clearInvocations; 26 import static org.mockito.Mockito.doNothing; 27 import static org.mockito.Mockito.doThrow; 28 import static org.mockito.Mockito.mock; 29 import static org.mockito.Mockito.reset; 30 import static org.mockito.Mockito.timeout; 31 import static org.mockito.Mockito.times; 32 import static org.mockito.Mockito.verify; 33 import static org.mockito.Mockito.when; 34 35 import android.car.hardware.property.CarPropertyManager; 36 import android.hardware.automotive.vehicle.FuelType; 37 import android.hardware.automotive.vehicle.RawPropValues; 38 import android.hardware.automotive.vehicle.StatusCode; 39 import android.hardware.automotive.vehicle.SubscribeOptions; 40 import android.hardware.automotive.vehicle.VehicleAreaConfig; 41 import android.hardware.automotive.vehicle.VehicleAreaDoor; 42 import android.hardware.automotive.vehicle.VehicleAreaSeat; 43 import android.hardware.automotive.vehicle.VehicleAreaWindow; 44 import android.hardware.automotive.vehicle.VehicleOilLevel; 45 import android.hardware.automotive.vehicle.VehiclePropConfig; 46 import android.hardware.automotive.vehicle.VehiclePropValue; 47 import android.hardware.automotive.vehicle.VehicleProperty; 48 import android.hardware.automotive.vehicle.VehiclePropertyAccess; 49 import android.os.RemoteException; 50 import android.os.ServiceSpecificException; 51 import android.os.SystemClock; 52 import android.platform.test.ravenwood.RavenwoodRule; 53 import android.util.SparseArray; 54 55 import androidx.test.filters.SmallTest; 56 57 import com.android.car.IVehicleDeathRecipient; 58 import com.android.car.VehicleStub; 59 import com.android.car.VehicleStub.AsyncGetSetRequest; 60 import com.android.car.VehicleStub.GetVehicleStubAsyncResult; 61 import com.android.car.VehicleStub.SetVehicleStubAsyncResult; 62 import com.android.car.VehicleStub.SubscriptionClient; 63 import com.android.car.VehicleStub.VehicleStubCallbackInterface; 64 import com.android.car.hal.AidlHalPropConfig; 65 import com.android.car.hal.HalPropConfig; 66 import com.android.car.hal.HalPropValue; 67 import com.android.car.hal.HalPropValueBuilder; 68 import com.android.car.hal.VehicleHalCallback; 69 import com.android.car.internal.property.CarPropertyErrorCodes; 70 71 import com.google.common.truth.Expect; 72 73 import org.junit.Before; 74 import org.junit.Rule; 75 import org.junit.Test; 76 import org.junit.runner.RunWith; 77 import org.mockito.ArgumentCaptor; 78 import org.mockito.Captor; 79 import org.mockito.Mock; 80 import org.mockito.junit.MockitoJUnitRunner; 81 82 import java.io.File; 83 import java.io.FileDescriptor; 84 import java.io.FileOutputStream; 85 import java.io.InputStream; 86 import java.util.ArrayList; 87 import java.util.List; 88 89 @SmallTest 90 @RunWith(MockitoJUnitRunner.class) 91 public class FakeVehicleStubUnitTest { 92 93 private static final int DOOR_1_LEFT = VehicleAreaDoor.ROW_1_LEFT; 94 private static final int WINDOW_1_LEFT = VehicleAreaWindow.ROW_1_LEFT; 95 private static final int SEAT_1_LEFT = VehicleAreaSeat.ROW_1_LEFT; 96 private static final int SEAT_1_RIGHT = VehicleAreaSeat.ROW_1_RIGHT; 97 private static final int HVAC_LEFT = SEAT_1_LEFT | VehicleAreaSeat.ROW_2_LEFT 98 | VehicleAreaSeat.ROW_2_CENTER; 99 private static final int HVAC_ALL = HVAC_LEFT | SEAT_1_RIGHT | VehicleAreaSeat.ROW_2_RIGHT; 100 private static final String PROPERTY_CONFIG_STRING_ON_CHANGE = "{\"property\":" 101 + "\"VehicleProperty::ENGINE_OIL_LEVEL\"," 102 + "\"defaultValue\": {\"int32Values\": [\"VehicleOilLevel::NORMAL\"]}," 103 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 104 + "\"changeMode\": \"VehiclePropertyChangeMode::ON_CHANGE\"}"; 105 private static final String PROPERTY_CONFIG_STRING_CONTINUOUS = "{\"property\":" 106 + "\"VehicleProperty::FUEL_LEVEL\"," 107 + "\"defaultValue\": {\"floatValues\": [100]}," 108 + "\"access\": \"VehiclePropertyAccess::READ\"," 109 + "\"changeMode\": \"VehiclePropertyChangeMode::CONTINUOUS\"," 110 + "\"maxSampleRate\": 100.0," 111 + "\"minSampleRate\": 1.0}"; 112 private static final String PROPERTY_CONFIG_STRING_CONTINUOUS_2 = "{\"property\":" 113 + "\"VehicleProperty::EV_BATTERY_LEVEL\"," 114 + "\"defaultValue\": {\"floatValues\": [100]}," 115 + "\"access\": \"VehiclePropertyAccess::READ\"," 116 + "\"changeMode\": \"VehiclePropertyChangeMode::CONTINUOUS\"," 117 + "\"maxSampleRate\": 100.0," 118 + "\"minSampleRate\": 1.0}"; 119 private static final String PROPERTY_CONFIG_STRING_STATIC = "{\"property\":" 120 + "\"VehicleProperty::INFO_FUEL_TYPE\"," 121 + "\"defaultValue\": {\"int32Values\": [\"FuelType::FUEL_TYPE_UNLEADED\"]}," 122 + "\"access\": \"VehiclePropertyAccess::READ\"," 123 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"}"; 124 private static final String PROPERTY_CONFIG_STRING_HVAC_POWER_ON = "{\"property\":" 125 + "\"VehicleProperty::HVAC_POWER_ON\"," 126 + "\"defaultValue\": {\"int32Values\": [1]}," 127 + "\"areas\": [{\"areaId\": \"Constants::HVAC_ALL\"}]," 128 + "\"configArray\": [\"VehicleProperty::HVAC_FAN_SPEED\"," 129 + "\"VehicleProperty::HVAC_FAN_DIRECTION\"]}"; 130 private static final String PROPERTY_CONFIG_STRING_HVAC_POWER_OFF = "{\"property\":" 131 + "\"VehicleProperty::HVAC_POWER_ON\"," 132 + "\"defaultValue\": {\"int32Values\": [0]}," 133 + "\"areas\": [{\"areaId\": \"Constants::HVAC_ALL\"}]," 134 + "\"configArray\": [\"VehicleProperty::HVAC_FAN_SPEED\"," 135 + "\"VehicleProperty::HVAC_FAN_DIRECTION\"]}"; 136 private static final String PROPERTY_CONFIG_STRING_HVAC_FAN_SPEED = "{\"property\":" 137 + "\"VehicleProperty::HVAC_FAN_SPEED\"," 138 + "\"defaultValue\": {\"int32Values\": [3]}," 139 + "\"areas\": [{" 140 + "\"areaId\": \"Constants::HVAC_ALL\"," 141 + "\"minInt32Value\": 1," 142 + "\"maxInt32Value\": 7}]}"; 143 private static final int DEFAULT_TIMEOUT = 1000; 144 @Captor 145 private ArgumentCaptor<List<GetVehicleStubAsyncResult>> mGetVehicleStubAsyncResultCaptor; 146 @Captor 147 private ArgumentCaptor<List<SetVehicleStubAsyncResult>> mSetVehicleStubAsyncResultCaptor; 148 149 @Mock 150 private VehicleStub mMockRealVehicleStub; 151 @Mock 152 private FakeVhalConfigParser mParser; 153 @Mock 154 private VehicleStubCallbackInterface mCallback; 155 156 @Rule 157 public final Expect expect = Expect.create(); 158 @Rule 159 public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder() 160 .setProvideMainThread(true) 161 .build(); 162 163 @Before setup()164 public void setup() throws Exception { 165 when(mMockRealVehicleStub.isValid()).thenReturn(true); 166 when(mMockRealVehicleStub.getAllPropConfigs()).thenReturn(new HalPropConfig[0]); 167 } 168 169 @Test testGetAllPropConfigsWithoutCustomConfig()170 public void testGetAllPropConfigsWithoutCustomConfig() throws Exception { 171 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 172 new FakeVhalConfigParser(), new ArrayList<>()); 173 174 HalPropConfig[] allPropConfig = fakeVehicleStub.getAllPropConfigs(); 175 HalPropConfig propConfigInfo = getPropConfigByPropId(allPropConfig, 176 VehicleProperty.INFO_MAKE); 177 HalPropConfig propConfigWindow = getPropConfigByPropId(allPropConfig, 178 VehicleProperty.WINDOW_POS); 179 180 expect.that(fakeVehicleStub.isValid()).isTrue(); 181 expect.that(propConfigInfo.getPropId()).isEqualTo(VehicleProperty.INFO_MAKE); 182 expect.that(propConfigWindow.getAreaConfigs()[0].getAreaId()) 183 .isEqualTo(VehicleAreaWindow.ROW_1_LEFT); 184 expect.that(propConfigWindow.getAreaConfigs()[0].getMaxInt32Value()).isEqualTo(10); 185 } 186 187 @Test testGetAllPropConfigsWithCustomConfigHasExistingPropId()188 public void testGetAllPropConfigsWithCustomConfigHasExistingPropId() throws Exception { 189 // Create a custom config file. 190 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::TIRE_PRESSURE\"," 191 + "\"defaultValue\": {\"floatValues\": [200.0]}, \"maxSampleRate\": 2.5}]}"; 192 List<File> customFileList = createFilenameList(jsonString); 193 194 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 195 new FakeVhalConfigParser(), customFileList); 196 HalPropConfig[] allPropConfig = fakeVehicleStub.getAllPropConfigs(); 197 HalPropConfig propConfig = getPropConfigByPropId(allPropConfig, 198 VehicleProperty.TIRE_PRESSURE); 199 200 expect.that(propConfig.getPropId()).isEqualTo(VehicleProperty.TIRE_PRESSURE); 201 expect.that(propConfig.getMaxSampleRate()).isEqualTo(2.5f); 202 } 203 204 @Test testGetAllPropConfigsWithCustomConfigHasNonExistingPropId()205 public void testGetAllPropConfigsWithCustomConfigHasNonExistingPropId() throws Exception { 206 // Create a custom config file. 207 String jsonString = "{\"properties\": [{\"property\": 123," 208 + "\"defaultValue\": {\"floatValues\": [200.0]}, " 209 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 210 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"," 211 + "\"maxSampleRate\": 5.0}]}"; 212 List<File> customFileList = createFilenameList(jsonString); 213 214 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 215 new FakeVhalConfigParser(), customFileList); 216 HalPropConfig[] allPropConfig = fakeVehicleStub.getAllPropConfigs(); 217 HalPropConfig propConfig = getPropConfigByPropId(allPropConfig, 123); 218 219 expect.that(propConfig.getPropId()).isEqualTo(123); 220 expect.that(propConfig.getMaxSampleRate()).isEqualTo(5.0f); 221 expect.that(allPropConfig.length).isEqualTo(new FakeVehicleStub(mMockRealVehicleStub, 222 new FakeVhalConfigParser(), new ArrayList<>()).getAllPropConfigs().length + 1); 223 } 224 225 @Test testGetAllPropConfigsWithSpecialProp()226 public void testGetAllPropConfigsWithSpecialProp() throws Exception { 227 // Access permission of VHAL_HEARTBEAT has been overridden by the mocked return result of 228 // AidlVehicleStub.getAllPropConfigs(). 229 when(mMockRealVehicleStub.getAllPropConfigs()).thenReturn(new HalPropConfig[]{ 230 new AidlHalPropConfig(createConfig(VehicleProperty.VHAL_HEARTBEAT, 231 /* sampleRate= */ 0, VehiclePropertyAccess.READ_WRITE, /* areaId= */ 0))}); 232 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 233 new FakeVhalConfigParser(), new ArrayList<>()); 234 235 HalPropConfig propConfig = getPropConfigByPropId(fakeVehicleStub.getAllPropConfigs(), 236 VehicleProperty.VHAL_HEARTBEAT); 237 238 verify(mMockRealVehicleStub, atLeastOnce()).getAllPropConfigs(); 239 expect.that(propConfig.getAccess()).isEqualTo(VehiclePropertyAccess.READ_WRITE); 240 } 241 242 @Test testParseConfigFilesThrowException()243 public void testParseConfigFilesThrowException() throws Exception { 244 when(mParser.parseJsonConfig(any(InputStream.class))).thenThrow( 245 new IllegalArgumentException("This file does not contain a valid JSONObject.")); 246 247 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 248 () -> new FakeVehicleStub(mMockRealVehicleStub, mParser, new ArrayList<>())); 249 250 expect.that(thrown).hasMessageThat().contains("This file does not contain a valid " 251 + "JSONObject."); 252 } 253 254 @Test testNoCustomFile()255 public void testNoCustomFile() throws Exception { 256 SparseArray<ConfigDeclaration> defaultParseResult = createParseResult( 257 /* propId= */ 123, /* maxSampleRate= */ 10.0f, 258 /* access= */ VehiclePropertyAccess.NONE, /* areaId= */ 0); 259 when(mParser.parseJsonConfig(any(InputStream.class))).thenReturn(defaultParseResult); 260 261 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, mParser, 262 new ArrayList<>()); 263 HalPropConfig[] allPropConfig = fakeVehicleStub.getAllPropConfigs(); 264 265 expect.that(allPropConfig.length).isEqualTo(defaultParseResult.size()); 266 } 267 268 @Test testCustomFileParseFailure()269 public void testCustomFileParseFailure() throws Exception { 270 // Parse this custom config file will throw an IllegalArgumentException with message 271 // "properties field value is not a valid JSONArray." 272 String jsonString = "{\"property\": 123," 273 + "\"defaultValue\": {\"floatValues\": [200.0]}, " 274 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 275 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"," 276 + "\"maxSampleRate\": 5.0}"; 277 List<File> customFileList = createFilenameList(jsonString); 278 279 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 280 new FakeVhalConfigParser(), customFileList); 281 282 expect.that(fakeVehicleStub.isFakeModeEnabled()).isEqualTo(true); 283 } 284 285 @Test testCustomFilesOneParseSuccessOneParseFailure()286 public void testCustomFilesOneParseSuccessOneParseFailure() throws Exception { 287 String validJsonString = "{\"properties\":[" 288 + "{\"property\": \"VehicleProperty::INFO_FUEL_TYPE\"," 289 + "\"defaultValue\": {\"floatValues\": [200.0]}, " 290 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 291 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"," 292 + "\"maxSampleRate\": 5.0}]}"; 293 List<File> customFileList = createFilenameList(validJsonString); 294 // Parse this custom config file will throw an IllegalArgumentException with message 295 // "properties field value is not a valid JSONArray." 296 String invalidJsonString = "{\"property\": 123," 297 + "\"defaultValue\": {\"floatValues\": [200.0]}, " 298 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 299 + "\"changeMode\": \"VehiclePropertyChangeMode::STATIC\"," 300 + "\"maxSampleRate\": 5.0}"; 301 customFileList.addAll(createFilenameList(invalidJsonString)); 302 // Create a request prop value. 303 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 304 .build(/* prop= */ VehicleProperty.INFO_FUEL_TYPE, /* areaId= */ 0); 305 306 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 307 new FakeVhalConfigParser(), customFileList); 308 309 expect.that(fakeVehicleStub.isFakeModeEnabled()).isEqualTo(true); 310 expect.that(fakeVehicleStub.get(requestPropValue).getPropId()) 311 .isEqualTo(VehicleProperty.INFO_FUEL_TYPE); 312 expect.that(fakeVehicleStub.get(requestPropValue).getFloatValue(0)).isEqualTo(200); 313 } 314 315 @Test testGetMethodPropIdNotSupported()316 public void testGetMethodPropIdNotSupported() throws Exception { 317 // Mock config files parsing results to be empty. 318 when(mParser.parseJsonConfig(any(InputStream.class))).thenReturn(new SparseArray<>()); 319 // Create a request prop value. 320 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 321 .build(/* prop= */ VehicleProperty.INFO_FUEL_TYPE, /* areaId= */ 0); 322 // Create a FakeVehicleStub instance. 323 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, mParser, 324 new ArrayList<>()); 325 326 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 327 () -> fakeVehicleStub.get(requestPropValue)); 328 329 330 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 331 expect.that(thrown).hasMessageThat().contains("The propId: " 332 + VehicleProperty.INFO_FUEL_TYPE + " is not supported."); 333 } 334 335 @Test testGetMethodNoReadPermission()336 public void testGetMethodNoReadPermission() throws Exception { 337 // Create a custom config file. 338 String jsonString = "{\"properties\": [{\"property\": " 339 + "\"VehicleProperty::ANDROID_EPOCH_TIME\"," 340 + "\"access\": \"VehiclePropertyAccess::WRITE\"}]}"; 341 List<File> customFileList = createFilenameList(jsonString); 342 // Create a request prop value. 343 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 344 .build(/* prop= */ VehicleProperty.ANDROID_EPOCH_TIME, /* areaId= */ 0); 345 // Create a FakeVehicleStub instance. 346 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 347 new FakeVhalConfigParser(), customFileList); 348 349 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 350 () -> fakeVehicleStub.get(requestPropValue)); 351 352 expect.that(thrown.errorCode).isEqualTo(StatusCode.ACCESS_DENIED); 353 expect.that(thrown).hasMessageThat().contains("doesn't have read permission"); 354 } 355 356 @Test testGetMethodPropIdIsGlobalHasNoDefaultValueAreaIdIgnored()357 public void testGetMethodPropIdIsGlobalHasNoDefaultValueAreaIdIgnored() throws Exception { 358 // Create a custom config file. 359 String jsonString = "{\"properties\": [{\"property\": " 360 + "\"VehicleProperty::INFO_FUEL_CAPACITY\"}]}"; 361 List<File> customFileList = createFilenameList(jsonString); 362 // Create a request prop value. 363 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 364 .build(/* prop= */ VehicleProperty.INFO_FUEL_CAPACITY, /* areaId= */ 123); 365 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 366 new FakeVhalConfigParser(), customFileList); 367 368 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 369 () -> fakeVehicleStub.get(requestPropValue)); 370 371 // For global properties, if default value is not defined, will throw 372 // ServiceSpecificException with StatusCode.NOT_AVAILABLE. 373 expect.that(thrown.errorCode).isEqualTo(StatusCode.NOT_AVAILABLE); 374 expect.that(thrown).hasMessageThat().contains("propId: " 375 + VehicleProperty.INFO_FUEL_CAPACITY + " has no property value."); 376 } 377 378 @Test testGetMethodGlobalPropWithAreaIdNotZero()379 public void testGetMethodGlobalPropWithAreaIdNotZero() throws Exception { 380 // Create a custom config file. 381 String jsonString = "{\"properties\": [{\"property\":" 382 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 383 + "\"defaultValue\": {\"int32Values\": [100]}," 384 + "\"areas\": [{\"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 100}]}]}"; 385 List<File> customFileList = createFilenameList(jsonString); 386 // Create a request prop value. 387 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 388 .build(/* prop= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 1); 389 390 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 391 new FakeVhalConfigParser(), customFileList); 392 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 393 () -> fakeVehicleStub.get(requestPropValue)); 394 395 // For global properties, if the supported area config array doesn't include 0, 396 // a ServiceSpecificException with StatusCode.INVALID_ARG. 397 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 398 expect.that(thrown).hasMessageThat().contains("The areaId: 0 is not supported."); 399 } 400 401 @Test testGetMethodPropIdIsGlobalHasDefaultValueAreaIdIgnored()402 public void testGetMethodPropIdIsGlobalHasDefaultValueAreaIdIgnored() throws Exception { 403 // Create a custom config file. 404 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::INFO_FUEL_TYPE\"," 405 + "\"defaultValue\": {\"int32Values\": [\"FuelType::FUEL_TYPE_UNLEADED\"]}}]}"; 406 List<File> customFileList = createFilenameList(jsonString); 407 // Create a request prop value. 408 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 409 .build(/* prop= */ VehicleProperty.INFO_FUEL_TYPE, /* areaId= */ 123); 410 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 411 new FakeVhalConfigParser(), customFileList); 412 413 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 414 415 // For global properties, if default value exists, will return the default value. 416 expect.that(propValue.getAreaId()).isEqualTo(0); 417 expect.that(propValue.getInt32ValuesSize()).isEqualTo(1); 418 expect.that(propValue.getInt32Value(0)).isEqualTo(FuelType.FUEL_TYPE_UNLEADED); 419 } 420 421 @Test testGetMethodPropIdHasAreasHasNoDefaultValueHasNoAreaValue()422 public void testGetMethodPropIdHasAreasHasNoDefaultValueHasNoAreaValue() throws Exception { 423 // Create a custom config file. 424 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::WINDOW_POS\"," 425 + "\"areas\": [{\"areaId\": \"Constants::WINDOW_1_LEFT\", \"minInt32Value\": 0," 426 + "\"maxInt32Value\": 10}]}]}"; 427 List<File> customFileList = createFilenameList(jsonString); 428 // Create a request prop value. 429 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 430 .build(/* prop= */ VehicleProperty.WINDOW_POS, /* areaId= */ WINDOW_1_LEFT); 431 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 432 new FakeVhalConfigParser(), customFileList); 433 434 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 435 () -> fakeVehicleStub.get(requestPropValue)); 436 437 // For properties have areas, if neither default prop value nor area value exists, then 438 // throw a ServiceSpecificException of StatusCode.NOT_AVAILABLE. 439 expect.that(thrown.errorCode).isEqualTo(StatusCode.NOT_AVAILABLE); 440 expect.that(thrown).hasMessageThat().contains("propId: " 441 + VehicleProperty.WINDOW_POS + ", areaId: " + WINDOW_1_LEFT + " has no property " 442 + "value"); 443 } 444 445 @Test testGetMethodPropIdHasAreasHasDefaultValueHasNoAreaValue()446 public void testGetMethodPropIdHasAreasHasDefaultValueHasNoAreaValue() throws Exception { 447 // Create a custom config file. 448 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::WINDOW_POS\"," 449 + "\"defaultValue\": {\"int32Values\": [0]},\"areas\": [{\"areaId\":" 450 + "\"Constants::WINDOW_1_LEFT\", \"minInt32Value\": 0, \"maxInt32Value\": 10}]}]}"; 451 List<File> customFileList = createFilenameList(jsonString); 452 // Create a request prop value. 453 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 454 .build(/* prop= */ VehicleProperty.WINDOW_POS, /* areaId= */ WINDOW_1_LEFT); 455 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 456 new FakeVhalConfigParser(), customFileList); 457 458 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 459 460 // For properties have areas, expect that default prop value will override area value when 461 // default prop value is set but the area value is not defined. 462 expect.that(propValue.getAreaId()).isEqualTo(WINDOW_1_LEFT); 463 expect.that(propValue.getInt32ValuesSize()).isEqualTo(1); 464 expect.that(propValue.getInt32Value(0)).isEqualTo(0); 465 } 466 467 @Test testGetMethodPropIdHasAreasHasAreaValue()468 public void testGetMethodPropIdHasAreasHasAreaValue() throws Exception { 469 // Create a custom config file. 470 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::DOOR_LOCK\"," 471 + "\"areas\": [{\"defaultValue\": {\"int32Values\": [1]}, \"areaId\":" 472 + "\"Constants::DOOR_1_LEFT\"}]}]}"; 473 List<File> customFileList = createFilenameList(jsonString); 474 // Create a request prop value. 475 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 476 .build(VehicleProperty.DOOR_LOCK, DOOR_1_LEFT); 477 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 478 new FakeVhalConfigParser(), customFileList); 479 480 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 481 482 // For properties have areas, get method returns the area value if it exists. 483 expect.that(propValue.getPropId()).isEqualTo(VehicleProperty.DOOR_LOCK); 484 expect.that(propValue.getInt32Value(0)).isEqualTo(1); 485 } 486 487 @Test testGetMethodPropIdHasAreasAreaIdNotSupport()488 public void testGetMethodPropIdHasAreasAreaIdNotSupport() throws Exception { 489 // Create a custom config file. 490 String jsonString = "{\"properties\": [{\"property\":" 491 + "\"VehicleProperty::SEAT_BELT_BUCKLED\"," 492 + "\"defaultValue\": {\"int32Values\": [0]}," 493 + "\"areas\": [{\"areaId\": \"Constants::SEAT_1_LEFT\"}]}]}"; 494 List<File> customFileList = createFilenameList(jsonString); 495 // Create a request prop value. 496 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 497 .build(/* prop= */ VehicleProperty.SEAT_BELT_BUCKLED, /* areaId= */ 0); 498 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 499 new FakeVhalConfigParser(), customFileList); 500 501 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 502 () -> fakeVehicleStub.get(requestPropValue)); 503 504 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 505 expect.that(thrown).hasMessageThat().contains("areaId: 0 is not supported"); 506 } 507 508 @Test testGetMethodForHvacProp()509 public void testGetMethodForHvacProp() throws Exception { 510 // Create a custom config file. 511 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_ON 512 + ", {\"property\": \"VehicleProperty::HVAC_FAN_SPEED\"," 513 + "\"defaultValue\": {\"int32Values\": [3]}," 514 + "\"areas\": [{" 515 + "\"areaId\": \"Constants::HVAC_ALL\"," 516 + "\"minInt32Value\": 1," 517 + "\"maxInt32Value\": 7}]}]}"; 518 List<File> customFileList = createFilenameList(jsonString); 519 // Create a request prop value. 520 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 521 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ HVAC_ALL); 522 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 523 new FakeVhalConfigParser(), customFileList); 524 525 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 526 527 expect.that(propValue.getPropId()).isEqualTo(VehicleProperty.HVAC_FAN_SPEED); 528 expect.that(propValue.getInt32Value(0)).isEqualTo(3); 529 } 530 531 @Test testGetMethodForHvacPropNotAvailable()532 public void testGetMethodForHvacPropNotAvailable() throws Exception { 533 // Create a custom config file. 534 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_OFF + "]}"; 535 List<File> customFileList = createFilenameList(jsonString); 536 // Create a request prop value. 537 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 538 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ SEAT_1_LEFT); 539 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 540 new FakeVhalConfigParser(), customFileList); 541 542 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 543 () -> fakeVehicleStub.get(requestPropValue)); 544 545 expect.that(thrown.errorCode).isEqualTo(StatusCode.NOT_AVAILABLE); 546 expect.that(thrown).hasMessageThat().contains("HVAC_POWER_ON is off. PropId: 356517120 " 547 + "is not available."); 548 } 549 550 @Test testGetMethodForHvacPropMatchedBitOrAreaId()551 public void testGetMethodForHvacPropMatchedBitOrAreaId() throws Exception { 552 // Create a custom config file. 553 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_ON 554 + ", {\"property\": \"VehicleProperty::HVAC_FAN_SPEED\"," 555 + "\"defaultValue\": {\"int32Values\": [3]}," 556 + "\"areas\": [{" 557 + "\"areaId\": \"Constants::HVAC_LEFT\"," 558 + "\"minInt32Value\": 1," 559 + "\"maxInt32Value\": 7}]}]}"; 560 List<File> customFileList = createFilenameList(jsonString); 561 // Create a request prop value. 562 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 563 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ HVAC_LEFT); 564 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 565 new FakeVhalConfigParser(), customFileList); 566 567 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 568 569 expect.that(propValue.getPropId()).isEqualTo(VehicleProperty.HVAC_FAN_SPEED); 570 expect.that(propValue.getInt32Value(0)).isEqualTo(3); 571 } 572 573 @Test testGetMethodForHvacPropNoMatchedAreaId()574 public void testGetMethodForHvacPropNoMatchedAreaId() throws Exception { 575 // Create a custom config file. 576 String jsonString = "{\"properties\": [{\"property\":" 577 + "\"VehicleProperty::HVAC_POWER_ON\"," 578 + "\"defaultValue\": {\"int32Values\": [1]}," 579 + "\"areas\": [{\"areaId\": \"Constants::HVAC_RIGHT\"}]," 580 + "\"configArray\": [\"VehicleProperty::HVAC_FAN_SPEED\"," 581 + "\"VehicleProperty::HVAC_FAN_DIRECTION\"]}" 582 + ", {\"property\": \"VehicleProperty::HVAC_FAN_SPEED\"," 583 + "\"defaultValue\": {\"int32Values\": [3]}," 584 + "\"areas\": [{" 585 + "\"areaId\": \"Constants::HVAC_LEFT\"," 586 + "\"minInt32Value\": 1," 587 + "\"maxInt32Value\": 7}]}]}"; 588 List<File> customFileList = createFilenameList(jsonString); 589 // Create a request prop value. 590 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 591 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ HVAC_LEFT); 592 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 593 new FakeVhalConfigParser(), customFileList); 594 595 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 596 () -> fakeVehicleStub.get(requestPropValue)); 597 598 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 599 expect.that(thrown).hasMessageThat().contains("This areaId: " + HVAC_LEFT + " doesn't match" 600 + " any supported areaIds in HVAC_POWER_ON"); 601 } 602 603 @Test testGetMethodForHvacPropWithMoreDefaultValues()604 public void testGetMethodForHvacPropWithMoreDefaultValues() throws Exception { 605 // Create a custom config file. 606 String jsonString = "{\"properties\": [{\"property\":" 607 + "\"VehicleProperty::HVAC_POWER_ON\"," 608 + "\"defaultValue\": {\"int32Values\": [1, 0]}," 609 + "\"areas\": [{\"areaId\": \"Constants::HVAC_ALL\"}]," 610 + "\"configArray\": [\"VehicleProperty::HVAC_FAN_SPEED\"," 611 + "\"VehicleProperty::HVAC_FAN_DIRECTION\"]}" 612 + ", {\"property\": \"VehicleProperty::HVAC_FAN_SPEED\"," 613 + "\"defaultValue\": {\"int32Values\": [3]}," 614 + "\"areas\": [{" 615 + "\"areaId\": \"Constants::HVAC_ALL\"," 616 + "\"minInt32Value\": 1," 617 + "\"maxInt32Value\": 7}]}]}"; 618 List<File> customFileList = createFilenameList(jsonString); 619 // Create a request prop value. 620 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 621 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ HVAC_ALL); 622 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 623 new FakeVhalConfigParser(), customFileList); 624 625 HalPropValue propValue = fakeVehicleStub.get(requestPropValue); 626 627 expect.that(propValue.getInt32Value(0)).isEqualTo(3); 628 } 629 630 @Test testGetAsyncMethodForSingleValue()631 public void testGetAsyncMethodForSingleValue() throws Exception { 632 String jsonString = "{\"properties\": [{\"property\": \"VehicleProperty::INFO_FUEL_TYPE\"," 633 + "\"defaultValue\": {\"int32Values\": [\"FuelType::FUEL_TYPE_UNLEADED\"]}}]}"; 634 List<File> customFileList = createFilenameList(jsonString); 635 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 636 .build(/* prop= */ VehicleProperty.INFO_FUEL_TYPE, /* areaId= */ 123); 637 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 638 new FakeVhalConfigParser(), customFileList); 639 AsyncGetSetRequest getRequest = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 640 requestPropValue, DEFAULT_TIMEOUT); 641 642 fakeVehicleStub.getAsync(List.of(getRequest), mCallback); 643 644 List<GetVehicleStubAsyncResult> getAsyncResult = captureOnGetAsyncResults(); 645 GetVehicleStubAsyncResult asyncResult = getAsyncResult.get(0); 646 HalPropValue propValue = asyncResult.getHalPropValue(); 647 expect.that(asyncResult.getServiceRequestId()).isEqualTo(0); 648 // For global properties, if default value exists, will return the default value. 649 expect.that(propValue.getAreaId()).isEqualTo(0); 650 expect.that(propValue.getInt32ValuesSize()).isEqualTo(1); 651 expect.that(propValue.getInt32Value(0)).isEqualTo(FuelType.FUEL_TYPE_UNLEADED); 652 } 653 654 @Test testGetAsyncMethodForSingleValueNoReadPermissionError()655 public void testGetAsyncMethodForSingleValueNoReadPermissionError() throws Exception { 656 String jsonString = "{\"properties\": [{\"property\": " 657 + "\"VehicleProperty::ANDROID_EPOCH_TIME\"," 658 + "\"access\": \"VehiclePropertyAccess::WRITE\"}]}"; 659 List<File> customFileList = createFilenameList(jsonString); 660 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 661 .build(/* prop= */ VehicleProperty.ANDROID_EPOCH_TIME, /* areaId= */ 0); 662 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 663 new FakeVhalConfigParser(), customFileList); 664 AsyncGetSetRequest getRequest = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 665 requestPropValue, DEFAULT_TIMEOUT); 666 667 fakeVehicleStub.getAsync(List.of(getRequest), mCallback); 668 669 List<GetVehicleStubAsyncResult> getAsyncResult = captureOnGetAsyncResults(); 670 GetVehicleStubAsyncResult asyncResult = getAsyncResult.get(0); 671 HalPropValue propValue = asyncResult.getHalPropValue(); 672 expect.that(propValue).isNull(); 673 expect.that(asyncResult.getServiceRequestId()).isEqualTo(0); 674 expect.that(asyncResult.getErrorCode()) 675 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 676 } 677 678 @Test testGetAsyncForPropNotAvailable()679 public void testGetAsyncForPropNotAvailable() throws Exception { 680 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_OFF + "]}"; 681 List<File> customFileList = createFilenameList(jsonString); 682 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 683 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ SEAT_1_LEFT); 684 AsyncGetSetRequest getRequest = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 685 requestPropValue, DEFAULT_TIMEOUT); 686 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 687 new FakeVhalConfigParser(), customFileList); 688 689 fakeVehicleStub.getAsync(List.of(getRequest), mCallback); 690 691 List<GetVehicleStubAsyncResult> getAsyncResult = captureOnGetAsyncResults(); 692 GetVehicleStubAsyncResult asyncResult = getAsyncResult.get(0); 693 expect.that(asyncResult.getHalPropValue()).isNull(); 694 expect.that(asyncResult.getServiceRequestId()).isEqualTo(0); 695 expect.that(asyncResult.getErrorCode()) 696 .isEqualTo(CarPropertyManager.STATUS_ERROR_NOT_AVAILABLE); 697 } 698 699 @Test testGetAsyncForSpecialPropInternalError()700 public void testGetAsyncForSpecialPropInternalError() throws Exception { 701 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 702 .build(VehicleProperty.VHAL_HEARTBEAT, 0); 703 AsyncGetSetRequest getRequest = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 704 requestPropValue, DEFAULT_TIMEOUT); 705 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 706 new FakeVhalConfigParser(), new ArrayList<>()); 707 when(mMockRealVehicleStub.get(requestPropValue)).thenThrow(RemoteException.class); 708 709 fakeVehicleStub.getAsync(List.of(getRequest), mCallback); 710 711 List<GetVehicleStubAsyncResult> getAsyncResult = captureOnGetAsyncResults(); 712 GetVehicleStubAsyncResult asyncResult = getAsyncResult.get(0); 713 expect.that(asyncResult.getHalPropValue()).isNull(); 714 expect.that(asyncResult.getServiceRequestId()).isEqualTo(0); 715 expect.that(asyncResult.getErrorCode()) 716 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 717 } 718 719 @Test testGetAsyncForMultipleGetRequestsSuccessAndError()720 public void testGetAsyncForMultipleGetRequestsSuccessAndError() throws Exception { 721 String jsonString = "{\"properties\": " 722 + "[{\"property\": \"VehicleProperty::INFO_FUEL_TYPE\"," 723 + "\"defaultValue\": {\"int32Values\": [\"FuelType::FUEL_TYPE_UNLEADED\"]}}, " 724 + "{\"property\": \"VehicleProperty::ANDROID_EPOCH_TIME\"," 725 + "\"access\": \"VehiclePropertyAccess::WRITE\"}]}"; 726 List<File> customFileList = createFilenameList(jsonString); 727 HalPropValue requestPropValue1 = new HalPropValueBuilder(/* isAidl= */ true) 728 .build(/* prop= */ VehicleProperty.ANDROID_EPOCH_TIME, /* areaId= */ 0); 729 HalPropValue requestPropValue2 = new HalPropValueBuilder(/* isAidl= */ true) 730 .build(/* prop= */ VehicleProperty.INFO_FUEL_TYPE, /* areaId= */ 123); 731 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 732 new FakeVhalConfigParser(), customFileList); 733 AsyncGetSetRequest getRequest1 = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 734 requestPropValue1, DEFAULT_TIMEOUT); 735 AsyncGetSetRequest getRequest2 = new AsyncGetSetRequest(/* serviceRequestId= */ 1, 736 requestPropValue2, DEFAULT_TIMEOUT); 737 738 fakeVehicleStub.getAsync(List.of(getRequest1, getRequest2), mCallback); 739 740 List<GetVehicleStubAsyncResult> getAsyncResult = captureOnGetAsyncResults(); 741 GetVehicleStubAsyncResult asyncResult1 = getAsyncResult.get(0); 742 HalPropValue propValue1 = asyncResult1.getHalPropValue(); 743 expect.that(asyncResult1.getServiceRequestId()).isEqualTo(0); 744 expect.that(propValue1).isNull(); 745 expect.that(asyncResult1.getErrorCode()) 746 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 747 GetVehicleStubAsyncResult asyncResult2 = getAsyncResult.get(1); 748 HalPropValue propValue2 = asyncResult2.getHalPropValue(); 749 expect.that(asyncResult2.getServiceRequestId()).isEqualTo(1); 750 expect.that(propValue2.getAreaId()).isEqualTo(0); 751 expect.that(propValue2.getInt32ValuesSize()).isEqualTo(1); 752 expect.that(propValue2.getInt32Value(0)).isEqualTo(FuelType.FUEL_TYPE_UNLEADED); 753 } 754 755 @Test testSetMethodPropConfigNotExist()756 public void testSetMethodPropConfigNotExist() throws Exception { 757 // Create a custom config file. 758 String jsonString = "{\"properties\": [{\"property\":" 759 + "\"VehicleProperty::SEAT_BELT_BUCKLED\"," 760 + "\"defaultValue\": {\"int32Values\": [0]}," 761 + "\"areas\": [{\"areaId\": \"Constants::SEAT_1_LEFT\"}]}]}"; 762 List<File> customFileList = createFilenameList(jsonString); 763 // Create a request prop value. 764 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 765 .build(/* prop= */ 123456, /* areaId= */ 0); 766 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 767 new FakeVhalConfigParser(), customFileList); 768 769 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 770 () -> fakeVehicleStub.set(requestPropValue)); 771 772 expect.that(thrown).hasMessageThat().contains("The propId: 123456 is not supported."); 773 } 774 775 @Test testSetMethodPropDefaultValueExist()776 public void testSetMethodPropDefaultValueExist() throws Exception { 777 // Create a custom config file. 778 String jsonString = "{\"properties\": [{\"property\":" 779 + "\"VehicleProperty::INFO_FUEL_CAPACITY\"," 780 + "\"defaultValue\": {\"floatValues\": [100.0]}," 781 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"}]}"; 782 List<File> customFileList = createFilenameList(jsonString); 783 // Create a request prop value. 784 RawPropValues rawPropValues = new RawPropValues(); 785 rawPropValues.floatValues = new float[]{10}; 786 HalPropValue requestPropValue = buildHalPropValue( 787 /* propId= */ VehicleProperty.INFO_FUEL_CAPACITY, /* areaId= */ 0, 788 SystemClock.elapsedRealtimeNanos(), rawPropValues); 789 790 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 791 new FakeVhalConfigParser(), customFileList); 792 HalPropValue oldPropValue = fakeVehicleStub.get(requestPropValue); 793 fakeVehicleStub.set(requestPropValue); 794 HalPropValue updatedPropValue = fakeVehicleStub.get(requestPropValue); 795 796 expect.that(updatedPropValue.getFloatValue(0)).isEqualTo(10.0f); 797 expect.that(updatedPropValue.getFloatValue(0)).isNotEqualTo(oldPropValue.getFloatValue(0)); 798 expect.that(updatedPropValue.getTimestamp()).isNotEqualTo(oldPropValue.getTimestamp()); 799 } 800 801 @Test testSetMethodPropDefaultValueNotExist()802 public void testSetMethodPropDefaultValueNotExist() throws Exception { 803 // Create a custom config file. 804 String jsonString = "{\"properties\": [{\"property\":" 805 + "\"VehicleProperty::INFO_FUEL_CAPACITY\"," 806 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"}]}"; 807 List<File> customFileList = createFilenameList(jsonString); 808 // Create a request prop value. 809 RawPropValues rawPropValues = new RawPropValues(); 810 rawPropValues.int32Values = new int[]{32}; 811 HalPropValue requestPropValue = buildHalPropValue( 812 /* propId= */ VehicleProperty.INFO_FUEL_CAPACITY, /* areaId= */ 0, 813 SystemClock.elapsedRealtimeNanos(), rawPropValues); 814 815 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 816 new FakeVhalConfigParser(), customFileList); 817 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 818 () -> fakeVehicleStub.get(requestPropValue)); 819 820 expect.that(thrown).hasMessageThat().contains("has no property value"); 821 822 fakeVehicleStub.set(requestPropValue); 823 HalPropValue updatedPropValue = fakeVehicleStub.get(requestPropValue); 824 825 expect.that(updatedPropValue.getInt32Value(0)).isEqualTo(32); 826 } 827 828 @Test testSetMethodValueOutOfRange()829 public void testSetMethodValueOutOfRange() throws Exception { 830 // Create a custom config file. 831 String jsonString = "{\"properties\": [{\"property\":" 832 + "\"VehicleProperty::SEAT_BELT_HEIGHT_POS\"," 833 + "\"defaultValue\": {\"int32Values\": [10]}," 834 + "\"areas\": [{\"areaId\": \"Constants::SEAT_1_LEFT\"," 835 + "\"minInt32Value\": 0, \"maxInt32Value\": 10}]}]}"; 836 List<File> customFileList = createFilenameList(jsonString); 837 // Create a request prop value. 838 RawPropValues rawPropValues = new RawPropValues(); 839 rawPropValues.int32Values = new int[]{15}; 840 HalPropValue requestPropValue = buildHalPropValue( 841 /* propId= */ VehicleProperty.SEAT_BELT_HEIGHT_POS, /* areaId= */ SEAT_1_LEFT, 842 SystemClock.elapsedRealtimeNanos(), rawPropValues); 843 844 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 845 new FakeVhalConfigParser(), customFileList); 846 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 847 () -> fakeVehicleStub.set(requestPropValue)); 848 849 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 850 expect.that(thrown).hasMessageThat().contains("The set value is outside the range"); 851 } 852 853 @Test testSetMethodGlobalPropWithAreaIdSetValueOutOfRange()854 public void testSetMethodGlobalPropWithAreaIdSetValueOutOfRange() throws Exception { 855 // Create a custom config file. 856 String jsonString = "{\"properties\": [{\"property\":" 857 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 858 + "\"defaultValue\": {\"int32Values\": [100]}," 859 + "\"areas\": [{\"areaId\": 0, \"minInt32Value\": 0, \"maxInt32Value\": 100}]}]}"; 860 List<File> customFileList = createFilenameList(jsonString); 861 // Create a request prop value. 862 RawPropValues rawPropValues = new RawPropValues(); 863 rawPropValues.int32Values = new int[]{120}; 864 HalPropValue requestPropValue = buildHalPropValue( 865 /* propId= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 0, 866 SystemClock.elapsedRealtimeNanos(), rawPropValues); 867 868 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 869 new FakeVhalConfigParser(), customFileList); 870 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 871 () -> fakeVehicleStub.set(requestPropValue)); 872 873 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 874 expect.that(thrown).hasMessageThat().contains("The set value is outside the range"); 875 } 876 877 @Test testSetMethodGlobalPropWithNoAreaIdSetValueOutOfRange()878 public void testSetMethodGlobalPropWithNoAreaIdSetValueOutOfRange() throws Exception { 879 // Create a custom config file. 880 String jsonString = "{\"properties\": [{\"property\":" 881 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 882 + "\"defaultValue\": {\"int32Values\": [100]}}]}"; 883 List<File> customFileList = createFilenameList(jsonString); 884 // Create a request prop value. 885 RawPropValues rawPropValues = new RawPropValues(); 886 rawPropValues.int32Values = new int[]{120}; 887 HalPropValue requestPropValue = buildHalPropValue( 888 /* propId= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 0, 889 SystemClock.elapsedRealtimeNanos(), rawPropValues); 890 891 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 892 new FakeVhalConfigParser(), customFileList); 893 fakeVehicleStub.set(requestPropValue); 894 HalPropValue updatedPropValue = fakeVehicleStub.get(requestPropValue); 895 896 expect.that(updatedPropValue.getInt32Value(0)).isEqualTo(120); 897 } 898 899 @Test testSetMethodGlobalPropWithAreaIdNotZero()900 public void testSetMethodGlobalPropWithAreaIdNotZero() throws Exception { 901 // Create a custom config file. 902 String jsonString = "{\"properties\": [{\"property\":" 903 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 904 + "\"defaultValue\": {\"int32Values\": [100]}," 905 + "\"areas\": [{\"areaId\": 1, \"minInt32Value\": 0, \"maxInt32Value\": 100}]}]}"; 906 List<File> customFileList = createFilenameList(jsonString); 907 // Create a request prop value. 908 RawPropValues rawPropValues = new RawPropValues(); 909 rawPropValues.int32Values = new int[]{120}; 910 HalPropValue requestPropValue = buildHalPropValue( 911 /* propId= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 1, 912 SystemClock.elapsedRealtimeNanos(), rawPropValues); 913 914 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 915 new FakeVhalConfigParser(), customFileList); 916 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 917 () -> fakeVehicleStub.get(requestPropValue)); 918 919 // For global properties, if the supported area config array doesn't include 0, 920 // a ServiceSpecificException with StatusCode.INVALID_ARG. 921 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 922 expect.that(thrown).hasMessageThat().contains("The areaId: 0 is not supported."); 923 } 924 925 @Test testSetMethodAreaConfigHasNoLimit()926 public void testSetMethodAreaConfigHasNoLimit() throws Exception { 927 // Create a custom config file. 928 String jsonString = "{\"properties\": [{\"property\":" 929 + "\"VehicleProperty::SEAT_BELT_BUCKLED\"," 930 + "\"defaultValue\": {\"int32Values\": [0]}," 931 + "\"areas\": [{\"areaId\": \"Constants::SEAT_1_LEFT\"}]}]}"; 932 List<File> customFileList = createFilenameList(jsonString); 933 // Create a request prop value. 934 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 935 new FakeVhalConfigParser(), customFileList); 936 RawPropValues rawPropValues = new RawPropValues(); 937 rawPropValues.int32Values = new int[]{32}; 938 HalPropValue requestPropValue = buildHalPropValue( 939 /* propId= */ VehicleProperty.SEAT_BELT_BUCKLED, /* areaId= */ SEAT_1_LEFT, 940 SystemClock.elapsedRealtimeNanos(), rawPropValues); 941 942 HalPropValue oldPropValue = fakeVehicleStub.get(requestPropValue); 943 fakeVehicleStub.set(requestPropValue); 944 HalPropValue updatedPropValue = fakeVehicleStub.get(requestPropValue); 945 946 expect.that(oldPropValue.getInt32Value(0)).isEqualTo(0); 947 expect.that(updatedPropValue.getInt32Value(0)).isEqualTo(32); 948 } 949 950 @Test testSetMethodForHvacProp()951 public void testSetMethodForHvacProp() throws Exception { 952 // Create a custom config file. 953 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_ON 954 + "," + PROPERTY_CONFIG_STRING_HVAC_FAN_SPEED + "]}"; 955 List<File> customFileList = createFilenameList(jsonString); 956 RawPropValues rawPropValues = new RawPropValues(); 957 rawPropValues.int32Values = new int[]{5}; 958 HalPropValue requestPropValue = buildHalPropValue( 959 /* propId= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ HVAC_ALL, 960 SystemClock.elapsedRealtimeNanos(), rawPropValues); 961 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 962 new FakeVhalConfigParser(), customFileList); 963 HalPropValue oldPropValue = fakeVehicleStub.get(requestPropValue); 964 fakeVehicleStub.set(requestPropValue); 965 HalPropValue updatedPropValue = fakeVehicleStub.get(requestPropValue); 966 967 expect.that(oldPropValue.getInt32Value(0)).isEqualTo(3); 968 expect.that(updatedPropValue.getInt32Value(0)).isEqualTo(5); 969 } 970 971 @Test testSetMethodForHvacPropNotAvailable()972 public void testSetMethodForHvacPropNotAvailable() throws Exception { 973 // Create a custom config file. 974 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_HVAC_POWER_OFF + "]}"; 975 List<File> customFileList = createFilenameList(jsonString); 976 // Create a request prop value. 977 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 978 .build(/* prop= */ VehicleProperty.HVAC_FAN_SPEED, /* areaId= */ SEAT_1_LEFT); 979 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 980 new FakeVhalConfigParser(), customFileList); 981 982 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 983 () -> fakeVehicleStub.set(requestPropValue)); 984 985 expect.that(thrown.errorCode).isEqualTo(StatusCode.NOT_AVAILABLE); 986 expect.that(thrown).hasMessageThat().contains("HVAC_POWER_ON is off. PropId: 356517120 " 987 + "is not available."); 988 } 989 990 @Test testSetAsyncForSingleProp()991 public void testSetAsyncForSingleProp() throws Exception { 992 String jsonString = "{\"properties\": [{\"property\":" 993 + "\"VehicleProperty::INFO_FUEL_CAPACITY\"," 994 + "\"defaultValue\": {\"floatValues\": [100.0]}," 995 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"}]}"; 996 List<File> customFileList = createFilenameList(jsonString); 997 RawPropValues rawPropValues = new RawPropValues(); 998 rawPropValues.floatValues = new float[]{10}; 999 HalPropValue requestPropValue = buildHalPropValue( 1000 /* propId= */ VehicleProperty.INFO_FUEL_CAPACITY, /* areaId= */ 0, 1001 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1002 AsyncGetSetRequest request = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 1003 requestPropValue, DEFAULT_TIMEOUT); 1004 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1005 new FakeVhalConfigParser(), customFileList); 1006 fakeVehicleStub.getAsync(List.of(request), mCallback); 1007 List<GetVehicleStubAsyncResult> getOldAsyncResult = captureOnGetAsyncResults(); 1008 HalPropValue oldPropValue = getOldAsyncResult.get(0).getHalPropValue(); 1009 reset(mCallback); 1010 1011 fakeVehicleStub.setAsync(List.of(request), mCallback); 1012 List<SetVehicleStubAsyncResult> setAsyncResult = captureOnSetAsyncResults(); 1013 1014 reset(mCallback); 1015 fakeVehicleStub.getAsync(List.of(request), mCallback); 1016 List<GetVehicleStubAsyncResult> getNewAsyncResult = captureOnGetAsyncResults(); 1017 GetVehicleStubAsyncResult newAsyncGetResult = getNewAsyncResult.get(0); 1018 SetVehicleStubAsyncResult setVehicleStubAsyncResult = setAsyncResult.get(0); 1019 HalPropValue updatedPropValue = newAsyncGetResult.getHalPropValue(); 1020 expect.that(setVehicleStubAsyncResult.getServiceRequestId()).isEqualTo(0); 1021 expect.that(setVehicleStubAsyncResult.getServiceRequestId()) 1022 .isEqualTo(newAsyncGetResult.getServiceRequestId()); 1023 expect.that(setVehicleStubAsyncResult.getErrorCode()) 1024 .isEqualTo(CarPropertyErrorCodes.STATUS_OK); 1025 expect.that(updatedPropValue.getFloatValue(0)).isEqualTo(10.0f); 1026 expect.that(updatedPropValue.getFloatValue(0)).isNotEqualTo(oldPropValue.getFloatValue(0)); 1027 expect.that(updatedPropValue.getTimestamp()).isNotEqualTo(oldPropValue.getTimestamp()); 1028 } 1029 1030 @Test testSetAsyncGlobalPropWithAreaIdSetValueOutOfRange()1031 public void testSetAsyncGlobalPropWithAreaIdSetValueOutOfRange() throws Exception { 1032 // Create a custom config file. 1033 String jsonString = "{\"properties\": [{\"property\":" 1034 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 1035 + "\"defaultValue\": {\"int32Values\": [100]}," 1036 + "\"areas\": [{\"areaId\": 0, \"minInt32Value\": 0, \"maxInt32Value\": 100}]}]}"; 1037 List<File> customFileList = createFilenameList(jsonString); 1038 RawPropValues rawPropValues = new RawPropValues(); 1039 rawPropValues.int32Values = new int[]{105}; 1040 HalPropValue requestPropValue = buildHalPropValue( 1041 /* propId= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 0, 1042 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1043 AsyncGetSetRequest request = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 1044 requestPropValue, DEFAULT_TIMEOUT); 1045 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1046 new FakeVhalConfigParser(), customFileList); 1047 1048 fakeVehicleStub.setAsync(List.of(request), mCallback); 1049 1050 List<SetVehicleStubAsyncResult> setAsyncResult = captureOnSetAsyncResults(); 1051 SetVehicleStubAsyncResult setVehicleStubAsyncResult = setAsyncResult.get(0); 1052 expect.that(setVehicleStubAsyncResult.getServiceRequestId()).isEqualTo(0); 1053 expect.that(setVehicleStubAsyncResult.getErrorCode()) 1054 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1055 } 1056 1057 @Test testSetAsyncForSpecialPropRemoteException()1058 public void testSetAsyncForSpecialPropRemoteException() throws Exception { 1059 // Create a request prop value. 1060 RawPropValues rawPropValues = new RawPropValues(); 1061 rawPropValues.floatValues = new float[]{10}; 1062 HalPropValue requestPropValue = buildHalPropValue( 1063 /* propId= */ VehicleProperty.SWITCH_USER, /* areaId= */ 0, 1064 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1065 doThrow(new RemoteException()).when(mMockRealVehicleStub).set(requestPropValue); 1066 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1067 new FakeVhalConfigParser(), new ArrayList<>()); 1068 AsyncGetSetRequest request = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 1069 requestPropValue, DEFAULT_TIMEOUT); 1070 1071 fakeVehicleStub.setAsync(List.of(request), mCallback); 1072 1073 List<SetVehicleStubAsyncResult> setAsyncResult = captureOnSetAsyncResults(); 1074 SetVehicleStubAsyncResult setVehicleStubAsyncResult = setAsyncResult.get(0); 1075 expect.that(setVehicleStubAsyncResult.getServiceRequestId()).isEqualTo(0); 1076 expect.that(setVehicleStubAsyncResult.getErrorCode()) 1077 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1078 verify(mMockRealVehicleStub).set(requestPropValue); 1079 } 1080 1081 @Test testSetAsyncOnMultipleRequests()1082 public void testSetAsyncOnMultipleRequests() throws Exception { 1083 String jsonString = "{\"properties\": [{\"property\":" 1084 + "\"VehicleProperty::DISPLAY_BRIGHTNESS\"," 1085 + "\"defaultValue\": {\"int32Values\": [100]}," 1086 + "\"areas\": [{\"areaId\": 0, \"minInt32Value\": 0, \"maxInt32Value\": 100}]}]}"; 1087 List<File> customFileList = createFilenameList(jsonString); 1088 RawPropValues rawPropValues1 = new RawPropValues(); 1089 rawPropValues1.floatValues = new float[]{10}; 1090 HalPropValue requestPropValue1 = buildHalPropValue( 1091 /* propId= */ VehicleProperty.SWITCH_USER, /* areaId= */ 0, 1092 SystemClock.elapsedRealtimeNanos(), rawPropValues1); 1093 doThrow(new RemoteException()).when(mMockRealVehicleStub).set(requestPropValue1); 1094 AsyncGetSetRequest request1 = new AsyncGetSetRequest(/* serviceRequestId= */ 0, 1095 requestPropValue1, DEFAULT_TIMEOUT); 1096 RawPropValues rawPropValues2 = new RawPropValues(); 1097 rawPropValues2.int32Values = new int[]{105}; 1098 HalPropValue requestPropValue2 = buildHalPropValue( 1099 /* propId= */ VehicleProperty.DISPLAY_BRIGHTNESS, /* areaId= */ 0, 1100 SystemClock.elapsedRealtimeNanos(), rawPropValues2); 1101 AsyncGetSetRequest request2 = new AsyncGetSetRequest(/* serviceRequestId= */ 1, 1102 requestPropValue2, DEFAULT_TIMEOUT); 1103 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1104 new FakeVhalConfigParser(), customFileList); 1105 1106 fakeVehicleStub.setAsync(List.of(request1, request2), mCallback); 1107 List<SetVehicleStubAsyncResult> setAsyncResult = captureOnSetAsyncResults(); 1108 SetVehicleStubAsyncResult setVehicleStubAsyncResult1 = setAsyncResult.get(0); 1109 expect.that(setVehicleStubAsyncResult1.getServiceRequestId()).isEqualTo(0); 1110 expect.that(setVehicleStubAsyncResult1.getErrorCode()) 1111 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1112 verify(mMockRealVehicleStub).set(requestPropValue1); 1113 SetVehicleStubAsyncResult setVehicleStubAsyncResult2 = setAsyncResult.get(1); 1114 expect.that(setVehicleStubAsyncResult2.getServiceRequestId()).isEqualTo(1); 1115 expect.that(setVehicleStubAsyncResult2.getErrorCode()) 1116 .isEqualTo(CarPropertyManager.STATUS_ERROR_INTERNAL_ERROR); 1117 } 1118 1119 @Test testSubscribeOnChangePropOneClientSubscribeOnePropManyTime()1120 public void testSubscribeOnChangePropOneClientSubscribeOnePropManyTime() throws Exception { 1121 // Create a custom config file. 1122 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_ON_CHANGE + "]}"; 1123 List<File> customFileList = createFilenameList(jsonString); 1124 // Create subscribe options array. 1125 SubscribeOptions option = new SubscribeOptions(); 1126 option.propId = VehicleProperty.ENGINE_OIL_LEVEL; 1127 option.sampleRate = 0.5f; 1128 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1129 // Create set value 1130 RawPropValues rawPropValues = new RawPropValues(); 1131 rawPropValues.int32Values = new int[]{VehicleOilLevel.LOW}; 1132 HalPropValue requestPropValue = buildHalPropValue( 1133 /* propId= */ VehicleProperty.ENGINE_OIL_LEVEL, /* areaId= */ 0, 1134 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1135 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1136 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1137 new FakeVhalConfigParser(), customFileList); 1138 1139 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1140 try { 1141 client.subscribe(options); 1142 client.subscribe(options); 1143 client.subscribe(options); 1144 fakeVehicleStub.set(requestPropValue); 1145 1146 verify(callback, times(1)).onPropertyEvent(any(ArrayList.class)); 1147 } finally { 1148 client.unsubscribe(VehicleProperty.ENGINE_OIL_LEVEL); 1149 } 1150 } 1151 1152 @Test testSubscribeOnChangePropOneClientSubscribeTwoProp()1153 public void testSubscribeOnChangePropOneClientSubscribeTwoProp() throws Exception { 1154 // Create a custom config file. 1155 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_ON_CHANGE + "," 1156 + "{\"property\": \"VehicleProperty::NIGHT_MODE\"," 1157 + "\"defaultValue\": {\"int32Values\": [0]}," 1158 + "\"access\": \"VehiclePropertyAccess::READ_WRITE\"," 1159 + "\"changeMode\": \"VehiclePropertyChangeMode::ON_CHANGE\"}]}"; 1160 List<File> customFileList = createFilenameList(jsonString); 1161 // Create subscribe options 1162 SubscribeOptions option1 = new SubscribeOptions(); 1163 option1.propId = VehicleProperty.ENGINE_OIL_LEVEL; 1164 option1.sampleRate = 0.5f; 1165 SubscribeOptions option2 = new SubscribeOptions(); 1166 option2.propId = VehicleProperty.NIGHT_MODE; 1167 option2.sampleRate = 0.5f; 1168 SubscribeOptions[] options = new SubscribeOptions[]{option1, option2}; 1169 // Create set value 1170 RawPropValues rawPropValues1 = new RawPropValues(); 1171 rawPropValues1.int32Values = new int[]{VehicleOilLevel.LOW}; 1172 HalPropValue requestPropValue1 = buildHalPropValue( 1173 /* propId= */ VehicleProperty.ENGINE_OIL_LEVEL, /* areaId= */ 0, 1174 SystemClock.elapsedRealtimeNanos(), rawPropValues1); 1175 RawPropValues rawPropValues2 = new RawPropValues(); 1176 rawPropValues2.int32Values = new int[]{0}; 1177 HalPropValue requestPropValue2 = buildHalPropValue( 1178 /* propId= */ VehicleProperty.NIGHT_MODE, /* areaId= */ 0, 1179 SystemClock.elapsedRealtimeNanos(), rawPropValues2); 1180 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1181 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1182 new FakeVhalConfigParser(), customFileList); 1183 1184 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1185 try { 1186 client.subscribe(options); 1187 fakeVehicleStub.set(requestPropValue1); 1188 fakeVehicleStub.set(requestPropValue2); 1189 1190 verify(callback, times(2)).onPropertyEvent(any(ArrayList.class)); 1191 } finally { 1192 client.unsubscribe(VehicleProperty.ENGINE_OIL_LEVEL); 1193 client.unsubscribe(VehicleProperty.NIGHT_MODE); 1194 } 1195 } 1196 1197 @Test testSubscribeAreaPropertyWithEmptyOptionsAreaIds()1198 public void testSubscribeAreaPropertyWithEmptyOptionsAreaIds() throws Exception { 1199 // Create a custom config file. 1200 String jsonString = "{\"properties\": [{\"property\": " 1201 + "\"VehicleProperty::SEAT_HEADREST_ANGLE_POS\"," 1202 + "\"defaultValue\": {\"int32Values\": [0]}," 1203 + "\"areas\":[" 1204 + "{\"areaId\": \"Constants::SEAT_1_LEFT\", \"minInt32Value\": -10," 1205 + "\"maxInt32Value\": 10}," 1206 + "{\"areaId\": \"Constants::SEAT_1_RIGHT\",\"minInt32Value\": -10," 1207 + "\"maxInt32Value\": 10}]}]}"; 1208 List<File> customFileList = createFilenameList(jsonString); 1209 // Create subscribe options array. 1210 SubscribeOptions option = new SubscribeOptions(); 1211 option.propId = VehicleProperty.SEAT_HEADREST_ANGLE_POS; 1212 // option.areaId array is null. 1213 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1214 // Create set value 1215 RawPropValues rawPropValues = new RawPropValues(); 1216 rawPropValues.int32Values = new int[]{10}; 1217 HalPropValue requestPropValue1 = buildHalPropValue( 1218 /* propId= */ VehicleProperty.SEAT_HEADREST_ANGLE_POS, SEAT_1_LEFT, 1219 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1220 HalPropValue requestPropValue2 = buildHalPropValue( 1221 /* propId= */ VehicleProperty.SEAT_HEADREST_ANGLE_POS, SEAT_1_RIGHT, 1222 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1223 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1224 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1225 new FakeVhalConfigParser(), customFileList); 1226 1227 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1228 client.subscribe(options); 1229 fakeVehicleStub.set(requestPropValue1); 1230 fakeVehicleStub.set(requestPropValue2); 1231 1232 verify(callback, times(2)).onPropertyEvent(any(ArrayList.class)); 1233 } 1234 1235 @Test testSubscribeOnChangePropTwoClientSubscribeSameProp()1236 public void testSubscribeOnChangePropTwoClientSubscribeSameProp() throws Exception { 1237 // Create a custom config file. 1238 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_ON_CHANGE + "]}"; 1239 List<File> customFileList = createFilenameList(jsonString); 1240 // Create subscribe options 1241 SubscribeOptions option = new SubscribeOptions(); 1242 option.propId = VehicleProperty.ENGINE_OIL_LEVEL; 1243 option.sampleRate = 2f; 1244 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1245 // Create set value 1246 RawPropValues rawPropValues = new RawPropValues(); 1247 rawPropValues.int32Values = new int[]{VehicleOilLevel.LOW}; 1248 HalPropValue requestPropValue = buildHalPropValue( 1249 /* propId= */ VehicleProperty.ENGINE_OIL_LEVEL, /* areaId= */ 0, 1250 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1251 VehicleHalCallback callback1 = mock(VehicleHalCallback.class); 1252 VehicleHalCallback callback2 = mock(VehicleHalCallback.class); 1253 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1254 new FakeVhalConfigParser(), customFileList); 1255 1256 VehicleStub.SubscriptionClient client1 = fakeVehicleStub.newSubscriptionClient(callback1); 1257 VehicleStub.SubscriptionClient client2 = fakeVehicleStub.newSubscriptionClient(callback2); 1258 try { 1259 client1.subscribe(options); 1260 client2.subscribe(options); 1261 fakeVehicleStub.set(requestPropValue); 1262 1263 verify(callback1, times(1)).onPropertyEvent(any(ArrayList.class)); 1264 verify(callback2, times(1)).onPropertyEvent(any(ArrayList.class)); 1265 } finally { 1266 client1.unsubscribe(VehicleProperty.ENGINE_OIL_LEVEL); 1267 client2.unsubscribe(VehicleProperty.ENGINE_OIL_LEVEL); 1268 } 1269 } 1270 1271 @Test testSubscribeContinuousProp()1272 public void testSubscribeContinuousProp() throws Exception { 1273 // Create a custom config file. 1274 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1275 List<File> customFileList = createFilenameList(jsonString); 1276 // Create subscribe options 1277 SubscribeOptions option = new SubscribeOptions(); 1278 option.propId = VehicleProperty.FUEL_LEVEL; 1279 option.sampleRate = 100f; 1280 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1281 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1282 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1283 new FakeVhalConfigParser(), customFileList); 1284 1285 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1286 try { 1287 client.subscribe(options); 1288 1289 verify(callback, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1290 } finally { 1291 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1292 } 1293 } 1294 1295 @Test testSubscribeContinuousPropDifferentRate()1296 public void testSubscribeContinuousPropDifferentRate() throws Exception { 1297 // Create a custom config file. 1298 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1299 List<File> customFileList = createFilenameList(jsonString); 1300 // Create subscribe options 1301 SubscribeOptions option1 = new SubscribeOptions(); 1302 option1.propId = VehicleProperty.FUEL_LEVEL; 1303 option1.sampleRate = 100f; 1304 SubscribeOptions[] options1 = new SubscribeOptions[]{option1}; 1305 SubscribeOptions option2 = new SubscribeOptions(); 1306 option2.propId = VehicleProperty.FUEL_LEVEL; 1307 option2.sampleRate = 50f; 1308 SubscribeOptions[] options2 = new SubscribeOptions[]{option2}; 1309 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1310 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1311 new FakeVhalConfigParser(), customFileList); 1312 1313 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1314 try { 1315 client.subscribe(options1); 1316 1317 verify(callback, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1318 clearInvocations(callback); 1319 1320 client.subscribe(options2); 1321 1322 verify(callback, timeout(200).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1323 } finally { 1324 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1325 } 1326 } 1327 1328 @Test testSubscribeContinuousPropRateTooLarge()1329 public void testSubscribeContinuousPropRateTooLarge() throws Exception { 1330 // Create a custom config file. 1331 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1332 List<File> customFileList = createFilenameList(jsonString); 1333 // Create subscribe options 1334 SubscribeOptions option = new SubscribeOptions(); 1335 option.propId = VehicleProperty.FUEL_LEVEL; 1336 option.sampleRate = 200f; 1337 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1338 1339 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1340 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1341 new FakeVhalConfigParser(), customFileList); 1342 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1343 try { 1344 client.subscribe(options); 1345 1346 verify(callback, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1347 } finally { 1348 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1349 } 1350 } 1351 1352 @Test testSubscribeContinuousPropRateTooSmall()1353 public void testSubscribeContinuousPropRateTooSmall() throws Exception { 1354 // Create a custom config file. 1355 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1356 List<File> customFileList = createFilenameList(jsonString); 1357 // Create subscribe options 1358 SubscribeOptions option = new SubscribeOptions(); 1359 option.propId = VehicleProperty.FUEL_LEVEL; 1360 option.sampleRate = -50f; 1361 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1362 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1363 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1364 new FakeVhalConfigParser(), customFileList); 1365 1366 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1367 try { 1368 client.subscribe(options); 1369 1370 verify(callback, timeout(100).atLeast(1)).onPropertyEvent(any(ArrayList.class)); 1371 } finally { 1372 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1373 } 1374 } 1375 1376 @Test testSubscribeNonSupportPropID()1377 public void testSubscribeNonSupportPropID() throws Exception { 1378 // Create subscribe options 1379 SubscribeOptions option = new SubscribeOptions(); 1380 option.propId = 123; 1381 option.sampleRate = 0f; 1382 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1383 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1384 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1385 new FakeVhalConfigParser(), new ArrayList<>()); 1386 1387 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1388 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 1389 () -> client.subscribe(options)); 1390 1391 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 1392 expect.that(thrown).hasMessageThat().contains("The propId: 123 is not supported."); 1393 } 1394 1395 @Test testSubscribeNonSupportAreaId()1396 public void testSubscribeNonSupportAreaId() throws Exception { 1397 // Create a custom config file. 1398 String jsonString = "{\"properties\": [{\"property\":" 1399 + "\"VehicleProperty::SEAT_BELT_BUCKLED\"," 1400 + "\"defaultValue\": {\"int32Values\": [0]}}]}"; 1401 List<File> customFileList = createFilenameList(jsonString); 1402 // Create subscribe options 1403 SubscribeOptions option = new SubscribeOptions(); 1404 option.propId = VehicleProperty.SEAT_BELT_BUCKLED; 1405 option.areaIds = new int[]{SEAT_1_LEFT}; 1406 option.sampleRate = 1f; 1407 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1408 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1409 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1410 new FakeVhalConfigParser(), customFileList); 1411 1412 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1413 ServiceSpecificException thrown; 1414 try { 1415 thrown = assertThrows(ServiceSpecificException.class, () -> client.subscribe(options)); 1416 } finally { 1417 client.unsubscribe(VehicleProperty.SEAT_BELT_BUCKLED); 1418 } 1419 1420 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 1421 expect.that(thrown).hasMessageThat().contains("The areaId: " + SEAT_1_LEFT 1422 + " is not supported."); 1423 } 1424 1425 @Test testSubscribeStaticPropThrowException()1426 public void testSubscribeStaticPropThrowException() throws Exception { 1427 // Create a custom config file. 1428 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_STATIC + "]}"; 1429 List<File> customFileList = createFilenameList(jsonString); 1430 // Create subscribe options 1431 SubscribeOptions option = new SubscribeOptions(); 1432 option.propId = VehicleProperty.INFO_FUEL_CAPACITY; 1433 option.sampleRate = 0f; 1434 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1435 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1436 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1437 new FakeVhalConfigParser(), customFileList); 1438 1439 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1440 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 1441 () -> client.subscribe(options)); 1442 1443 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 1444 expect.that(thrown).hasMessageThat().contains("Static property cannot be subscribed."); 1445 } 1446 1447 @Test testUnsubscribePropIdNotSupport()1448 public void testUnsubscribePropIdNotSupport() throws Exception { 1449 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1450 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1451 new FakeVhalConfigParser(), new ArrayList<>()); 1452 1453 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1454 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 1455 () -> client.unsubscribe(1234)); 1456 1457 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 1458 expect.that(thrown).hasMessageThat().contains("The propId: 1234 is not supported"); 1459 } 1460 1461 @Test testUnsubscribeStaticProp()1462 public void testUnsubscribeStaticProp() throws Exception { 1463 // Create a custom config file. 1464 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_STATIC + "]}"; 1465 List<File> customFileList = createFilenameList(jsonString); 1466 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1467 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1468 new FakeVhalConfigParser(), customFileList); 1469 1470 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1471 ServiceSpecificException thrown = assertThrows(ServiceSpecificException.class, 1472 () -> client.unsubscribe(VehicleProperty.INFO_FUEL_TYPE)); 1473 1474 expect.that(thrown.errorCode).isEqualTo(StatusCode.INVALID_ARG); 1475 expect.that(thrown).hasMessageThat().contains("Static property cannot be unsubscribed."); 1476 } 1477 1478 @Test testUnsubscribeOnChangeProp()1479 public void testUnsubscribeOnChangeProp() throws Exception { 1480 // Create a custom config file. 1481 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_ON_CHANGE + "]}"; 1482 List<File> customFileList = createFilenameList(jsonString); 1483 // Create subscribe options array. 1484 SubscribeOptions option = new SubscribeOptions(); 1485 option.propId = VehicleProperty.ENGINE_OIL_LEVEL; 1486 option.sampleRate = 1f; 1487 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1488 // Create set value 1489 RawPropValues rawPropValues = new RawPropValues(); 1490 rawPropValues.int32Values = new int[]{VehicleOilLevel.LOW}; 1491 HalPropValue requestPropValue = buildHalPropValue( 1492 /* propId= */ VehicleProperty.ENGINE_OIL_LEVEL, /* areaId= */ 0, 1493 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1494 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1495 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1496 new FakeVhalConfigParser(), customFileList); 1497 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1498 client.subscribe(options); 1499 fakeVehicleStub.set(requestPropValue); 1500 verify(callback, times(1)).onPropertyEvent(any(ArrayList.class)); 1501 1502 client.unsubscribe(VehicleProperty.ENGINE_OIL_LEVEL); 1503 clearInvocations(callback); 1504 fakeVehicleStub.set(requestPropValue); 1505 1506 // Because in the FakeVehicleStub.set method, we copy the subscription client set from the 1507 // lock to a local variable and use it outside the lock to call callbacks. After 1508 // unsubscription, there is still slight chance the callback might be used once. 1509 verify(callback, atMost(1)).onPropertyEvent(any(ArrayList.class)); 1510 } 1511 1512 @Test testUnsubscribeContinuousPropOneClient()1513 public void testUnsubscribeContinuousPropOneClient() throws Exception { 1514 // Create a custom config file. 1515 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1516 List<File> customFileList = createFilenameList(jsonString); 1517 // Create subscribe options 1518 SubscribeOptions option = new SubscribeOptions(); 1519 option.propId = VehicleProperty.FUEL_LEVEL; 1520 option.sampleRate = 100f; 1521 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1522 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1523 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1524 new FakeVhalConfigParser(), customFileList); 1525 1526 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1527 client.subscribe(options); 1528 1529 verify(callback, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1530 1531 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1532 clearInvocations(callback); 1533 1534 verify(callback, after(200).atMost(1)).onPropertyEvent(any(ArrayList.class)); 1535 } 1536 1537 @Test testUnsubscribeContinuousPropTwoClient()1538 public void testUnsubscribeContinuousPropTwoClient() throws Exception { 1539 // Create a custom config file. 1540 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + "]}"; 1541 List<File> customFileList = createFilenameList(jsonString); 1542 // Create subscribe options 1543 SubscribeOptions option = new SubscribeOptions(); 1544 option.propId = VehicleProperty.FUEL_LEVEL; 1545 option.sampleRate = 100f; 1546 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1547 VehicleHalCallback callback1 = mock(VehicleHalCallback.class); 1548 VehicleHalCallback callback2 = mock(VehicleHalCallback.class); 1549 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1550 new FakeVhalConfigParser(), customFileList); 1551 1552 VehicleStub.SubscriptionClient client1 = fakeVehicleStub.newSubscriptionClient(callback1); 1553 VehicleStub.SubscriptionClient client2 = fakeVehicleStub.newSubscriptionClient(callback2); 1554 try { 1555 client1.subscribe(options); 1556 client2.subscribe(options); 1557 1558 verify(callback1, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1559 verify(callback2, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1560 1561 client1.unsubscribe(VehicleProperty.FUEL_LEVEL); 1562 clearInvocations(callback1); 1563 clearInvocations(callback2); 1564 1565 verify(callback1, after(200).atMost(1)).onPropertyEvent(any(ArrayList.class)); 1566 verify(callback2, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1567 } finally { 1568 client2.unsubscribe(VehicleProperty.FUEL_LEVEL); 1569 } 1570 } 1571 1572 @Test testUnsubscribeContinuousPropOneClientTwoSubscription()1573 public void testUnsubscribeContinuousPropOneClientTwoSubscription() throws Exception { 1574 // Create a custom config file. 1575 String jsonString = "{\"properties\": [" + PROPERTY_CONFIG_STRING_CONTINUOUS + ", " 1576 + PROPERTY_CONFIG_STRING_CONTINUOUS_2 + "]}"; 1577 List<File> customFileList = createFilenameList(jsonString); 1578 // Create subscribe options 1579 SubscribeOptions option1 = new SubscribeOptions(); 1580 option1.propId = VehicleProperty.FUEL_LEVEL; 1581 option1.sampleRate = 100f; 1582 SubscribeOptions option2 = new SubscribeOptions(); 1583 option2.propId = VehicleProperty.EV_BATTERY_LEVEL; 1584 option2.sampleRate = 100f; 1585 SubscribeOptions[] options = new SubscribeOptions[]{option1, option2}; 1586 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1587 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1588 new FakeVhalConfigParser(), customFileList); 1589 1590 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1591 client.subscribe(options); 1592 1593 verify(callback, timeout(100).atLeast(10)).onPropertyEvent(any(ArrayList.class)); 1594 1595 client.unsubscribe(VehicleProperty.FUEL_LEVEL); 1596 clearInvocations(callback); 1597 1598 verify(callback, timeout(100).atLeast(5)).onPropertyEvent(any(ArrayList.class)); 1599 } 1600 1601 @Test testGetValueForSpecialProp()1602 public void testGetValueForSpecialProp() throws Exception { 1603 // Create a request prop value. 1604 HalPropValue requestPropValue = new HalPropValueBuilder(/* isAidl= */ true) 1605 .build(VehicleProperty.VHAL_HEARTBEAT, 0); 1606 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1607 new FakeVhalConfigParser(), new ArrayList<>()); 1608 1609 fakeVehicleStub.get(requestPropValue); 1610 1611 verify(mMockRealVehicleStub).get(requestPropValue); 1612 } 1613 1614 @Test testSetValueForSpecialProp()1615 public void testSetValueForSpecialProp() throws Exception { 1616 // Create a request prop value. 1617 RawPropValues rawPropValues = new RawPropValues(); 1618 rawPropValues.floatValues = new float[]{10}; 1619 HalPropValue requestPropValue = buildHalPropValue( 1620 /* propId= */ VehicleProperty.SWITCH_USER, /* areaId= */ 0, 1621 SystemClock.elapsedRealtimeNanos(), rawPropValues); 1622 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1623 new FakeVhalConfigParser(), new ArrayList<>()); 1624 1625 fakeVehicleStub.set(requestPropValue); 1626 1627 verify(mMockRealVehicleStub).set(requestPropValue); 1628 } 1629 1630 @Test testSubscribeSpecialProp()1631 public void testSubscribeSpecialProp() throws Exception { 1632 // Create subscribe options 1633 SubscribeOptions option = new SubscribeOptions(); 1634 option.propId = VehicleProperty.VHAL_HEARTBEAT; 1635 option.sampleRate = 100f; 1636 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1637 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1638 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1639 new FakeVhalConfigParser(), new ArrayList<>()); 1640 SubscriptionClient realClient = mock(SubscriptionClient.class); 1641 when(mMockRealVehicleStub.newSubscriptionClient(callback)).thenReturn(realClient); 1642 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1643 1644 doNothing().when(realClient).subscribe(options); 1645 client.subscribe(options); 1646 1647 verify(realClient).subscribe(options); 1648 } 1649 1650 @Test testUnsubscribeSpecialProp()1651 public void testUnsubscribeSpecialProp() throws Exception { 1652 // Create subscribe options 1653 SubscribeOptions option = new SubscribeOptions(); 1654 option.propId = VehicleProperty.VHAL_HEARTBEAT; 1655 option.sampleRate = 100f; 1656 SubscribeOptions[] options = new SubscribeOptions[]{option}; 1657 VehicleHalCallback callback = mock(VehicleHalCallback.class); 1658 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1659 new FakeVhalConfigParser(), new ArrayList<>()); 1660 SubscriptionClient realClient = mock(SubscriptionClient.class); 1661 when(mMockRealVehicleStub.newSubscriptionClient(callback)).thenReturn(realClient); 1662 VehicleStub.SubscriptionClient client = fakeVehicleStub.newSubscriptionClient(callback); 1663 1664 doNothing().when(realClient).subscribe(options); 1665 client.subscribe(options); 1666 1667 verify(realClient).subscribe(options); 1668 1669 doNothing().when(realClient).unsubscribe(VehicleProperty.VHAL_HEARTBEAT); 1670 client.unsubscribe(VehicleProperty.VHAL_HEARTBEAT); 1671 1672 verify(realClient).unsubscribe(VehicleProperty.VHAL_HEARTBEAT); 1673 } 1674 1675 @Test testLinkToDeath()1676 public void testLinkToDeath() throws Exception { 1677 IVehicleDeathRecipient recipient = mock(IVehicleDeathRecipient.class); 1678 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1679 new FakeVhalConfigParser(), new ArrayList<>()); 1680 1681 fakeVehicleStub.linkToDeath(recipient); 1682 1683 verify(mMockRealVehicleStub).linkToDeath(recipient); 1684 } 1685 1686 @Test testUnLinkToDeath()1687 public void testUnLinkToDeath() throws Exception { 1688 IVehicleDeathRecipient recipient = mock(IVehicleDeathRecipient.class); 1689 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1690 new FakeVhalConfigParser(), new ArrayList<>()); 1691 1692 fakeVehicleStub.unlinkToDeath(recipient); 1693 1694 verify(mMockRealVehicleStub).unlinkToDeath(recipient); 1695 } 1696 1697 @Test testDump()1698 public void testDump() throws Exception { 1699 FileDescriptor fd = mock(FileDescriptor.class); 1700 FakeVehicleStub fakeVehicleStub = new FakeVehicleStub(mMockRealVehicleStub, 1701 new FakeVhalConfigParser(), new ArrayList<>()); 1702 1703 fakeVehicleStub.dump(fd, new ArrayList<>()); 1704 1705 verify(mMockRealVehicleStub).dump(eq(fd), eq(new ArrayList<>())); 1706 } 1707 buildHalPropValue(int propId, int areaId, long timestamp, RawPropValues rawPropValues)1708 private HalPropValue buildHalPropValue(int propId, int areaId, long timestamp, 1709 RawPropValues rawPropValues) { 1710 VehiclePropValue propValue = new VehiclePropValue(); 1711 propValue.prop = propId; 1712 propValue.areaId = areaId; 1713 propValue.timestamp = timestamp; 1714 propValue.value = rawPropValues; 1715 return new HalPropValueBuilder(/* isAidl= */ true).build(propValue); 1716 } 1717 createParseResult(int propId, float maxSampleRate, int access, int areaId)1718 private SparseArray<ConfigDeclaration> createParseResult(int propId, float maxSampleRate, 1719 int access, int areaId) { 1720 SparseArray<ConfigDeclaration> parseResult = new SparseArray<>(); 1721 ConfigDeclaration propConfig = new ConfigDeclaration( 1722 createConfig(propId, maxSampleRate, access, areaId), null, new SparseArray<>()); 1723 parseResult.put(propId, propConfig); 1724 return parseResult; 1725 } 1726 getPropConfigByPropId(HalPropConfig[] propConfigs, int propId)1727 private HalPropConfig getPropConfigByPropId(HalPropConfig[] propConfigs, int propId) { 1728 for (int i = 0; i < propConfigs.length; i++) { 1729 if (propConfigs[i].getPropId() == propId) { 1730 return propConfigs[i]; 1731 } 1732 } 1733 return null; 1734 } 1735 createConfig(int propId, float sampleRate, int access, int areaId)1736 private VehiclePropConfig createConfig(int propId, float sampleRate, int access, int areaId) { 1737 VehiclePropConfig propConfigValue = new VehiclePropConfig(); 1738 propConfigValue.prop = propId; 1739 propConfigValue.access = access; 1740 VehicleAreaConfig vehicleAreaConfig = new VehicleAreaConfig(); 1741 vehicleAreaConfig.areaId = areaId; 1742 propConfigValue.areaConfigs = new VehicleAreaConfig[]{vehicleAreaConfig}; 1743 propConfigValue.maxSampleRate = sampleRate; 1744 return propConfigValue; 1745 } 1746 createFilenameList(String fileContent)1747 private List<File> createFilenameList(String fileContent) throws Exception { 1748 List<File> customFileList = new ArrayList<>(); 1749 File tempFile = File.createTempFile("custom_config_", ".json"); 1750 tempFile.deleteOnExit(); 1751 try (FileOutputStream os = new FileOutputStream(tempFile)) { 1752 os.write(fileContent.getBytes()); 1753 customFileList.add(tempFile); 1754 } 1755 return customFileList; 1756 } 1757 captureOnGetAsyncResults()1758 private List<GetVehicleStubAsyncResult> captureOnGetAsyncResults() { 1759 verify(mCallback, timeout(DEFAULT_TIMEOUT)).onGetAsyncResults( 1760 mGetVehicleStubAsyncResultCaptor.capture()); 1761 return mGetVehicleStubAsyncResultCaptor.getValue(); 1762 } 1763 captureOnSetAsyncResults()1764 private List<SetVehicleStubAsyncResult> captureOnSetAsyncResults() { 1765 verify(mCallback, timeout(DEFAULT_TIMEOUT)).onSetAsyncResults( 1766 mSetVehicleStubAsyncResultCaptor.capture()); 1767 return mSetVehicleStubAsyncResultCaptor.getValue(); 1768 } 1769 } 1770