1 /* 2 * Copyright (C) 2015 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.os.Parcel; 20 import android.os.Parcelable; 21 22 /** 23 * A CarSensorEvent object corresponds to a single sensor event coming from the car. The sensor 24 * data is stored in a sensor-type specific format in the object's float and byte arrays. 25 * 26 * To aid unmarshalling the object's data arrays, this class provides static nested classes and 27 * conversion methods, for example {@link EnvironmentData} and {@link #getEnvironmentData}. The 28 * conversion methods each have an optional data parameter which, if not null, will be used and 29 * returned. This parameter should be used to avoid unnecessary object churn whenever possible. 30 * Additionally, calling a conversion method on a CarSensorEvent object with an inappropriate type 31 * will result in an {@code UnsupportedOperationException} being thrown. 32 */ 33 public class CarSensorEvent implements Parcelable { 34 35 /** 36 * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 37 * sensor. This value is fuel level in percentile. 38 */ 39 public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; 40 /** 41 * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 42 * sensor. This value is fuel level in coverable distance. The unit is Km. 43 */ 44 public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; 45 /** 46 * Index in {@link #intValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 47 * sensor. This value is set to 1 if fuel low level warning is on. 48 */ 49 public static final int INDEX_FUEL_LOW_WARNING = 0; 50 51 /** 52 * GEAR_* represents meaning of intValues[0] for {@link CarSensorManager#SENSOR_TYPE_GEAR} 53 * sensor type. 54 * GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving. 55 */ 56 public static final int GEAR_NEUTRAL = 0; 57 /** 58 * intValues[0] from 1 to 99 represents transmission gear number for moving forward. 59 * GEAR_FIRST is for gear number 1. 60 */ 61 public static final int GEAR_FIRST = 1; 62 /** Gear number 2. */ 63 public static final int GEAR_SECOND = 2; 64 /** Gear number 3. */ 65 public static final int GEAR_THIRD = 3; 66 /** Gear number 4. */ 67 public static final int GEAR_FOURTH = 4; 68 /** Gear number 5. */ 69 public static final int GEAR_FIFTH = 5; 70 /** Gear number 6. */ 71 public static final int GEAR_SIXTH = 6; 72 /** Gear number 7. */ 73 public static final int GEAR_SEVENTH = 7; 74 /** Gear number 8. */ 75 public static final int GEAR_EIGHTH = 8; 76 /** Gear number 9. */ 77 public static final int GEAR_NINTH = 9; 78 /** Gear number 10. */ 79 public static final int GEAR_TENTH = 10; 80 /** 81 * This is for transmission without specific gear number for moving forward like CVT. It tells 82 * that car is in a transmission state to move it forward. 83 */ 84 public static final int GEAR_DRIVE = 100; 85 /** Gear in parking state */ 86 public static final int GEAR_PARK = 101; 87 /** Gear in reverse */ 88 public static final int GEAR_REVERSE = 102; 89 90 /** 91 * Ignition state is unknown. 92 * 93 * The constants that starts with IGNITION_STATE_ represent values for 94 * {@link CarSensorManager#SENSOR_TYPE_IGNITION_STATE} sensor. 95 * */ 96 public static final int IGNITION_STATE_UNDEFINED = 0; 97 /** 98 * Steering wheel is locked. 99 */ 100 public static final int IGNITION_STATE_LOCK = 1; 101 /** Typically engine is off, but steering wheel is unlocked. */ 102 public static final int IGNITION_STATE_OFF = 2; 103 /** Accessory is turned off, but engine is not running yet (for EV car is not ready to move). */ 104 public static final int IGNITION_STATE_ACC = 3; 105 /** In this state engine typically is running (for EV, car is ready to move). */ 106 public static final int IGNITION_STATE_ON = 4; 107 /** In this state engine is typically starting (cranking). */ 108 public static final int IGNITION_STATE_START = 5; 109 110 /** 111 * Bitmask of driving restrictions. 112 */ 113 /** No restrictions. */ 114 public static final int DRIVE_STATUS_UNRESTRICTED = 0; 115 /** No video playback allowed. */ 116 public static final int DRIVE_STATUS_NO_VIDEO = 0x1; 117 /** No keyboard or rotary controller input allowed. */ 118 public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 0x2; 119 /** No voice input allowed. */ 120 public static final int DRIVE_STATUS_NO_VOICE_INPUT = 0x4; 121 /** No setup / configuration allowed. */ 122 public static final int DRIVE_STATUS_NO_CONFIG = 0x8; 123 /** Limit displayed message length. */ 124 public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 0x10; 125 /** represents case where all of the above items are restricted */ 126 public static final int DRIVE_STATUS_FULLY_RESTRICTED = DRIVE_STATUS_NO_VIDEO | 127 DRIVE_STATUS_NO_KEYBOARD_INPUT | DRIVE_STATUS_NO_VOICE_INPUT | DRIVE_STATUS_NO_CONFIG | 128 DRIVE_STATUS_LIMIT_MESSAGE_LEN; 129 130 /** 131 * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues. 132 * Temperature in Celsius degrees. 133 */ 134 public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; 135 /** 136 * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues. 137 * Pressure in kPa. 138 */ 139 public static final int INDEX_ENVIRONMENT_PRESSURE = 1; 140 141 private static final long MILLI_IN_NANOS = 1000000L; 142 143 /** Sensor type for this event like {@link CarSensorManager#SENSOR_TYPE_CAR_SPEED}. */ 144 public int sensorType; 145 146 /** 147 * When this data was acquired in car or received from car. It is elapsed real-time of data 148 * reception from car in nanoseconds since system boot. 149 */ 150 public long timestamp; 151 /** 152 * array holding float type of sensor data. If the sensor has single value, only floatValues[0] 153 * should be used. */ 154 public final float[] floatValues; 155 /** array holding int type of sensor data */ 156 public final int[] intValues; 157 158 /** @hide */ CarSensorEvent(Parcel in)159 public CarSensorEvent(Parcel in) { 160 sensorType = in.readInt(); 161 timestamp = in.readLong(); 162 int len = in.readInt(); 163 floatValues = new float[len]; 164 in.readFloatArray(floatValues); 165 len = in.readInt(); 166 intValues = new int[len]; 167 in.readIntArray(intValues); 168 // version 1 up to here 169 } 170 171 @Override describeContents()172 public int describeContents() { 173 return 0; 174 } 175 176 @Override writeToParcel(Parcel dest, int flags)177 public void writeToParcel(Parcel dest, int flags) { 178 dest.writeInt(sensorType); 179 dest.writeLong(timestamp); 180 dest.writeInt(floatValues.length); 181 dest.writeFloatArray(floatValues); 182 dest.writeInt(intValues.length); 183 dest.writeIntArray(intValues); 184 } 185 186 public static final Parcelable.Creator<CarSensorEvent> CREATOR 187 = new Parcelable.Creator<CarSensorEvent>() { 188 public CarSensorEvent createFromParcel(Parcel in) { 189 return new CarSensorEvent(in); 190 } 191 192 public CarSensorEvent[] newArray(int size) { 193 return new CarSensorEvent[size]; 194 } 195 }; 196 197 /** @hide */ CarSensorEvent(int sensorType, long timestamp, int floatValueSize, int intValueSize)198 public CarSensorEvent(int sensorType, long timestamp, int floatValueSize, int intValueSize) { 199 this.sensorType = sensorType; 200 this.timestamp = timestamp; 201 floatValues = new float[floatValueSize]; 202 intValues = new int[intValueSize]; 203 } 204 205 /** @hide */ CarSensorEvent(int sensorType, long timestamp, float[] floatValues, int[] intValues)206 CarSensorEvent(int sensorType, long timestamp, float[] floatValues, int[] intValues) { 207 this.sensorType = sensorType; 208 this.timestamp = timestamp; 209 this.floatValues = floatValues; 210 this.intValues = intValues; 211 } 212 checkType(int type)213 private void checkType(int type) { 214 if (sensorType == type) { 215 return; 216 } 217 throw new UnsupportedOperationException(String.format( 218 "Invalid sensor type: expected %d, got %d", type, sensorType)); 219 } 220 221 public static class EnvironmentData { 222 public long timestamp; 223 /** If unsupported by the car, this value is NaN. */ 224 public float temperature; 225 /** If unsupported by the car, this value is NaN. */ 226 public float pressure; 227 228 /** @hide */ EnvironmentData()229 private EnvironmentData() {}; 230 } 231 232 /** 233 * Convenience method for obtaining an {@link EnvironmentData} object from a CarSensorEvent 234 * object with type {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT}. 235 * 236 * @param data an optional output parameter which, if non-null, will be used by this method 237 * instead of a newly created object. 238 * @return an EnvironmentData object corresponding to the data contained in the CarSensorEvent. 239 * @hide 240 */ getEnvironmentData(EnvironmentData data)241 public EnvironmentData getEnvironmentData(EnvironmentData data) { 242 checkType(CarSensorManager.SENSOR_TYPE_ENVIRONMENT); 243 if (data == null) { 244 data = new EnvironmentData(); 245 } 246 data.timestamp = timestamp; 247 data.temperature = floatValues[INDEX_ENVIRONMENT_TEMPERATURE]; 248 data.pressure = floatValues[INDEX_ENVIRONMENT_PRESSURE]; 249 return data; 250 } 251 252 /** @hide */ 253 public static class NightData { 254 public long timestamp; 255 public boolean isNightMode; 256 257 /** @hide */ NightData()258 private NightData() {}; 259 } 260 261 /** 262 * Convenience method for obtaining a {@link NightData} object from a CarSensorEvent 263 * object with type {@link CarSensorManager#SENSOR_TYPE_NIGHT}. 264 * 265 * @param data an optional output parameter which, if non-null, will be used by this method 266 * instead of a newly created object. 267 * @return a NightData object corresponding to the data contained in the CarSensorEvent. 268 * @hide 269 */ getNightData(NightData data)270 public NightData getNightData(NightData data) { 271 checkType(CarSensorManager.SENSOR_TYPE_NIGHT); 272 if (data == null) { 273 data = new NightData(); 274 } 275 data.timestamp = timestamp; 276 data.isNightMode = intValues[0] == 1; 277 return data; 278 } 279 280 /** @hide */ 281 public static class GearData { 282 public long timestamp; 283 public int gear; 284 285 /** @hide */ GearData()286 private GearData() {}; 287 } 288 289 /** 290 * Convenience method for obtaining a {@link GearData} object from a CarSensorEvent 291 * object with type {@link CarSensorManager#SENSOR_TYPE_GEAR}. 292 * 293 * @param data an optional output parameter which, if non-null, will be used by this method 294 * instead of a newly created object. 295 * @return a GearData object corresponding to the data contained in the CarSensorEvent. 296 * @hide 297 */ getGearData(GearData data)298 public GearData getGearData(GearData data) { 299 checkType(CarSensorManager.SENSOR_TYPE_GEAR); 300 if (data == null) { 301 data = new GearData(); 302 } 303 data.timestamp = timestamp; 304 data.gear = intValues[0]; 305 return data; 306 } 307 308 /** @hide */ 309 public static class ParkingBrakeData { 310 public long timestamp; 311 public boolean isEngaged; 312 313 /** @hide */ ParkingBrakeData()314 private ParkingBrakeData() {} 315 } 316 317 /** 318 * Convenience method for obtaining a {@link ParkingBrakeData} object from a CarSensorEvent 319 * object with type {@link CarSensorManager#SENSOR_TYPE_PARKING_BRAKE}. 320 * 321 * @param data an optional output parameter which, if non-null, will be used by this method 322 * instead of a newly created object. 323 * @return a ParkingBreakData object corresponding to the data contained in the CarSensorEvent. 324 * @hide 325 */ getParkingBrakeData(ParkingBrakeData data)326 public ParkingBrakeData getParkingBrakeData(ParkingBrakeData data) { 327 checkType(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE); 328 if (data == null) { 329 data = new ParkingBrakeData(); 330 } 331 data.timestamp = timestamp; 332 data.isEngaged = intValues[0] == 1; 333 return data; 334 } 335 336 /** @hide */ 337 public static class FuelLevelData { 338 public long timestamp; 339 /** Fuel level in %. If unsupported by the car, this value is -1. */ 340 public int level; 341 /** Fuel as possible range in Km. If unsupported by the car, this value is -1. */ 342 public float range; 343 /** If unsupported by the car, this value is false. */ 344 public boolean lowFuelWarning; 345 346 /** @hide */ FuelLevelData()347 private FuelLevelData() {}; 348 } 349 350 /** 351 * Convenience method for obtaining a {@link FuelLevelData} object from a CarSensorEvent 352 * object with type {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL}. 353 * 354 * @param data an optional output parameter which, if non-null, will be used by this method 355 * instead of a newly created object. 356 * @return a FuelLevel object corresponding to the data contained in the CarSensorEvent. 357 * @hide 358 */ getFuelLevelData(FuelLevelData data)359 public FuelLevelData getFuelLevelData(FuelLevelData data) { 360 checkType(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL); 361 if (data == null) { 362 data = new FuelLevelData(); 363 } 364 data.timestamp = timestamp; 365 if (floatValues == null) { 366 data.level = -1; 367 data.range = -1; 368 } else { 369 if (floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE] < 0) { 370 data.level = -1; 371 } else { 372 data.level = (int) floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE]; 373 } 374 if (floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE] < 0) { 375 data.range = -1; 376 } else { 377 data.range = floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE]; 378 } 379 } 380 data.lowFuelWarning = intValues[0] == 1; 381 return data; 382 } 383 384 /** @hide */ 385 public static class OdometerData { 386 public long timestamp; 387 public float kms; 388 389 /** @hide */ OdometerData()390 private OdometerData() {}; 391 } 392 393 /** 394 * Convenience method for obtaining an {@link OdometerData} object from a CarSensorEvent 395 * object with type {@link CarSensorManager#SENSOR_TYPE_ODOMETER}. 396 * 397 * @param data an optional output parameter which, if non-null, will be used by this method 398 * instead of a newly created object. 399 * @return an OdometerData object corresponding to the data contained in the CarSensorEvent. 400 * @hide 401 */ getOdometerData(OdometerData data)402 public OdometerData getOdometerData(OdometerData data) { 403 checkType(CarSensorManager.SENSOR_TYPE_ODOMETER); 404 if (data == null) { 405 data = new OdometerData(); 406 } 407 data.timestamp = timestamp; 408 data.kms = floatValues[0]; 409 return data; 410 } 411 412 /** @hide */ 413 public static class RpmData { 414 public long timestamp; 415 public float rpm; 416 417 /** @hide */ RpmData()418 private RpmData() {}; 419 } 420 421 /** 422 * Convenience method for obtaining a {@link RpmData} object from a CarSensorEvent 423 * object with type {@link CarSensorManager#SENSOR_TYPE_RPM}. 424 * 425 * @param data an optional output parameter which, if non-null, will be used by this method 426 * instead of a newly created object. 427 * @return a RpmData object corresponding to the data contained in the CarSensorEvent. 428 * @hide 429 */ getRpmData(RpmData data)430 public RpmData getRpmData(RpmData data) { 431 checkType(CarSensorManager.SENSOR_TYPE_RPM); 432 if (data == null) { 433 data = new RpmData(); 434 } 435 data.timestamp = timestamp; 436 data.rpm = floatValues[0]; 437 return data; 438 } 439 440 /** @hide */ 441 public static class CarSpeedData { 442 public long timestamp; 443 public float carSpeed; 444 445 /** @hide */ CarSpeedData()446 private CarSpeedData() {}; 447 } 448 449 /** 450 * Convenience method for obtaining a {@link CarSpeedData} object from a CarSensorEvent 451 * object with type {@link CarSensorManager#SENSOR_TYPE_CAR_SPEED}. 452 * 453 * @param data an optional output parameter which, if non-null, will be used by this method 454 * instead of a newly created object. 455 * @return a CarSpeedData object corresponding to the data contained in the CarSensorEvent. 456 * @hide 457 */ getCarSpeedData(CarSpeedData data)458 public CarSpeedData getCarSpeedData(CarSpeedData data) { 459 checkType(CarSensorManager.SENSOR_TYPE_CAR_SPEED); 460 if (data == null) { 461 data = new CarSpeedData(); 462 } 463 data.timestamp = timestamp; 464 data.carSpeed = floatValues[0]; 465 return data; 466 } 467 468 /** @hide */ 469 public static class DrivingStatusData { 470 public long timestamp; 471 public int status; 472 473 /** @hide */ DrivingStatusData()474 private DrivingStatusData() {}; 475 } 476 477 /** 478 * Convenience method for obtaining a {@link DrivingStatusData} object from a CarSensorEvent 479 * object with type {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}. 480 * 481 * @param data an optional output parameter which, if non-null, will be used by this method 482 * instead of a newly created object. 483 * @return a DrivingStatusData object corresponding to the data contained in the CarSensorEvent. 484 * @hide 485 */ getDrivingStatusData(DrivingStatusData data)486 public DrivingStatusData getDrivingStatusData(DrivingStatusData data) { 487 checkType(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS); 488 if (data == null) { 489 data = new DrivingStatusData(); 490 } 491 data.status = intValues[0]; 492 return data; 493 } 494 495 /** @hide */ 496 @Override toString()497 public String toString() { 498 StringBuilder sb = new StringBuilder(); 499 sb.append(getClass().getName() + "["); 500 sb.append("type:" + Integer.toHexString(sensorType)); 501 if (floatValues != null && floatValues.length > 0) { 502 sb.append(" float values:"); 503 for (float v: floatValues) { 504 sb.append(" " + v); 505 } 506 } 507 if (intValues != null && intValues.length > 0) { 508 sb.append(" int values:"); 509 for (int v: intValues) { 510 sb.append(" " + v); 511 } 512 } 513 sb.append("]"); 514 return sb.toString(); 515 } 516 } 517