1#!/usr/bin/env python 2# 3# Copyright (C) 2016 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import logging 19import time 20 21from vts.runners.host import asserts 22from vts.runners.host import const 23from vts.runners.host import test_runner 24from vts.testcases.template.hal_hidl_host_test import hal_hidl_host_test 25 26VEHICLE_V2_0_HAL = "android.hardware.automotive.vehicle@2.0::IVehicle" 27DBG = False 28 29class VtsHalAutomotiveVehicleV2_0HostTest(hal_hidl_host_test.HalHidlHostTest): 30 """A simple testcase for the VEHICLE HIDL HAL. 31 32 Attributes: 33 _arrived: boolean, the flag of onPropertyEvent received. 34 onPropertyEventCalled: integer, the number of onPropertyEvent received. 35 onPropertySetErrorCalled: integer, the number of onPropertySetError 36 received. 37 DEVICE_TMP_DIR: string, target device's tmp directory path. 38 """ 39 40 TEST_HAL_SERVICES = { 41 VEHICLE_V2_0_HAL, 42 } 43 DEVICE_TMP_DIR = "/data/local/tmp" 44 45 def setUpClass(self): 46 """Creates a mirror and init vehicle hal.""" 47 super(VtsHalAutomotiveVehicleV2_0HostTest, self).setUpClass() 48 49 results = self.shell.Execute("id -u system") 50 system_uid = results[const.STDOUT][0].strip() 51 if DBG: 52 logging.info("system_uid: %s", system_uid) 53 54 self.dut.hal.InitHidlHal( 55 target_type="vehicle", 56 target_basepaths=self.dut.libPaths, 57 target_version=2.0, 58 target_package="android.hardware.automotive.vehicle", 59 target_component_name="IVehicle", 60 hw_binder_service_name=self.getHalServiceName(VEHICLE_V2_0_HAL), 61 bits=int(self.abi_bitness)) 62 63 self.vehicle = self.dut.hal.vehicle # shortcut 64 self.vehicle.SetCallerUid(system_uid) 65 self.vtypes = self.dut.hal.vehicle.GetHidlTypeInterface("types") 66 if DBG: 67 logging.info("vehicle types: %s", self.vtypes) 68 asserts.assertEqual(0x00ff0000, self.vtypes.VehiclePropertyType.MASK) 69 asserts.assertEqual(0x0f000000, self.vtypes.VehicleArea.MASK) 70 71 self.propToConfig = {} 72 for config in self.vehicle.getAllPropConfigs(): 73 self.propToConfig[config['prop']] = config 74 self.configList = self.propToConfig.values() 75 76 def tearDownClass(self): 77 """Performs clean-up pushed file""" 78 79 cmd_results = self.shell.Execute("rm -rf %s" % self.DEVICE_TMP_DIR) 80 if not cmd_results or any(cmd_results[const.EXIT_CODE]) and DBG: 81 logging.info("Failed to remove: %s", cmd_results) 82 super(VtsHalAutomotiveVehicleV2_0HostTest, self).tearDownClass() 83 84 def testListProperties(self): 85 """Checks whether some PropConfigs are returned. 86 87 Verifies that call to getAllPropConfigs is not failing and 88 it returns at least 1 vehicle property config. 89 """ 90 if DBG: 91 logging.info("all supported properties: %s", self.configList) 92 asserts.assertLess(0, len(self.configList)) 93 94 def emptyValueProperty(self, propertyId, areaId=0): 95 """Creates a property structure for use with the Vehicle HAL. 96 97 Args: 98 propertyId: the numeric identifier of the output property. 99 areaId: the numeric identifier of the vehicle area of the output 100 property. 0, or omitted, for global. 101 102 Returns: 103 a property structure for use with the Vehicle HAL. 104 """ 105 return { 106 'prop': propertyId, 107 'timestamp': 0, 108 'areaId': areaId, 109 'status': self.vtypes.VehiclePropertyStatus.AVAILABLE, 110 'value': { 111 'int32Values': [], 112 'floatValues': [], 113 'int64Values': [], 114 'bytes': [], 115 'stringValue': "" 116 } 117 } 118 119 def readVhalProperty(self, propertyId, areaId=0): 120 """Reads a specified property from Vehicle HAL. 121 122 Args: 123 propertyId: the numeric identifier of the property to be read. 124 areaId: the numeric identifier of the vehicle area to retrieve the 125 property for. 0, or omitted, for global. 126 127 Returns: 128 the value of the property as read from Vehicle HAL, or None 129 if it could not read successfully. 130 """ 131 vp = self.vtypes.Py2Pb("VehiclePropValue", 132 self.emptyValueProperty(propertyId, areaId)) 133 if DBG: 134 logging.info("0x%x get request: %s", propertyId, vp) 135 status, value = self.vehicle.get(vp) 136 if DBG: 137 logging.info("0x%x get response: %s, %s", propertyId, status, value) 138 if self.vtypes.StatusCode.OK == status: 139 return value 140 if DBG: 141 logging.warning("attempt to read property 0x%x returned error %d", 142 propertyId, status) 143 144 def setVhalProperty(self, propertyId, value, areaId=0, expectedStatus=0): 145 """Sets a specified property in the Vehicle HAL. 146 147 Args: 148 propertyId: the numeric identifier of the property to be set. 149 value: the value of the property, formatted as per the Vehicle HAL 150 (use emptyValueProperty() as a helper). 151 areaId: the numeric identifier of the vehicle area to set the 152 property for. 0, or omitted, for global. 153 expectedStatus: the StatusCode expected to be returned from setting 154 the property. 0, or omitted, for OK. 155 """ 156 propValue = self.emptyValueProperty(propertyId, areaId) 157 for k in propValue["value"]: 158 if k in value: 159 if k == "stringValue": 160 propValue["value"][k] += value[k] 161 else: 162 propValue["value"][k].extend(value[k]) 163 vp = self.vtypes.Py2Pb("VehiclePropValue", propValue) 164 if DBG: 165 logging.info("0x%x set request: %s", propertyId, vp) 166 status = self.vehicle.set(vp) 167 if DBG: 168 logging.info("0x%x set response: %s", propertyId, status) 169 if 0 == expectedStatus: 170 expectedStatus = self.vtypes.StatusCode.OK 171 asserts.assertEqual(expectedStatus, status, "Prop 0x%x" % propertyId) 172 173 def setAndVerifyIntProperty(self, propertyId, value, areaId=0): 174 """Sets a integer property in the Vehicle HAL and reads it back. 175 176 Args: 177 propertyId: the numeric identifier of the property to be set. 178 value: the int32 value of the property to be set. 179 areaId: the numeric identifier of the vehicle area to set the 180 property for. 0, or omitted, for global. 181 """ 182 self.setVhalProperty( 183 propertyId, {"int32Values": [value]}, areaId=areaId) 184 185 propValue = self.readVhalProperty(propertyId, areaId=areaId) 186 asserts.assertEqual(1, len(propValue["value"]["int32Values"])) 187 asserts.assertEqual(value, propValue["value"]["int32Values"][0]) 188 189 def extractZonesAsList(self, supportedAreas): 190 """Converts bitwise area flags to list of zones""" 191 allZones = [ 192 self.vtypes.VehicleAreaZone.ROW_1_LEFT, 193 self.vtypes.VehicleAreaZone.ROW_1_CENTER, 194 self.vtypes.VehicleAreaZone.ROW_1_RIGHT, 195 self.vtypes.VehicleAreaZone.ROW_2_LEFT, 196 self.vtypes.VehicleAreaZone.ROW_2_CENTER, 197 self.vtypes.VehicleAreaZone.ROW_2_RIGHT, 198 self.vtypes.VehicleAreaZone.ROW_3_LEFT, 199 self.vtypes.VehicleAreaZone.ROW_3_CENTER, 200 self.vtypes.VehicleAreaZone.ROW_3_RIGHT, 201 self.vtypes.VehicleAreaZone.ROW_4_LEFT, 202 self.vtypes.VehicleAreaZone.ROW_4_CENTER, 203 self.vtypes.VehicleAreaZone.ROW_4_RIGHT, 204 ] 205 206 extractedZones = [] 207 for zone in allZones: 208 if (zone & supportedAreas == zone): 209 extractedZones.append(zone) 210 return extractedZones 211 212 def disableTestHvacPowerOn(self): 213 # Disable this test for now. HVAC Power On will no longer behave like this now that we've 214 # added the status field in VehiclePropValue. Need to update the test for this. 215 """Test power on/off and properties associated with it. 216 217 Gets the list of properties that are affected by the HVAC power state 218 and validates them. 219 220 Turns power on to start in a defined state, verifies that power is on 221 and properties are available. State change from on->off and verifies 222 that properties are no longer available, then state change again from 223 off->on to verify properties are now available again. 224 """ 225 226 # Checks that HVAC_POWER_ON property is supported and returns valid 227 # result initially. 228 hvacPowerOnConfig = self.propToConfig[ 229 self.vtypes.VehicleProperty.HVAC_POWER_ON] 230 if hvacPowerOnConfig is None: 231 if DBG: 232 logging.info("HVAC_POWER_ON not supported") 233 return 234 235 zones = self.extractZonesAsList(hvacPowerOnConfig['supportedAreas']) 236 asserts.assertLess( 237 0, len(zones), 238 "supportedAreas for HVAC_POWER_ON property is invalid") 239 240 # TODO(pavelm): consider to check for all zones 241 zone = zones[0] 242 243 propValue = self.readVhalProperty( 244 self.vtypes.VehicleProperty.HVAC_POWER_ON, areaId=zone) 245 246 asserts.assertEqual(1, len(propValue["value"]["int32Values"])) 247 asserts.assertTrue( 248 propValue["value"]["int32Values"][0] in [0, 1], 249 "%d not a valid value for HVAC_POWER_ON" % 250 propValue["value"]["int32Values"][0]) 251 252 # Checks that HVAC_POWER_ON config string returns valid result. 253 requestConfig = [ 254 self.vtypes.Py2Pb("VehicleProperty", 255 self.vtypes.VehicleProperty.HVAC_POWER_ON) 256 ] 257 if DBG: 258 logging.info("HVAC power on config request: %s", requestConfig) 259 responseConfig = self.vehicle.getPropConfigs(requestConfig) 260 if DBG: 261 logging.info("HVAC power on config response: %s", responseConfig) 262 hvacTypes = set([ 263 self.vtypes.VehicleProperty.HVAC_FAN_SPEED, 264 self.vtypes.VehicleProperty.HVAC_FAN_DIRECTION, 265 self.vtypes.VehicleProperty.HVAC_TEMPERATURE_CURRENT, 266 self.vtypes.VehicleProperty.HVAC_TEMPERATURE_SET, 267 self.vtypes.VehicleProperty.HVAC_DEFROSTER, 268 self.vtypes.VehicleProperty.HVAC_AC_ON, 269 self.vtypes.VehicleProperty.HVAC_MAX_AC_ON, 270 self.vtypes.VehicleProperty.HVAC_MAX_DEFROST_ON, 271 self.vtypes.VehicleProperty.HVAC_RECIRC_ON, 272 self.vtypes.VehicleProperty.HVAC_DUAL_ON, 273 self.vtypes.VehicleProperty.HVAC_AUTO_ON, 274 self.vtypes.VehicleProperty.HVAC_ACTUAL_FAN_SPEED_RPM, 275 ]) 276 status = responseConfig[0] 277 asserts.assertEqual(self.vtypes.StatusCode.OK, status) 278 configString = responseConfig[1][0]["configString"] 279 configProps = [] 280 if configString != "": 281 for prop in configString.split(","): 282 configProps.append(int(prop, 16)) 283 for prop in configProps: 284 asserts.assertTrue(prop in hvacTypes, 285 "0x%X not an HVAC type" % prop) 286 287 # Turn power on. 288 self.setAndVerifyIntProperty( 289 self.vtypes.VehicleProperty.HVAC_POWER_ON, 1, areaId=zone) 290 291 # Check that properties that require power to be on can be set. 292 propVals = {} 293 for prop in configProps: 294 v = self.readVhalProperty(prop, areaId=zone)["value"] 295 self.setVhalProperty(prop, v, areaId=zone) 296 # Save the value for use later when trying to set the property when 297 # HVAC is off. 298 propVals[prop] = v 299 300 # Turn power off. 301 self.setAndVerifyIntProperty( 302 self.vtypes.VehicleProperty.HVAC_POWER_ON, 0, areaId=zone) 303 304 # Check that properties that require power to be on can't be set. 305 for prop in configProps: 306 self.setVhalProperty( 307 prop, 308 propVals[prop], 309 areaId=zone, 310 expectedStatus=self.vtypes.StatusCode.NOT_AVAILABLE) 311 312 # Turn power on. 313 self.setAndVerifyIntProperty( 314 self.vtypes.VehicleProperty.HVAC_POWER_ON, 1, areaId=zone) 315 316 # Check that properties that require power to be on can be set. 317 for prop in configProps: 318 self.setVhalProperty(prop, propVals[prop], areaId=zone) 319 320 def testSetBoolPropResponseTime(self): 321 """Verifies that a PropertyEvent arrives in a reasonable time on Boolean Properties""" 322 323 # PropertyEvent is received 324 self._arrived = False 325 326 def onPropertyEvent(vehiclePropValues): 327 for vp in vehiclePropValues: 328 if vp["prop"] & self.vtypes.VehiclePropertyType.BOOLEAN != 0: 329 if DBG: 330 logging.info("onPropertyEvent received: %s", 331 vehiclePropValues) 332 self._arrived = True 333 334 def onPropertySetError(errorCode, propId, areaId): 335 if DBG: 336 logging.info( 337 "onPropertySetError, error: %d, prop: 0x%x, area: 0x%x", 338 errorCode, propId, areaId) 339 self._arrived = True 340 341 for c in self.configList: 342 if (c["access"] != self.vtypes.VehiclePropertyAccess.READ_WRITE or 343 c["changeMode"] != self.vtypes.VehiclePropertyChangeMode.ON_CHANGE or 344 c["prop"] & self.vtypes.VehiclePropertyType.MASK 345 != self.vtypes.VehiclePropertyType.BOOLEAN): 346 continue 347 348 self._arrived = False 349 350 # Register for on_change property 351 prop = c["prop"] 352 callback = self.vehicle.GetHidlCallbackInterface( 353 "IVehicleCallback", 354 onPropertyEvent=onPropertyEvent, 355 onPropertySetError=onPropertySetError 356 ) 357 subscribeOption = { 358 "propId": prop, 359 "sampleRate": 0.0, # ON_CHANGE 360 "flags": self.vtypes.SubscribeFlags.EVENTS_FROM_CAR, 361 } 362 pbSubscribeOption = self.vtypes.Py2Pb("SubscribeOptions", 363 subscribeOption) 364 statusCode = self.vehicle.subscribe(callback, [pbSubscribeOption]) 365 asserts.assertEqual(statusCode, 0, 366 "Must successfully subscribe to property 0x%x" % prop) 367 368 # Change value of properties 369 for area in c["areaConfigs"]: 370 currPropVal = self.readVhalProperty(prop, area["areaId"]) 371 updateVal = [0] 372 if (currPropVal["value"]["int32Values"] is None or 373 currPropVal["value"]["int32Values"] == [0]): 374 updateVal = [1] 375 propValue = self.emptyValueProperty(prop, area["areaId"]) 376 for index in propValue["value"]: 377 if index == "int32Values": 378 propValue["value"][index].extend(updateVal) 379 vp = self.vtypes.Py2Pb("VehiclePropValue", propValue) 380 status = self.vehicle.set(vp) 381 if status != 0: 382 if DBG: 383 logging.warning("Set value failed for Property 0x%x" % prop) 384 continue 385 386 # Check callback is received in 5 second 387 waitingTime = 5 388 checkTimes = 5 389 for _ in xrange(checkTimes): 390 if self._arrived: 391 if DBG: 392 logging.info("callback for Property: 0x%x is received" % prop) 393 break 394 time.sleep(waitingTime/checkTimes) 395 396 if not self._arrived: 397 asserts.fail( 398 "callback is not received in 5 seconds for Property: 0x%x" 399 % prop) 400 self.vehicle.unsubscribe(callback, prop) 401 402 def testVehicleStaticProps(self): 403 """Verifies that static properties are configured correctly""" 404 staticProperties = set([ 405 self.vtypes.VehicleProperty.INFO_VIN, 406 self.vtypes.VehicleProperty.INFO_MAKE, 407 self.vtypes.VehicleProperty.INFO_MODEL, 408 self.vtypes.VehicleProperty.INFO_MODEL_YEAR, 409 self.vtypes.VehicleProperty.INFO_FUEL_CAPACITY, 410 self.vtypes.VehicleProperty.INFO_FUEL_TYPE, 411 self.vtypes.VehicleProperty.INFO_EV_BATTERY_CAPACITY, 412 self.vtypes.VehicleProperty.INFO_EV_CONNECTOR_TYPE, 413 self.vtypes.VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE, 414 self.vtypes.VehicleProperty.AP_POWER_BOOTUP_REASON, 415 self.vtypes.VehicleProperty.INFO_FUEL_DOOR_LOCATION, 416 self.vtypes.VehicleProperty.INFO_EV_PORT_LOCATION, 417 self.vtypes.VehicleProperty.INFO_DRIVER_SEAT, 418 ]) 419 420 def checkForStaticCondition(propConfig): 421 asserts.assertEqual( 422 self.vtypes.VehiclePropertyAccess.READ, 423 propConfig["access"], 424 "Prop 0x%x must be read access" % propConfig['prop']) 425 for area in propConfig["areaConfigs"]: 426 propValue = self.readVhalProperty( 427 propConfig['prop'], area["areaId"]) 428 asserts.assertEqual(propConfig['prop'], propValue["prop"]) 429 self.setVhalProperty( 430 propConfig['prop'], propValue["value"], 431 expectedStatus=self.vtypes.StatusCode.ACCESS_DENIED) 432 433 for c in self.configList: 434 # Static system property 435 if (c["prop"] in staticProperties): 436 asserts.assertEqual( 437 self.vtypes.VehiclePropertyChangeMode.STATIC, 438 c["changeMode"], 439 "Prop 0x%x must be static change mode" % c['prop']) 440 checkForStaticCondition(c) 441 # Static vendor property 442 elif (c["prop"] & self.vtypes.VehiclePropertyGroup.MASK 443 == self.vtypes.VehiclePropertyGroup.VENDOR and 444 c["changeMode"] == self.vtypes.VehiclePropertyChangeMode.STATIC): 445 checkForStaticCondition(c) 446 # Non-static property 447 else: 448 asserts.assertNotEqual( 449 self.vtypes.VehiclePropertyChangeMode.STATIC, 450 c["changeMode"], 451 "Prop 0x%x cannot be static change mode" % c['prop']) 452 453 def testPropertyRanges(self): 454 """Retrieve the property ranges for all areas. 455 456 This checks that the areas noted in the config all give valid area 457 configs. Once these are validated, the values for all these areas 458 retrieved from the HIDL must be within the ranges defined.""" 459 460 enumProperties = { 461 self.vtypes.VehicleProperty.INFO_FUEL_TYPE, 462 self.vtypes.VehicleProperty.INFO_EV_CONNECTOR_TYPE, 463 self.vtypes.VehicleProperty.INFO_FUEL_DOOR_LOCATION, 464 self.vtypes.VehicleProperty.INFO_EV_PORT_LOCATION, 465 self.vtypes.VehicleProperty.INFO_DRIVER_SEAT, 466 self.vtypes.VehicleProperty.ENGINE_OIL_LEVEL, 467 self.vtypes.VehicleProperty.GEAR_SELECTION, 468 self.vtypes.VehicleProperty.CURRENT_GEAR, 469 self.vtypes.VehicleProperty.TURN_SIGNAL_STATE, 470 self.vtypes.VehicleProperty.IGNITION_STATE, 471 self.vtypes.VehicleProperty.HVAC_FAN_DIRECTION, 472 self.vtypes.VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS, 473 self.vtypes.VehicleProperty.HVAC_FAN_DIRECTION_AVAILABLE, 474 self.vtypes.VehicleProperty.DISTANCE_DISPLAY_UNITS, 475 self.vtypes.VehicleProperty.FUEL_VOLUME_DISPLAY_UNITS, 476 self.vtypes.VehicleProperty.TIRE_PRESSURE_DISPLAY_UNITS, 477 self.vtypes.VehicleProperty.EV_BATTERY_DISPLAY_UNITS, 478 self.vtypes.VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS, 479 self.vtypes.VehicleProperty.AP_POWER_STATE_REQ, 480 self.vtypes.VehicleProperty.AP_POWER_STATE_REPORT, 481 self.vtypes.VehicleProperty.AP_POWER_BOOTUP_REASON, 482 self.vtypes.VehicleProperty.HW_KEY_INPUT, 483 self.vtypes.VehicleProperty.SEAT_OCCUPANCY, 484 self.vtypes.VehicleProperty.HEADLIGHTS_STATE, 485 self.vtypes.VehicleProperty.HIGH_BEAM_LIGHTS_STATE, 486 self.vtypes.VehicleProperty.FOG_LIGHTS_STATE, 487 self.vtypes.VehicleProperty.HAZARD_LIGHTS_STATE, 488 self.vtypes.VehicleProperty.HEADLIGHTS_SWITCH, 489 self.vtypes.VehicleProperty.HIGH_BEAM_LIGHTS_SWITCH, 490 self.vtypes.VehicleProperty.FOG_LIGHTS_SWITCH, 491 self.vtypes.VehicleProperty.HAZARD_LIGHTS_SWITCH, 492 self.vtypes.VehicleProperty.CABIN_LIGHTS_STATE, 493 self.vtypes.VehicleProperty.CABIN_LIGHTS_SWITCH, 494 self.vtypes.VehicleProperty.READING_LIGHTS_STATE, 495 self.vtypes.VehicleProperty.READING_LIGHTS_SWITCH, 496 } 497 498 for c in self.configList: 499 # Continuous properties need to have a sampling frequency. 500 if c["changeMode"] == self.vtypes.VehiclePropertyChangeMode.CONTINUOUS: 501 asserts.assertTrue( 502 c["minSampleRate"] >= 0.0 , 503 "minSampleRate should be >= 0. Config list: %s" % c) 504 asserts.assertLess( 505 0.0, c["maxSampleRate"], 506 "maxSampleRate should be > 0. Config list: %s" % c) 507 asserts.assertFalse( 508 c["minSampleRate"] > c["maxSampleRate"], 509 "Prop 0x%x minSampleRate > maxSampleRate" % c["prop"]) 510 511 if c["prop"] & self.vtypes.VehiclePropertyType.BOOLEAN != 0: 512 # Boolean types don't have ranges 513 continue 514 515 if (c["access"] != self.vtypes.VehiclePropertyAccess.READ_WRITE and 516 c["access"] != self.vtypes.VehiclePropertyAccess.READ): 517 # Skip the test if properties are not readable. 518 continue 519 520 if c["prop"] in enumProperties: 521 # This property does not use traditional min/max ranges 522 continue 523 524 asserts.assertTrue(c["areaConfigs"] != None, 525 "Prop 0x%x must have areaConfigs" % c["prop"]) 526 areasFound = 0 527 for a in c["areaConfigs"]: 528 # Make sure this doesn't override one of the other areas found. 529 asserts.assertEqual(0, areasFound & a["areaId"]) 530 areasFound |= a["areaId"] 531 532 # Do some basic checking the min and max aren't mixed up. 533 checks = [("minInt32Value", "maxInt32Value"), 534 ("minInt64Value", "maxInt64Value"), 535 ("minFloatValue", "maxFloatValue")] 536 for minName, maxName in checks: 537 asserts.assertFalse( 538 a[minName] > a[maxName], 539 "Prop 0x%x Area 0x%X %s > %s: %d > %d" % 540 (c["prop"], a["areaId"], minName, maxName, a[minName], 541 a[maxName])) 542 543 # Get a value and make sure it's within the bounds. 544 propVal = self.readVhalProperty(c["prop"], a["areaId"]) 545 # Some values may not be available, which is not an error. 546 if propVal is None: 547 continue 548 val = propVal["value"] 549 valTypes = { 550 "int32Values": ("minInt32Value", "maxInt32Value"), 551 "int64Values": ("minInt64Value", "maxInt64Value"), 552 "floatValues": ("minFloatValue", "maxFloatValue"), 553 } 554 for valType, valBoundNames in valTypes.items(): 555 for v in val[valType]: 556 # If it is a vendor property and does not have range values, 557 # it is excluded from testing. 558 if (c["prop"] & self.vtypes.VehiclePropertyGroup.MASK 559 == self.vtypes.VehiclePropertyGroup.VENDOR and 560 a[valBoundNames[0]] == 0 and a[valBoundNames[1]] == 0): 561 continue 562 # Make sure value isn't less than the minimum. 563 asserts.assertFalse( 564 v < a[valBoundNames[0]], 565 "Prop 0x%x Area 0x%X %s < min: %s < %s" % 566 (c["prop"], a["areaId"], valType, v, 567 a[valBoundNames[0]])) 568 # Make sure value isn't greater than the maximum. 569 asserts.assertFalse( 570 v > a[valBoundNames[1]], 571 "Prop 0x%x Area 0x%X %s > max: %s > %s" % 572 (c["prop"], a["areaId"], valType, v, 573 a[valBoundNames[1]])) 574 575 def getValueIfPropSupported(self, propertyId): 576 """Returns tuple of boolean (indicating value supported or not) and the value itself""" 577 if (propertyId in self.propToConfig): 578 propValue = self.readVhalProperty(propertyId) 579 asserts.assertNotEqual(None, propValue, 580 "expected value, prop: 0x%x" % propertyId) 581 asserts.assertEqual(propertyId, propValue['prop']) 582 return True, self.extractValue(propValue) 583 else: 584 return False, None 585 586 def testInfoVinMakeModel(self): 587 """Verifies INFO_VIN, INFO_MAKE, INFO_MODEL properties""" 588 stringProperties = set([ 589 self.vtypes.VehicleProperty.INFO_VIN, 590 self.vtypes.VehicleProperty.INFO_MAKE, 591 self.vtypes.VehicleProperty.INFO_MODEL 592 ]) 593 for prop in stringProperties: 594 supported, val = self.getValueIfPropSupported(prop) 595 if supported: 596 asserts.assertEqual(str, type(val), "prop: 0x%x" % prop) 597 asserts.assertTrue(0 <= (len(val)), "prop: 0x%x" % prop) 598 599 def testGlobalFloatProperties(self): 600 """Verifies that values of global float properties are in the correct range""" 601 floatProperties = { 602 self.vtypes.VehicleProperty.ENV_OUTSIDE_TEMPERATURE: (-50, 100), # celsius 603 self.vtypes.VehicleProperty.ENGINE_RPM : (0, 30000), # RPMs 604 self.vtypes.VehicleProperty.ENGINE_OIL_TEMP : (-50, 150), # celsius 605 self.vtypes.VehicleProperty.ENGINE_COOLANT_TEMP : (-50, 150), # 606 self.vtypes.VehicleProperty.PERF_VEHICLE_SPEED : (0, 150), # m/s, 150 m/s = 330 mph 607 self.vtypes.VehicleProperty.PERF_VEHICLE_SPEED_DISPLAY : (0, 150), # 150 m/s = 330 mph 608 self.vtypes.VehicleProperty.PERF_STEERING_ANGLE : (-180, 180), # degrees 609 self.vtypes.VehicleProperty.PERF_ODOMETER : (0, 1000000), # km 610 self.vtypes.VehicleProperty.INFO_FUEL_CAPACITY : (0, 1000000), # milliliter 611 } 612 613 for prop, validRange in floatProperties.iteritems(): 614 supported, val = self.getValueIfPropSupported(prop) 615 if supported: 616 asserts.assertEqual(float, type(val)) 617 self.assertValueInRangeForProp(val, validRange[0], 618 validRange[1], prop) 619 620 def testGlobalBoolProperties(self): 621 """Verifies that values of global boolean properties are in the correct range""" 622 booleanProperties = set([ 623 self.vtypes.VehicleProperty.PARKING_BRAKE_ON, 624 self.vtypes.VehicleProperty.FUEL_LEVEL_LOW, 625 self.vtypes.VehicleProperty.NIGHT_MODE, 626 self.vtypes.VehicleProperty.ABS_ACTIVE, 627 self.vtypes.VehicleProperty.FUEL_DOOR_OPEN, 628 self.vtypes.VehicleProperty.EV_CHARGE_PORT_OPEN, 629 self.vtypes.VehicleProperty.EV_CHARGE_PORT_CONNECTED, 630 ]) 631 for prop in booleanProperties: 632 self.verifyEnumPropIfSupported(prop, [0, 1]) 633 634 def testGlobalEnumProperties(self): 635 """Verifies that values of global enum properties are in the correct range""" 636 enumProperties = { 637 self.vtypes.VehicleProperty.ENGINE_OIL_LEVEL: 638 self.vtypes.VehicleOilLevel, 639 self.vtypes.VehicleProperty.GEAR_SELECTION: 640 self.vtypes.VehicleGear, 641 self.vtypes.VehicleProperty.CURRENT_GEAR: 642 self.vtypes.VehicleGear, 643 self.vtypes.VehicleProperty.TURN_SIGNAL_STATE: 644 self.vtypes.VehicleTurnSignal, 645 self.vtypes.VehicleProperty.IGNITION_STATE: 646 self.vtypes.VehicleIgnitionState, 647 } 648 for prop, enum in enumProperties.iteritems(): 649 self.verifyEnumPropIfSupported(prop, vars(enum).values()) 650 651 def testDebugDump(self): 652 """Verifies that call to IVehicle#debugDump is not failing""" 653 dumpStr = self.vehicle.debugDump() 654 asserts.assertNotEqual(None, dumpStr) 655 656 def extractValue(self, propValue): 657 """Extracts value depending on data type of the property""" 658 if propValue == None: 659 return None 660 661 # Extract data type 662 dataType = propValue['prop'] & self.vtypes.VehiclePropertyType.MASK 663 val = propValue['value'] 664 if self.vtypes.VehiclePropertyType.STRING == dataType: 665 asserts.assertNotEqual(None, val['stringValue']) 666 return val['stringValue'] 667 elif self.vtypes.VehiclePropertyType.INT32 == dataType or \ 668 self.vtypes.VehiclePropertyType.BOOLEAN == dataType: 669 asserts.assertEqual(1, len(val["int32Values"])) 670 return val["int32Values"][0] 671 elif self.vtypes.VehiclePropertyType.INT64 == dataType: 672 asserts.assertEqual(1, len(val["int64Values"])) 673 return val["int64Values"][0] 674 elif self.vtypes.VehiclePropertyType.FLOAT == dataType: 675 asserts.assertEqual(1, len(val["floatValues"])) 676 return val["floatValues"][0] 677 elif self.vtypes.VehiclePropertyType.INT32_VEC == dataType: 678 asserts.assertLess(0, len(val["int32Values"])) 679 return val["int32Values"] 680 elif self.vtypes.VehiclePropertyType.FLOAT_VEC == dataType: 681 asserts.assertLess(0, len(val["floatValues"])) 682 return val["floatValues"] 683 elif self.vtypes.VehiclePropertyType.BYTES == dataType: 684 asserts.assertLess(0, len(val["bytes"])) 685 return val["bytes"] 686 else: 687 return val 688 689 def verifyEnumPropIfSupported(self, propertyId, validValues): 690 """Verifies that if given property supported it is one of the value in validValues set""" 691 supported, val = self.getValueIfPropSupported(propertyId) 692 if supported: 693 asserts.assertEqual(int, type(val)) 694 self.assertIntValueInRangeForProp(val, validValues, propertyId) 695 696 def assertLessOrEqual(self, first, second, msg=None): 697 """Asserts that first <= second""" 698 if second < first: 699 fullMsg = "%s is not less or equal to %s" % (first, second) 700 if msg: 701 fullMsg = "%s %s" % (fullMsg, msg) 702 fail(fullMsg) 703 704 def assertIntValueInRangeForProp(self, value, validValues, prop): 705 """Asserts that given value is in the validValues range""" 706 asserts.assertTrue( 707 value in validValues, 708 "Invalid value %d for property: 0x%x, expected one of: %s" % 709 (value, prop, validValues)) 710 711 def assertValueInRangeForProp(self, value, rangeBegin, rangeEnd, prop): 712 """Asserts that given value is in the range [rangeBegin, rangeEnd]""" 713 msg = "Value %s is out of range [%s, %s] for property 0x%x" % ( 714 value, rangeBegin, rangeEnd, prop) 715 self.assertLessOrEqual(rangeBegin, value, msg) 716 self.assertLessOrEqual(value, rangeEnd, msg) 717 718 def getPropConfig(self, propertyId): 719 return self.propToConfig.get(propertyId) 720 721 722 def isPropSupported(self, propertyId): 723 return self.getPropConfig(propertyId) is not None 724 725 def testEngineOilTemp(self): 726 """tests engine oil temperature. 727 728 This also tests an HIDL async callback. 729 """ 730 self.onPropertyEventCalled = 0 731 self.onPropertySetErrorCalled = 0 732 733 def onPropertyEvent(vehiclePropValues): 734 if DBG: 735 logging.info("onPropertyEvent received: %s", vehiclePropValues) 736 self.onPropertyEventCalled += 1 737 738 def onPropertySetError(erroCode, propId, areaId): 739 if DBG: 740 logging.info( 741 "onPropertySetError, error: %d, prop: 0x%x, area: 0x%x", 742 erroCode, prop, area) 743 self.onPropertySetErrorCalled += 1 744 745 config = self.getPropConfig( 746 self.vtypes.VehicleProperty.ENGINE_OIL_TEMP) 747 if (config is None) and DBG: 748 logging.info("ENGINE_OIL_TEMP property is not supported") 749 return # Property not supported, we are done here. 750 751 propValue = self.readVhalProperty( 752 self.vtypes.VehicleProperty.ENGINE_OIL_TEMP) 753 asserts.assertEqual(1, len(propValue['value']['floatValues'])) 754 oilTemp = propValue['value']['floatValues'][0] 755 if DBG: 756 logging.info("Current oil temperature: %f C", oilTemp) 757 asserts.assertLess(oilTemp, 200) # Check it is in reasinable range 758 asserts.assertLess(-50, oilTemp) 759 760 if (config["changeMode"] == 761 self.vtypes.VehiclePropertyChangeMode.CONTINUOUS): 762 if DBG: 763 logging.info( 764 "ENGINE_OIL_TEMP is continuous property, subscribing...") 765 callback = self.vehicle.GetHidlCallbackInterface( 766 "IVehicleCallback", 767 onPropertyEvent=onPropertyEvent, 768 onPropertySetError=onPropertySetError) 769 770 subscribeOptions = { 771 "propId": self.vtypes.VehicleProperty.ENGINE_OIL_TEMP, 772 "sampleRate": 1.0, # Hz 773 "flags": self.vtypes.SubscribeFlags.EVENTS_FROM_CAR, 774 } 775 pbSubscribeOptions = self.vtypes.Py2Pb("SubscribeOptions", 776 subscribeOptions) 777 778 statusCode = self.vehicle.subscribe(callback, [pbSubscribeOptions]) 779 if statusCode != 0: 780 asserts.fail("Can not register ENGINE_OIL_TEMP") 781 782 for _ in range(5): 783 if (self.onPropertyEventCalled > 0 784 or self.onPropertySetErrorCalled > 0): 785 self.vehicle.unsubscribe( 786 callback, self.vtypes.VehicleProperty.ENGINE_OIL_TEMP) 787 return 788 time.sleep(1) 789 asserts.fail("Callback not called in 5 seconds.") 790 791 def getDiagnosticSupportInfo(self): 792 """Check which of the OBD2 diagnostic properties are supported.""" 793 properties = [ 794 self.vtypes.VehicleProperty.OBD2_LIVE_FRAME, 795 self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME, 796 self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO, 797 self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_CLEAR 798 ] 799 return {x: self.isPropSupported(x) for x in properties} 800 801 class CheckRead(object): 802 """An object whose job it is to read a Vehicle HAL property and run 803 routine validation checks on the result.""" 804 805 def __init__(self, test, propertyId, areaId=0): 806 """Creates a CheckRead instance. 807 808 Args: 809 test: the containing testcase object. 810 propertyId: the numeric identifier of the vehicle property. 811 """ 812 self.test = test 813 self.propertyId = propertyId 814 self.areaId = 0 815 816 def validateGet(self, status, value): 817 """Validate the result of IVehicle.get. 818 819 Args: 820 status: the StatusCode returned from Vehicle HAL. 821 value: the VehiclePropValue returned from Vehicle HAL. 822 823 Returns: a VehiclePropValue instance, or None on failure.""" 824 asserts.assertEqual(self.test.vtypes.StatusCode.OK, status) 825 asserts.assertNotEqual(value, None) 826 asserts.assertEqual(self.propertyId, value['prop']) 827 return value 828 829 def prepareRequest(self, propValue): 830 """Setup this request with any property-specific data. 831 832 Args: 833 propValue: a dictionary in the format of a VehiclePropValue. 834 835 Returns: a dictionary in the format of a VehclePropValue.""" 836 return propValue 837 838 def __call__(self): 839 asserts.assertTrue( 840 self.test.isPropSupported(self.propertyId), "error") 841 request = { 842 'prop': self.propertyId, 843 'timestamp': 0, 844 'areaId': self.areaId, 845 'status': self.test.vtypes.VehiclePropertyStatus.AVAILABLE, 846 'value': { 847 'int32Values': [], 848 'floatValues': [], 849 'int64Values': [], 850 'bytes': [], 851 'stringValue': "" 852 } 853 } 854 request = self.prepareRequest(request) 855 requestPropValue = self.test.vtypes.Py2Pb("VehiclePropValue", 856 request) 857 status, responsePropValue = self.test.vehicle.get(requestPropValue) 858 return self.validateGet(status, responsePropValue) 859 860 class CheckWrite(object): 861 """An object whose job it is to write a Vehicle HAL property and run 862 routine validation checks on the result.""" 863 864 def __init__(self, test, propertyId, areaId=0): 865 """Creates a CheckWrite instance. 866 867 Args: 868 test: the containing testcase object. 869 propertyId: the numeric identifier of the vehicle property. 870 areaId: the numeric identifier of the vehicle area. 871 """ 872 self.test = test 873 self.propertyId = propertyId 874 self.areaId = 0 875 876 def validateSet(self, status): 877 """Validate the result of IVehicle.set. 878 Reading back the written-to property to ensure a consistent 879 value is fair game for this method. 880 881 Args: 882 status: the StatusCode returned from Vehicle HAL. 883 884 Returns: None.""" 885 asserts.assertEqual(self.test.vtypes.StatusCode.OK, status) 886 887 def prepareRequest(self, propValue): 888 """Setup this request with any property-specific data. 889 890 Args: 891 propValue: a dictionary in the format of a VehiclePropValue. 892 893 Returns: a dictionary in the format of a VehclePropValue.""" 894 return propValue 895 896 def __call__(self): 897 asserts.assertTrue( 898 self.test.isPropSupported(self.propertyId), "error") 899 request = { 900 'prop': self.propertyId, 901 'timestamp': 0, 902 'areaId': self.areaId, 903 'status': self.test.vtypes.VehiclePropertyStatus.AVAILABLE, 904 'value': { 905 'int32Values': [], 906 'floatValues': [], 907 'int64Values': [], 908 'bytes': [], 909 'stringValue': "" 910 } 911 } 912 request = self.prepareRequest(request) 913 requestPropValue = self.test.vtypes.Py2Pb("VehiclePropValue", 914 request) 915 status = self.test.vehicle.set(requestPropValue) 916 return self.validateSet(status) 917 918 def testReadObd2LiveFrame(self): 919 """Test that one can correctly read the OBD2 live frame.""" 920 supportInfo = self.getDiagnosticSupportInfo() 921 if supportInfo[self.vtypes.VehicleProperty.OBD2_LIVE_FRAME]: 922 checkRead = self.CheckRead( 923 self, self.vtypes.VehicleProperty.OBD2_LIVE_FRAME) 924 checkRead() 925 else: 926 # live frame not supported by this HAL implementation. done 927 if DBG: 928 logging.info("OBD2_LIVE_FRAME not supported.") 929 930 def testReadObd2FreezeFrameInfo(self): 931 """Test that one can read the list of OBD2 freeze timestamps.""" 932 supportInfo = self.getDiagnosticSupportInfo() 933 if supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO]: 934 checkRead = self.CheckRead( 935 self, self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO) 936 checkRead() 937 else: 938 # freeze frame info not supported by this HAL implementation. done 939 if DBG: 940 logging.info("OBD2_FREEZE_FRAME_INFO not supported.") 941 942 def testReadValidObd2FreezeFrame(self): 943 """Test that one can read the OBD2 freeze frame data.""" 944 945 class FreezeFrameCheckRead(self.CheckRead): 946 def __init__(self, test, timestamp): 947 self.test = test 948 self.propertyId = \ 949 self.test.vtypes.VehicleProperty.OBD2_FREEZE_FRAME 950 self.timestamp = timestamp 951 self.areaId = 0 952 953 def prepareRequest(self, propValue): 954 propValue['value']['int64Values'] = [self.timestamp] 955 return propValue 956 957 def validateGet(self, status, value): 958 # None is acceptable, as a newer fault could have overwritten 959 # the one we're trying to read 960 if value is not None: 961 asserts.assertEqual(self.test.vtypes.StatusCode.OK, status) 962 asserts.assertEqual(self.propertyId, value['prop']) 963 asserts.assertEqual(self.timestamp, value['timestamp']) 964 965 supportInfo = self.getDiagnosticSupportInfo() 966 if supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO] \ 967 and supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME]: 968 infoCheckRead = self.CheckRead( 969 self, self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO) 970 frameInfos = infoCheckRead() 971 timestamps = frameInfos["value"]["int64Values"] 972 for timestamp in timestamps: 973 freezeCheckRead = FreezeFrameCheckRead(self, timestamp) 974 freezeCheckRead() 975 else: 976 # freeze frame not supported by this HAL implementation. done 977 if DBG: 978 logging.info("OBD2_FREEZE_FRAME and _INFO not supported.") 979 980 def testReadInvalidObd2FreezeFrame(self): 981 """Test that trying to read freeze frame at invalid timestamps 982 behaves correctly (i.e. returns an error code).""" 983 984 class FreezeFrameCheckRead(self.CheckRead): 985 def __init__(self, test, timestamp): 986 self.test = test 987 self.propertyId = self.test.vtypes.VehicleProperty.OBD2_FREEZE_FRAME 988 self.timestamp = timestamp 989 self.areaId = 0 990 991 def prepareRequest(self, propValue): 992 propValue['value']['int64Values'] = [self.timestamp] 993 return propValue 994 995 def validateGet(self, status, value): 996 asserts.assertEqual(self.test.vtypes.StatusCode.INVALID_ARG, 997 status) 998 999 supportInfo = self.getDiagnosticSupportInfo() 1000 invalidTimestamps = [0, 482005800] 1001 if supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME]: 1002 for timestamp in invalidTimestamps: 1003 freezeCheckRead = FreezeFrameCheckRead(self, timestamp) 1004 freezeCheckRead() 1005 else: 1006 # freeze frame not supported by this HAL implementation. done 1007 if DBG: 1008 logging.info("OBD2_FREEZE_FRAME not supported.") 1009 1010 def testClearValidObd2FreezeFrame(self): 1011 """Test that deleting a diagnostic freeze frame works. 1012 Given the timing behavor of OBD2_FREEZE_FRAME, the only sensible 1013 definition of works here is that, after deleting a frame, trying to read 1014 at its timestamp, will not be successful.""" 1015 1016 class FreezeFrameClearCheckWrite(self.CheckWrite): 1017 def __init__(self, test, timestamp): 1018 self.test = test 1019 self.propertyId = self.test.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_CLEAR 1020 self.timestamp = timestamp 1021 self.areaId = 0 1022 1023 def prepareRequest(self, propValue): 1024 propValue['value']['int64Values'] = [self.timestamp] 1025 return propValue 1026 1027 def validateSet(self, status): 1028 asserts.assertTrue( 1029 status in [ 1030 self.test.vtypes.StatusCode.OK, 1031 self.test.vtypes.StatusCode.INVALID_ARG 1032 ], "error") 1033 1034 class FreezeFrameCheckRead(self.CheckRead): 1035 def __init__(self, test, timestamp): 1036 self.test = test 1037 self.propertyId = \ 1038 self.test.vtypes.VehicleProperty.OBD2_FREEZE_FRAME 1039 self.timestamp = timestamp 1040 self.areaId = 0 1041 1042 def prepareRequest(self, propValue): 1043 propValue['value']['int64Values'] = [self.timestamp] 1044 return propValue 1045 1046 def validateGet(self, status, value): 1047 asserts.assertEqual(self.test.vtypes.StatusCode.INVALID_ARG, 1048 status) 1049 1050 supportInfo = self.getDiagnosticSupportInfo() 1051 if supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO] \ 1052 and supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME] \ 1053 and supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_CLEAR]: 1054 infoCheckRead = self.CheckRead( 1055 self, self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_INFO) 1056 frameInfos = infoCheckRead() 1057 timestamps = frameInfos["value"]["int64Values"] 1058 for timestamp in timestamps: 1059 checkWrite = FreezeFrameClearCheckWrite(self, timestamp) 1060 checkWrite() 1061 checkRead = FreezeFrameCheckRead(self, timestamp) 1062 checkRead() 1063 else: 1064 # freeze frame not supported by this HAL implementation. done 1065 if DBG: 1066 logging.info("OBD2_FREEZE_FRAME, _CLEAR and _INFO not supported.") 1067 1068 def testClearInvalidObd2FreezeFrame(self): 1069 """Test that deleting an invalid freeze frame behaves correctly.""" 1070 1071 class FreezeFrameClearCheckWrite(self.CheckWrite): 1072 def __init__(self, test, timestamp): 1073 self.test = test 1074 self.propertyId = \ 1075 self.test.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_CLEAR 1076 self.timestamp = timestamp 1077 self.areaId = 0 1078 1079 def prepareRequest(self, propValue): 1080 propValue['value']['int64Values'] = [self.timestamp] 1081 return propValue 1082 1083 def validateSet(self, status): 1084 asserts.assertEqual( 1085 self.test.vtypes.StatusCode.INVALID_ARG, status, 1086 "PropId: 0x%s, Timestamp: %d" % (self.propertyId, 1087 self.timestamp)) 1088 1089 supportInfo = self.getDiagnosticSupportInfo() 1090 if supportInfo[self.vtypes.VehicleProperty.OBD2_FREEZE_FRAME_CLEAR]: 1091 invalidTimestamps = [0, 482005800] 1092 for timestamp in invalidTimestamps: 1093 checkWrite = FreezeFrameClearCheckWrite(self, timestamp) 1094 checkWrite() 1095 else: 1096 # freeze frame not supported by this HAL implementation. done 1097 if DBG: 1098 logging.info("OBD2_FREEZE_FRAME_CLEAR not supported.") 1099 1100 def testVendorPermission(self): 1101 """Verfies SUPPORT_CUSTOMIZE_VENDOR_PERMISSION property""" 1102 config = self.getPropConfig( 1103 self.vtypes.VehicleProperty.SUPPORT_CUSTOMIZE_VENDOR_PERMISSION) 1104 if (config is None) and DBG: 1105 logging.info("SUPPORT_CUSTOMIZE_VENDOR_PERMISSION is not supported") 1106 return 1107 configArray = config["configArray"] 1108 1109 asserts.assertEqual(0, len(configArray) % 3) 1110 index = 0; 1111 while index < len(configArray): 1112 propId = configArray[index] 1113 index += 1 1114 # only vendor properties can have vendor permissions 1115 asserts.assertTrue(self.isVendorProperty(propId), "0x%X not a vendor property" % propId) 1116 1117 readPermission = configArray[index] 1118 index += 1 1119 writePermission = configArray[index] 1120 index += 1 1121 asserts.assertTrue(self.checkVendorPermissonConfig(readPermission, writePermission), 1122 "permissions for 0x%X are not valid vendor permissions" % propId) 1123 1124 def checkVendorPermissonConfig(self, readPermission, writePermission): 1125 permissions = set([ 1126 self.vtypes.VehicleVendorPermission.PERMISSION_DEFAULT, 1127 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_WINDOW, 1128 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_WINDOW, 1129 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_DOOR, 1130 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_DOOR, 1131 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_SEAT, 1132 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_SEAT, 1133 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_MIRROR, 1134 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_MIRROR, 1135 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_INFO, 1136 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_INFO, 1137 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_ENGINE, 1138 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_ENGINE, 1139 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_HVAC, 1140 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_HVAC, 1141 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_LIGHT, 1142 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_LIGHT, 1143 1144 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_1, 1145 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_1, 1146 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_2, 1147 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_2, 1148 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_3, 1149 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_3, 1150 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_4, 1151 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_4, 1152 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_5, 1153 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_5, 1154 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_6, 1155 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_6, 1156 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_7, 1157 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_7, 1158 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_8, 1159 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_8, 1160 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_9, 1161 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_9, 1162 self.vtypes.VehicleVendorPermission.PERMISSION_SET_VENDOR_CATEGORY_10, 1163 self.vtypes.VehicleVendorPermission.PERMISSION_GET_VENDOR_CATEGORY_10, 1164 self.vtypes.VehicleVendorPermission.PERMISSION_NOT_ACCESSIBLE]) 1165 return (readPermission in permissions) and (writePermission in permissions) 1166 1167 def isVendorProperty(self, propId): 1168 return (propId & self.vtypes.VehiclePropertyGroup.MASK) == self.vtypes.VehiclePropertyGroup.VENDOR 1169 1170if __name__ == "__main__": 1171 test_runner.main() 1172