1 /* 2 * Copyright (C) 2017 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; 18 19 import static java.lang.Integer.toHexString; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 26 import android.car.Car; 27 import android.car.diagnostic.CarDiagnosticEvent; 28 import android.car.diagnostic.CarDiagnosticEvent.CommonIgnitionMonitors; 29 import android.car.diagnostic.CarDiagnosticEvent.CompressionIgnitionMonitors; 30 import android.car.diagnostic.CarDiagnosticEvent.FuelSystemStatus; 31 import android.car.diagnostic.CarDiagnosticEvent.FuelType; 32 import android.car.diagnostic.CarDiagnosticEvent.SecondaryAirStatus; 33 import android.car.diagnostic.CarDiagnosticEvent.SparkIgnitionMonitors; 34 import android.car.diagnostic.CarDiagnosticManager; 35 import android.car.diagnostic.FloatSensorIndex; 36 import android.car.diagnostic.IntegerSensorIndex; 37 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 38 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 39 import android.os.SystemClock; 40 import android.support.test.filters.MediumTest; 41 import android.support.test.runner.AndroidJUnit4; 42 import android.util.JsonReader; 43 import android.util.JsonWriter; 44 import android.util.Log; 45 46 import com.android.car.vehiclehal.DiagnosticEventBuilder; 47 import com.android.car.vehiclehal.DiagnosticJson; 48 import com.android.car.vehiclehal.VehiclePropValueBuilder; 49 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler; 50 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 import java.io.StringReader; 55 import java.io.StringWriter; 56 import java.util.Arrays; 57 import java.util.Collections; 58 import java.util.HashMap; 59 import java.util.HashSet; 60 import java.util.Set; 61 62 /** Test the public entry points for the CarDiagnosticManager */ 63 @RunWith(AndroidJUnit4.class) 64 @MediumTest 65 public class CarDiagnosticManagerTest extends MockedCarTestBase { 66 private static final String TAG = CarDiagnosticManagerTest.class.getSimpleName(); 67 68 private final DiagnosticEventBuilder mLiveFrameEventBuilder = 69 new DiagnosticEventBuilder(VehicleProperty.OBD2_LIVE_FRAME); 70 private final DiagnosticEventBuilder mFreezeFrameEventBuilder = 71 new DiagnosticEventBuilder(VehicleProperty.OBD2_FREEZE_FRAME); 72 private final FreezeFrameProperties mFreezeFrameProperties = new FreezeFrameProperties(); 73 74 private CarDiagnosticManager mCarDiagnosticManager; 75 76 private static final String DTC = "P1010"; 77 private static final float EPS = 1e-9f; 78 79 /** 80 * This class is a central repository for freeze frame data. It ensures that timestamps and 81 * events are kept in sync and provides a consistent access model for diagnostic properties. 82 */ 83 class FreezeFrameProperties { 84 private final HashMap<Long, VehiclePropValue> mEvents = new HashMap<>(); 85 86 public final VehicleHalPropertyHandler mFreezeFrameInfoHandler = 87 new FreezeFrameInfoHandler(); 88 public final VehicleHalPropertyHandler mFreezeFrameHandler = new FreezeFrameHandler(); 89 public final VehicleHalPropertyHandler mFreezeFrameClearHandler = 90 new FreezeFrameClearHandler(); 91 addNewEvent(DiagnosticEventBuilder builder)92 synchronized VehiclePropValue addNewEvent(DiagnosticEventBuilder builder) { 93 long timestamp = SystemClock.elapsedRealtimeNanos(); 94 return addNewEvent(builder, timestamp); 95 } 96 addNewEvent(DiagnosticEventBuilder builder, long timestamp)97 synchronized VehiclePropValue addNewEvent(DiagnosticEventBuilder builder, long timestamp) { 98 VehiclePropValue newEvent = builder.build(timestamp); 99 mEvents.put(timestamp, newEvent); 100 return newEvent; 101 } 102 removeEvent(long timestamp)103 synchronized VehiclePropValue removeEvent(long timestamp) { 104 return mEvents.remove(timestamp); 105 } 106 removeEvents()107 synchronized void removeEvents() { 108 mEvents.clear(); 109 } 110 getTimestamps()111 synchronized long[] getTimestamps() { 112 return mEvents.keySet().stream().mapToLong(Long::longValue).toArray(); 113 } 114 getEvent(long timestamp)115 synchronized VehiclePropValue getEvent(long timestamp) { 116 return mEvents.get(timestamp); 117 } 118 119 class FreezeFramePropertyHandler implements VehicleHalPropertyHandler { 120 private boolean mSubscribed = false; 121 122 protected final int VEHICLE_PROPERTY; 123 FreezeFramePropertyHandler(int propertyId)124 protected FreezeFramePropertyHandler(int propertyId) { 125 VEHICLE_PROPERTY = propertyId; 126 } 127 128 @Override onPropertySet(VehiclePropValue value)129 public synchronized void onPropertySet(VehiclePropValue value) { 130 assertEquals(VEHICLE_PROPERTY, value.prop); 131 } 132 133 @Override onPropertyGet(VehiclePropValue value)134 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 135 assertEquals(VEHICLE_PROPERTY, value.prop); 136 return null; 137 } 138 139 @Override onPropertySubscribe(int property, float sampleRate)140 public synchronized void onPropertySubscribe(int property, float sampleRate) { 141 assertEquals(VEHICLE_PROPERTY, property); 142 mSubscribed = true; 143 } 144 145 @Override onPropertyUnsubscribe(int property)146 public synchronized void onPropertyUnsubscribe(int property) { 147 assertEquals(VEHICLE_PROPERTY, property); 148 if (!mSubscribed) { 149 throw new IllegalArgumentException( 150 "Property was not subscribed 0x" + toHexString(property)); 151 } 152 mSubscribed = false; 153 } 154 } 155 156 class FreezeFrameInfoHandler extends FreezeFramePropertyHandler { FreezeFrameInfoHandler()157 FreezeFrameInfoHandler() { 158 super(VehicleProperty.OBD2_FREEZE_FRAME_INFO); 159 } 160 161 @Override onPropertyGet(VehiclePropValue value)162 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 163 super.onPropertyGet(value); 164 VehiclePropValueBuilder builder = 165 VehiclePropValueBuilder.newBuilder(VEHICLE_PROPERTY); 166 builder.setInt64Value(getTimestamps()); 167 return builder.build(); 168 } 169 } 170 171 class FreezeFrameHandler extends FreezeFramePropertyHandler { FreezeFrameHandler()172 FreezeFrameHandler() { 173 super(VehicleProperty.OBD2_FREEZE_FRAME); 174 } 175 176 @Override onPropertyGet(VehiclePropValue value)177 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 178 super.onPropertyGet(value); 179 long timestamp = value.value.int64Values.get(0); 180 return getEvent(timestamp); 181 } 182 } 183 184 class FreezeFrameClearHandler extends FreezeFramePropertyHandler { FreezeFrameClearHandler()185 FreezeFrameClearHandler() { 186 super(VehicleProperty.OBD2_FREEZE_FRAME_CLEAR); 187 } 188 189 @Override onPropertySet(VehiclePropValue value)190 public synchronized void onPropertySet(VehiclePropValue value) { 191 super.onPropertySet(value); 192 if (0 == value.value.int64Values.size()) { 193 removeEvents(); 194 } else { 195 for (long timestamp : value.value.int64Values) { 196 removeEvent(timestamp); 197 } 198 } 199 } 200 } 201 } 202 203 @Override configureMockedHal()204 protected synchronized void configureMockedHal() { 205 java.util.Collection<Integer> numVendorSensors = Arrays.asList(0, 0); 206 java.util.Collection<Integer> selectiveClear = Collections.singletonList(1); 207 addProperty(VehicleProperty.OBD2_LIVE_FRAME, mLiveFrameEventBuilder.build()) 208 .setConfigArray(numVendorSensors); 209 addProperty( 210 VehicleProperty.OBD2_FREEZE_FRAME_INFO, 211 mFreezeFrameProperties.mFreezeFrameInfoHandler); 212 addProperty(VehicleProperty.OBD2_FREEZE_FRAME, mFreezeFrameProperties.mFreezeFrameHandler) 213 .setConfigArray(numVendorSensors); 214 addProperty( 215 VehicleProperty.OBD2_FREEZE_FRAME_CLEAR, 216 mFreezeFrameProperties.mFreezeFrameClearHandler) 217 .setConfigArray(selectiveClear); 218 } 219 220 @Override setUp()221 public void setUp() throws Exception { 222 mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE, 30); 223 mLiveFrameEventBuilder.addIntSensor( 224 IntegerSensorIndex.FUEL_SYSTEM_STATUS, 225 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION); 226 mLiveFrameEventBuilder.addIntSensor( 227 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5000); 228 mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE, 2); 229 mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD, 0.125f); 230 mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.VEHICLE_SPEED, 12.5f); 231 232 mFreezeFrameEventBuilder.addIntSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE, 30); 233 mFreezeFrameEventBuilder.addIntSensor( 234 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5000); 235 mFreezeFrameEventBuilder.addIntSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE, 2); 236 mFreezeFrameEventBuilder.addFloatSensor( 237 FloatSensorIndex.CALCULATED_ENGINE_LOAD, 0.125f); 238 mFreezeFrameEventBuilder.addFloatSensor(FloatSensorIndex.VEHICLE_SPEED, 12.5f); 239 mFreezeFrameEventBuilder.setDTC(DTC); 240 241 super.setUp(); 242 243 Log.i(TAG, "attempting to get DIAGNOSTIC_SERVICE"); 244 mCarDiagnosticManager = 245 (CarDiagnosticManager) getCar().getCarManager(Car.DIAGNOSTIC_SERVICE); 246 } 247 testLiveFrameRead()248 @Test public void testLiveFrameRead() throws Exception { 249 CarDiagnosticEvent liveFrame = mCarDiagnosticManager.getLatestLiveFrame(); 250 251 assertNotNull(liveFrame); 252 assertTrue(liveFrame.isLiveFrame()); 253 assertFalse(liveFrame.isFreezeFrame()); 254 assertFalse(liveFrame.isEmptyFrame()); 255 256 assertEquals( 257 5000, 258 liveFrame 259 .getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START) 260 .intValue()); 261 assertEquals( 262 30, 263 liveFrame 264 .getSystemIntegerSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE) 265 .intValue()); 266 assertEquals( 267 2, 268 liveFrame 269 .getSystemIntegerSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE) 270 .intValue()); 271 assertEquals( 272 0.125f, 273 liveFrame.getSystemFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD), 274 EPS); 275 assertEquals( 276 12.5f, 277 liveFrame.getSystemFloatSensor(FloatSensorIndex.VEHICLE_SPEED), 278 EPS); 279 } 280 testLiveFrameEvent()281 @Test public void testLiveFrameEvent() throws Exception { 282 Listener listener = new Listener(); 283 mCarDiagnosticManager.registerListener( 284 listener, 285 CarDiagnosticManager.FRAME_TYPE_LIVE, 286 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 287 288 listener.reset(); 289 long time = SystemClock.elapsedRealtimeNanos(); 290 mLiveFrameEventBuilder.addIntSensor( 291 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5100); 292 293 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time)); 294 assertTrue(listener.waitForEvent(time)); 295 296 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 297 298 assertEquals( 299 5100, 300 liveFrame 301 .getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START) 302 .intValue()); 303 } 304 testMissingSensorRead()305 @Test public void testMissingSensorRead() throws Exception { 306 Listener listener = new Listener(); 307 mCarDiagnosticManager.registerListener( 308 listener, 309 CarDiagnosticManager.FRAME_TYPE_LIVE, 310 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 311 312 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build()); 313 assertTrue(listener.waitForEvent()); 314 315 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 316 assertNotNull(liveFrame); 317 318 assertNull( 319 liveFrame.getSystemIntegerSensor( 320 IntegerSensorIndex.DRIVER_DEMAND_PERCENT_TORQUE)); 321 assertEquals( 322 -1, 323 liveFrame.getSystemIntegerSensor( 324 IntegerSensorIndex.DRIVER_DEMAND_PERCENT_TORQUE, -1)); 325 326 assertNull(liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR6_VOLTAGE)); 327 assertEquals( 328 0.25f, 329 liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR5_VOLTAGE, 0.25f), EPS); 330 331 assertNull(liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START)); 332 assertEquals(-1, liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START, -1)); 333 334 assertNull(liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START)); 335 assertEquals( 336 0.25f, liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START, 0.25f), EPS); 337 } 338 testFuelSystemStatus()339 @Test public void testFuelSystemStatus() throws Exception { 340 Listener listener = new Listener(); 341 mCarDiagnosticManager.registerListener( 342 listener, 343 CarDiagnosticManager.FRAME_TYPE_LIVE, 344 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 345 346 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build()); 347 assertTrue(listener.waitForEvent()); 348 349 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 350 assertNotNull(liveFrame); 351 352 assertEquals( 353 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION, 354 liveFrame 355 .getSystemIntegerSensor(IntegerSensorIndex.FUEL_SYSTEM_STATUS) 356 .intValue()); 357 assertEquals( 358 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION, 359 liveFrame.getFuelSystemStatus().intValue()); 360 } 361 testSecondaryAirStatus()362 @Test public void testSecondaryAirStatus() throws Exception { 363 Listener listener = new Listener(); 364 mCarDiagnosticManager.registerListener( 365 listener, 366 CarDiagnosticManager.FRAME_TYPE_LIVE, 367 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 368 369 mLiveFrameEventBuilder.addIntSensor( 370 IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS, 371 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF); 372 long timestamp = SystemClock.elapsedRealtimeNanos(); 373 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp)); 374 375 assertTrue(listener.waitForEvent(timestamp)); 376 377 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 378 assertNotNull(liveFrame); 379 380 assertEquals( 381 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF, 382 liveFrame 383 .getSystemIntegerSensor( 384 IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS) 385 .intValue()); 386 assertEquals( 387 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF, 388 liveFrame.getSecondaryAirStatus().intValue()); 389 } 390 testIgnitionMonitors()391 @Test public void testIgnitionMonitors() throws Exception { 392 Listener listener = new Listener(); 393 mCarDiagnosticManager.registerListener( 394 listener, 395 CarDiagnosticManager.FRAME_TYPE_LIVE, 396 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 397 398 // cfr. CarDiagnosticEvent for the meaning of the several bits 399 final int sparkMonitorsValue = 400 0x1 | (0x1 << 2) | (0x1 << 3) | (0x1 << 6) | (0x1 << 10) | (0x1 << 11); 401 402 final int compressionMonitorsValue = 403 (0x1 << 2) | (0x1 << 3) | (0x1 << 6) | (0x1 << 12) | (0x1 << 13); 404 405 mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED, 0); 406 mLiveFrameEventBuilder.addIntSensor( 407 IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS, sparkMonitorsValue); 408 409 long timestamp = SystemClock.elapsedRealtimeNanos(); 410 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp)); 411 412 assertTrue(listener.waitForEvent(timestamp)); 413 414 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 415 assertNotNull(liveFrame); 416 417 CommonIgnitionMonitors commonIgnitionMonitors = liveFrame.getIgnitionMonitors(); 418 assertNotNull(commonIgnitionMonitors); 419 assertTrue(commonIgnitionMonitors.components.available); 420 assertFalse(commonIgnitionMonitors.components.incomplete); 421 assertTrue(commonIgnitionMonitors.fuelSystem.available); 422 assertTrue(commonIgnitionMonitors.fuelSystem.incomplete); 423 assertFalse(commonIgnitionMonitors.misfire.available); 424 assertFalse(commonIgnitionMonitors.misfire.incomplete); 425 426 SparkIgnitionMonitors sparkIgnitionMonitors = 427 commonIgnitionMonitors.asSparkIgnitionMonitors(); 428 assertNotNull(sparkIgnitionMonitors); 429 assertNull(commonIgnitionMonitors.asCompressionIgnitionMonitors()); 430 431 assertTrue(sparkIgnitionMonitors.EGR.available); 432 assertFalse(sparkIgnitionMonitors.EGR.incomplete); 433 assertFalse(sparkIgnitionMonitors.oxygenSensorHeater.available); 434 assertFalse(sparkIgnitionMonitors.oxygenSensorHeater.incomplete); 435 assertTrue(sparkIgnitionMonitors.oxygenSensor.available); 436 assertTrue(sparkIgnitionMonitors.oxygenSensor.incomplete); 437 assertFalse(sparkIgnitionMonitors.ACRefrigerant.available); 438 assertFalse(sparkIgnitionMonitors.ACRefrigerant.incomplete); 439 assertFalse(sparkIgnitionMonitors.secondaryAirSystem.available); 440 assertFalse(sparkIgnitionMonitors.secondaryAirSystem.incomplete); 441 assertFalse(sparkIgnitionMonitors.evaporativeSystem.available); 442 assertFalse(sparkIgnitionMonitors.evaporativeSystem.incomplete); 443 assertFalse(sparkIgnitionMonitors.heatedCatalyst.available); 444 assertFalse(sparkIgnitionMonitors.heatedCatalyst.incomplete); 445 assertFalse(sparkIgnitionMonitors.catalyst.available); 446 assertFalse(sparkIgnitionMonitors.catalyst.incomplete); 447 448 mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED, 1); 449 mLiveFrameEventBuilder.addIntSensor( 450 IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS, compressionMonitorsValue); 451 452 timestamp += 1000; 453 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp)); 454 455 assertTrue(listener.waitForEvent(timestamp)); 456 457 liveFrame = listener.getLastEvent(); 458 assertNotNull(liveFrame); 459 assertEquals(timestamp, liveFrame.timestamp); 460 461 commonIgnitionMonitors = liveFrame.getIgnitionMonitors(); 462 assertNotNull(commonIgnitionMonitors); 463 assertFalse(commonIgnitionMonitors.components.available); 464 assertFalse(commonIgnitionMonitors.components.incomplete); 465 assertTrue(commonIgnitionMonitors.fuelSystem.available); 466 assertTrue(commonIgnitionMonitors.fuelSystem.incomplete); 467 assertFalse(commonIgnitionMonitors.misfire.available); 468 assertFalse(commonIgnitionMonitors.misfire.incomplete); 469 CompressionIgnitionMonitors compressionIgnitionMonitors = 470 commonIgnitionMonitors.asCompressionIgnitionMonitors(); 471 assertNull(commonIgnitionMonitors.asSparkIgnitionMonitors()); 472 assertNotNull(compressionIgnitionMonitors); 473 474 assertTrue(compressionIgnitionMonitors.EGROrVVT.available); 475 assertFalse(compressionIgnitionMonitors.EGROrVVT.incomplete); 476 assertFalse(compressionIgnitionMonitors.PMFilter.available); 477 assertFalse(compressionIgnitionMonitors.PMFilter.incomplete); 478 assertFalse(compressionIgnitionMonitors.exhaustGasSensor.available); 479 assertFalse(compressionIgnitionMonitors.exhaustGasSensor.incomplete); 480 assertTrue(compressionIgnitionMonitors.boostPressure.available); 481 assertTrue(compressionIgnitionMonitors.boostPressure.incomplete); 482 assertFalse(compressionIgnitionMonitors.NOxSCR.available); 483 assertFalse(compressionIgnitionMonitors.NOxSCR.incomplete); 484 assertFalse(compressionIgnitionMonitors.NMHCCatalyst.available); 485 assertFalse(compressionIgnitionMonitors.NMHCCatalyst.incomplete); 486 } 487 testFuelType()488 @Test public void testFuelType() throws Exception { 489 Listener listener = new Listener(); 490 mCarDiagnosticManager.registerListener( 491 listener, 492 CarDiagnosticManager.FRAME_TYPE_LIVE, 493 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 494 495 mLiveFrameEventBuilder.addIntSensor( 496 IntegerSensorIndex.FUEL_TYPE, FuelType.BIFUEL_RUNNING_LPG); 497 long timestamp = SystemClock.elapsedRealtimeNanos(); 498 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp)); 499 500 assertTrue(listener.waitForEvent(timestamp)); 501 502 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 503 assertNotNull(liveFrame); 504 505 assertEquals( 506 FuelType.BIFUEL_RUNNING_LPG, 507 liveFrame.getSystemIntegerSensor(IntegerSensorIndex.FUEL_TYPE).intValue()); 508 assertEquals(FuelType.BIFUEL_RUNNING_LPG, liveFrame.getFuelType().intValue()); 509 } 510 testDiagnosticJson()511 @Test public void testDiagnosticJson() throws Exception { 512 Listener listener = new Listener(); 513 mCarDiagnosticManager.registerListener( 514 listener, 515 CarDiagnosticManager.FRAME_TYPE_LIVE, 516 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 517 518 mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE, 74); 519 mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE, 0.125f); 520 521 long timestamp = SystemClock.elapsedRealtimeNanos(); 522 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp)); 523 524 assertTrue(listener.waitForEvent(timestamp)); 525 526 CarDiagnosticEvent liveFrame = listener.getLastEvent(); 527 assertNotNull(liveFrame); 528 529 assertEquals( 530 74, 531 liveFrame 532 .getSystemIntegerSensor(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE) 533 .intValue()); 534 assertEquals( 535 0.125f, 536 liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE), 537 EPS); 538 539 StringWriter stringWriter = new StringWriter(); 540 JsonWriter jsonWriter = new JsonWriter(stringWriter); 541 542 liveFrame.writeToJson(jsonWriter); 543 jsonWriter.flush(); 544 545 StringReader stringReader = new StringReader(stringWriter.toString()); 546 JsonReader jsonReader = new JsonReader(stringReader); 547 DiagnosticJson diagnosticJson = DiagnosticJson.build(jsonReader); 548 549 assertEquals( 550 74, 551 diagnosticJson 552 .intValues 553 .get(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE) 554 .intValue()); 555 assertEquals( 556 0.125f, 557 diagnosticJson.floatValues.get(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE), 558 EPS); 559 } 560 561 @Test testMultipleListeners()562 public void testMultipleListeners() throws Exception { 563 Listener listener1 = new Listener(); 564 Listener listener2 = new Listener(); 565 566 mCarDiagnosticManager.registerListener( 567 listener1, 568 CarDiagnosticManager.FRAME_TYPE_LIVE, 569 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 570 mCarDiagnosticManager.registerListener( 571 listener2, 572 CarDiagnosticManager.FRAME_TYPE_LIVE, 573 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 574 575 listener1.reset(); 576 listener2.reset(); 577 578 long time = SystemClock.elapsedRealtimeNanos(); 579 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time)); 580 assertTrue(listener1.waitForEvent(time)); 581 assertTrue(listener2.waitForEvent(time)); 582 583 CarDiagnosticEvent event1 = listener1.getLastEvent(); 584 CarDiagnosticEvent event2 = listener2.getLastEvent(); 585 586 assertTrue(event1.equals(event1)); 587 assertTrue(event2.equals(event2)); 588 assertTrue(event1.equals(event2)); 589 assertTrue(event2.equals(event1)); 590 591 assertTrue(event1.hashCode() == event1.hashCode()); 592 assertTrue(event1.hashCode() == event2.hashCode()); 593 594 assertEquals( 595 5000, 596 event1.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START) 597 .intValue()); 598 assertEquals( 599 5000, 600 event2.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START) 601 .intValue()); 602 603 listener1.reset(); 604 listener2.reset(); 605 606 mCarDiagnosticManager.unregisterListener(listener1); 607 608 time += 1000; 609 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time)); 610 assertFalse(listener1.waitForEvent(time)); 611 assertTrue(listener2.waitForEvent(time)); 612 613 assertNull(listener1.getLastEvent()); 614 event2 = listener2.getLastEvent(); 615 616 assertTrue(event1.isEarlierThan(event2)); 617 assertFalse(event1.equals(event2)); 618 assertFalse(event2.equals(event1)); 619 620 assertEquals( 621 5000, 622 event2.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START) 623 .intValue()); 624 } 625 626 @Test testFreezeFrameEvent()627 public void testFreezeFrameEvent() throws Exception { 628 Listener listener = new Listener(); 629 mCarDiagnosticManager.registerListener( 630 listener, 631 CarDiagnosticManager.FRAME_TYPE_FREEZE, 632 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 633 634 listener.reset(); 635 VehiclePropValue injectedEvent = 636 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder); 637 getMockedVehicleHal().injectEvent(injectedEvent); 638 assertTrue(listener.waitForEvent(injectedEvent.timestamp)); 639 640 CarDiagnosticEvent freezeFrame = listener.getLastEvent(); 641 642 assertEquals(DTC, freezeFrame.dtc); 643 644 mFreezeFrameEventBuilder.addIntSensor( 645 IntegerSensorIndex.ABSOLUTE_BAROMETRIC_PRESSURE, 22); 646 injectedEvent = mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder); 647 getMockedVehicleHal().injectEvent(injectedEvent); 648 assertTrue(listener.waitForEvent(injectedEvent.timestamp)); 649 650 freezeFrame = listener.getLastEvent(); 651 652 assertNotNull(freezeFrame); 653 assertFalse(freezeFrame.isLiveFrame()); 654 assertTrue(freezeFrame.isFreezeFrame()); 655 assertFalse(freezeFrame.isEmptyFrame()); 656 657 assertEquals(DTC, freezeFrame.dtc); 658 assertEquals( 659 22, 660 freezeFrame 661 .getSystemIntegerSensor(IntegerSensorIndex.ABSOLUTE_BAROMETRIC_PRESSURE) 662 .intValue()); 663 } 664 665 @Test testFreezeFrameTimestamps()666 public void testFreezeFrameTimestamps() throws Exception { 667 Listener listener = new Listener(); 668 mCarDiagnosticManager.registerListener( 669 listener, 670 CarDiagnosticManager.FRAME_TYPE_FREEZE, 671 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 672 673 Set<Long> generatedTimestamps = new HashSet<>(); 674 675 VehiclePropValue injectedEvent = 676 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder); 677 getMockedVehicleHal().injectEvent(injectedEvent); 678 generatedTimestamps.add(injectedEvent.timestamp); 679 assertTrue(listener.waitForEvent(injectedEvent.timestamp)); 680 681 injectedEvent = 682 mFreezeFrameProperties.addNewEvent( 683 mFreezeFrameEventBuilder, injectedEvent.timestamp + 1000); 684 getMockedVehicleHal().injectEvent(injectedEvent); 685 generatedTimestamps.add(injectedEvent.timestamp); 686 assertTrue(listener.waitForEvent(injectedEvent.timestamp)); 687 688 long[] acquiredTimestamps = mCarDiagnosticManager.getFreezeFrameTimestamps(); 689 assertEquals(generatedTimestamps.size(), acquiredTimestamps.length); 690 for (long acquiredTimestamp : acquiredTimestamps) { 691 assertTrue(generatedTimestamps.contains(acquiredTimestamp)); 692 } 693 } 694 695 @Test testClearFreezeFrameTimestamps()696 public void testClearFreezeFrameTimestamps() throws Exception { 697 Listener listener = new Listener(); 698 mCarDiagnosticManager.registerListener( 699 listener, 700 CarDiagnosticManager.FRAME_TYPE_FREEZE, 701 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 702 703 VehiclePropValue injectedEvent = 704 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder); 705 getMockedVehicleHal().injectEvent(injectedEvent); 706 assertTrue(listener.waitForEvent(injectedEvent.timestamp)); 707 708 assertNotNull(mCarDiagnosticManager.getFreezeFrame(injectedEvent.timestamp)); 709 mCarDiagnosticManager.clearFreezeFrames(injectedEvent.timestamp); 710 assertNull(mCarDiagnosticManager.getFreezeFrame(injectedEvent.timestamp)); 711 } 712 713 @Test testListenerUnregister()714 public void testListenerUnregister() throws Exception { 715 Listener listener1 = new Listener(); 716 Listener listener2 = new Listener(); 717 mCarDiagnosticManager.registerListener( 718 listener1, 719 CarDiagnosticManager.FRAME_TYPE_LIVE, 720 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 721 mCarDiagnosticManager.registerListener( 722 listener1, 723 CarDiagnosticManager.FRAME_TYPE_FREEZE, 724 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 725 726 mCarDiagnosticManager.unregisterListener(listener1); 727 728 // you need a listener to be registered before MockedVehicleHal will actually dispatch 729 // your events - add one, but do it *after* unregistering the first listener 730 mCarDiagnosticManager.registerListener( 731 listener2, 732 CarDiagnosticManager.FRAME_TYPE_LIVE, 733 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 734 mCarDiagnosticManager.registerListener( 735 listener2, 736 CarDiagnosticManager.FRAME_TYPE_FREEZE, 737 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL); 738 739 VehiclePropValue injectedEvent = 740 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder); 741 long time = injectedEvent.timestamp; 742 getMockedVehicleHal().injectEvent(injectedEvent); 743 assertFalse(listener1.waitForEvent(time)); 744 assertTrue(listener2.waitForEvent(time)); 745 746 time += 1000; 747 getMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time)); 748 assertFalse(listener1.waitForEvent(time)); 749 assertTrue(listener2.waitForEvent(time)); 750 } 751 752 @Test testIsSupportedApiCalls()753 public void testIsSupportedApiCalls() throws Exception { 754 assertTrue(mCarDiagnosticManager.isLiveFrameSupported()); 755 assertTrue(mCarDiagnosticManager.isFreezeFrameNotificationSupported()); 756 assertTrue(mCarDiagnosticManager.isGetFreezeFrameSupported()); 757 assertTrue(mCarDiagnosticManager.isClearFreezeFramesSupported()); 758 assertTrue(mCarDiagnosticManager.isSelectiveClearFreezeFramesSupported()); 759 } 760 761 class Listener implements CarDiagnosticManager.OnDiagnosticEventListener { 762 private final Object mSync = new Object(); 763 764 private CarDiagnosticEvent mLastEvent = null; 765 getLastEvent()766 CarDiagnosticEvent getLastEvent() { 767 return mLastEvent; 768 } 769 reset()770 void reset() { 771 synchronized (mSync) { 772 mLastEvent = null; 773 } 774 } 775 waitForEvent()776 boolean waitForEvent() throws InterruptedException { 777 return waitForEvent(0); 778 } 779 waitForEvent(long eventTimeStamp)780 boolean waitForEvent(long eventTimeStamp) throws InterruptedException { 781 long start = SystemClock.elapsedRealtime(); 782 boolean matchTimeStamp = eventTimeStamp != 0; 783 synchronized (mSync) { 784 while ((mLastEvent == null 785 || (matchTimeStamp && mLastEvent.timestamp != eventTimeStamp)) 786 && (start + SHORT_WAIT_TIMEOUT_MS > SystemClock.elapsedRealtime())) { 787 mSync.wait(10L); 788 } 789 return mLastEvent != null 790 && (!matchTimeStamp || mLastEvent.timestamp == eventTimeStamp); 791 } 792 } 793 794 @Override onDiagnosticEvent(CarDiagnosticEvent event)795 public void onDiagnosticEvent(CarDiagnosticEvent event) { 796 synchronized (mSync) { 797 // We're going to hold a reference to this object 798 mLastEvent = event; 799 mSync.notify(); 800 } 801 } 802 } 803 } 804