• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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