Home | History | Annotate | Download | only in hardware
      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.support.car.hardware;
     18 
     19 import android.location.GpsSatellite;
     20 import android.location.Location;
     21 import android.os.SystemClock;
     22 import android.support.annotation.RestrictTo;
     23 
     24 import static android.support.annotation.RestrictTo.Scope.GROUP_ID;
     25 
     26 /**
     27  * A CarSensorEvent object corresponds to a single sensor event coming from the car. Sensor
     28  * data is stored in a sensor type-specific format in the object's float and byte arrays.
     29  * </p>
     30  * To aid in unmarshalling the object's data arrays, this class provides static nested classes and
     31  * conversion methods (such as {@link DrivingStatusData} and {@link #getDrivingStatusData}).
     32  * Additionally, calling a conversion method on a CarSensorEvent object with an inappropriate type
     33  * results in an {@code UnsupportedOperationException} being thrown.
     34  */
     35 public class CarSensorEvent {
     36 
     37 
     38     /**
     39      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: No restrictions.
     40      */
     41     public static final int DRIVE_STATUS_UNRESTRICTED = 0;
     42     /**
     43      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: No video playback allowed.
     44      * See {@link #getDrivingStatusData()}.
     45      */
     46     public static final int DRIVE_STATUS_NO_VIDEO = 0x1;
     47     /**
     48      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: No keyboard or rotary
     49      * controller input allowed. See {@link #getDrivingStatusData()}.
     50      */
     51     public static final int DRIVE_STATUS_NO_KEYBOARD_INPUT = 0x2;
     52     /**
     53      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: No voice input allowed.
     54      * See {@link #getDrivingStatusData()}.
     55      */
     56     public static final int DRIVE_STATUS_NO_VOICE_INPUT = 0x4;
     57     /**
     58      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: No setup/configuration
     59      * allowed. See {@link #getDrivingStatusData()}.
     60      */
     61     public static final int DRIVE_STATUS_NO_CONFIG = 0x8;
     62     /**
     63      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: Limit displayed message
     64      * length. See {@link #getDrivingStatusData()}.
     65      */
     66     public static final int DRIVE_STATUS_LIMIT_MESSAGE_LEN = 0x10;
     67     /**
     68      * Status for {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}: All driving restrictions
     69      * enabled. See {@link #getDrivingStatusData()}.
     70      */
     71     public static final int DRIVE_STATUS_FULLY_RESTRICTED = DRIVE_STATUS_NO_VIDEO |
     72             DRIVE_STATUS_NO_KEYBOARD_INPUT | DRIVE_STATUS_NO_VOICE_INPUT | DRIVE_STATUS_NO_CONFIG |
     73             DRIVE_STATUS_LIMIT_MESSAGE_LEN;
     74     /**
     75      * Indices for {@link CarSensorManager#SENSOR_TYPE_COMPASS} in floatValues.
     76      * Angles are in degrees. Can be NaN if not available. See {@link #getCompassData()}.
     77      */
     78     public static final int INDEX_COMPASS_BEARING = 0;
     79     /**
     80      * Indices for {@link CarSensorManager#SENSOR_TYPE_COMPASS} in floatValues.
     81      * Angles are in degrees. Can be NaN if not available. See {@link #getCompassData()}.
     82      */
     83     public static final int INDEX_COMPASS_PITCH   = 1;
     84     /**
     85      * Indices for {@link CarSensorManager#SENSOR_TYPE_COMPASS} in floatValues.
     86      * Angles are in degrees. Can be NaN if not available. See {@link #getCompassData()}.
     87      */
     88     public static final int INDEX_COMPASS_ROLL    = 2;
     89 
     90 
     91     /**
     92      * Index for {@link CarSensorManager#SENSOR_TYPE_WHEEL_TICK_DISTANCE} in longValues.
     93      */
     94     public static final int INDEX_WHEEL_DISTANCE_RESET_COUNT = 0;
     95     public static final int INDEX_WHEEL_DISTANCE_FRONT_LEFT = 1;
     96     public static final int INDEX_WHEEL_DISTANCE_FRONT_RIGHT = 2;
     97     public static final int INDEX_WHEEL_DISTANCE_REAR_RIGHT = 3;
     98     public static final int INDEX_WHEEL_DISTANCE_REAR_LEFT = 4;
     99 
    100     private static final long MILLI_IN_NANOS = 1000000L;
    101 
    102     /** Sensor type for this event, such as {@link CarSensorManager#SENSOR_TYPE_COMPASS}. */
    103     public final int sensorType;
    104 
    105     /**
    106      * When this data was acquired in car or received from car. It is the elapsed time of data
    107      * reception from the car in nanoseconds since system boot.
    108      */
    109     public final long timestamp;
    110     /**
    111      * Array holding float type of sensor data. If the sensor has single value, only floatValues[0]
    112      * should be used. */
    113     public final float[] floatValues;
    114     /** Array holding int type of sensor data. */
    115     public final int[] intValues;
    116     /** array holding long int type of sensor data */
    117     public final long[] longValues;
    118 
    119     private static final float[] EMPTY_FLOAT_ARRAY = {};
    120     private static final int[] EMPTY_INT_ARRAY = {};
    121     private static final long[] EMPTY_LONG_ARRAY = {};
    122 
    123     /**
    124      * Constructs a {@link CarSensorEvent} from integer values. Handled by
    125      * CarSensorManager implementations. App developers need not worry about constructing these
    126      * objects.
    127      * @hide
    128      */
    129     @RestrictTo(GROUP_ID)
    130     public CarSensorEvent(int sensorType, long timestamp, int floatValueSize, int intValueSize,
    131                           int longValueSize) {
    132         this.sensorType = sensorType;
    133         this.timestamp = timestamp;
    134         floatValues = new float[floatValueSize];
    135         intValues = new int[intValueSize];
    136         longValues = new long[longValueSize];
    137     }
    138 
    139     /**
    140      * Constructor
    141      * @param sensorType one of the {@link CarSensorManager}'s SENSOR_TYPE_* constants
    142      * @param timestamp time since system start in nanoseconds
    143      * @param floatValues {@code null} will be converted to an empty array
    144      * @param intValues {@code null} will be converted to an empty array
    145      * @param longValues {@code null} will be converted to an empty array
    146      * @hide
    147      */
    148     @RestrictTo(GROUP_ID)
    149     public CarSensorEvent(int sensorType, long timestamp, float[] floatValues, int[] intValues,
    150                           long[] longValues) {
    151         this.sensorType = sensorType;
    152         this.timestamp = timestamp;
    153         this.floatValues = (floatValues == null) ? EMPTY_FLOAT_ARRAY : floatValues;
    154         this.intValues = (intValues == null) ? EMPTY_INT_ARRAY : intValues;
    155         this.longValues = (longValues == null) ? EMPTY_LONG_ARRAY : longValues;
    156     }
    157 
    158     /**
    159      * Constructor
    160      * @param sensorType one of the {@link CarSensorManager}'s SENSOR_TYPE_* constants
    161      * @param timestamp time since system start in nanoseconds
    162      * @param floatValues {@code null} will be converted to an empty array
    163      * @param byteValues bytes will be converted into the intValues array. {@code null} will be
    164      * converted to an empty array.
    165      * @param longValues {@code null} will be converted to an empty array
    166      * @hide
    167      */
    168     @RestrictTo(GROUP_ID)
    169     public CarSensorEvent(int sensorType, long timestamp, float[] floatValues, byte[] byteValues,
    170                           long[] longValues) {
    171         this.sensorType = sensorType;
    172         this.timestamp = timestamp;
    173         this.floatValues = (floatValues == null) ? EMPTY_FLOAT_ARRAY : floatValues;
    174         if (byteValues == null) {
    175             this.intValues = EMPTY_INT_ARRAY;
    176         } else {
    177             this.intValues = new int[byteValues.length];
    178             for (int i = 0; i < byteValues.length; i++) {
    179                 this.intValues[i] = byteValues[i];
    180             }
    181         }
    182         this.longValues = (longValues == null) ? EMPTY_LONG_ARRAY : longValues;
    183     }
    184 
    185     private void checkType(int type) {
    186         if (sensorType == type) {
    187             return;
    188         }
    189         throw new UnsupportedOperationException(String.format(
    190                 "Invalid sensor type: expected %d, got %d", type, sensorType));
    191     }
    192 
    193     /**
    194      * Holds data about the car's compass readings. See {@link #getCompassData()}.
    195      */
    196     public static class CompassData {
    197         /** The time in nanoseconds since system boot. */
    198         public final long timestamp;
    199         /** The bearing in degrees. If unsupported by the car, this value is NaN. */
    200         public final float bearing;
    201         /**
    202          * The pitch in degrees. Nose down is positive. If unsupported by the car, this value is
    203          * NaN.
    204          */
    205         public final float pitch;
    206         /**
    207          * The roll in degrees. Right door down is positive. If unsupported by the car, this value
    208          * is NaN.
    209          */
    210         public final float roll;
    211 
    212         /** @hide */
    213         @RestrictTo(GROUP_ID)
    214         public CompassData(long timestamp, float bearing, float pitch, float roll) {
    215             this.timestamp = timestamp;
    216             this.bearing = bearing;
    217             this.pitch = pitch;
    218             this.roll = roll;
    219         }
    220     }
    221 
    222     /**
    223      * Convenience method for obtaining a {@link CompassData} object from a CarSensorEvent object
    224      * with type {@link CarSensorManager#SENSOR_TYPE_COMPASS}.
    225      *
    226      * @return A CompassData object corresponding to the data contained in the CarSensorEvent.
    227      */
    228     public CompassData getCompassData() {
    229         checkType(CarSensorManager.SENSOR_TYPE_COMPASS);
    230         return new CompassData(0, floatValues[INDEX_COMPASS_BEARING],
    231                 floatValues[INDEX_COMPASS_PITCH], floatValues[INDEX_COMPASS_ROLL]);
    232     }
    233 
    234     /**
    235      * Indicates the state of the parking brake (engaged or not). See
    236      * {@link #getParkingBrakeData()}.
    237      */
    238     public static class ParkingBrakeData {
    239         /** The time in nanoseconds since system boot. */
    240         public final long timestamp;
    241         /** Returns {@code true} if the parking brake is engaged. */
    242         public final boolean isEngaged;
    243 
    244         /** @hide */
    245         @RestrictTo(GROUP_ID)
    246         public ParkingBrakeData(long timestamp, boolean isEngaged) {
    247             this.timestamp = timestamp;
    248             this.isEngaged = isEngaged;
    249         }
    250     }
    251 
    252     /**
    253      * Convenience method for obtaining a {@link ParkingBrakeData} object from a CarSensorEvent
    254      * object with type {@link CarSensorManager#SENSOR_TYPE_PARKING_BRAKE}. See
    255      * {@link #getParkingBrakeData()}.
    256      *
    257      * @return A ParkingBreakData object corresponding to the data contained in the CarSensorEvent.
    258      */
    259     public ParkingBrakeData getParkingBrakeData() {
    260         checkType(CarSensorManager.SENSOR_TYPE_PARKING_BRAKE);
    261         return new ParkingBrakeData(timestamp, (intValues[0] == 1));
    262     }
    263 
    264     /**
    265      * Indicates if the system is in night mode (a state in which the screen is
    266      * darkened or displays a darker color palette). See {@link #getNightData()}.
    267      */
    268     public static class NightData {
    269         /** The time in nanoseconds since system boot. */
    270         public final long timestamp;
    271         /** Returns {@code true} if the system is in night mode. */
    272         public final boolean isNightMode;
    273 
    274         /** @hide */
    275         @RestrictTo(GROUP_ID)
    276         public NightData(long timestamp, boolean isNightMode) {
    277             this.timestamp = timestamp;
    278             this.isNightMode = isNightMode;
    279         }
    280     }
    281 
    282     /**
    283      * Convenience method for obtaining a {@link NightData} object from a CarSensorEvent object
    284      * with type {@link CarSensorManager#SENSOR_TYPE_NIGHT}.
    285      *
    286      * @return A NightData object corresponding to the data contained in the CarSensorEvent.
    287      */
    288     public NightData getNightData() {
    289         checkType(CarSensorManager.SENSOR_TYPE_NIGHT);
    290         return new NightData(timestamp, (intValues[0] == 1));
    291     }
    292 
    293     /**
    294      * Indicates the restrictions in effect based on the status of the vehicle. See
    295      * {@link #getDrivingStatusData()}.
    296      */
    297     public static class DrivingStatusData {
    298         /**
    299          * The time in nanoseconds since system boot.
    300          */
    301         public final long timestamp;
    302         /**
    303          * A bitmask with the following field values: {@link #DRIVE_STATUS_NO_VIDEO},
    304          * {@link #DRIVE_STATUS_NO_KEYBOARD_INPUT}, {@link #DRIVE_STATUS_NO_VOICE_INPUT},
    305          * {@link #DRIVE_STATUS_NO_CONFIG}, {@link #DRIVE_STATUS_LIMIT_MESSAGE_LEN}. You may read
    306          * this or use the convenience methods.
    307          */
    308         public final int status;
    309 
    310         /** @hide */
    311         @RestrictTo(GROUP_ID)
    312         public DrivingStatusData(long timestamp, int status) {
    313             this.timestamp = timestamp;
    314             this.status = status;
    315         }
    316 
    317         /**
    318          * @return Returns {@code true} if the keyboard is not allowed at this time.
    319          */
    320         public boolean isKeyboardRestricted() {
    321             return DRIVE_STATUS_NO_KEYBOARD_INPUT == (status & DRIVE_STATUS_NO_KEYBOARD_INPUT);
    322         }
    323 
    324         /**
    325          * @return Returns {@code true} if voice commands are not allowed at this time.
    326          */
    327         public boolean isVoiceRestricted() {
    328             return DRIVE_STATUS_NO_VOICE_INPUT == (status & DRIVE_STATUS_NO_VOICE_INPUT);
    329         }
    330 
    331         /**
    332          * @return Returns {@code true} if video is not allowed at this time.
    333          */
    334         public boolean isVideoRestricted() {
    335             return DRIVE_STATUS_NO_VIDEO == (status & DRIVE_STATUS_NO_VIDEO);
    336         }
    337 
    338         /**
    339          * @return Returns {@code true} if configuration should not be performed at this time.
    340          */
    341         public boolean isConfigurationRestricted() {
    342             return DRIVE_STATUS_NO_CONFIG == (status & DRIVE_STATUS_NO_CONFIG);
    343         }
    344 
    345         /**
    346          * @return Returns {@code true} if message length should be limited at this time.
    347          */
    348         public boolean isMessageLengthRestricted() {
    349             return DRIVE_STATUS_LIMIT_MESSAGE_LEN == (status & DRIVE_STATUS_LIMIT_MESSAGE_LEN);
    350         }
    351 
    352         /**
    353          * @return Returns {@code true} if all restrictions are in place at this time.
    354          */
    355         public boolean isFullyRestricted() {
    356             return DRIVE_STATUS_FULLY_RESTRICTED == (status & DRIVE_STATUS_FULLY_RESTRICTED);
    357         }
    358     }
    359 
    360     /**
    361      * Convenience method for obtaining a {@link DrivingStatusData} object from a CarSensorEvent
    362      * object with type {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS}.
    363      *
    364      * @return A DrivingStatusData object corresponding to the data contained in the
    365      * CarSensorEvent.
    366      */
    367     public DrivingStatusData getDrivingStatusData() {
    368         checkType(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS);
    369         return new DrivingStatusData(timestamp, intValues[0]);
    370     }
    371 
    372 
    373     /*things that are currently hidden*/
    374 
    375 
    376     /**
    377      * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
    378      * sensor. This value is fuel level in percentile.
    379      * @hide
    380      */
    381     public static final int INDEX_FUEL_LEVEL_IN_PERCENTILE = 0;
    382     /**
    383      * Index in {@link #floatValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
    384      * sensor. This value is fuel level in coverable distance. The unit is Km.
    385      * @hide
    386      */
    387     public static final int INDEX_FUEL_LEVEL_IN_DISTANCE = 1;
    388     /**
    389      * Index in {@link #intValues} for {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL} type of
    390      * sensor. This value is set to 1 if fuel low level warning is on.
    391      * @hide
    392      */
    393     public static final int INDEX_FUEL_LOW_WARNING = 0;
    394 
    395     /**
    396      *  GEAR_* represents meaning of intValues[0] for {@link CarSensorManager#SENSOR_TYPE_GEAR}
    397      *  sensor type.
    398      *  GEAR_NEUTRAL means transmission gear is in neutral state, and the car may be moving.
    399      * @hide
    400      */
    401     public static final int GEAR_NEUTRAL    = 0;
    402     /**
    403      * intValues[0] from 1 to 99 represents transmission gear number for moving forward.
    404      * GEAR_FIRST is for gear number 1.
    405      * @hide
    406      */
    407     public static final int GEAR_FIRST      = 1;
    408     /** Gear number 2. @hide */
    409     public static final int GEAR_SECOND     = 2;
    410     /** Gear number 3. @hide */
    411     public static final int GEAR_THIRD      = 3;
    412     /** Gear number 4. @hide */
    413     public static final int GEAR_FOURTH     = 4;
    414     /** Gear number 5. @hide */
    415     public static final int GEAR_FIFTH      = 5;
    416     /** Gear number 6. @hide */
    417     public static final int GEAR_SIXTH      = 6;
    418     /** Gear number 7. @hide */
    419     public static final int GEAR_SEVENTH    = 7;
    420     /** Gear number 8. @hide */
    421     public static final int GEAR_EIGHTH     = 8;
    422     /** Gear number 9. @hide */
    423     public static final int GEAR_NINTH      = 9;
    424     /** Gear number 10. @hide */
    425     public static final int GEAR_TENTH      = 10;
    426     /**
    427      * This is for transmission without specific gear number for moving forward like CVT. It tells
    428      * that car is in a transmission state to move it forward.
    429      * @hide
    430      */
    431     public static final int GEAR_DRIVE      = 100;
    432     /** Gear in parking state @hide */
    433     public static final int GEAR_PARK       = 101;
    434     /** Gear in reverse @hide */
    435     public static final int GEAR_REVERSE    = 102;
    436 
    437     /**
    438      * Indices for {@link CarSensorManager#SENSOR_TYPE_GYROSCOPE} in floatValues.
    439      * Rotation speed is in rad/s. Any component can be NaN if it is not available.
    440      */
    441     /**@hide*/
    442     public static final int INDEX_GYROSCOPE_X = 0;
    443     /**@hide*/
    444     public static final int INDEX_GYROSCOPE_Y = 1;
    445     /**@hide*/
    446     public static final int INDEX_GYROSCOPE_Z = 2;
    447 
    448     /**
    449      * Indices for {@link CarSensorManager#SENSOR_TYPE_GPS_SATELLITE}.
    450      * Both byte values and float values are used.
    451      * Two first bytes encode number of satellites in-use/in-view (or 0xFF if unavailable).
    452      * Then optionally with INDEX_GPS_SATELLITE_ARRAY_BYTE_OFFSET offset and interval
    453      * INDEX_GPS_SATELLITE_ARRAY_BYTE_INTERVAL between elements are encoded boolean flags of
    454      * whether particular satellite from in-view participate in in-use subset.
    455      * Float values with INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET offset and interval
    456      * INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL between elements can optionally contain
    457      * per-satellite values of signal strength and other values or NaN if unavailable.
    458      */
    459     /**@hide*/
    460     public static final int INDEX_GPS_SATELLITE_NUMBER_IN_USE = 0;
    461     /**@hide*/
    462     public static final int INDEX_GPS_SATELLITE_NUMBER_IN_VIEW = 1;
    463     /**@hide*/
    464     public static final int INDEX_GPS_SATELLITE_ARRAY_INT_OFFSET = 2;
    465     /**@hide*/
    466     public static final int INDEX_GPS_SATELLITE_ARRAY_INT_INTERVAL = 1;
    467     /**@hide*/
    468     public static final int INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET = 0;
    469     /**@hide*/
    470     public static final int INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL = 4;
    471     /**@hide*/
    472     public static final int INDEX_GPS_SATELLITE_PRN_OFFSET = 0;
    473     /**@hide*/
    474     public static final int INDEX_GPS_SATELLITE_SNR_OFFSET = 1;
    475     /**@hide*/
    476     public static final int INDEX_GPS_SATELLITE_AZIMUTH_OFFSET = 2;
    477     /**@hide*/
    478     public static final int INDEX_GPS_SATELLITE_ELEVATION_OFFSET = 3;
    479 
    480 
    481     /**
    482      * Index for {@link CarSensorManager#SENSOR_TYPE_LOCATION} in floatValues.
    483      * Each bit intValues[0] represents whether the corresponding data is present.
    484      */
    485     /**@hide*/
    486     public static final int INDEX_LOCATION_LATITUDE  = 0;
    487     /**@hide*/
    488     public static final int INDEX_LOCATION_LONGITUDE = 1;
    489     /**@hide*/
    490     public static final int INDEX_LOCATION_ACCURACY  = 2;
    491     /**@hide*/
    492     public static final int INDEX_LOCATION_ALTITUDE  = 3;
    493     /**@hide*/
    494     public static final int INDEX_LOCATION_SPEED     = 4;
    495     /**@hide*/
    496     public static final int INDEX_LOCATION_BEARING   = 5;
    497     /**@hide*/
    498     public static final int INDEX_LOCATION_MAX = INDEX_LOCATION_BEARING;
    499     /**@hide*/
    500     public static final int INDEX_LOCATION_LATITUDE_INTS = 1;
    501     /**@hide*/
    502     public static final int INDEX_LOCATION_LONGITUDE_INTS = 2;
    503 
    504 
    505     /**
    506      * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues.
    507      * Temperature in Celsius degrees.
    508      * @hide
    509      */
    510     public static final int INDEX_ENVIRONMENT_TEMPERATURE = 0;
    511     /**
    512      * Index for {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT} in floatValues.
    513      * Pressure in kPa.
    514      * @hide
    515      */
    516     public static final int INDEX_ENVIRONMENT_PRESSURE = 1;
    517 
    518 
    519     /**
    520      * Indices for {@link CarSensorManager#SENSOR_TYPE_ACCELEROMETER} in floatValues.
    521      * Acceleration (gravity) is in m/s^2. Any component can be NaN if it is not available.
    522      */
    523     /**@hide*/
    524     public static final int INDEX_ACCELEROMETER_X = 0;
    525     /**@hide*/
    526     public static final int INDEX_ACCELEROMETER_Y = 1;
    527     /**@hide*/
    528     public static final int INDEX_ACCELEROMETER_Z = 2;
    529 
    530     /** @hide */
    531     public static class EnvironmentData {
    532         /** The time in nanoseconds since system boot. */
    533         public final long timestamp;
    534         /** If unsupported by the car, this value is NaN. */
    535         public final float temperature;
    536         /** If unsupported by the car, this value is NaN. */
    537         public final float pressure;
    538 
    539         /** @hide */
    540         @RestrictTo(GROUP_ID)
    541         public EnvironmentData(long timestamp, float temperature, float pressure) {
    542             this.timestamp = timestamp;
    543             this.temperature = temperature;
    544             this.pressure = pressure;
    545         }
    546     }
    547 
    548     /**
    549      * Convenience method for obtaining an {@link EnvironmentData} object from a CarSensorEvent
    550      * object with type {@link CarSensorManager#SENSOR_TYPE_ENVIRONMENT}.
    551      *
    552      * @return an EnvironmentData object corresponding to the data contained in the CarSensorEvent.
    553      * @hide
    554      */
    555     public EnvironmentData getEnvironmentData() {
    556         checkType(CarSensorManager.SENSOR_TYPE_ENVIRONMENT);
    557 
    558         float temperature = floatValues[INDEX_ENVIRONMENT_TEMPERATURE];
    559         float pressure = floatValues[INDEX_ENVIRONMENT_PRESSURE];
    560         return new EnvironmentData(timestamp, temperature, pressure);
    561     }
    562 
    563     /** @hide */
    564     public static class GearData {
    565         /** The time in nanoseconds since system boot. */
    566         public final long timestamp;
    567         public final int gear;
    568 
    569         /** @hide */
    570         @RestrictTo(GROUP_ID)
    571         public GearData(long timestamp, int gear) {
    572             this.timestamp = timestamp;
    573             this.gear = gear;
    574         }
    575     }
    576 
    577     /**
    578      * Convenience method for obtaining a {@link GearData} object from a CarSensorEvent
    579      * object with type {@link CarSensorManager#SENSOR_TYPE_GEAR}.
    580      *
    581      * @return a GearData object corresponding to the data contained in the CarSensorEvent.
    582      * @hide
    583      */
    584     public GearData getGearData() {
    585         checkType(CarSensorManager.SENSOR_TYPE_GEAR);
    586         return new GearData(timestamp, intValues[0]);
    587     }
    588 
    589     /** @hide */
    590     public static class FuelLevelData {
    591         /** The time in nanoseconds since system boot. */
    592         public final long timestamp;
    593         /** Fuel level in %. If unsupported by the car, this value is -1. */
    594         public final int level;
    595         /** Fuel as possible range in Km. If unsupported by the car, this value is -1. */
    596         public final float range;
    597         /** If unsupported by the car, this value is false. */
    598         public final boolean lowFuelWarning;
    599 
    600         /** @hide */
    601         @RestrictTo(GROUP_ID)
    602         public FuelLevelData(long timestamp, int level, float range, boolean lowFuelWarning) {
    603             this.timestamp = timestamp;
    604             this.level = level;
    605             this.range = range;
    606             this.lowFuelWarning = lowFuelWarning;
    607         }
    608     }
    609 
    610     /**
    611      * Convenience method for obtaining a {@link FuelLevelData} object from a CarSensorEvent object
    612      * with type {@link CarSensorManager#SENSOR_TYPE_FUEL_LEVEL}.
    613      *
    614      * @return A FuelLevel object corresponding to the data contained in the CarSensorEvent.
    615      * @hide
    616      */
    617     public FuelLevelData getFuelLevelData() {
    618         checkType(CarSensorManager.SENSOR_TYPE_FUEL_LEVEL);
    619         int level = -1;
    620         float range = -1;
    621         if (floatValues != null) {
    622             if (floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE] >= 0) {
    623                 level = (int) floatValues[INDEX_FUEL_LEVEL_IN_PERCENTILE];
    624             }
    625 
    626             if (floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE] >= 0) {
    627                 range = floatValues[INDEX_FUEL_LEVEL_IN_DISTANCE];
    628             }
    629         }
    630         boolean lowFuelWarning = (intValues[0] == 1);
    631         return new FuelLevelData(timestamp, level, range, lowFuelWarning);
    632     }
    633 
    634     /** @hide */
    635     public static class OdometerData {
    636         /** The time in nanoseconds since system boot. */
    637         public final long timestamp;
    638         public final float kms;
    639 
    640         /** @hide */
    641         @RestrictTo(GROUP_ID)
    642         public OdometerData(long timestamp, float kms) {
    643             this.timestamp = timestamp;
    644             this.kms = kms;
    645         }
    646     }
    647 
    648     /**
    649      * Convenience method for obtaining an {@link OdometerData} object from a CarSensorEvent
    650      * object with type {@link CarSensorManager#SENSOR_TYPE_ODOMETER}.
    651      *
    652      * @return an OdometerData object corresponding to the data contained in the CarSensorEvent.
    653      * @hide
    654      */
    655     public OdometerData getOdometerData() {
    656         checkType(CarSensorManager.SENSOR_TYPE_ODOMETER);
    657             return new OdometerData(timestamp, floatValues[0]);
    658     }
    659 
    660     /** @hide */
    661     public static class RpmData {
    662         /** The time in nanoseconds since system boot. */
    663         public final long timestamp;
    664         public final float rpm;
    665 
    666         /** @hide */
    667         @RestrictTo(GROUP_ID)
    668         public RpmData(long timestamp, float rpm) {
    669             this.timestamp = timestamp;
    670             this.rpm = rpm;
    671         }
    672     }
    673 
    674     /**
    675      * Convenience method for obtaining a {@link RpmData} object from a CarSensorEvent object with
    676      * type {@link CarSensorManager#SENSOR_TYPE_RPM}.
    677      *
    678      * @return An RpmData object corresponding to the data contained in the CarSensorEvent.
    679      * @hide
    680      */
    681     public RpmData getRpmData() {
    682         checkType(CarSensorManager.SENSOR_TYPE_RPM);
    683         return new RpmData(timestamp, floatValues[0]);
    684     }
    685 
    686     /** @hide */
    687     public static class CarSpeedData {
    688         /** The time in nanoseconds since system boot. */
    689         public final long timestamp;
    690         public final float carSpeed;
    691 
    692         /** @hide */
    693         @RestrictTo(GROUP_ID)
    694         public CarSpeedData(long timestamp, float carSpeed) {
    695             this.timestamp = timestamp;
    696             this.carSpeed = carSpeed;
    697         }
    698     }
    699 
    700     /**
    701      * Convenience method for obtaining a {@link CarSpeedData} object from a CarSensorEvent
    702      * object with type {@link CarSensorManager#SENSOR_TYPE_CAR_SPEED}.
    703      *
    704      * @return a CarSpeedData object corresponding to the data contained in the CarSensorEvent.
    705      * @hide
    706      */
    707     public CarSpeedData getCarSpeedData() {
    708         checkType(CarSensorManager.SENSOR_TYPE_CAR_SPEED);
    709         return new CarSpeedData(timestamp, floatValues[0]);
    710     }
    711 
    712     /**
    713      * Convenience method for obtaining a {@link Location} object from a CarSensorEvent
    714      * object with type {@link CarSensorManager#SENSOR_TYPE_LOCATION}.
    715      *
    716      * @param location an optional output parameter which, if non-null, will be used by this method
    717      *     instead of a newly created object.
    718      * @return a Location object corresponding to the data contained in the CarSensorEvent.
    719      * @hide
    720      */
    721     public Location getLocation(Location location) {
    722         checkType(CarSensorManager.SENSOR_TYPE_LOCATION);
    723         if (location == null) {
    724             location = new Location("Car-GPS");
    725         }
    726         // intValues[0]: bit flags for the presence of other values following.
    727         int presense = intValues[0];
    728         if ((presense & (0x1 << INDEX_LOCATION_LATITUDE)) != 0) {
    729             int latE7 = intValues[INDEX_LOCATION_LATITUDE_INTS];
    730             location.setLatitude(latE7 * 1e-7);
    731         }
    732         if ((presense & (0x1 << INDEX_LOCATION_LONGITUDE)) != 0) {
    733             int longE7 = intValues[INDEX_LOCATION_LONGITUDE_INTS];
    734             location.setLongitude(longE7 * 1e-7);
    735         }
    736         if ((presense & (0x1 << INDEX_LOCATION_ACCURACY)) != 0) {
    737             location.setAccuracy(floatValues[INDEX_LOCATION_ACCURACY]);
    738         }
    739         if ((presense & (0x1 << INDEX_LOCATION_ALTITUDE)) != 0) {
    740             location.setAltitude(floatValues[INDEX_LOCATION_ALTITUDE]);
    741         }
    742         if ((presense & (0x1 << INDEX_LOCATION_SPEED)) != 0) {
    743             location.setSpeed(floatValues[INDEX_LOCATION_SPEED]);
    744         }
    745         if ((presense & (0x1 << INDEX_LOCATION_BEARING)) != 0) {
    746             location.setBearing(floatValues[INDEX_LOCATION_BEARING]);
    747         }
    748         location.setElapsedRealtimeNanos(timestamp);
    749         // There is a risk of scheduler delaying 2nd elapsedRealtimeNs value.
    750         // But will not try to fix it assuming that is acceptable as UTC time's accuracy is not
    751         // guaranteed in Location data.
    752         long currentTimeMs = System.currentTimeMillis();
    753         long elapsedRealtimeNs = SystemClock.elapsedRealtimeNanos();
    754         location.setTime(
    755                 currentTimeMs - (elapsedRealtimeNs - timestamp) / MILLI_IN_NANOS);
    756         return location;
    757     }
    758 
    759     /** @hide */
    760     public static class AccelerometerData  {
    761         /** The time in nanoseconds since system boot. */
    762         public final long timestamp;
    763         /** If unsupported by the car, this value is NaN. */
    764         public final float x;
    765         /** If unsupported by the car, this value is NaN. */
    766         public final float y;
    767         /** If unsupported by the car, this value is NaN. */
    768         public final float z;
    769 
    770         /** @hide */
    771         @RestrictTo(GROUP_ID)
    772         public AccelerometerData(long timestamp, float x, float y, float z) {
    773             this.timestamp = timestamp;
    774             this.x = x;
    775             this.y = y;
    776             this.z = z;
    777         }
    778     }
    779 
    780     /**
    781      * Convenience method for obtaining an {@link AccelerometerData} object from a CarSensorEvent
    782      * object with type {@link CarSensorManager#SENSOR_TYPE_ACCELEROMETER}.
    783      *
    784      * @return An AccelerometerData object corresponding to the data contained in the
    785      * CarSensorEvent.
    786      * @hide
    787      */
    788     public AccelerometerData getAccelerometerData() {
    789         checkType(CarSensorManager.SENSOR_TYPE_ACCELEROMETER);
    790         float x = floatValues[INDEX_ACCELEROMETER_X];
    791         float y = floatValues[INDEX_ACCELEROMETER_Y];
    792         float z = floatValues[INDEX_ACCELEROMETER_Z];
    793         return new AccelerometerData(timestamp, x, y, z);
    794     }
    795 
    796     /** @hide */
    797     public static class GyroscopeData {
    798         /** The time in nanoseconds since system boot. */
    799         public final long timestamp;
    800         /** If unsupported by the car, this value is NaN. */
    801         public final float x;
    802         /** If unsupported by the car, this value is NaN. */
    803         public final float y;
    804         /** If unsupported by the car, this value is NaN. */
    805         public final float z;
    806 
    807         /** @hide */
    808         @RestrictTo(GROUP_ID)
    809         public GyroscopeData(long timestamp, float x, float y, float z) {
    810             this.timestamp = timestamp;
    811             this.x = x;
    812             this.y = y;
    813             this.z = z;
    814         }
    815     }
    816 
    817     /**
    818      * Convenience method for obtaining a {@link GyroscopeData} object from a CarSensorEvent object
    819      * with type {@link CarSensorManager#SENSOR_TYPE_GYROSCOPE}.
    820      *
    821      * @return A GyroscopeData object corresponding to the data contained in the CarSensorEvent.
    822      * @hide
    823      */
    824     public GyroscopeData getGyroscopeData() {
    825         checkType(CarSensorManager.SENSOR_TYPE_GYROSCOPE);
    826         float x = floatValues[INDEX_GYROSCOPE_X];
    827         float y = floatValues[INDEX_GYROSCOPE_Y];
    828         float z = floatValues[INDEX_GYROSCOPE_Z];
    829         return new GyroscopeData(timestamp, x, y, z);
    830     }
    831 
    832     // android.location.GpsSatellite doesn't have a public constructor, so that can't be used.
    833     /**
    834      * Class that contains GPS satellite status. For more info on meaning of these fields refer
    835      * to the documentation to the {@link GpsSatellite} class.
    836      * @hide
    837      */
    838     public static class GpsSatelliteData {
    839         /** The time in nanoseconds since system boot. */
    840         public final long timestamp;
    841         /**
    842          * Number of satellites used in GPS fix or -1 of unavailable.
    843          */
    844         public final int numberInUse;
    845         /**
    846          * Number of satellites in view or -1 of unavailable.
    847          */
    848         public final int numberInView;
    849         /**
    850          * Per-satellite flag if this satellite was used for GPS fix.
    851          * Can be null if per-satellite data is unavailable.
    852          */
    853         public final boolean[] usedInFix;
    854         /**
    855          * Per-satellite pseudo-random id.
    856          * Can be null if per-satellite data is unavailable.
    857          */
    858         public final int[] prn;
    859         /**
    860          * Per-satellite signal to noise ratio.
    861          * Can be null if per-satellite data is unavailable.
    862          */
    863         public final float[] snr;
    864         /**
    865          * Per-satellite azimuth.
    866          * Can be null if per-satellite data is unavailable.
    867          */
    868         public final float[] azimuth;
    869         /**
    870          * Per-satellite elevation.
    871          * Can be null if per-satellite data is unavailable.
    872          */
    873         public final float[] elevation;
    874 
    875         /** @hide */
    876         @RestrictTo(GROUP_ID)
    877         public GpsSatelliteData(long timestamp, int numberInUse, int numberInView,
    878                 boolean[] usedInFix, int[] prn, float[] snr, float[] azimuth, float[] elevation) {
    879             this.timestamp = timestamp;
    880             this.numberInUse = numberInUse;
    881             this.numberInView = numberInView;
    882             this.usedInFix = usedInFix;
    883             this.prn = prn;
    884             this.snr = snr;
    885             this.azimuth = azimuth;
    886             this.elevation = elevation;
    887         }
    888     }
    889 
    890     private final int intOffset = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_INT_OFFSET;
    891     private final int intInterval = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_INT_INTERVAL;
    892     private final int floatOffset = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_FLOAT_OFFSET;
    893     private final int floatInterval = CarSensorEvent.INDEX_GPS_SATELLITE_ARRAY_FLOAT_INTERVAL;
    894 
    895     /**
    896      * Convenience method for obtaining a {@link GpsSatelliteData} object from a CarSensorEvent
    897      * object with type {@link CarSensorManager#SENSOR_TYPE_GPS_SATELLITE} with optional
    898      * per-satellite info.
    899      *
    900      * @param withPerSatellite whether to include per-satellite data.
    901      * @return a GpsSatelliteData object corresponding to the data contained in the CarSensorEvent.
    902      * @hide
    903      */
    904     public GpsSatelliteData getGpsSatelliteData(boolean withPerSatellite) {
    905         checkType(CarSensorManager.SENSOR_TYPE_GPS_SATELLITE);
    906 
    907         //init all vars
    908         int numberInUse = intValues[CarSensorEvent.INDEX_GPS_SATELLITE_NUMBER_IN_USE];
    909         int numberInView = intValues[CarSensorEvent.INDEX_GPS_SATELLITE_NUMBER_IN_VIEW];
    910         boolean[] usedInFix = null;
    911         int[] prn = null;
    912         float[] snr = null;
    913         float[] azimuth = null;
    914         float[] elevation = null;
    915 
    916         if (withPerSatellite && numberInView >= 0) {
    917             final int numberOfSats = (floatValues.length - floatOffset) / floatInterval;
    918             usedInFix = new boolean[numberOfSats];
    919             prn = new int[numberOfSats];
    920             snr = new float[numberOfSats];
    921             azimuth = new float[numberOfSats];
    922             elevation = new float[numberOfSats];
    923 
    924             for (int i = 0; i < numberOfSats; ++i) {
    925                 int iInt = intOffset + intInterval * i;
    926                 int iFloat = floatOffset + floatInterval * i;
    927                 usedInFix[i] = intValues[iInt] != 0;
    928                 prn[i] = Math.round(
    929                         floatValues[iFloat + CarSensorEvent.INDEX_GPS_SATELLITE_PRN_OFFSET]);
    930                 snr[i] =
    931                         floatValues[iFloat + CarSensorEvent.INDEX_GPS_SATELLITE_SNR_OFFSET];
    932                 azimuth[i] = floatValues[iFloat
    933                         + CarSensorEvent.INDEX_GPS_SATELLITE_AZIMUTH_OFFSET];
    934                 elevation[i] = floatValues[iFloat
    935                         + CarSensorEvent.INDEX_GPS_SATELLITE_ELEVATION_OFFSET];
    936             }
    937         }
    938         return new GpsSatelliteData(timestamp, numberInUse, numberInView, usedInFix, prn, snr,
    939                 azimuth, elevation);
    940     }
    941 
    942     /** @hide */
    943     public static class CarWheelTickDistanceData {
    944         public final long timestamp;
    945         public final long sensorResetCount;
    946         public final long frontLeftWheelDistanceMm;
    947         public final long frontRightWheelDistanceMm;
    948         public final long rearRightWheelDistanceMm;
    949         public final long rearLeftWheelDistanceMm;
    950 
    951         /** @hide */
    952         @RestrictTo(GROUP_ID)
    953         public CarWheelTickDistanceData(long timestamp, long sensorResetCount,
    954                                     long frontLeftWheelDistanceMm, long frontRightWheelDistanceMm,
    955                                     long rearRightWheelDistanceMm, long rearLeftWheelDistanceMm) {
    956             this.timestamp = timestamp;
    957             this.sensorResetCount = sensorResetCount;
    958             this.frontLeftWheelDistanceMm = frontLeftWheelDistanceMm;
    959             this.frontRightWheelDistanceMm = frontRightWheelDistanceMm;
    960             this.rearRightWheelDistanceMm = rearRightWheelDistanceMm;
    961             this.rearLeftWheelDistanceMm = rearLeftWheelDistanceMm;
    962         }
    963     }
    964 
    965     /**
    966      * Convenience method for obtaining a {@link CarWheelTickDistanceData} object from a
    967      * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_WHEEL_TICK_DISTANCE}.
    968      *
    969      * @return CarWheelTickDistanceData object corresponding to data contained in the CarSensorEvent
    970      * @hide
    971      */
    972     public CarWheelTickDistanceData getCarWheelTickDistanceData() {
    973         checkType(CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE);
    974         long sensorResetCount = longValues[INDEX_WHEEL_DISTANCE_RESET_COUNT];
    975         long frontLeftWheelDistanceMm = longValues[INDEX_WHEEL_DISTANCE_FRONT_LEFT];
    976         long frontRightWheelDistanceMm = longValues[INDEX_WHEEL_DISTANCE_FRONT_RIGHT];
    977         long rearRightWheelDistanceMm = longValues[INDEX_WHEEL_DISTANCE_REAR_RIGHT];
    978         long rearLeftWheelDistanceMm = longValues[INDEX_WHEEL_DISTANCE_REAR_LEFT];
    979         return new CarWheelTickDistanceData(timestamp, sensorResetCount, frontLeftWheelDistanceMm,
    980             frontRightWheelDistanceMm, rearRightWheelDistanceMm, rearLeftWheelDistanceMm);
    981     }
    982 
    983     /** @hide */
    984     public static class CarAbsActiveData {
    985         public final long timestamp;
    986         public final boolean absIsActive;
    987 
    988         /** @hide */
    989         @RestrictTo(GROUP_ID)
    990         public CarAbsActiveData(long timestamp, boolean absIsActive) {
    991             this.timestamp = timestamp;
    992             this.absIsActive = absIsActive;
    993         };
    994     }
    995 
    996     /**
    997      * Convenience method for obtaining a {@link CarAbsActiveData} object from a CarSensorEvent
    998      * object with type {@link CarSensorManager#SENSOR_TYPE_ABS_ACTIVE}.
    999      *
   1000      * @param data an optional output parameter which, if non-null, will be used by this method
   1001      *     instead of a newly created object.
   1002      * @return a CarAbsActiveData object corresponding to data contained in the CarSensorEvent.
   1003      * @hide
   1004      */
   1005     public CarAbsActiveData getCarAbsActiveData() {
   1006         checkType(CarSensorManager.SENSOR_TYPE_ABS_ACTIVE);
   1007         boolean absIsActive = intValues[0] == 1;
   1008         return new CarAbsActiveData(timestamp, absIsActive);
   1009     }
   1010 
   1011     /** @hide */
   1012     public static class CarTractionControlActiveData {
   1013         public final long timestamp;
   1014         public final boolean tractionControlIsActive;
   1015 
   1016         /** @hide */
   1017         @RestrictTo(GROUP_ID)
   1018         public CarTractionControlActiveData(long timestamp, boolean tractionControlIsActive) {
   1019             this.timestamp = timestamp;
   1020             this.tractionControlIsActive = tractionControlIsActive;
   1021         };
   1022     }
   1023 
   1024     /**
   1025      * Convenience method for obtaining a {@link CarTractionControlActiveData} object from a
   1026      * CarSensorEvent object with type {@link CarSensorManager#SENSOR_TYPE_TRACTION_CONTROL_ACTIVE}.
   1027      *
   1028      * @param data an optional output parameter which, if non-null, will be used by this method
   1029      *     instead of a newly created object.
   1030      * @return a CarTractionControlActiveData object corresponding to data contained in the
   1031      *     CarSensorEvent.
   1032      * @hide
   1033      */
   1034     public CarTractionControlActiveData getCarTractionControlActiveData() {
   1035         checkType(CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE);
   1036         boolean tractionControlIsActive = intValues[0] == 1;
   1037         return new CarTractionControlActiveData(timestamp, tractionControlIsActive);
   1038     }
   1039 
   1040     /** @hide */
   1041     @Override
   1042     public String toString() {
   1043         StringBuilder sb = new StringBuilder();
   1044         sb.append(getClass().getName() + "[");
   1045         sb.append("type:" + Integer.toHexString(sensorType));
   1046         if (floatValues != null && floatValues.length > 0) {
   1047             sb.append(" float values:");
   1048             for (float v: floatValues) {
   1049                 sb.append(" " + v);
   1050             }
   1051         }
   1052         if (intValues != null && intValues.length > 0) {
   1053             sb.append(" int values:");
   1054             for (int v: intValues) {
   1055                 sb.append(" " + v);
   1056             }
   1057         }
   1058         if (longValues != null && longValues.length > 0) {
   1059             sb.append(" long values:");
   1060             for (long v: longValues) {
   1061                 sb.append(" " + v);
   1062             }
   1063         }
   1064         sb.append("]");
   1065         return sb.toString();
   1066     }
   1067 }
   1068