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