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