• 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 android.car.test.mocks.JavaMockitoHelper.silentAwait;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertTrue;
26 
27 import android.car.Car;
28 import android.car.diagnostic.CarDiagnosticEvent;
29 import android.car.diagnostic.CarDiagnosticEvent.CommonIgnitionMonitors;
30 import android.car.diagnostic.CarDiagnosticEvent.CompressionIgnitionMonitors;
31 import android.car.diagnostic.CarDiagnosticEvent.FuelSystemStatus;
32 import android.car.diagnostic.CarDiagnosticEvent.FuelType;
33 import android.car.diagnostic.CarDiagnosticEvent.SecondaryAirStatus;
34 import android.car.diagnostic.CarDiagnosticEvent.SparkIgnitionMonitors;
35 import android.car.diagnostic.CarDiagnosticManager;
36 import android.car.diagnostic.FloatSensorIndex;
37 import android.car.diagnostic.IntegerSensorIndex;
38 import android.car.hardware.property.VehicleHalStatusCode;
39 import android.hardware.automotive.vehicle.VehiclePropValue;
40 import android.hardware.automotive.vehicle.VehicleProperty;
41 import android.os.ServiceSpecificException;
42 import android.os.SystemClock;
43 import android.util.JsonReader;
44 import android.util.JsonWriter;
45 import android.util.Log;
46 
47 import androidx.test.ext.junit.runners.AndroidJUnit4;
48 import androidx.test.filters.FlakyTest;
49 import androidx.test.filters.MediumTest;
50 
51 import com.android.car.hal.test.AidlMockedVehicleHal.ErrorCodeHandler;
52 import com.android.car.hal.test.AidlMockedVehicleHal.VehicleHalPropertyHandler;
53 import com.android.car.hal.test.AidlVehiclePropValueBuilder;
54 import com.android.car.hal.test.DiagnosticEventBuilder;
55 import com.android.car.hal.test.DiagnosticJson;
56 import com.android.internal.annotations.GuardedBy;
57 
58 import org.junit.Rule;
59 import org.junit.Test;
60 import org.junit.rules.TestName;
61 import org.junit.runner.RunWith;
62 
63 import static java.lang.Integer.toHexString;
64 
65 import java.io.StringReader;
66 import java.io.StringWriter;
67 import java.util.ArrayList;
68 import java.util.Arrays;
69 import java.util.Collection;
70 import java.util.Collections;
71 import java.util.HashMap;
72 import java.util.HashSet;
73 import java.util.List;
74 import java.util.Objects;
75 import java.util.Set;
76 import java.util.concurrent.CountDownLatch;
77 
78 /** Test the public entry points for the CarDiagnosticManager */
79 @RunWith(AndroidJUnit4.class)
80 @MediumTest
81 public class CarDiagnosticManagerTest extends MockedCarTestBase {
82     private static final String TAG = CarDiagnosticManagerTest.class.getSimpleName();
83 
84     private final DiagnosticEventBuilder mLiveFrameEventBuilder =
85             new DiagnosticEventBuilder(VehicleProperty.OBD2_LIVE_FRAME);
86     private final DiagnosticEventBuilder mFreezeFrameEventBuilder =
87             new DiagnosticEventBuilder(VehicleProperty.OBD2_FREEZE_FRAME);
88     private final FreezeFrameProperties mFreezeFrameProperties = new FreezeFrameProperties();
89 
90     private CarDiagnosticManager mCarDiagnosticManager;
91 
92     private static final String DTC = "P1010";
93     private static final float EPS = 1e-9f;
94 
95     @Rule public TestName mTestName = new TestName();
96 
97     /**
98      * This class is a central repository for freeze frame data. It ensures that timestamps and
99      * events are kept in sync and provides a consistent access model for diagnostic properties.
100      */
101     class FreezeFrameProperties {
102         private final HashMap<Long, VehiclePropValue> mEvents = new HashMap<>();
103 
104         public final FreezeFramePropertyHandler mFreezeFrameInfoHandler =
105                 new FreezeFrameInfoHandler();
106         public final FreezeFramePropertyHandler mFreezeFrameHandler = new FreezeFrameHandler();
107         public final FreezeFramePropertyHandler mFreezeFrameClearHandler =
108                 new FreezeFrameClearHandler();
109 
addNewEvent(DiagnosticEventBuilder builder)110         synchronized VehiclePropValue addNewEvent(DiagnosticEventBuilder builder) {
111             long timestamp = SystemClock.elapsedRealtimeNanos();
112             return addNewEvent(builder, timestamp);
113         }
114 
addNewEvent(DiagnosticEventBuilder builder, long timestamp)115         synchronized VehiclePropValue addNewEvent(DiagnosticEventBuilder builder, long timestamp) {
116             VehiclePropValue newEvent = builder.build(timestamp);
117             mEvents.put(timestamp, newEvent);
118             return newEvent;
119         }
120 
removeEvent(long timestamp)121         synchronized VehiclePropValue removeEvent(long timestamp) {
122             return mEvents.remove(timestamp);
123         }
124 
removeEvents()125         synchronized void removeEvents() {
126             mEvents.clear();
127         }
128 
getTimestamps()129         synchronized long[] getTimestamps() {
130             return mEvents.keySet().stream().mapToLong(Long::longValue).toArray();
131         }
132 
getEvent(long timestamp)133         synchronized VehiclePropValue getEvent(long timestamp) {
134             return mEvents.get(timestamp);
135         }
136 
137         class FreezeFramePropertyHandler implements VehicleHalPropertyHandler {
138             private boolean mSubscribed = false;
139             private int mStatus;
140 
141             protected final int VEHICLE_PROPERTY;
142 
FreezeFramePropertyHandler(int propertyId)143             protected FreezeFramePropertyHandler(int propertyId) {
144                 VEHICLE_PROPERTY = propertyId;
145             }
146 
setStatus(int status)147             public void setStatus(int status) {
148                 mStatus = status;
149             }
150 
151             @Override
onPropertySet(VehiclePropValue value)152             public synchronized void onPropertySet(VehiclePropValue value) {
153                 if (mStatus != VehicleHalStatusCode.STATUS_OK) {
154                     throw new ServiceSpecificException(mStatus);
155                 }
156                 assertEquals(VEHICLE_PROPERTY, value.prop);
157             }
158 
159             @Override
onPropertyGet(VehiclePropValue value)160             public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
161                 if (mStatus != VehicleHalStatusCode.STATUS_OK) {
162                     throw new ServiceSpecificException(mStatus);
163                 }
164                 assertEquals(VEHICLE_PROPERTY, value.prop);
165                 return null;
166             }
167 
168             @Override
onPropertySubscribe(int property, float sampleRate)169             public synchronized void onPropertySubscribe(int property, float sampleRate) {
170                 assertEquals(VEHICLE_PROPERTY, property);
171                 mSubscribed = true;
172             }
173 
174             @Override
onPropertyUnsubscribe(int property)175             public synchronized void onPropertyUnsubscribe(int property) {
176                 assertEquals(VEHICLE_PROPERTY, property);
177                 if (!mSubscribed) {
178                     throw new IllegalArgumentException(
179                             "Property was not subscribed 0x" + toHexString(property));
180                 }
181                 mSubscribed = false;
182             }
183         }
184 
185         class FreezeFrameInfoHandler extends FreezeFramePropertyHandler {
FreezeFrameInfoHandler()186             FreezeFrameInfoHandler() {
187                 super(VehicleProperty.OBD2_FREEZE_FRAME_INFO);
188             }
189 
190             @Override
onPropertyGet(VehiclePropValue value)191             public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
192                 super.onPropertyGet(value);
193                 AidlVehiclePropValueBuilder builder =
194                         AidlVehiclePropValueBuilder.newBuilder(VEHICLE_PROPERTY);
195                 builder.addInt64Values(getTimestamps());
196                 return builder.build();
197             }
198         }
199 
200         class FreezeFrameHandler extends FreezeFramePropertyHandler {
FreezeFrameHandler()201             FreezeFrameHandler() {
202                 super(VehicleProperty.OBD2_FREEZE_FRAME);
203             }
204 
205             @Override
onPropertyGet(VehiclePropValue value)206             public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
207                 super.onPropertyGet(value);
208                 long timestamp = value.value.int64Values[0];
209                 return getEvent(timestamp);
210             }
211         }
212 
213         class FreezeFrameClearHandler extends FreezeFramePropertyHandler {
FreezeFrameClearHandler()214             FreezeFrameClearHandler() {
215                 super(VehicleProperty.OBD2_FREEZE_FRAME_CLEAR);
216             }
217 
218             @Override
onPropertySet(VehiclePropValue value)219             public synchronized void onPropertySet(VehiclePropValue value) {
220                 super.onPropertySet(value);
221                 if (0 == value.value.int64Values.length) {
222                     removeEvents();
223                 } else {
224                     for (long timestamp : value.value.int64Values) {
225                         removeEvent(timestamp);
226                     }
227                 }
228             }
229         }
230     }
231 
232     @Override
configureResourceOverrides(MockResources resources)233     protected void configureResourceOverrides(MockResources resources) {
234         super.configureResourceOverrides(resources);
235         resources.overrideResource(com.android.car.R.array.config_allowed_optional_car_features,
236                 new String[]{Car.DIAGNOSTIC_SERVICE});
237     }
238 
239     @Override
configureMockedHal()240     protected void configureMockedHal() {
241         Collection<Integer> numVendorSensors = Arrays.asList(0, 0);
242         Collection<Integer> selectiveClear = Collections.singletonList(1);
243         Log.i(TAG, mTestName.getMethodName());
244         String methodName = mTestName.getMethodName();
245         ErrorCodeHandler handler = new ErrorCodeHandler();
246         if (Objects.equals(methodName, "testInitialLiveFrameException_Invalid_Arg")) {
247             handler.setStatus(VehicleHalStatusCode.STATUS_INVALID_ARG);
248             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, handler)
249                     .setConfigArray(numVendorSensors);
250         } else if (Objects.equals(methodName, "testInitialLiveFrameException_NOT_AVAILABLE")) {
251             handler.setStatus(VehicleHalStatusCode.STATUS_NOT_AVAILABLE);
252             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, handler)
253                     .setConfigArray(numVendorSensors);
254         } else if (Objects.equals(methodName, "testInitialLiveFrameException_ACCESS_DENIED")) {
255             handler.setStatus(VehicleHalStatusCode.STATUS_ACCESS_DENIED);
256             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, handler)
257                     .setConfigArray(numVendorSensors);
258         } else if (Objects.equals(methodName, "testInitialLiveFrameException_TRY_AGAIN")) {
259             handler.setStatus(VehicleHalStatusCode.STATUS_TRY_AGAIN);
260             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, handler)
261                     .setConfigArray(numVendorSensors);
262         } else if (Objects.equals(methodName, "testInitialLiveFrameException_INTERNAL_ERROR")) {
263             handler.setStatus(VehicleHalStatusCode.STATUS_INTERNAL_ERROR);
264             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, handler)
265                     .setConfigArray(numVendorSensors);
266         } else {
267             addAidlProperty(VehicleProperty.OBD2_LIVE_FRAME, mLiveFrameEventBuilder.build())
268                     .setConfigArray(numVendorSensors);
269         }
270         if (Objects.equals(methodName, "testInitialFreezeFrameInfoException_Invalid_Arg")) {
271             mFreezeFrameProperties.mFreezeFrameInfoHandler.setStatus(
272                     VehicleHalStatusCode.STATUS_INVALID_ARG);
273         } else if (Objects.equals(methodName,
274                 "testInitialFreezeFrameInfoException_NOT_AVAILABLE")) {
275             mFreezeFrameProperties.mFreezeFrameInfoHandler.setStatus(
276                     VehicleHalStatusCode.STATUS_NOT_AVAILABLE);
277         } else if (Objects.equals(methodName,
278                 "testInitialFreezeFrameInfoException_ACCESS_DENIED")) {
279             mFreezeFrameProperties.mFreezeFrameInfoHandler.setStatus(
280                     VehicleHalStatusCode.STATUS_ACCESS_DENIED);
281         } else if (Objects.equals(methodName, "testInitialFreezeFrameInfoException_TRY_AGAIN")) {
282             mFreezeFrameProperties.mFreezeFrameInfoHandler.setStatus(
283                     VehicleHalStatusCode.STATUS_TRY_AGAIN);
284         } else if (Objects.equals(methodName,
285                 "testInitialFreezeFrameInfoException_INTERNAL_ERROR")) {
286             mFreezeFrameProperties.mFreezeFrameInfoHandler.setStatus(
287                     VehicleHalStatusCode.STATUS_INTERNAL_ERROR);
288         }
289         addAidlProperty(
290                 VehicleProperty.OBD2_FREEZE_FRAME_INFO,
291                 mFreezeFrameProperties.mFreezeFrameInfoHandler);
292 
293         if (Objects.equals(methodName, "testInitialFreezeFrameException_Invalid_Arg")) {
294             mFreezeFrameProperties.mFreezeFrameHandler.setStatus(
295                     VehicleHalStatusCode.STATUS_INVALID_ARG);
296         } else if (Objects.equals(methodName, "testInitialFreezeFrameException_NOT_AVAILABLE")) {
297             mFreezeFrameProperties.mFreezeFrameHandler.setStatus(
298                     VehicleHalStatusCode.STATUS_NOT_AVAILABLE);
299         } else if (Objects.equals(methodName, "testInitialFreezeFrameException_ACCESS_DENIED")) {
300             mFreezeFrameProperties.mFreezeFrameHandler.setStatus(
301                     VehicleHalStatusCode.STATUS_ACCESS_DENIED);
302         } else if (Objects.equals(methodName, "testInitialFreezeFrameException_TRY_AGAIN")) {
303             mFreezeFrameProperties.mFreezeFrameHandler.setStatus(
304                     VehicleHalStatusCode.STATUS_TRY_AGAIN);
305         } else if (Objects.equals(methodName, "testInitialFreezeFrameException_INTERNAL_ERROR")) {
306             mFreezeFrameProperties.mFreezeFrameHandler.setStatus(
307                     VehicleHalStatusCode.STATUS_INTERNAL_ERROR);
308         }
309         addAidlProperty(VehicleProperty.OBD2_FREEZE_FRAME,
310                 mFreezeFrameProperties.mFreezeFrameHandler).setConfigArray(numVendorSensors);
311 
312         addAidlProperty(
313                 VehicleProperty.OBD2_FREEZE_FRAME_CLEAR,
314                 mFreezeFrameProperties.mFreezeFrameClearHandler)
315                 .setConfigArray(selectiveClear);
316     }
317 
318     @Override
setUp()319     public void setUp() throws Exception {
320         mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE, 30);
321         mLiveFrameEventBuilder.addIntSensor(
322                 IntegerSensorIndex.FUEL_SYSTEM_STATUS,
323                 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION);
324         mLiveFrameEventBuilder.addIntSensor(
325                 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5000);
326         mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE, 2);
327         mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD, 0.125f);
328         mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.VEHICLE_SPEED, 12.5f);
329 
330         mFreezeFrameEventBuilder.addIntSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE, 30);
331         mFreezeFrameEventBuilder.addIntSensor(
332                 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5000);
333         mFreezeFrameEventBuilder.addIntSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE, 2);
334         mFreezeFrameEventBuilder.addFloatSensor(
335                 FloatSensorIndex.CALCULATED_ENGINE_LOAD, 0.125f);
336         mFreezeFrameEventBuilder.addFloatSensor(FloatSensorIndex.VEHICLE_SPEED, 12.5f);
337         mFreezeFrameEventBuilder.setDTC(DTC);
338 
339         super.setUp();
340 
341         Log.i(TAG, "attempting to get DIAGNOSTIC_SERVICE");
342         mCarDiagnosticManager =
343                 (CarDiagnosticManager) getCar().getCarManager(Car.DIAGNOSTIC_SERVICE);
344     }
345 
testInitialLiveFrameException_Invalid_Arg()346     @Test public void testInitialLiveFrameException_Invalid_Arg() {
347         // Do nothing, this test is to test the exception returned by VHAL during initialization
348         // should not be propagated.
349         assertThat(mCarDiagnosticManager.getLatestLiveFrame()).isNull();
350     }
351 
testInitialLiveFrameException_NOT_AVAILABLE()352     @Test public void testInitialLiveFrameException_NOT_AVAILABLE() {
353         // Do nothing, this test is to test the exception returned by VHAL during initialization
354         // should not be propagated.
355         assertThat(mCarDiagnosticManager.getLatestLiveFrame()).isNull();
356     }
357 
testInitialLiveFrameException_ACCESS_DENIED()358     @Test public void testInitialLiveFrameException_ACCESS_DENIED() {
359         // Do nothing, this test is to test the exception returned by VHAL during initialization
360         // should not be propagated.
361         assertThat(mCarDiagnosticManager.getLatestLiveFrame()).isNull();
362     }
363 
testInitialLiveFrameException_TRY_AGAIN()364     @Test public void testInitialLiveFrameException_TRY_AGAIN() {
365         // Do nothing, this test is to test the exception returned by VHAL during initialization
366         // should not be propagated.
367         assertThat(mCarDiagnosticManager.getLatestLiveFrame()).isNull();
368     }
369 
testInitialLiveFrameException_INTERNAL_ERROR()370     @Test public void testInitialLiveFrameException_INTERNAL_ERROR() {
371         // Do nothing, this test is to test the exception returned by VHAL during initialization
372         // should not be propagated.
373         assertThat(mCarDiagnosticManager.getLatestLiveFrame()).isNull();
374     }
375 
testInitialFreezeFrameInfoException_Invalid_Arg()376     @Test public void testInitialFreezeFrameInfoException_Invalid_Arg() {
377         // Do nothing, this test is to test the exception returned by VHAL during initialization
378         // should not be propagated.
379         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
380     }
381 
testInitialFreezeFrameInfoException_NOT_AVAILABLE()382     @Test public void testInitialFreezeFrameInfoException_NOT_AVAILABLE() {
383         // Do nothing, this test is to test the exception returned by VHAL during initialization
384         // should not be propagated.
385         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
386     }
387 
testInitialFreezeFrameInfoException_ACCESS_DENIED()388     @Test public void testInitialFreezeFrameInfoException_ACCESS_DENIED() {
389         // Do nothing, this test is to test the exception returned by VHAL during initialization
390         // should not be propagated.
391         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
392     }
393 
testInitialFreezeFrameInfoException_TRY_AGAIN()394     @Test public void testInitialFreezeFrameInfoException_TRY_AGAIN() {
395         // Do nothing, this test is to test the exception returned by VHAL during initialization
396         // should not be propagated.
397         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
398     }
399 
testInitialFreezeFrameInfoException_INTERNAL_ERROR()400     @Test public void testInitialFreezeFrameInfoException_INTERNAL_ERROR() {
401         // Do nothing, this test is to test the exception returned by VHAL during initialization
402         // should not be propagated.
403         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
404     }
405 
testInitialFreezeFrameException_Invalid_Arg()406     @Test public void testInitialFreezeFrameException_Invalid_Arg() {
407         // Do nothing, this test is to test the exception returned by VHAL during initialization
408         // should not be propagated.
409         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
410     }
411 
testInitialFreezeFrameException_NOT_AVAILABLE()412     @Test public void testInitialFreezeFrameException_NOT_AVAILABLE() {
413         // Do nothing, this test is to test the exception returned by VHAL during initialization
414         // should not be propagated.
415         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
416     }
417 
testInitialFreezeFrameException_ACCESS_DENIED()418     @Test public void testInitialFreezeFrameException_ACCESS_DENIED() {
419         // Do nothing, this test is to test the exception returned by VHAL during initialization
420         // should not be propagated.
421         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
422     }
423 
testInitialFreezeFrameException_TRY_AGAIN()424     @Test public void testInitialFreezeFrameException_TRY_AGAIN() {
425         // Do nothing, this test is to test the exception returned by VHAL during initialization
426         // should not be propagated.
427         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
428     }
429 
testInitialFreezeFrameException_INTERNAL_ERROR()430     @Test public void testInitialFreezeFrameException_INTERNAL_ERROR() {
431         // Do nothing, this test is to test the exception returned by VHAL during initialization
432         // should not be propagated.
433         assertEquals(mCarDiagnosticManager.getFreezeFrameTimestamps().length, 0);
434     }
435 
436 
testLiveFrameRead()437     @Test public void testLiveFrameRead() throws Exception {
438         CarDiagnosticEvent liveFrame = mCarDiagnosticManager.getLatestLiveFrame();
439 
440         assertThat(liveFrame).isNotNull();
441         assertTrue(liveFrame.isLiveFrame());
442         assertFalse(liveFrame.isFreezeFrame());
443         assertFalse(liveFrame.isEmptyFrame());
444 
445         assertEquals(
446                 5000,
447                 liveFrame
448                         .getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
449                         .intValue());
450         assertEquals(
451                 30,
452                 liveFrame
453                         .getSystemIntegerSensor(IntegerSensorIndex.AMBIENT_AIR_TEMPERATURE)
454                         .intValue());
455         assertEquals(
456                 2,
457                 liveFrame
458                         .getSystemIntegerSensor(IntegerSensorIndex.CONTROL_MODULE_VOLTAGE)
459                         .intValue());
460         assertEquals(
461                 0.125f,
462                 liveFrame.getSystemFloatSensor(FloatSensorIndex.CALCULATED_ENGINE_LOAD),
463                 EPS);
464         assertEquals(
465                 12.5f,
466                 liveFrame.getSystemFloatSensor(FloatSensorIndex.VEHICLE_SPEED),
467                 EPS);
468     }
469 
testLiveFrameEvent()470     @Test public void testLiveFrameEvent() throws Exception {
471         Listener listener = new Listener();
472         mCarDiagnosticManager.registerListener(
473                 listener,
474                 CarDiagnosticManager.FRAME_TYPE_LIVE,
475                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
476 
477         listener.reset();
478         long time = SystemClock.elapsedRealtimeNanos();
479         mLiveFrameEventBuilder.addIntSensor(
480                 IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START, 5100);
481 
482         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time));
483         CarDiagnosticEvent liveFrame = listener.waitForEvent(time);
484 
485         assertThat(liveFrame).isNotNull();
486 
487         assertEquals(
488                 5100,
489                 liveFrame
490                         .getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
491                         .intValue());
492     }
493 
testMissingSensorRead()494     @Test public void testMissingSensorRead() throws Exception {
495         Listener listener = new Listener();
496         mCarDiagnosticManager.registerListener(
497                 listener,
498                 CarDiagnosticManager.FRAME_TYPE_LIVE,
499                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
500 
501         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build());
502         CarDiagnosticEvent liveFrame = listener.waitForEvent();
503 
504         assertThat(liveFrame).isNotNull();
505 
506         assertThat(
507                 liveFrame.getSystemIntegerSensor(
508                         IntegerSensorIndex.DRIVER_DEMAND_PERCENT_TORQUE)).isNull();
509         assertEquals(
510                 -1,
511                 liveFrame.getSystemIntegerSensor(
512                         IntegerSensorIndex.DRIVER_DEMAND_PERCENT_TORQUE, -1));
513 
514         assertThat(
515                 liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR6_VOLTAGE)).isNull();
516         assertEquals(
517                 0.25f,
518                 liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR5_VOLTAGE, 0.25f), EPS);
519 
520         assertThat(liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START)).isNull();
521         assertEquals(-1, liveFrame.getVendorIntegerSensor(IntegerSensorIndex.VENDOR_START, -1));
522 
523         assertThat(liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START)).isNull();
524         assertEquals(
525                 0.25f, liveFrame.getVendorFloatSensor(FloatSensorIndex.VENDOR_START, 0.25f), EPS);
526     }
527 
testFuelSystemStatus()528     @Test public void testFuelSystemStatus() throws Exception {
529         Listener listener = new Listener();
530         mCarDiagnosticManager.registerListener(
531                 listener,
532                 CarDiagnosticManager.FRAME_TYPE_LIVE,
533                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
534 
535         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build());
536         CarDiagnosticEvent liveFrame = listener.waitForEvent();
537 
538         assertThat(liveFrame).isNotNull();
539 
540         assertEquals(
541                 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION,
542                 liveFrame
543                         .getSystemIntegerSensor(IntegerSensorIndex.FUEL_SYSTEM_STATUS)
544                         .intValue());
545         assertEquals(
546                 FuelSystemStatus.OPEN_ENGINE_LOAD_OR_DECELERATION,
547                 liveFrame.getFuelSystemStatus().intValue());
548     }
549 
testSecondaryAirStatus()550     @Test public void testSecondaryAirStatus() throws Exception {
551         Listener listener = new Listener();
552         mCarDiagnosticManager.registerListener(
553                 listener,
554                 CarDiagnosticManager.FRAME_TYPE_LIVE,
555                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
556 
557         mLiveFrameEventBuilder.addIntSensor(
558                 IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS,
559                 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF);
560         long timestamp = SystemClock.elapsedRealtimeNanos();
561         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp));
562 
563         CarDiagnosticEvent liveFrame = listener.waitForEvent(timestamp);
564 
565         assertThat(liveFrame).isNotNull();
566 
567         assertEquals(
568                 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF,
569                 liveFrame
570                         .getSystemIntegerSensor(
571                                 IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS)
572                         .intValue());
573         assertEquals(
574                 SecondaryAirStatus.FROM_OUTSIDE_OR_OFF,
575                 liveFrame.getSecondaryAirStatus().intValue());
576     }
577 
testIgnitionMonitors()578     @Test public void testIgnitionMonitors() throws Exception {
579         Listener listener = new Listener();
580         mCarDiagnosticManager.registerListener(
581                 listener,
582                 CarDiagnosticManager.FRAME_TYPE_LIVE,
583                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
584 
585         // cfr. CarDiagnosticEvent for the meaning of the several bits
586         final int sparkMonitorsValue =
587                 0x1 | (0x1 << 2) | (0x1 << 3) | (0x1 << 6) | (0x1 << 10) | (0x1 << 11);
588 
589         final int compressionMonitorsValue =
590                 (0x1 << 2) | (0x1 << 3) | (0x1 << 6) | (0x1 << 12) | (0x1 << 13);
591 
592         mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED, 0);
593         mLiveFrameEventBuilder.addIntSensor(
594                 IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS, sparkMonitorsValue);
595 
596         long timestamp = SystemClock.elapsedRealtimeNanos();
597         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp));
598 
599         CarDiagnosticEvent liveFrame = listener.waitForEvent(timestamp);
600 
601         assertThat(liveFrame).isNotNull();
602 
603         CommonIgnitionMonitors commonIgnitionMonitors = liveFrame.getIgnitionMonitors();
604         assertThat(commonIgnitionMonitors).isNotNull();
605         assertTrue(commonIgnitionMonitors.components.available);
606         assertFalse(commonIgnitionMonitors.components.incomplete);
607         assertTrue(commonIgnitionMonitors.fuelSystem.available);
608         assertTrue(commonIgnitionMonitors.fuelSystem.incomplete);
609         assertFalse(commonIgnitionMonitors.misfire.available);
610         assertFalse(commonIgnitionMonitors.misfire.incomplete);
611 
612         SparkIgnitionMonitors sparkIgnitionMonitors =
613                 commonIgnitionMonitors.asSparkIgnitionMonitors();
614         assertThat(sparkIgnitionMonitors).isNotNull();
615         assertThat(commonIgnitionMonitors.asCompressionIgnitionMonitors()).isNull();
616 
617         assertTrue(sparkIgnitionMonitors.EGR.available);
618         assertFalse(sparkIgnitionMonitors.EGR.incomplete);
619         assertFalse(sparkIgnitionMonitors.oxygenSensorHeater.available);
620         assertFalse(sparkIgnitionMonitors.oxygenSensorHeater.incomplete);
621         assertTrue(sparkIgnitionMonitors.oxygenSensor.available);
622         assertTrue(sparkIgnitionMonitors.oxygenSensor.incomplete);
623         assertFalse(sparkIgnitionMonitors.ACRefrigerant.available);
624         assertFalse(sparkIgnitionMonitors.ACRefrigerant.incomplete);
625         assertFalse(sparkIgnitionMonitors.secondaryAirSystem.available);
626         assertFalse(sparkIgnitionMonitors.secondaryAirSystem.incomplete);
627         assertFalse(sparkIgnitionMonitors.evaporativeSystem.available);
628         assertFalse(sparkIgnitionMonitors.evaporativeSystem.incomplete);
629         assertFalse(sparkIgnitionMonitors.heatedCatalyst.available);
630         assertFalse(sparkIgnitionMonitors.heatedCatalyst.incomplete);
631         assertFalse(sparkIgnitionMonitors.catalyst.available);
632         assertFalse(sparkIgnitionMonitors.catalyst.incomplete);
633 
634         mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED, 1);
635         mLiveFrameEventBuilder.addIntSensor(
636                 IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS, compressionMonitorsValue);
637 
638         timestamp += 1000;
639         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp));
640 
641         liveFrame = listener.waitForEvent(timestamp);
642 
643         assertThat(liveFrame).isNotNull();
644         assertEquals(timestamp, liveFrame.timestamp);
645 
646         commonIgnitionMonitors = liveFrame.getIgnitionMonitors();
647         assertThat(commonIgnitionMonitors).isNotNull();
648         assertFalse(commonIgnitionMonitors.components.available);
649         assertFalse(commonIgnitionMonitors.components.incomplete);
650         assertTrue(commonIgnitionMonitors.fuelSystem.available);
651         assertTrue(commonIgnitionMonitors.fuelSystem.incomplete);
652         assertFalse(commonIgnitionMonitors.misfire.available);
653         assertFalse(commonIgnitionMonitors.misfire.incomplete);
654         CompressionIgnitionMonitors compressionIgnitionMonitors =
655                 commonIgnitionMonitors.asCompressionIgnitionMonitors();
656         assertThat(commonIgnitionMonitors.asSparkIgnitionMonitors()).isNull();
657         assertThat(compressionIgnitionMonitors).isNotNull();
658 
659         assertTrue(compressionIgnitionMonitors.EGROrVVT.available);
660         assertFalse(compressionIgnitionMonitors.EGROrVVT.incomplete);
661         assertFalse(compressionIgnitionMonitors.PMFilter.available);
662         assertFalse(compressionIgnitionMonitors.PMFilter.incomplete);
663         assertFalse(compressionIgnitionMonitors.exhaustGasSensor.available);
664         assertFalse(compressionIgnitionMonitors.exhaustGasSensor.incomplete);
665         assertTrue(compressionIgnitionMonitors.boostPressure.available);
666         assertTrue(compressionIgnitionMonitors.boostPressure.incomplete);
667         assertFalse(compressionIgnitionMonitors.NOxSCR.available);
668         assertFalse(compressionIgnitionMonitors.NOxSCR.incomplete);
669         assertFalse(compressionIgnitionMonitors.NMHCCatalyst.available);
670         assertFalse(compressionIgnitionMonitors.NMHCCatalyst.incomplete);
671     }
672 
673     @Test
674     @FlakyTest
testFuelType()675     public void testFuelType() throws Exception {
676         Listener listener = new Listener();
677         mCarDiagnosticManager.registerListener(
678                 listener,
679                 CarDiagnosticManager.FRAME_TYPE_LIVE,
680                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
681 
682         mLiveFrameEventBuilder.addIntSensor(
683                 IntegerSensorIndex.FUEL_TYPE, FuelType.BIFUEL_RUNNING_LPG);
684         long timestamp = SystemClock.elapsedRealtimeNanos();
685         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp));
686 
687         CarDiagnosticEvent liveFrame = listener.waitForEvent(timestamp);
688 
689         assertThat(liveFrame).isNotNull();
690 
691         assertEquals(
692                 FuelType.BIFUEL_RUNNING_LPG,
693                 liveFrame.getSystemIntegerSensor(IntegerSensorIndex.FUEL_TYPE).intValue());
694         assertEquals(FuelType.BIFUEL_RUNNING_LPG, liveFrame.getFuelType().intValue());
695     }
696 
testDiagnosticJson()697     @Test public void testDiagnosticJson() throws Exception {
698         Listener listener = new Listener();
699         mCarDiagnosticManager.registerListener(
700                 listener,
701                 CarDiagnosticManager.FRAME_TYPE_LIVE,
702                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
703 
704         mLiveFrameEventBuilder.addIntSensor(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE, 74);
705         mLiveFrameEventBuilder.addFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE, 0.125f);
706 
707         long timestamp = SystemClock.elapsedRealtimeNanos();
708         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(timestamp));
709 
710         CarDiagnosticEvent liveFrame = listener.waitForEvent(timestamp);
711 
712         assertThat(liveFrame).isNotNull();
713 
714         assertEquals(
715                 74,
716                 liveFrame
717                         .getSystemIntegerSensor(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE)
718                         .intValue());
719         assertEquals(
720                 0.125f,
721                 liveFrame.getSystemFloatSensor(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE),
722                 EPS);
723 
724         StringWriter stringWriter = new StringWriter();
725         JsonWriter jsonWriter = new JsonWriter(stringWriter);
726 
727         liveFrame.writeToJson(jsonWriter);
728         jsonWriter.flush();
729 
730         StringReader stringReader = new StringReader(stringWriter.toString());
731         JsonReader jsonReader = new JsonReader(stringReader);
732         DiagnosticJson diagnosticJson = DiagnosticJson.build(jsonReader);
733 
734         assertEquals(
735                 74,
736                 diagnosticJson
737                         .intValues
738                         .get(IntegerSensorIndex.ENGINE_OIL_TEMPERATURE)
739                         .intValue());
740         assertEquals(
741                 0.125f,
742                 diagnosticJson.floatValues.get(FloatSensorIndex.OXYGEN_SENSOR1_VOLTAGE),
743                 EPS);
744     }
745 
746     @Test
testMultipleListeners()747     public void testMultipleListeners() throws Exception {
748         Listener listener1 = new Listener();
749         Listener listener2 = new Listener();
750 
751         mCarDiagnosticManager.registerListener(
752                 listener1,
753                 CarDiagnosticManager.FRAME_TYPE_LIVE,
754                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
755         mCarDiagnosticManager.registerListener(
756                 listener2,
757                 CarDiagnosticManager.FRAME_TYPE_LIVE,
758                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
759 
760         listener1.reset();
761         listener2.reset();
762 
763         long time = SystemClock.elapsedRealtimeNanos();
764         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time));
765         CarDiagnosticEvent event1 = listener1.waitForEvent(time);
766         assertThat(event1).isNotNull();
767         CarDiagnosticEvent event2 = listener2.waitForEvent(time);
768         assertThat(event2).isNotNull();
769 
770         assertTrue(event1.equals(event1));
771         assertTrue(event2.equals(event2));
772         assertTrue(event1.equals(event2));
773         assertTrue(event2.equals(event1));
774 
775         assertTrue(event1.hashCode() == event1.hashCode());
776         assertTrue(event1.hashCode() == event2.hashCode());
777 
778         assertEquals(
779                 5000,
780                 event1.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
781                         .intValue());
782         assertEquals(
783                 5000,
784                 event2.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
785                         .intValue());
786 
787         listener1.reset();
788         listener2.reset();
789 
790         mCarDiagnosticManager.unregisterListener(listener1);
791 
792         time += 1000;
793         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time));
794         assertThat(listener1.waitForEvent(time)).isNull();
795 
796         event2 = listener2.waitForEvent(time);
797         assertThat(event2).isNotNull();
798 
799         assertTrue(event1.isEarlierThan(event2));
800         assertFalse(event1.equals(event2));
801         assertFalse(event2.equals(event1));
802 
803         assertEquals(
804                 5000,
805                 event2.getSystemIntegerSensor(IntegerSensorIndex.RUNTIME_SINCE_ENGINE_START)
806                         .intValue());
807     }
808 
809     @Test
testFreezeFrameEvent()810     public void testFreezeFrameEvent() throws Exception {
811         Listener listener = new Listener();
812         mCarDiagnosticManager.registerListener(
813                 listener,
814                 CarDiagnosticManager.FRAME_TYPE_FREEZE,
815                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
816 
817         listener.reset();
818         VehiclePropValue injectedEvent =
819                 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder);
820         getAidlMockedVehicleHal().injectEvent(injectedEvent);
821         CarDiagnosticEvent freezeFrame = listener.waitForEvent(injectedEvent.timestamp);
822 
823         assertThat(freezeFrame).isNotNull();
824         assertEquals(DTC, freezeFrame.dtc);
825 
826         mFreezeFrameEventBuilder.addIntSensor(
827                 IntegerSensorIndex.ABSOLUTE_BAROMETRIC_PRESSURE, 22);
828         injectedEvent = mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder);
829         getAidlMockedVehicleHal().injectEvent(injectedEvent);
830         freezeFrame = listener.waitForEvent(injectedEvent.timestamp);
831 
832         assertThat(freezeFrame).isNotNull();
833         assertThat(freezeFrame).isNotNull();
834         assertFalse(freezeFrame.isLiveFrame());
835         assertTrue(freezeFrame.isFreezeFrame());
836         assertFalse(freezeFrame.isEmptyFrame());
837 
838         assertEquals(DTC, freezeFrame.dtc);
839         assertEquals(
840                 22,
841                 freezeFrame
842                         .getSystemIntegerSensor(IntegerSensorIndex.ABSOLUTE_BAROMETRIC_PRESSURE)
843                         .intValue());
844     }
845 
846     @Test
testFreezeFrameTimestamps()847     public void testFreezeFrameTimestamps() throws Exception {
848         Listener listener = new Listener();
849         mCarDiagnosticManager.registerListener(
850                 listener,
851                 CarDiagnosticManager.FRAME_TYPE_FREEZE,
852                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
853 
854         Set<Long> generatedTimestamps = new HashSet<>();
855 
856         VehiclePropValue injectedEvent =
857                 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder);
858         getAidlMockedVehicleHal().injectEvent(injectedEvent);
859         generatedTimestamps.add(injectedEvent.timestamp);
860         assertThat(listener.waitForEvent(injectedEvent.timestamp)).isNotNull();
861 
862         injectedEvent =
863                 mFreezeFrameProperties.addNewEvent(
864                         mFreezeFrameEventBuilder, injectedEvent.timestamp + 1000);
865         getAidlMockedVehicleHal().injectEvent(injectedEvent);
866         generatedTimestamps.add(injectedEvent.timestamp);
867         assertThat(listener.waitForEvent(injectedEvent.timestamp)).isNotNull();
868 
869         long[] acquiredTimestamps = mCarDiagnosticManager.getFreezeFrameTimestamps();
870         assertEquals(generatedTimestamps.size(), acquiredTimestamps.length);
871         for (long acquiredTimestamp : acquiredTimestamps) {
872             assertTrue(generatedTimestamps.contains(acquiredTimestamp));
873         }
874     }
875 
876     @Test
testClearFreezeFrameTimestamps()877     public void testClearFreezeFrameTimestamps() throws Exception {
878         Listener listener = new Listener();
879         mCarDiagnosticManager.registerListener(
880                 listener,
881                 CarDiagnosticManager.FRAME_TYPE_FREEZE,
882                 android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
883 
884         VehiclePropValue injectedEvent =
885                 mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder);
886         getAidlMockedVehicleHal().injectEvent(injectedEvent);
887         assertThat(listener.waitForEvent(injectedEvent.timestamp)).isNotNull();
888 
889         assertThat(mCarDiagnosticManager.getFreezeFrame(injectedEvent.timestamp)).isNotNull();
890         mCarDiagnosticManager.clearFreezeFrames(injectedEvent.timestamp);
891         assertThat(mCarDiagnosticManager.getFreezeFrame(injectedEvent.timestamp)).isNull();
892     }
893 
894     @Test
testClearFreezeFrameTimestamps_ErrorCodeFromHal()895     public void testClearFreezeFrameTimestamps_ErrorCodeFromHal() {
896         long timestamp = SystemClock.elapsedRealtimeNanos();
897         // All the exceptions from the HAL should not be propagated up.
898         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(
899                 VehicleHalStatusCode.STATUS_TRY_AGAIN);
900         mCarDiagnosticManager.clearFreezeFrames(timestamp);
901         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(
902                 VehicleHalStatusCode.STATUS_INVALID_ARG);
903         mCarDiagnosticManager.clearFreezeFrames(timestamp);
904         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(
905                 VehicleHalStatusCode.STATUS_NOT_AVAILABLE);
906         mCarDiagnosticManager.clearFreezeFrames(timestamp);
907         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(
908                 VehicleHalStatusCode.STATUS_ACCESS_DENIED);
909         mCarDiagnosticManager.clearFreezeFrames(timestamp);
910         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(
911                 VehicleHalStatusCode.STATUS_INTERNAL_ERROR);
912         mCarDiagnosticManager.clearFreezeFrames(timestamp);
913 
914         // Clear the status code.
915         mFreezeFrameProperties.mFreezeFrameClearHandler.setStatus(VehicleHalStatusCode.STATUS_OK);
916     }
917 
918     @Test
testListenerUnregister()919     public void testListenerUnregister() throws Exception {
920         Listener listener1 = new Listener();
921         Listener listener2 = new Listener();
922         mCarDiagnosticManager.registerListener(
923             listener1,
924             CarDiagnosticManager.FRAME_TYPE_LIVE,
925             android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
926         mCarDiagnosticManager.registerListener(
927             listener1,
928             CarDiagnosticManager.FRAME_TYPE_FREEZE,
929             android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
930 
931         mCarDiagnosticManager.unregisterListener(listener1);
932 
933         // you need a listener to be registered before MockedVehicleHal will actually dispatch
934         // your events - add one, but do it *after* unregistering the first listener
935         mCarDiagnosticManager.registerListener(
936             listener2,
937             CarDiagnosticManager.FRAME_TYPE_LIVE,
938             android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
939         mCarDiagnosticManager.registerListener(
940             listener2,
941             CarDiagnosticManager.FRAME_TYPE_FREEZE,
942             android.car.hardware.CarSensorManager.SENSOR_RATE_NORMAL);
943 
944         VehiclePropValue injectedEvent =
945             mFreezeFrameProperties.addNewEvent(mFreezeFrameEventBuilder);
946         long time = injectedEvent.timestamp;
947         getAidlMockedVehicleHal().injectEvent(injectedEvent);
948         assertThat(listener1.waitForEvent(time)).isNull();
949         assertThat(listener2.waitForEvent(time)).isNotNull();
950 
951         time += 1000;
952         getAidlMockedVehicleHal().injectEvent(mLiveFrameEventBuilder.build(time));
953         assertThat(listener1.waitForEvent(time)).isNull();
954         assertThat(listener2.waitForEvent(time)).isNotNull();
955     }
956 
957     @Test
testIsSupportedApiCalls()958     public void testIsSupportedApiCalls() throws Exception {
959         assertTrue(mCarDiagnosticManager.isLiveFrameSupported());
960         assertTrue(mCarDiagnosticManager.isFreezeFrameNotificationSupported());
961         assertTrue(mCarDiagnosticManager.isGetFreezeFrameSupported());
962         assertTrue(mCarDiagnosticManager.isClearFreezeFramesSupported());
963         assertTrue(mCarDiagnosticManager.isSelectiveClearFreezeFramesSupported());
964     }
965 
966     class Listener implements CarDiagnosticManager.OnDiagnosticEventListener {
967         private final Object mLock = new Object();
968 
969         @GuardedBy("mLock")
970         private final List<CarDiagnosticEvent> mEvents = new ArrayList<>();
971         @GuardedBy("mLock")
972         private long mEventTimestamp;
973         // By default we are not waiting for any event. When we start waiting for an event, a new
974         // CountDownLatch with count 1 will be used.
975         @GuardedBy("mLock")
976         private CountDownLatch mCountDownLatch;
977 
978         @GuardedBy("mLock")
checkReceivedEventsLocked(long eventTimeStamp)979         private CarDiagnosticEvent checkReceivedEventsLocked(long eventTimeStamp) {
980             for (int i = 0; i < mEvents.size(); i++) {
981                 if (mEventTimestamp == 0 || mEvents.get(i).timestamp == eventTimeStamp) {
982                     return mEvents.get(i);
983                 }
984             }
985             return null;
986         }
987 
reset()988         void reset() {
989             synchronized (mLock) {
990                 mEvents.clear();
991             }
992         }
993 
waitForEvent()994         CarDiagnosticEvent waitForEvent() {
995             return waitForEvent(0);
996         }
997 
998         // Wait for a event with certain eventTimeStamp to happen.
waitForEvent(long eventTimeStamp)999         CarDiagnosticEvent waitForEvent(long eventTimeStamp) {
1000             CountDownLatch countDownlatch;
1001             synchronized (mLock) {
1002                 mEventTimestamp = eventTimeStamp;
1003                 mCountDownLatch = new CountDownLatch(1);
1004                 CarDiagnosticEvent matchedEvent = checkReceivedEventsLocked(eventTimeStamp);
1005                 if (matchedEvent != null) {
1006                     return matchedEvent;
1007                 }
1008                 countDownlatch = mCountDownLatch;
1009             }
1010             silentAwait(countDownlatch, DEFAULT_WAIT_TIMEOUT_MS);
1011             synchronized (mLock) {
1012                 // Set the latch to null to indicate we are not waiting for an event any more.
1013                 mCountDownLatch = null;
1014                 return checkReceivedEventsLocked(eventTimeStamp);
1015             }
1016         }
1017 
1018         @Override
onDiagnosticEvent(CarDiagnosticEvent event)1019         public void onDiagnosticEvent(CarDiagnosticEvent event) {
1020             synchronized (mLock) {
1021                 mEvents.add(event);
1022                 if (mCountDownLatch == null) {
1023                     return;
1024                 }
1025                 // If we are currently waiting for an event, check whether we have a match.
1026                 if (mEventTimestamp == 0 || event.timestamp == mEventTimestamp) {
1027                     mCountDownLatch.countDown();
1028                 }
1029             }
1030         }
1031     }
1032 }
1033