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