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 17package android.support.car.hardware; 18 19import android.location.GpsSatellite; 20import android.location.Location; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.os.SystemClock; 24import android.support.car.annotation.VersionDef; 25import android.support.car.os.ExtendableParcelable; 26 27 28/** 29 * A CarSensorEvent object corresponds to a single sensor event coming from the car. The sensor 30 * data is stored in a sensor-type specific format in the object's float and byte arrays. 31 * 32 * To aid unmarshalling the object's data arrays, this class provides static nested classes and 33 * conversion methods, for example {@link EnvironmentData} and {@link #getEnvironmentData}. The 34 * conversion methods each have an optional data parameter which, if not null, will be used and 35 * returned. This parameter should be used to avoid unnecessary object churn whenever possible. 36 * Additionally, calling a conversion method on a CarSensorEvent object with an inappropriate type 37 * will result in an {@code UnsupportedOperationException} being thrown. 38 */ 39public class CarSensorEvent extends ExtendableParcelable { 40 41 private static final int VERSION = 1; 42 43 /** 44 * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 45 * sensor. This value is fuel level in percentile. 46 */ 47 public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0; 48 /** 49 * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 50 * sensor. This value is fuel level in coverable distance. The unit is Km. 51 */ 52 public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1; 53 /** 54 * Index in {@link #intValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of 55 * sensor. This value is set to 1 if fuel low level warning is on. 56 */ 57 public static final int INDEX_FUEL_LOW_WARNING = 0; 58 59 /** 60 * GEAR_* represents meaning of intValues[0] for {@link CarSensorManager#SENSOR_TYPE_GEAR} 61 * sensor type. 62 * GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving. 63 */ 64 public static final int GEAR_NEUTRAL = 0; 65 /** 66 * intValues[0] from 1 to 99 represents transmission gear number for moving forward. 67 * GEAR_FIRST is for gear number 1. 68 */ 69 public static final int GEAR_FIRST = 1; 70 /** Gear number 2. */ 71 public static final int GEAR_SECOND = 2; 72 /** Gear number 3. */ 73 public static final int GEAR_THIRD = 3; 74 /** Gear number 4. */ 75 public static final int GEAR_FOURTH = 4; 76 /** Gear number 5. */ 77 public static final int GEAR_FIFTH = 5; 78 /** Gear number 6. */ 79 public static final int GEAR_SIXTH = 6; 80 /** Gear number 7. */ 81 public static final int GEAR_SEVENTH = 7; 82 /** Gear number 8. */ 83 public static final int GEAR_EIGHTH = 8; 84 /** Gear number 9. */ 85 public static final int GEAR_NINTH = 9; 86 /** Gear number 10. */ 87 public static final int GEAR_TENTH = 10; 88 /** 89 * This is for transmission without specific gear number for moving forward like CVT. It tells 90 * that car is in a transmission state to move it forward. 91 */ 92 public static final int GEAR_DRIVE = 100; 93 /** Gear in parking state */ 94 public static final int GEAR_PARK = 101; 95 /** Gear in reverse */ 96 public static final int GEAR_REVERSE = 102; 97 98 /** 99 * Bitmask of driving restrictions. 100 */ 101 /** No restrictions. */ 102 public static final int DRIVE_STATUS_UNRESTRICTED = 0; 103 /** No video playback allowed. */ 104 public static final int DRIVE_STATUS_NO_VIDEO = 0x1; 105 /** No keyboard or rotary controller input allowed. */ 106 public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 0x2; 107 /** No voice input allowed. */ 108 public static final int DRIVE_STATUS_NO_VOICE_INPUT = 0x4; 109 /** No setup / configuration allowed. */ 110 public static final int DRIVE_STATUS_NO_CONFIG = 0x8; 111 /** Limit displayed message length. */ 112 public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 0x10; 113 /** represents case where all of the above items are restricted */ 114 public static final int DRIVE_STATUS_FULLY_RESTRICTED = DRIVE_STATUS_NO_VIDEO | 115 DRIVE_STATUS_NO_KEYBOARD_INPUT | DRIVE_STATUS_NO_VOICE_INPUT | DRIVE_STATUS_NO_CONFIG | 116 DRIVE_STATUS_LIMIT_MESSAGE_LEN; 117 /** 118 * Index for {@link CarSensorManager#SENSOR_TYPE_LOCATION} in floatValues. 119 * Each bit intValues[0] represents whether the corresponding data is present. 120 */ 121 public static final int INDEX_LOCATION_LATITUDE = 0; 122 public static final int INDEX_LOCATION_LONGITUDE = 1; 123 public static final int INDEX_LOCATION_ACCURACY = 2; 124 public static final int INDEX_LOCATION_ALTITUDE = 3; 125 public static final int INDEX_LOCATION_SPEED = 4; 126 public static final int INDEX_LOCATION_BEARING = 5; 127 public static final int INDEX_LOCATION_MAX = INDEX_LOCATION_BEARING; 128 public static final int INDEX_LOCATION_LATITUDE_INTS = 1; 129 public static final int INDEX_LOCATION_LONGITUDE_INTS = 2; 130 131 /** 132 * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues. 133 * Temperature in Celsius degrees. 134 */ 135 public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0; 136 /** 137 * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues. 138 * Pressure in kPa. 139 */ 140 public static final int INDEX_ENVIRONMENT_PRESSURE = 1; 141 142 /** 143 * Indices for {@link CarSensorManager#SENSOR_TYPE_COMPASS} in floatValues. 144 * Angles are in degrees. Pitch or/and roll can be NaN if it is not available. 145 */ 146 public static final int INDEX_COMPASS_BEARING = 0; 147 public static final int INDEX_COMPASS_PITCH = 1; 148 public static final int INDEX_COMPASS_ROLL = 2; 149 150 /** 151 * Indices for {@link CarSensorManager#SENSOR_TYPE_ACCELEROMETER} in floatValues. 152 * Acceleration (gravity) is in m/s^2. Any component can be NaN if it is not available. 153 */ 154 public static final int INDEX_ACCELEROMETER_X = 0; 155 public static final int INDEX_ACCELEROMETER_Y = 1; 156 public static final int INDEX_ACCELEROMETER_Z = 2; 157 158 /** 159 * Indices for {@link CarSensorManager#SENSOR_TYPE_GYROSCOPE} in floatValues. 160 * Rotation speed is in rad/s. Any component can be NaN if it is not available. 161 */ 162 public static final int INDEX_GYROSCOPE_X = 0; 163 public static final int INDEX_GYROSCOPE_Y = 1; 164 public static final int INDEX_GYROSCOPE_Z = 2; 165 166 /** 167 * Indices for {@link CarSensorManager#SENSOR_TYPE_GPS_SATELLITE}. 168 * Both byte values and float values are used. 169 * Two first bytes encode number of satellites in-use/in-view (or 0xFF if unavailable). 170 * Then optionally with INDEX_GPS_SATELLITE_ARRAY_BYTE_OFFSET offset and interval 171 * INDEX_GPS_SATELLITE_ARRAY_BYTE_INTERVAL between elements are encoded boolean flags of whether 172 * particular satellite from in-view participate in in-use subset. 173 * Float values with INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET offset and interval 174 * INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL between elements can optionally contain 175 * per-satellite values of signal strength and other values or NaN if unavailable. 176 */ 177 public static final int INDEX_GPS_SATELLITE_NUMBER_IN_USE = 0; 178 public static final int INDEX_GPS_SATELLITE_NUMBER_IN_VIEW = 1; 179 public static final int INDEX_GPS_SATELLITE_ARRAY_INT_OFFSET = 2; 180 public static final int INDEX_GPS_SATELLITE_ARRAY_INT_INTERVAL = 1; 181 public static final int INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET = 0; 182 public static final int INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL = 4; 183 public static final int INDEX_GPS_SATELLITE_PRN_OFFSET = 0; 184 public static final int INDEX_GPS_SATELLITE_SNR_OFFSET = 1; 185 public static final int INDEX_GPS_SATELLITE_AZIMUTH_OFFSET = 2; 186 public static final int INDEX_GPS_SATELLITE_ELEVATION_OFFSET = 3; 187 188 private static final long MILLI_IN_NANOS = 1000000L; 189 190 /** Sensor type for this event like {@link CarSensorManager#SENSOR_TYPE_CAR_SPEED}. */ 191 @VersionDef(version = 1) 192 public int sensorType; 193 194 /** 195 * When this data was acquired in car or received from car. It is elapsed real-time of data 196 * reception from car in nanoseconds since system boot. 197 */ 198 @VersionDef(version = 1) 199 public long timeStampNs; 200 /** 201 * array holding float type of sensor data. If the sensor has single value, only floatValues[0] 202 * should be used. */ 203 @VersionDef(version = 1) 204 public final float[] floatValues; 205 /** array holding int type of sensor data */ 206 @VersionDef(version = 1) 207 public final int[] intValues; 208 209 public CarSensorEvent(Parcel in) { 210 super(in, VERSION); 211 int lastPosition = readHeader(in); 212 sensorType = in.readInt(); 213 timeStampNs = in.readLong(); 214 int len = in.readInt(); 215 floatValues = new float[len]; 216 in.readFloatArray(floatValues); 217 len = in.readInt(); 218 intValues = new int[len]; 219 in.readIntArray(intValues); 220 // version 1 up to here 221 completeReading(in, lastPosition); 222 } 223 224 @Override 225 public int describeContents() { 226 return 0; 227 } 228 229 @Override 230 public void writeToParcel(Parcel dest, int flags) { 231 int startingPosition = writeHeader(dest); 232 dest.writeInt(sensorType); 233 dest.writeLong(timeStampNs); 234 dest.writeInt(floatValues.length); 235 dest.writeFloatArray(floatValues); 236 dest.writeInt(intValues.length); 237 dest.writeIntArray(intValues); 238 // version 1 up to here 239 completeWriting(dest, startingPosition); 240 } 241 242 public static final Parcelable.Creator<CarSensorEvent> CREATOR 243 = new Parcelable.Creator<CarSensorEvent>() { 244 public CarSensorEvent createFromParcel(Parcel in) { 245 return new CarSensorEvent(in); 246 } 247 248 public CarSensorEvent[] newArray(int size) { 249 return new CarSensorEvent[size]; 250 } 251 }; 252 253 public CarSensorEvent(int sensorType, long timeStampNs, int floatValueSize, int intValueSize) { 254 super(VERSION); 255 this.sensorType = sensorType; 256 this.timeStampNs = timeStampNs; 257 floatValues = new float[floatValueSize]; 258 intValues = new int[intValueSize]; 259 } 260 261 /** @hide */ 262 CarSensorEvent(int sensorType, long timeStampNs, float[] floatValues, int[] intValues) { 263 super(VERSION); 264 this.sensorType = sensorType; 265 this.timeStampNs = timeStampNs; 266 this.floatValues = floatValues; 267 this.intValues = intValues; 268 } 269 270 private void checkType(int type) { 271 if (sensorType == type) { 272 return; 273 } 274 throw new UnsupportedOperationException(String.format( 275 "Invalid sensor type: expected %d, got %d", type, sensorType)); 276 } 277 278 public static class EnvironmentData { 279 public long timeStampNs; 280 /** If unsupported by the car, this value is NaN. */ 281 public float temperature; 282 /** If unsupported by the car, this value is NaN. */ 283 public float pressure; 284 } 285 286 /** 287 * Convenience method for obtaining an {@link EnvironmentData} object from a CarSensorEvent 288 * object with type {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT}. 289 * 290 * @param data an optional output parameter which, if non-null, will be used by this method 291 * instead of a newly created object. 292 * @return an EnvironmentData object corresponding to the data contained in the CarSensorEvent. 293 */ 294 public EnvironmentData getEnvironmentData(EnvironmentData data) { 295 checkType(CarSensorManager.SENSOR_TYPE_ENVIRONMENT); 296 if (data == null) { 297 data = new EnvironmentData(); 298 } 299 data.timeStampNs = timeStampNs; 300 data.temperature = floatValues[INDEX_ENVIRONMENT_TEMPERATURE]; 301 data.pressure = floatValues[INDEX_ENVIRONMENT_PRESSURE]; 302 return data; 303 } 304 305 public static class NightData { 306 public long timeStampNs; 307 public boolean isNightMode; 308 } 309 310 /** 311 * Convenience method for obtaining a {@link NightData} object from a CarSensorEvent 312 * object with type {@link CarSensorManager#SENSOR_TYPE_NIGHT}. 313 * 314 * @param data an optional output parameter which, if non-null, will be used by this method 315 * instead of a newly created object. 316 * @return a NightData object corresponding to the data contained in the CarSensorEvent. 317 */ 318 public NightData getNightData(NightData data) { 319 checkType(CarSensorManager.SENSOR_TYPE_NIGHT); 320 if (data == null) { 321 data = new NightData(); 322 } 323 data.timeStampNs = timeStampNs; 324 data.isNightMode = intValues[0] == 1; 325 return data; 326 } 327 328 public static class GearData { 329 public long timeStampNs; 330 public int gear; 331 } 332 333 /** 334 * Convenience method for obtaining a {@link GearData} object from a CarSensorEvent 335 * object with type {@link CarSensorManager#SENSOR_TYPE_GEAR}. 336 * 337 * @param data an optional output parameter which, if non-null, will be used by this method 338 * instead of a newly created object. 339 * @return a GearData object corresponding to the data contained in the CarSensorEvent. 340 */ 341 public GearData getGearData(GearData data) { 342 checkType(CarSensorManager.SENSOR_TYPE_GEAR); 343 if (data == null) { 344 data = new GearData(); 345 } 346 data.timeStampNs = timeStampNs; 347 data.gear = intValues[0]; 348 return data; 349 } 350 351 public static class ParkingBrakeData { 352 public long timeStampNs; 353 public boolean isEngaged; 354 } 355 356 /** 357 * Convenience method for obtaining a {@link ParkingBrakeData} object from a CarSensorEvent 358 * object with type {@link CarSensorManager#SENSOR_TYPE_PARKING_BRAKE}. 359 * 360 * @param data an optional output parameter which, if non-null, will be used by this method 361 * instead of a newly created object. 362 * @return a ParkingBreakData object corresponding to the data contained in the CarSensorEvent. 363 */ 364 public ParkingBrakeData getParkingBrakeData(ParkingBrakeData data) { 365 checkType(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE); 366 if (data == null) { 367 data = new ParkingBrakeData(); 368 } 369 data.timeStampNs = timeStampNs; 370 data.isEngaged = intValues[0] == 1; 371 return data; 372 } 373 374 public static class FuelLevelData { 375 public long timeStampNs; 376 /** Fuel level in %. If unsupported by the car, this value is -1. */ 377 public int level; 378 /** Fuel as possible range in Km. If unsupported by the car, this value is -1. */ 379 public float range; 380 /** If unsupported by the car, this value is false. */ 381 public boolean lowFuelWarning; 382 } 383 384 /** 385 * Convenience method for obtaining a {@link FuelLevelData} object from a CarSensorEvent 386 * object with type {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL}. 387 * 388 * @param data an optional output parameter which, if non-null, will be used by this method 389 * instead of a newly created object. 390 * @return a FuelLevel object corresponding to the data contained in the CarSensorEvent. 391 */ 392 public FuelLevelData getFuelLevelData(FuelLevelData data) { 393 checkType(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL); 394 if (data == null) { 395 data = new FuelLevelData(); 396 } 397 data.timeStampNs = timeStampNs; 398 if (floatValues == null) { 399 data.level = -1; 400 data.range = -1; 401 } else { 402 if (floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE] < 0) { 403 data.level = -1; 404 } else { 405 data.level = (int) floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE]; 406 } 407 if (floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE] < 0) { 408 data.range = -1; 409 } else { 410 data.range = floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE]; 411 } 412 } 413 data.lowFuelWarning = intValues[0] == 1; 414 return data; 415 } 416 417 public static class OdometerData { 418 public long timeStampNs; 419 public float kms; 420 } 421 422 /** 423 * Convenience method for obtaining an {@link OdometerData} object from a CarSensorEvent 424 * object with type {@link CarSensorManager#SENSOR_TYPE_ODOMETER}. 425 * 426 * @param data an optional output parameter which, if non-null, will be used by this method 427 * instead of a newly created object. 428 * @return an OdometerData object corresponding to the data contained in the CarSensorEvent. 429 */ 430 public OdometerData getOdometerData(OdometerData data) { 431 checkType(CarSensorManager.SENSOR_TYPE_ODOMETER); 432 if (data == null) { 433 data = new OdometerData(); 434 } 435 data.timeStampNs = timeStampNs; 436 data.kms = floatValues[0]; 437 return data; 438 } 439 440 public static class RpmData { 441 public long timeStampNs; 442 public float rpm; 443 } 444 445 /** 446 * Convenience method for obtaining a {@link RpmData} object from a CarSensorEvent 447 * object with type {@link CarSensorManager#SENSOR_TYPE_RPM}. 448 * 449 * @param data an optional output parameter which, if non-null, will be used by this method 450 * instead of a newly created object. 451 * @return a RpmData object corresponding to the data contained in the CarSensorEvent. 452 */ 453 public RpmData getRpmData(RpmData data) { 454 checkType(CarSensorManager.SENSOR_TYPE_RPM); 455 if (data == null) { 456 data = new RpmData(); 457 } 458 data.timeStampNs = timeStampNs; 459 data.rpm = floatValues[0]; 460 return data; 461 } 462 463 public static class CarSpeedData { 464 public long timeStampNs; 465 public float carSpeed; 466 } 467 468 /** 469 * Convenience method for obtaining a {@link CarSpeedData} object from a CarSensorEvent 470 * object with type {@link CarSensorManager#SENSOR_TYPE_CAR_SPEED}. 471 * 472 * @param data an optional output parameter which, if non-null, will be used by this method 473 * instead of a newly created object. 474 * @return a CarSpeedData object corresponding to the data contained in the CarSensorEvent. 475 */ 476 public CarSpeedData getCarSpeedData(CarSpeedData data) { 477 checkType(CarSensorManager.SENSOR_TYPE_CAR_SPEED); 478 if (data == null) { 479 data = new CarSpeedData(); 480 } 481 data.timeStampNs = timeStampNs; 482 data.carSpeed = floatValues[0]; 483 return data; 484 } 485 486 public static class CompassData { 487 public long timeStampNs; 488 /** If unsupported by the car, this value is NaN. */ 489 public float bearing; 490 /** If unsupported by the car, this value is NaN. */ 491 public float pitch; 492 /** If unsupported by the car, this value is NaN. */ 493 public float roll; 494 } 495 496 /** 497 * Convenience method for obtaining a {@link CompassData} object from a CarSensorEvent 498 * object with type {@link CarSensorManager#SENSOR_TYPE_COMPASS}. 499 * 500 * @param data an optional output parameter which, if non-null, will be used by this method 501 * instead of a newly created object. 502 * @return a CompassData object corresponding to the data contained in the CarSensorEvent. 503 */ 504 public CompassData getCompassData(CompassData data) { 505 checkType(CarSensorManager.SENSOR_TYPE_COMPASS); 506 if (data == null) { 507 data = new CompassData(); 508 } 509 data.bearing = floatValues[INDEX_COMPASS_BEARING]; 510 data.pitch = floatValues[INDEX_COMPASS_PITCH]; 511 data.roll = floatValues[INDEX_COMPASS_ROLL]; 512 return data; 513 } 514 515 /** 516 * Convenience method for obtaining a {@link Location} object from a CarSensorEvent 517 * object with type {@link CarSensorManager#SENSOR_TYPE_LOCATION}. 518 * 519 * @param location an optional output parameter which, if non-null, will be used by this method 520 * instead of a newly created object. 521 * @return a Location object corresponding to the data contained in the CarSensorEvent. 522 */ 523 public Location getLocation(Location location) { 524 checkType(CarSensorManager.SENSOR_TYPE_LOCATION); 525 if (location == null) { 526 location = new Location("Car-GPS"); 527 } 528 // intValues[0]: bit flags for the presence of other values following. 529 int presense = intValues[0]; 530 if ((presense & (0x1 << INDEX_LOCATION_LATITUDE)) != 0) { 531 int latE7 = intValues[INDEX_LOCATION_LATITUDE_INTS]; 532 location.setLatitude(latE7 * 1e-7); 533 } 534 if ((presense & (0x1 << INDEX_LOCATION_LONGITUDE)) != 0) { 535 int longE7 = intValues[INDEX_LOCATION_LONGITUDE_INTS]; 536 location.setLongitude(longE7 * 1e-7); 537 } 538 if ((presense & (0x1 << INDEX_LOCATION_ACCURACY)) != 0) { 539 location.setAccuracy(floatValues[INDEX_LOCATION_ACCURACY]); 540 } 541 if ((presense & (0x1 << INDEX_LOCATION_ALTITUDE)) != 0) { 542 location.setAltitude(floatValues[INDEX_LOCATION_ALTITUDE]); 543 } 544 if ((presense & (0x1 << INDEX_LOCATION_SPEED)) != 0) { 545 location.setSpeed(floatValues[INDEX_LOCATION_SPEED]); 546 } 547 if ((presense & (0x1 << INDEX_LOCATION_BEARING)) != 0) { 548 location.setBearing(floatValues[INDEX_LOCATION_BEARING]); 549 } 550 location.setElapsedRealtimeNanos(timeStampNs); 551 // There is a risk of scheduler delaying 2nd elapsedRealtimeNs value. 552 // But will not try to fix it assuming that is acceptable as UTC time's accuracy is not 553 // guaranteed in Location data. 554 long currentTimeMs = System.currentTimeMillis(); 555 long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos(); 556 location.setTime( 557 currentTimeMs - (elapsedRealtimeNs - timeStampNs) / MILLI_IN_NANOS); 558 return location; 559 } 560 561 public static class DrivingStatusData { 562 public long timeStampNs; 563 public int status; 564 } 565 566 /** 567 * Convenience method for obtaining a {@link DrivingStatusData} object from a CarSensorEvent 568 * object with type {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}. 569 * 570 * @param data an optional output parameter which, if non-null, will be used by this method 571 * instead of a newly created object. 572 * @return a DrivingStatusData object corresponding to the data contained in the CarSensorEvent. 573 */ 574 public DrivingStatusData getDrivingStatusData(DrivingStatusData data) { 575 checkType(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS); 576 if (data == null) { 577 data = new DrivingStatusData(); 578 } 579 data.status = intValues[0]; 580 return data; 581 } 582 583 public static class AccelerometerData { 584 public long timeStampNs; 585 /** If unsupported by the car, this value is NaN. */ 586 public float x; 587 /** If unsupported by the car, this value is NaN. */ 588 public float y; 589 /** If unsupported by the car, this value is NaN. */ 590 public float z; 591 } 592 593 /** 594 * Convenience method for obtaining an {@link AccelerometerData} object from a CarSensorEvent 595 * object with type {@link CarSensorManager#SENSOR_TYPE_ACCELEROMETER}. 596 * 597 * @param data an optional output parameter which, if non-null, will be used by this method 598 * instead of a newly created object. 599 * @return a AccelerometerData object corresponding to the data contained in the CarSensorEvent. 600 */ 601 public AccelerometerData getAccelerometerData(AccelerometerData data) { 602 checkType(CarSensorManager.SENSOR_TYPE_ACCELEROMETER); 603 if (data == null) { 604 data = new AccelerometerData(); 605 } 606 data.x = floatValues[INDEX_ACCELEROMETER_X]; 607 data.y = floatValues[INDEX_ACCELEROMETER_Y]; 608 data.z = floatValues[INDEX_ACCELEROMETER_Z]; 609 return data; 610 } 611 612 public static class GyroscopeData { 613 public long timeStampNs; 614 /** If unsupported by the car, this value is NaN. */ 615 public float x; 616 /** If unsupported by the car, this value is NaN. */ 617 public float y; 618 /** If unsupported by the car, this value is NaN. */ 619 public float z; 620 } 621 622 /** 623 * Convenience method for obtaining a {@link GyroscopeData} object from a CarSensorEvent 624 * object with type {@link CarSensorManager#SENSOR_TYPE_GYROSCOPE}. 625 * 626 * @param data an optional output parameter which, if non-null, will be used by this method 627 * instead of a newly created object. 628 * @return a GyroscopeData object corresponding to the data contained in the CarSensorEvent. 629 */ 630 public GyroscopeData getGyroscopeData(GyroscopeData data) { 631 checkType(CarSensorManager.SENSOR_TYPE_GYROSCOPE); 632 if (data == null) { 633 data = new GyroscopeData(); 634 } 635 data.x = floatValues[INDEX_GYROSCOPE_X]; 636 data.y = floatValues[INDEX_GYROSCOPE_Y]; 637 data.z = floatValues[INDEX_GYROSCOPE_Z]; 638 return data; 639 } 640 641 // android.location.GpsSatellite doesn't have a public constructor, so that can't be used. 642 /** 643 * Class that contains GPS satellite status. For more info on meaning of these fields refer 644 * to the documentation to the {@link GpsSatellite} class. 645 */ 646 public static class GpsSatelliteData { 647 public long timeStampNs; 648 /** 649 * Number of satellites used in GPS fix or -1 of unavailable. 650 */ 651 public int numberInUse = -1; 652 /** 653 * Number of satellites in view or -1 of unavailable. 654 */ 655 public int numberInView = -1; 656 /** 657 * Per-satellite flag if this satellite was used for GPS fix. 658 * Can be null if per-satellite data is unavailable. 659 */ 660 public boolean[] usedInFix = null; 661 /** 662 * Per-satellite pseudo-random id. 663 * Can be null if per-satellite data is unavailable. 664 */ 665 public int[] prn = null; 666 /** 667 * Per-satellite signal to noise ratio. 668 * Can be null if per-satellite data is unavailable. 669 */ 670 public float[] snr = null; 671 /** 672 * Per-satellite azimuth. 673 * Can be null if per-satellite data is unavailable. 674 */ 675 public float[] azimuth = null; 676 /** 677 * Per-satellite elevation. 678 * Can be null if per-satellite data is unavailable. 679 */ 680 public float[] elevation = null; 681 } 682 683 /** 684 * Convenience method for obtaining a {@link GpsSatelliteData} object from a CarSensorEvent 685 * object with type {@link CarSensorManager#SENSOR_TYPE_HVAC} with optional per-satellite info. 686 * 687 * @param data an optional output parameter which, if non-null, will be used by this method 688 * instead of a newly created object. 689 * @param withPerSatellite whether to include per-satellite data. 690 * @return a GpsSatelliteData object corresponding to the data contained in the CarSensorEvent. 691 */ 692 public GpsSatelliteData getGpsSatelliteData(GpsSatelliteData data, 693 boolean withPerSatellite) { 694 checkType(CarSensorManager.SENSOR_TYPE_GPS_SATELLITE); 695 if (data == null) { 696 data = new GpsSatelliteData(); 697 } 698 final int intOffset = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_INT_OFFSET; 699 final int intInterval = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_INT_INTERVAL; 700 final int floatOffset = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET; 701 final int floatInterval = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL; 702 final int numberOfSats = (floatValues.length - floatOffset) / floatInterval; 703 704 data.numberInUse = intValues[CarSensorEvent.INDEX_GPS_SATELLITE_NUMBER_IN_USE]; 705 data.numberInView = intValues[CarSensorEvent.INDEX_GPS_SATELLITE_NUMBER_IN_VIEW]; 706 if (withPerSatellite && data.numberInView >= 0) { 707 data.usedInFix = new boolean[numberOfSats]; 708 data.prn = new int[numberOfSats]; 709 data.snr = new float[numberOfSats]; 710 data.azimuth = new float[numberOfSats]; 711 data.elevation = new float[numberOfSats]; 712 713 for (int i = 0; i < numberOfSats; ++i) { 714 int iInt = intOffset + intInterval * i; 715 int iFloat = floatOffset + floatInterval * i; 716 data.usedInFix[i] = intValues[iInt] != 0; 717 data.prn[i] = Math.round( 718 floatValues[iFloat + CarSensorEvent.INDEX_GPS_SATELLITE_PRN_OFFSET]); 719 data.snr[i] = 720 floatValues[iFloat + CarSensorEvent.INDEX_GPS_SATELLITE_SNR_OFFSET]; 721 data.azimuth[i] = floatValues[iFloat 722 + CarSensorEvent.INDEX_GPS_SATELLITE_AZIMUTH_OFFSET]; 723 data.elevation[i] = floatValues[iFloat 724 + CarSensorEvent.INDEX_GPS_SATELLITE_ELEVATION_OFFSET]; 725 } 726 } 727 return data; 728 } 729 730 /** @hide */ 731 @Override 732 public String toString() { 733 StringBuilder sb = new StringBuilder(); 734 sb.append(getClass().getName() + "["); 735 sb.append("type:" + Integer.toHexString(sensorType)); 736 if (floatValues != null && floatValues.length > 0) { 737 sb.append(" float values:"); 738 for (float v: floatValues) { 739 sb.append(" " + v); 740 } 741 } 742 if (intValues != null && intValues.length > 0) { 743 sb.append(" int values:"); 744 for (int v: intValues) { 745 sb.append(" " + v); 746 } 747 } 748 sb.append("]"); 749 return sb.toString(); 750 } 751} 752