• 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 android.car.hardware;
18 
19 import android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.car.annotation.FutureFeature;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.util.SparseArray;
25 import android.util.SparseIntArray;
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.Objects;
29 
30 /**
31  * A CarDiagnosticEvent object corresponds to a single diagnostic event frame coming from the car.
32  *
33  * @hide
34  */
35 @FutureFeature
36 public class CarDiagnosticEvent implements Parcelable {
37     /** Whether this frame represents a live or a freeze frame */
38     public final int frameType;
39 
40     /**
41      * When this data was acquired in car or received from car. It is elapsed real-time of data
42      * reception from car in nanoseconds since system boot.
43      */
44     public final long timestamp;
45 
46     /**
47      * Sparse array that contains the mapping of OBD2 diagnostic properties to their values for
48      * integer valued properties
49      */
50     private final SparseIntArray intValues;
51 
52     /**
53      * Sparse array that contains the mapping of OBD2 diagnostic properties to their values for
54      * float valued properties
55      */
56     private final SparseArray<Float> floatValues;
57 
58     /**
59      * Diagnostic Troubleshooting Code (DTC) that was detected and caused this frame to be stored
60      * (if a freeze frame). Always null for a live frame.
61      */
62     public final String dtc;
63 
CarDiagnosticEvent(Parcel in)64     public CarDiagnosticEvent(Parcel in) {
65         frameType = in.readInt();
66         timestamp = in.readLong();
67         int len = in.readInt();
68         floatValues = new SparseArray<>(len);
69         for (int i = 0; i < len; ++i) {
70             int key = in.readInt();
71             float value = in.readFloat();
72             floatValues.put(key, value);
73         }
74         len = in.readInt();
75         intValues = new SparseIntArray(len);
76         for (int i = 0; i < len; ++i) {
77             int key = in.readInt();
78             int value = in.readInt();
79             intValues.put(key, value);
80         }
81         dtc = (String)in.readValue(String.class.getClassLoader());
82         // version 1 up to here
83     }
84 
85     @Override
describeContents()86     public int describeContents() {
87         return 0;
88     }
89 
90     @Override
writeToParcel(Parcel dest, int flags)91     public void writeToParcel(Parcel dest, int flags) {
92         dest.writeInt(frameType);
93         dest.writeLong(timestamp);
94         dest.writeInt(floatValues.size());
95         for (int i = 0; i < floatValues.size(); ++i) {
96             int key = floatValues.keyAt(i);
97             dest.writeInt(key);
98             dest.writeFloat(floatValues.get(key));
99         }
100         dest.writeInt(intValues.size());
101         for (int i = 0; i < intValues.size(); ++i) {
102             int key = intValues.keyAt(i);
103             dest.writeInt(key);
104             dest.writeInt(intValues.get(key));
105         }
106         dest.writeValue(dtc);
107     }
108 
109     public static final Parcelable.Creator<CarDiagnosticEvent> CREATOR =
110             new Parcelable.Creator<CarDiagnosticEvent>() {
111                 public CarDiagnosticEvent createFromParcel(Parcel in) {
112                     return new CarDiagnosticEvent(in);
113                 }
114 
115                 public CarDiagnosticEvent[] newArray(int size) {
116                     return new CarDiagnosticEvent[size];
117                 }
118             };
119 
CarDiagnosticEvent( int frameType, long timestamp, SparseArray<Float> floatValues, SparseIntArray intValues, String dtc)120     private CarDiagnosticEvent(
121             int frameType,
122             long timestamp,
123             SparseArray<Float> floatValues,
124             SparseIntArray intValues,
125             String dtc) {
126         this.frameType = frameType;
127         this.timestamp = timestamp;
128         this.floatValues = floatValues;
129         this.intValues = intValues;
130         this.dtc = dtc;
131     }
132 
133     public static class Builder {
134         private int mType = CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE;
135         private long mTimestamp = 0;
136         private SparseArray<Float> mFloatValues = new SparseArray<>();
137         private SparseIntArray mIntValues = new SparseIntArray();
138         private String mDtc = null;
139 
Builder(int type)140         private Builder(int type) {
141             mType = type;
142         }
143 
newLiveFrameBuilder()144         public static Builder newLiveFrameBuilder() {
145             return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE);
146         }
147 
newFreezeFrameBuilder()148         public static Builder newFreezeFrameBuilder() {
149             return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE);
150         }
151 
atTimestamp(long timestamp)152         public Builder atTimestamp(long timestamp) {
153             mTimestamp = timestamp;
154             return this;
155         }
156 
withIntValue(int key, int value)157         public Builder withIntValue(int key, int value) {
158             mIntValues.put(key, value);
159             return this;
160         }
161 
withFloatValue(int key, float value)162         public Builder withFloatValue(int key, float value) {
163             mFloatValues.put(key, value);
164             return this;
165         }
166 
withDTC(String dtc)167         public Builder withDTC(String dtc) {
168             mDtc = dtc;
169             return this;
170         }
171 
build()172         public CarDiagnosticEvent build() {
173             return new CarDiagnosticEvent(mType, mTimestamp, mFloatValues, mIntValues, mDtc);
174         }
175     }
176 
177     /**
178      * Returns a copy of this CarDiagnosticEvent with all vendor-specific sensors removed.
179      * @hide
180      */
withVendorSensorsRemoved()181     public CarDiagnosticEvent withVendorSensorsRemoved() {
182         SparseIntArray newIntValues = intValues.clone();
183         SparseArray<Float> newFloatValues = floatValues.clone();
184         for(int i = 0; i < intValues.size(); ++i) {
185             int key = intValues.keyAt(i);
186             if (key >= CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.LAST_SYSTEM) {
187                 newIntValues.delete(key);
188             }
189         }
190         for(int i = 0; i < floatValues.size(); ++i) {
191             int key = floatValues.keyAt(i);
192             if (key >= CarDiagnosticSensorIndices.Obd2FloatSensorIndex.LAST_SYSTEM) {
193                 newFloatValues.delete(key);
194             }
195         }
196         return new CarDiagnosticEvent(frameType, timestamp, newFloatValues, newIntValues, dtc);
197     }
198 
isLiveFrame()199     public boolean isLiveFrame() {
200         return CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE == frameType;
201     }
202 
isFreezeFrame()203     public boolean isFreezeFrame() {
204         return CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE == frameType;
205     }
206 
isEmptyFrame()207     public boolean isEmptyFrame() {
208         boolean empty = (0 == intValues.size());
209         empty &= (0 == floatValues.size());
210         if (isFreezeFrame()) empty &= dtc.isEmpty();
211         return empty;
212     }
213 
214     /** @hide */
checkLiveFrame()215     public CarDiagnosticEvent checkLiveFrame() {
216         if (!isLiveFrame()) throw new IllegalStateException("frame is not a live frame");
217         return this;
218     }
219 
220     /** @hide */
checkFreezeFrame()221     public CarDiagnosticEvent checkFreezeFrame() {
222         if (!isFreezeFrame()) throw new IllegalStateException("frame is not a freeze frame");
223         return this;
224     }
225 
226     /** @hide */
isEarlierThan(CarDiagnosticEvent otherEvent)227     public boolean isEarlierThan(CarDiagnosticEvent otherEvent) {
228         otherEvent = Objects.requireNonNull(otherEvent);
229         return (timestamp < otherEvent.timestamp);
230     }
231 
232     @Override
toString()233     public String toString() {
234         return String.format(
235                 "%s diagnostic frame {\n"
236                         + "\ttimestamp: %d, "
237                         + "DTC: %s\n"
238                         + "\tintValues: %s\n"
239                         + "\tfloatValues: %s\n}",
240                 isLiveFrame() ? "live" : "freeze",
241                 timestamp,
242                 dtc,
243                 intValues.toString(),
244                 floatValues.toString());
245     }
246 
getSystemIntegerSensor(@arDiagnosticSensorIndices.IntegerSensorIndex int sensor, int defaultValue)247     public int getSystemIntegerSensor(@CarDiagnosticSensorIndices.IntegerSensorIndex int sensor, int defaultValue) {
248         return intValues.get(sensor, defaultValue);
249     }
250 
getSystemFloatSensor(@arDiagnosticSensorIndices.FloatSensorIndex int sensor, float defaultValue)251     public float getSystemFloatSensor(@CarDiagnosticSensorIndices.FloatSensorIndex int sensor, float defaultValue) {
252         return floatValues.get(sensor, defaultValue);
253     }
254 
getVendorIntegerSensor(int sensor, int defaultValue)255     public int getVendorIntegerSensor(int sensor, int defaultValue) {
256         return intValues.get(sensor, defaultValue);
257     }
258 
getVendorFloatSensor(int sensor, float defaultValue)259     public float getVendorFloatSensor(int sensor, float defaultValue) {
260         return floatValues.get(sensor, defaultValue);
261     }
262 
getSystemIntegerSensor(@arDiagnosticSensorIndices.IntegerSensorIndex int sensor)263     public @Nullable Integer getSystemIntegerSensor(@CarDiagnosticSensorIndices.IntegerSensorIndex int sensor) {
264         int index = intValues.indexOfKey(sensor);
265         if(index < 0) return null;
266         return intValues.valueAt(index);
267     }
268 
getSystemFloatSensor(@arDiagnosticSensorIndices.FloatSensorIndex int sensor)269     public @Nullable Float getSystemFloatSensor(@CarDiagnosticSensorIndices.FloatSensorIndex int sensor) {
270         int index = floatValues.indexOfKey(sensor);
271         if(index < 0) return null;
272         return floatValues.valueAt(index);
273     }
274 
getVendorIntegerSensor(int sensor)275     public @Nullable Integer getVendorIntegerSensor(int sensor) {
276         int index = intValues.indexOfKey(sensor);
277         if(index < 0) return null;
278         return intValues.valueAt(index);
279     }
280 
getVendorFloatSensor(int sensor)281     public @Nullable Float getVendorFloatSensor(int sensor) {
282         int index = floatValues.indexOfKey(sensor);
283         if(index < 0) return null;
284         return floatValues.valueAt(index);
285     }
286 
287     /**
288      * Represents possible states of the fuel system;
289      * see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#FUEL_SYSTEM_STATUS}
290      */
291     public static final class FuelSystemStatus {
FuelSystemStatus()292         private FuelSystemStatus() {}
293 
294         public static final int OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1;
295         public static final int CLOSED_LOOP = 2;
296         public static final int OPEN_ENGINE_LOAD_OR_DECELERATION = 4;
297         public static final int OPEN_SYSTEM_FAILURE = 8;
298         public static final int CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16;
299 
300         @Retention(RetentionPolicy.SOURCE)
301         @IntDef({
302             OPEN_INSUFFICIENT_ENGINE_TEMPERATURE,
303             CLOSED_LOOP,
304             OPEN_ENGINE_LOAD_OR_DECELERATION,
305             OPEN_SYSTEM_FAILURE,
306             CLOSED_LOOP_BUT_FEEDBACK_FAULT
307         })
308         public @interface Status {}
309     }
310 
311     /**
312      * Represents possible states of the secondary air system;
313      * see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#COMMANDED_SECONDARY_AIR_STATUS}
314      */
315     public static final class SecondaryAirStatus {
SecondaryAirStatus()316         private SecondaryAirStatus() {}
317 
318         public static final int UPSTREAM = 1;
319         public static final int DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2;
320         public static final int FROM_OUTSIDE_OR_OFF = 4;
321         public static final int PUMP_ON_FOR_DIAGNOSTICS = 8;
322 
323         @Retention(RetentionPolicy.SOURCE)
324         @IntDef({
325             UPSTREAM,
326             DOWNSTREAM_OF_CATALYCIC_CONVERTER,
327             FROM_OUTSIDE_OR_OFF,
328             PUMP_ON_FOR_DIAGNOSTICS
329         })
330         public @interface Status {}
331     }
332 
333     /**
334      * Represents possible types of fuel;
335      * see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#FUEL_TYPE}
336      */
337     public static final class FuelType {
FuelType()338         private FuelType() {}
339 
340         public static final int NOT_AVAILABLE = 0;
341         public static final int GASOLINE = 1;
342         public static final int METHANOL = 2;
343         public static final int ETHANOL = 3;
344         public static final int DIESEL = 4;
345         public static final int LPG = 5;
346         public static final int CNG = 6;
347         public static final int PROPANE = 7;
348         public static final int ELECTRIC = 8;
349         public static final int BIFUEL_RUNNING_GASOLINE = 9;
350         public static final int BIFUEL_RUNNING_METHANOL = 10;
351         public static final int BIFUEL_RUNNING_ETHANOL = 11;
352         public static final int BIFUEL_RUNNING_LPG = 12;
353         public static final int BIFUEL_RUNNING_CNG = 13;
354         public static final int BIFUEL_RUNNING_PROPANE = 14;
355         public static final int BIFUEL_RUNNING_ELECTRIC = 15;
356         public static final int BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16;
357         public static final int HYBRID_GASOLINE = 17;
358         public static final int HYBRID_ETHANOL = 18;
359         public static final int HYBRID_DIESEL = 19;
360         public static final int HYBRID_ELECTRIC = 20;
361         public static final int HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21;
362         public static final int HYBRID_REGENERATIVE = 22;
363         public static final int BIFUEL_RUNNING_DIESEL = 23;
364 
365         @Retention(RetentionPolicy.SOURCE)
366         @IntDef({
367             NOT_AVAILABLE,
368             GASOLINE,
369             METHANOL,
370             ETHANOL,
371             DIESEL,
372             LPG,
373             CNG,
374             PROPANE,
375             ELECTRIC,
376             BIFUEL_RUNNING_GASOLINE,
377             BIFUEL_RUNNING_METHANOL,
378             BIFUEL_RUNNING_ETHANOL,
379             BIFUEL_RUNNING_LPG,
380             BIFUEL_RUNNING_CNG,
381             BIFUEL_RUNNING_PROPANE,
382             BIFUEL_RUNNING_ELECTRIC,
383             BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION,
384             HYBRID_GASOLINE,
385             HYBRID_ETHANOL,
386             HYBRID_DIESEL,
387             HYBRID_ELECTRIC,
388             HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION,
389             HYBRID_REGENERATIVE,
390             BIFUEL_RUNNING_DIESEL
391         })
392         public @interface Type {}
393     }
394 
395     /**
396      * Represents possible states of the ignition monitors on the vehicle;
397      * see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#IGNITION_MONITORS_SUPPORTED}
398      * see {@link CarDiagnosticSensorIndices.Obd2IntegerSensorIndex#IGNITION_SPECIFIC_MONITORS}
399      */
400     public static final class IgnitionMonitors {
401         public static final class IgnitionMonitor {
402             public final boolean available;
403             public final boolean incomplete;
404 
IgnitionMonitor(boolean available, boolean incomplete)405             IgnitionMonitor(boolean available, boolean incomplete) {
406                 this.available = available;
407                 this.incomplete = incomplete;
408             }
409 
410             public static final class Builder {
411                 private int mAvailableBitmask;
412                 private int mIncompleteBitmask;
413 
Builder()414                 Builder() {
415                     mAvailableBitmask = 0;
416                     mIncompleteBitmask = 0;
417                 }
418 
withAvailableBitmask(int bitmask)419                 public Builder withAvailableBitmask(int bitmask) {
420                     mAvailableBitmask = bitmask;
421                     return this;
422                 }
423 
withIncompleteBitmask(int bitmask)424                 public Builder withIncompleteBitmask(int bitmask) {
425                     mIncompleteBitmask = bitmask;
426                     return this;
427                 }
428 
buildForValue(int value)429                 public IgnitionMonitor buildForValue(int value) {
430                     boolean available = (0 != (value & mAvailableBitmask));
431                     boolean incomplete = (0 != (value & mIncompleteBitmask));
432 
433                     return new IgnitionMonitor(available, incomplete);
434                 }
435             }
436         }
437 
438         public static class CommonIgnitionMonitors {
439             public final IgnitionMonitor components;
440             public final IgnitionMonitor fuelSystem;
441             public final IgnitionMonitor misfire;
442 
443             static final int COMPONENTS_AVAILABLE = 0x1 << 0;
444             static final int COMPONENTS_INCOMPLETE = 0x1 << 1;
445 
446             static final int FUEL_SYSTEM_AVAILABLE = 0x1 << 2;
447             static final int FUEL_SYSTEM_INCOMPLETE = 0x1 << 3;
448 
449             static final int MISFIRE_AVAILABLE = 0x1 << 4;
450             static final int MISFIRE_INCOMPLETE = 0x1 << 5;
451 
452             static final IgnitionMonitor.Builder COMPONENTS_BUILDER =
453                     new IgnitionMonitor.Builder()
454                             .withAvailableBitmask(COMPONENTS_AVAILABLE)
455                             .withIncompleteBitmask(COMPONENTS_INCOMPLETE);
456 
457             static final IgnitionMonitor.Builder FUEL_SYSTEM_BUILDER =
458                     new IgnitionMonitor.Builder()
459                             .withAvailableBitmask(FUEL_SYSTEM_AVAILABLE)
460                             .withIncompleteBitmask(FUEL_SYSTEM_INCOMPLETE);
461 
462             static final IgnitionMonitor.Builder MISFIRE_BUILDER =
463                     new IgnitionMonitor.Builder()
464                             .withAvailableBitmask(MISFIRE_AVAILABLE)
465                             .withIncompleteBitmask(MISFIRE_INCOMPLETE);
466 
CommonIgnitionMonitors(int bitmask)467             CommonIgnitionMonitors(int bitmask) {
468                 components = COMPONENTS_BUILDER.buildForValue(bitmask);
469                 fuelSystem = FUEL_SYSTEM_BUILDER.buildForValue(bitmask);
470                 misfire = MISFIRE_BUILDER.buildForValue(bitmask);
471             }
472 
asSparkIgnitionMonitors()473             public @Nullable SparkIgnitionMonitors asSparkIgnitionMonitors() {
474                 if (this instanceof SparkIgnitionMonitors)
475                     return (SparkIgnitionMonitors)this;
476                 return null;
477             }
478 
asCompressionIgnitionMonitors()479             public @Nullable CompressionIgnitionMonitors asCompressionIgnitionMonitors() {
480                 if (this instanceof CompressionIgnitionMonitors)
481                     return (CompressionIgnitionMonitors)this;
482                 return null;
483             }
484         }
485 
486         public static final class SparkIgnitionMonitors extends CommonIgnitionMonitors {
487             public final IgnitionMonitor EGR;
488             public final IgnitionMonitor oxygenSensorHeater;
489             public final IgnitionMonitor oxygenSensor;
490             public final IgnitionMonitor ACRefrigerant;
491             public final IgnitionMonitor secondaryAirSystem;
492             public final IgnitionMonitor evaporativeSystem;
493             public final IgnitionMonitor heatedCatalyst;
494             public final IgnitionMonitor catalyst;
495 
496             static final int EGR_AVAILABLE = 0x1 << 6;
497             static final int EGR_INCOMPLETE = 0x1 << 7;
498 
499             static final int OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8;
500             static final int OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9;
501 
502             static final int OXYGEN_SENSOR_AVAILABLE = 0x1 << 10;
503             static final int OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11;
504 
505             static final int AC_REFRIGERANT_AVAILABLE = 0x1 << 12;
506             static final int AC_REFRIGERANT_INCOMPLETE = 0x1 << 13;
507 
508             static final int SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14;
509             static final int SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15;
510 
511             static final int EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16;
512             static final int EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17;
513 
514             static final int HEATED_CATALYST_AVAILABLE = 0x1 << 18;
515             static final int HEATED_CATALYST_INCOMPLETE = 0x1 << 19;
516 
517             static final int CATALYST_AVAILABLE = 0x1 << 20;
518             static final int CATALYST_INCOMPLETE = 0x1 << 21;
519 
520             static final IgnitionMonitor.Builder EGR_BUILDER =
521                 new IgnitionMonitor.Builder()
522                     .withAvailableBitmask(EGR_AVAILABLE)
523                     .withIncompleteBitmask(EGR_INCOMPLETE);
524 
525             static final IgnitionMonitor.Builder OXYGEN_SENSOR_HEATER_BUILDER =
526                 new IgnitionMonitor.Builder()
527                     .withAvailableBitmask(OXYGEN_SENSOR_HEATER_AVAILABLE)
528                     .withIncompleteBitmask(OXYGEN_SENSOR_HEATER_INCOMPLETE);
529 
530             static final IgnitionMonitor.Builder OXYGEN_SENSOR_BUILDER =
531                 new IgnitionMonitor.Builder()
532                     .withAvailableBitmask(OXYGEN_SENSOR_AVAILABLE)
533                     .withIncompleteBitmask(OXYGEN_SENSOR_INCOMPLETE);
534 
535             static final IgnitionMonitor.Builder AC_REFRIGERANT_BUILDER =
536                 new IgnitionMonitor.Builder()
537                     .withAvailableBitmask(AC_REFRIGERANT_AVAILABLE)
538                     .withIncompleteBitmask(AC_REFRIGERANT_INCOMPLETE);
539 
540             static final IgnitionMonitor.Builder SECONDARY_AIR_SYSTEM_BUILDER =
541                 new IgnitionMonitor.Builder()
542                     .withAvailableBitmask(SECONDARY_AIR_SYSTEM_AVAILABLE)
543                     .withIncompleteBitmask(SECONDARY_AIR_SYSTEM_INCOMPLETE);
544 
545             static final IgnitionMonitor.Builder EVAPORATIVE_SYSTEM_BUILDER =
546                 new IgnitionMonitor.Builder()
547                     .withAvailableBitmask(EVAPORATIVE_SYSTEM_AVAILABLE)
548                     .withIncompleteBitmask(EVAPORATIVE_SYSTEM_INCOMPLETE);
549 
550             static final IgnitionMonitor.Builder HEATED_CATALYST_BUILDER =
551                 new IgnitionMonitor.Builder()
552                     .withAvailableBitmask(HEATED_CATALYST_AVAILABLE)
553                     .withIncompleteBitmask(HEATED_CATALYST_INCOMPLETE);
554 
555             static final IgnitionMonitor.Builder CATALYST_BUILDER =
556                 new IgnitionMonitor.Builder()
557                     .withAvailableBitmask(CATALYST_AVAILABLE)
558                     .withIncompleteBitmask(CATALYST_INCOMPLETE);
559 
SparkIgnitionMonitors(int bitmask)560             SparkIgnitionMonitors(int bitmask) {
561                 super(bitmask);
562                 EGR = EGR_BUILDER.buildForValue(bitmask);
563                 oxygenSensorHeater = OXYGEN_SENSOR_HEATER_BUILDER.buildForValue(bitmask);
564                 oxygenSensor = OXYGEN_SENSOR_BUILDER.buildForValue(bitmask);
565                 ACRefrigerant = AC_REFRIGERANT_BUILDER.buildForValue(bitmask);
566                 secondaryAirSystem = SECONDARY_AIR_SYSTEM_BUILDER.buildForValue(bitmask);
567                 evaporativeSystem = EVAPORATIVE_SYSTEM_BUILDER.buildForValue(bitmask);
568                 heatedCatalyst = HEATED_CATALYST_BUILDER.buildForValue(bitmask);
569                 catalyst = CATALYST_BUILDER.buildForValue(bitmask);
570             }
571         }
572 
573         public static final class CompressionIgnitionMonitors extends CommonIgnitionMonitors {
574             public final IgnitionMonitor EGROrVVT;
575             public final IgnitionMonitor PMFilter;
576             public final IgnitionMonitor exhaustGasSensor;
577             public final IgnitionMonitor boostPressure;
578             public final IgnitionMonitor NOxSCR;
579             public final IgnitionMonitor NMHCCatalyst;
580 
581             static final int EGR_OR_VVT_AVAILABLE = 0x1 << 6;
582             static final int EGR_OR_VVT_INCOMPLETE = 0x1 << 7;
583 
584             static final int PM_FILTER_AVAILABLE = 0x1 << 8;
585             static final int PM_FILTER_INCOMPLETE = 0x1 << 9;
586 
587             static final int EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10;
588             static final int EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11;
589 
590             static final int BOOST_PRESSURE_AVAILABLE = 0x1 << 12;
591             static final int BOOST_PRESSURE_INCOMPLETE = 0x1 << 13;
592 
593             static final int NOx_SCR_AVAILABLE = 0x1 << 14;
594             static final int NOx_SCR_INCOMPLETE = 0x1 << 15;
595 
596             static final int NMHC_CATALYST_AVAILABLE = 0x1 << 16;
597             static final int NMHC_CATALYST_INCOMPLETE = 0x1 << 17;
598 
599             static final IgnitionMonitor.Builder EGR_OR_VVT_BUILDER =
600                 new IgnitionMonitor.Builder()
601                     .withAvailableBitmask(EGR_OR_VVT_AVAILABLE)
602                     .withIncompleteBitmask(EGR_OR_VVT_INCOMPLETE);
603 
604             static final IgnitionMonitor.Builder PM_FILTER_BUILDER =
605                 new IgnitionMonitor.Builder()
606                     .withAvailableBitmask(PM_FILTER_AVAILABLE)
607                     .withIncompleteBitmask(PM_FILTER_INCOMPLETE);
608 
609             static final IgnitionMonitor.Builder EXHAUST_GAS_SENSOR_BUILDER =
610                 new IgnitionMonitor.Builder()
611                     .withAvailableBitmask(EXHAUST_GAS_SENSOR_AVAILABLE)
612                     .withIncompleteBitmask(EXHAUST_GAS_SENSOR_INCOMPLETE);
613 
614             static final IgnitionMonitor.Builder BOOST_PRESSURE_BUILDER =
615                 new IgnitionMonitor.Builder()
616                     .withAvailableBitmask(BOOST_PRESSURE_AVAILABLE)
617                     .withIncompleteBitmask(BOOST_PRESSURE_INCOMPLETE);
618 
619             static final IgnitionMonitor.Builder NOx_SCR_BUILDER =
620                 new IgnitionMonitor.Builder()
621                     .withAvailableBitmask(NOx_SCR_AVAILABLE)
622                     .withIncompleteBitmask(NOx_SCR_INCOMPLETE);
623 
624             static final IgnitionMonitor.Builder NMHC_CATALYST_BUILDER =
625                 new IgnitionMonitor.Builder()
626                     .withAvailableBitmask(NMHC_CATALYST_AVAILABLE)
627                     .withIncompleteBitmask(NMHC_CATALYST_INCOMPLETE);
628 
CompressionIgnitionMonitors(int bitmask)629             CompressionIgnitionMonitors(int bitmask) {
630                 super(bitmask);
631                 EGROrVVT = EGR_OR_VVT_BUILDER.buildForValue(bitmask);
632                 PMFilter = PM_FILTER_BUILDER.buildForValue(bitmask);
633                 exhaustGasSensor = EXHAUST_GAS_SENSOR_BUILDER.buildForValue(bitmask);
634                 boostPressure = BOOST_PRESSURE_BUILDER.buildForValue(bitmask);
635                 NOxSCR = NOx_SCR_BUILDER.buildForValue(bitmask);
636                 NMHCCatalyst = NMHC_CATALYST_BUILDER.buildForValue(bitmask);
637             }
638         }
639     }
640 
getFuelSystemStatus()641     public @Nullable @FuelSystemStatus.Status Integer getFuelSystemStatus() {
642         return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_SYSTEM_STATUS);
643     }
644 
getSecondaryAirStatus()645     public @Nullable @SecondaryAirStatus.Status Integer getSecondaryAirStatus() {
646         return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS);
647     }
648 
getIgnitionMonitors()649     public @Nullable IgnitionMonitors.CommonIgnitionMonitors getIgnitionMonitors() {
650         Integer ignitionMonitorsType = getSystemIntegerSensor(
651             CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.IGNITION_MONITORS_SUPPORTED);
652         Integer ignitionMonitorsBitmask = getSystemIntegerSensor(
653             CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.IGNITION_SPECIFIC_MONITORS);
654         if (null == ignitionMonitorsType) return null;
655         if (null == ignitionMonitorsBitmask) return null;
656         switch (ignitionMonitorsType) {
657             case 0: return new IgnitionMonitors.SparkIgnitionMonitors(
658                     ignitionMonitorsBitmask);
659             case 1: return new IgnitionMonitors.CompressionIgnitionMonitors(
660                     ignitionMonitorsBitmask);
661             default: return null;
662         }
663     }
664 
getFuelType()665     public @Nullable @FuelType.Type Integer getFuelType() {
666         return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_TYPE);
667     }
668 }
669