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 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 86 public int describeContents() { 87 return 0; 88 } 89 90 @Override 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 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 140 private Builder(int type) { 141 mType = type; 142 } 143 144 public static Builder newLiveFrameBuilder() { 145 return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE); 146 } 147 148 public static Builder newFreezeFrameBuilder() { 149 return new Builder(CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE); 150 } 151 152 public Builder atTimestamp(long timestamp) { 153 mTimestamp = timestamp; 154 return this; 155 } 156 157 public Builder withIntValue(int key, int value) { 158 mIntValues.put(key, value); 159 return this; 160 } 161 162 public Builder withFloatValue(int key, float value) { 163 mFloatValues.put(key, value); 164 return this; 165 } 166 167 public Builder withDTC(String dtc) { 168 mDtc = dtc; 169 return this; 170 } 171 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 */ 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 199 public boolean isLiveFrame() { 200 return CarDiagnosticManager.FRAME_TYPE_FLAG_LIVE == frameType; 201 } 202 203 public boolean isFreezeFrame() { 204 return CarDiagnosticManager.FRAME_TYPE_FLAG_FREEZE == frameType; 205 } 206 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 */ 215 public CarDiagnosticEvent checkLiveFrame() { 216 if (!isLiveFrame()) throw new IllegalStateException("frame is not a live frame"); 217 return this; 218 } 219 220 /** @hide */ 221 public CarDiagnosticEvent checkFreezeFrame() { 222 if (!isFreezeFrame()) throw new IllegalStateException("frame is not a freeze frame"); 223 return this; 224 } 225 226 /** @hide */ 227 public boolean isEarlierThan(CarDiagnosticEvent otherEvent) { 228 otherEvent = Objects.requireNonNull(otherEvent); 229 return (timestamp < otherEvent.timestamp); 230 } 231 232 @Override 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 247 public int getSystemIntegerSensor(@CarDiagnosticSensorIndices.IntegerSensorIndex int sensor, int defaultValue) { 248 return intValues.get(sensor, defaultValue); 249 } 250 251 public float getSystemFloatSensor(@CarDiagnosticSensorIndices.FloatSensorIndex int sensor, float defaultValue) { 252 return floatValues.get(sensor, defaultValue); 253 } 254 255 public int getVendorIntegerSensor(int sensor, int defaultValue) { 256 return intValues.get(sensor, defaultValue); 257 } 258 259 public float getVendorFloatSensor(int sensor, float defaultValue) { 260 return floatValues.get(sensor, defaultValue); 261 } 262 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 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 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 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 { 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 { 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 { 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 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 414 Builder() { 415 mAvailableBitmask = 0; 416 mIncompleteBitmask = 0; 417 } 418 419 public Builder withAvailableBitmask(int bitmask) { 420 mAvailableBitmask = bitmask; 421 return this; 422 } 423 424 public Builder withIncompleteBitmask(int bitmask) { 425 mIncompleteBitmask = bitmask; 426 return this; 427 } 428 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 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 473 public @Nullable SparkIgnitionMonitors asSparkIgnitionMonitors() { 474 if (this instanceof SparkIgnitionMonitors) 475 return (SparkIgnitionMonitors)this; 476 return null; 477 } 478 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 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 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 641 public @Nullable @FuelSystemStatus.Status Integer getFuelSystemStatus() { 642 return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_SYSTEM_STATUS); 643 } 644 645 public @Nullable @SecondaryAirStatus.Status Integer getSecondaryAirStatus() { 646 return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.COMMANDED_SECONDARY_AIR_STATUS); 647 } 648 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 665 public @Nullable @FuelType.Type Integer getFuelType() { 666 return getSystemIntegerSensor(CarDiagnosticSensorIndices.Obd2IntegerSensorIndex.FUEL_TYPE); 667 } 668 } 669