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