• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest;
20 import android.annotation.RequiresPermission;
21 import android.car.Car;
22 import android.car.CarApiUtil;
23 import android.car.CarLibLog;
24 import android.car.CarManagerBase;
25 import android.car.CarNotConnectedException;
26 import android.content.Context;
27 import android.os.Handler;
28 import android.os.Handler.Callback;
29 import android.os.IBinder;
30 import android.os.Looper;
31 import android.os.Message;
32 import android.os.RemoteException;
33 import android.util.Log;
34 
35 import java.lang.ref.WeakReference;
36 import java.util.HashMap;
37 import java.util.Iterator;
38 import java.util.LinkedList;
39 import java.util.List;
40 
41 /**
42  *  API for monitoring car sensor data.
43  */
44 public class CarSensorManager implements CarManagerBase {
45     /** @hide */
46     public static final int SENSOR_TYPE_RESERVED1           = 1;
47     /**
48      * This sensor represents vehicle speed in m/s.
49      * Sensor data in {@link CarSensorEvent} is a float which will be >= 0.
50      * This requires {@link Car#PERMISSION_SPEED} permission.
51      */
52     public static final int SENSOR_TYPE_CAR_SPEED         = 2;
53     /**
54      * Represents engine RPM of the car. Sensor data in {@link CarSensorEvent} is a float.
55      */
56     public static final int SENSOR_TYPE_RPM               = 3;
57     /**
58      * Total travel distance of the car in Kilometer. Sensor data is a float.
59      * This requires {@link Car#PERMISSION_MILEAGE} permission.
60      */
61     public static final int SENSOR_TYPE_ODOMETER          = 4;
62     /**
63      * Indicates fuel level of the car.
64      * In {@link CarSensorEvent}, floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_PERCENTILE}]
65      * represents fuel level in percentile (0 to 100) while
66      * floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_DISTANCE}] represents estimated range
67      * in Kilometer with the remaining fuel.
68      * Note that the gas mileage used for the estimation may not represent the current driving
69      * condition.
70      * This requires {@link Car#PERMISSION_FUEL} permission.
71      */
72     public static final int SENSOR_TYPE_FUEL_LEVEL        = 5;
73     /**
74      * Represents the current status of parking brake. Sensor data in {@link CarSensorEvent} is an
75      * intValues[0]. Value of 1 represents parking brake applied while 0 means the other way
76      * around. For this sensor, rate in {@link #registerListener(CarSensorEventListener, int, int)}
77      * will be ignored and all changes will be notified.
78      */
79     public static final int SENSOR_TYPE_PARKING_BRAKE     = 6;
80     /**
81      * This represents the current position of transmission gear. Sensor data in
82      * {@link CarSensorEvent} is an intValues[0]. For the meaning of the value, check
83      * {@link CarSensorEvent#GEAR_NEUTRAL} and other GEAR_*.
84      */
85     public static final int SENSOR_TYPE_GEAR              = 7;
86     /** @hide */
87     public static final int SENSOR_TYPE_RESERVED8        = 8;
88     /**
89      * Day/night sensor. Sensor data is intValues[0].
90      */
91     public static final int SENSOR_TYPE_NIGHT             = 9;
92     /** @hide */
93     public static final int SENSOR_TYPE_RESERVED10         = 10;
94     /**
95      * Represents the current driving status of car. Different user interaction should be used
96      * depending on the current driving status. Driving status is intValues[0].
97      */
98     public static final int SENSOR_TYPE_DRIVING_STATUS    = 11;
99     /**
100      * Environment like temperature and pressure.
101      */
102     public static final int SENSOR_TYPE_ENVIRONMENT       = 12;
103     /** @hide */
104     public static final int SENSOR_TYPE_RESERVED13        = 13;
105     /** @hide */
106     public static final int SENSOR_TYPE_RESERVED14        = 14;
107     /** @hide */
108     public static final int SENSOR_TYPE_RESERVED15        = 15;
109     /** @hide */
110     public static final int SENSOR_TYPE_RESERVED16        = 16;
111     /** @hide */
112     public static final int SENSOR_TYPE_RESERVED17        = 17;
113     /** @hide */
114     public static final int SENSOR_TYPE_RESERVED18        = 18;
115     /** @hide */
116     public static final int SENSOR_TYPE_RESERVED19        = 19;
117     /** @hide */
118     public static final int SENSOR_TYPE_RESERVED20        = 20;
119     /** @hide */
120     public static final int SENSOR_TYPE_RESERVED21        = 21;
121 
122     /**
123      * Sensor type bigger than this is invalid. Always update this after adding a new sensor.
124      * @hide
125      */
126     private static final int SENSOR_TYPE_MAX = SENSOR_TYPE_ENVIRONMENT;
127 
128     /**
129      * Sensors defined in this range [{@link #SENSOR_TYPE_VENDOR_EXTENSION_START},
130      * {@link #SENSOR_TYPE_VENDOR_EXTENSION_END}] is for each car vendor's to use.
131      * This should be only used for system app to access sensors not defined as standard types.
132      * So the sensor supported in this range can vary depending on car models / manufacturers.
133      * 3rd party apps should not use sensors in this range as they are not compatible across
134      * different cars. Additionally 3rd party apps trying to access sensor in this range will get
135      * security exception as their access is restricted to system apps.
136      *
137      * @hide
138      */
139     public static final int SENSOR_TYPE_VENDOR_EXTENSION_START = 0x60000000;
140     public static final int SENSOR_TYPE_VENDOR_EXTENSION_END   = 0x6fffffff;
141 
142     /** Read sensor in default normal rate set for each sensors. This is default rate. */
143     public static final int SENSOR_RATE_NORMAL  = 3;
144     public static final int SENSOR_RATE_UI = 2;
145     public static final int SENSOR_RATE_FAST = 1;
146     /** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
147     public static final int SENSOR_RATE_FASTEST = 0;
148 
149     private static final int MSG_SENSOR_EVENTS = 0;
150 
151     private final ICarSensor mService;
152 
153     private CarSensorEventListenerToService mCarSensorEventListenerToService;
154 
155     /**
156      * To keep record of locally active sensors. Key is sensor type. This is used as a basic lock
157      * for all client accesses.
158      */
159     private final HashMap<Integer, CarSensorListeners> mActiveSensorListeners =
160             new HashMap<Integer, CarSensorListeners>();
161 
162     /** Handles call back into projected apps. */
163     private final Handler mHandler;
164     private final Callback mHandlerCallback = new Callback() {
165         @Override
166         public boolean handleMessage(Message msg) {
167             switch (msg.what) {
168                 case MSG_SENSOR_EVENTS:
169                     synchronized(mActiveSensorListeners) {
170                         List<CarSensorEvent> events = (List<CarSensorEvent>) msg.obj;
171                         for (CarSensorEvent event: events) {
172                             CarSensorListeners listeners =
173                                     mActiveSensorListeners.get(event.sensorType);
174                             if (listeners != null) {
175                                 listeners.onSensorChanged(event);
176                             }
177                         }
178                     }
179                     break;
180                 default:
181                     break;
182             }
183             return true;
184         }
185     };
186 
187 
188     /** @hide */
CarSensorManager(IBinder service, Context context, Looper looper)189     public CarSensorManager(IBinder service, Context context, Looper looper) {
190         mService = ICarSensor.Stub.asInterface(service);
191         mHandler = new Handler(looper, mHandlerCallback);
192     }
193 
194     /** @hide */
195     @Override
onCarDisconnected()196     public void onCarDisconnected() {
197         synchronized(mActiveSensorListeners) {
198             mActiveSensorListeners.clear();
199             mCarSensorEventListenerToService = null;
200         }
201     }
202 
203     /**
204      * Give the list of CarSensors available in the connected car.
205      * @return array of all sensor types supported.
206      * @throws CarNotConnectedException
207      */
getSupportedSensors()208     public int[] getSupportedSensors() throws CarNotConnectedException {
209         try {
210             return mService.getSupportedSensors();
211         } catch (IllegalStateException e) {
212             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
213         } catch (RemoteException e) {
214             throw new CarNotConnectedException(e);
215         }
216         return new int[0];
217     }
218 
219     /**
220      * Tells if given sensor is supported or not.
221      * @param sensorType
222      * @return true if the sensor is supported.
223      * @throws CarNotConnectedException
224      */
isSensorSupported(int sensorType)225     public boolean isSensorSupported(int sensorType) throws CarNotConnectedException {
226         int[] sensors = getSupportedSensors();
227         for (int sensorSupported: sensors) {
228             if (sensorType == sensorSupported) {
229                 return true;
230             }
231         }
232         return false;
233     }
234 
235     /**
236      * Check if given sensorList is including the sensorType.
237      * @param sensorList
238      * @param sensorType
239      * @return
240      */
isSensorSupported(int[] sensorList, int sensorType)241     public static boolean isSensorSupported(int[] sensorList, int sensorType) {
242         for (int sensorSupported: sensorList) {
243             if (sensorType == sensorSupported) {
244                 return true;
245             }
246         }
247         return false;
248     }
249 
250     /**
251      * Listener for car sensor data change.
252      * Callbacks are called in the Looper context.
253      */
254     public interface CarSensorEventListener {
255         /**
256          * Called when there is a new sensor data from car.
257          * @param event Incoming sensor event for the given sensor type.
258          */
onSensorChanged(final CarSensorEvent event)259         void onSensorChanged(final CarSensorEvent event);
260     }
261 
262     /**
263      * Register {@link CarSensorEventListener} to get repeated sensor updates. Multiple listeners
264      * can be registered for a single sensor or the same listener can be used for different sensors.
265      * If the same listener is registered again for the same sensor, it will be either ignored or
266      * updated depending on the rate.
267      * <p>
268      * Requires {@link Car#PERMISSION_SPEED} for {@link #SENSOR_TYPE_CAR_SPEED},
269      *  {@link Car#PERMISSION_MILEAGE} for {@link #SENSOR_TYPE_ODOMETER},
270      *  or {@link Car#PERMISSION_FUEL} for {@link #SENSOR_TYPE_FUEL_LEVEL}.
271      *
272      * @param listener
273      * @param sensorType sensor type to subscribe.
274      * @param rate how fast the sensor events are delivered. It should be one of
275      *        {@link #SENSOR_RATE_FASTEST} or {@link #SENSOR_RATE_NORMAL}. Rate may not be respected
276      *        especially when the same sensor is registered with different listener with different
277      *        rates.
278      * @return if the sensor was successfully enabled.
279      * @throws CarNotConnectedException
280      * @throws IllegalArgumentException for wrong argument like wrong rate
281      * @throws SecurityException if missing the appropriate permission
282      */
283     @RequiresPermission(anyOf={Manifest.permission.ACCESS_FINE_LOCATION, Car.PERMISSION_SPEED,
284             Car.PERMISSION_MILEAGE, Car.PERMISSION_FUEL}, conditional=true)
registerListener(CarSensorEventListener listener, int sensorType, int rate)285     public boolean registerListener(CarSensorEventListener listener, int sensorType, int rate)
286             throws CarNotConnectedException, IllegalArgumentException {
287         assertSensorType(sensorType);
288         if (rate != SENSOR_RATE_FASTEST && rate != SENSOR_RATE_NORMAL) {
289             throw new IllegalArgumentException("wrong rate " + rate);
290         }
291         synchronized(mActiveSensorListeners) {
292             if (mCarSensorEventListenerToService == null) {
293                 mCarSensorEventListenerToService = new CarSensorEventListenerToService(this);
294             }
295             boolean needsServerUpdate = false;
296             CarSensorListeners listeners;
297             listeners = mActiveSensorListeners.get(sensorType);
298             if (listeners == null) {
299                 listeners = new CarSensorListeners(rate);
300                 mActiveSensorListeners.put(sensorType, listeners);
301                 needsServerUpdate = true;
302             }
303             if (listeners.addAndUpdateRate(listener, rate)) {
304                 needsServerUpdate = true;
305             }
306             if (needsServerUpdate) {
307                 if (!registerOrUpdateSensorListener(sensorType, rate)) {
308                     return false;
309                 }
310             }
311         }
312         return true;
313     }
314 
315     /**
316      * Stop getting sensor update for the given listener. If there are multiple registrations for
317      * this listener, all listening will be stopped.
318      * @param listener
319      * @throws CarNotConnectedException
320      */
unregisterListener(CarSensorEventListener listener)321     public void unregisterListener(CarSensorEventListener listener)
322             throws CarNotConnectedException {
323         //TODO: removing listener should reset update rate
324         synchronized(mActiveSensorListeners) {
325             Iterator<Integer> sensorIterator = mActiveSensorListeners.keySet().iterator();
326             while (sensorIterator.hasNext()) {
327                 Integer sensor = sensorIterator.next();
328                 doUnregisterListenerLocked(listener, sensor, sensorIterator);
329             }
330         }
331     }
332 
333     /**
334      * Stop getting sensor update for the given listener and sensor. If the same listener is used
335      * for other sensors, those subscriptions will not be affected.
336      * @param listener
337      * @param sensorType
338      * @throws CarNotConnectedException
339      */
unregisterListener(CarSensorEventListener listener, int sensorType)340     public void unregisterListener(CarSensorEventListener listener, int sensorType)
341             throws CarNotConnectedException {
342         synchronized(mActiveSensorListeners) {
343             doUnregisterListenerLocked(listener, sensorType, null);
344         }
345     }
346 
doUnregisterListenerLocked(CarSensorEventListener listener, Integer sensor, Iterator<Integer> sensorIterator)347     private void doUnregisterListenerLocked(CarSensorEventListener listener, Integer sensor,
348             Iterator<Integer> sensorIterator) throws CarNotConnectedException {
349         CarSensorListeners listeners = mActiveSensorListeners.get(sensor);
350         if (listeners != null) {
351             if (listeners.contains(listener)) {
352                 listeners.remove(listener);
353             }
354             if (listeners.isEmpty()) {
355                 try {
356                     mService.unregisterSensorListener(sensor.intValue(),
357                             mCarSensorEventListenerToService);
358                 } catch (RemoteException e) {
359                     throw new CarNotConnectedException(e);
360                 }
361                 if (sensorIterator == null) {
362                     mActiveSensorListeners.remove(sensor);
363                 } else {
364                     sensorIterator.remove();
365                 }
366             }
367         }
368     }
369 
registerOrUpdateSensorListener(int sensor, int rate)370     private boolean registerOrUpdateSensorListener(int sensor, int rate)
371             throws CarNotConnectedException {
372         try {
373             if (!mService.registerOrUpdateSensorListener(sensor, rate,
374                     mCarSensorEventListenerToService)) {
375                 return false;
376             }
377         } catch (IllegalStateException e) {
378             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
379         } catch (RemoteException e) {
380             throw new CarNotConnectedException(e);
381         }
382         return true;
383     }
384 
385     /**
386      * Get the most recent CarSensorEvent for the given type. Note that latest sensor data from car
387      * will not be available if it was never subscribed before. This call will return immediately
388      * with null if there is no data available.
389      * @param type A sensor to request
390      * @return null if there was no sensor update since connected to the car.
391      * @throws CarNotConnectedException
392      */
getLatestSensorEvent(int type)393     public CarSensorEvent getLatestSensorEvent(int type) throws CarNotConnectedException {
394         assertSensorType(type);
395         try {
396             return mService.getLatestSensorEvent(type);
397         } catch (IllegalStateException e) {
398             CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
399         } catch(RemoteException e) {
400             handleCarServiceRemoteExceptionAndThrow(e);
401         }
402         return null;
403     }
404 
handleCarServiceRemoteExceptionAndThrow(RemoteException e)405     private void handleCarServiceRemoteExceptionAndThrow(RemoteException e)
406             throws CarNotConnectedException {
407         if (Log.isLoggable(CarLibLog.TAG_SENSOR, Log.INFO)) {
408             Log.i(CarLibLog.TAG_SENSOR, "RemoteException from car service:" + e.getMessage());
409         }
410         throw new CarNotConnectedException();
411     }
412 
assertSensorType(int sensorType)413     private void assertSensorType(int sensorType) {
414         if (sensorType == 0 || !((sensorType <= SENSOR_TYPE_MAX) ||
415                 ((sensorType >= SENSOR_TYPE_VENDOR_EXTENSION_START) &&
416                         (sensorType <= SENSOR_TYPE_VENDOR_EXTENSION_END)))) {
417             throw new IllegalArgumentException("invalid sensor type " + sensorType);
418         }
419     }
420 
handleOnSensorChanged(List<CarSensorEvent> events)421     private void handleOnSensorChanged(List<CarSensorEvent> events) {
422         mHandler.sendMessage(mHandler.obtainMessage(MSG_SENSOR_EVENTS, events));
423     }
424 
425     private static class CarSensorEventListenerToService extends ICarSensorEventListener.Stub {
426         private final WeakReference<CarSensorManager> mManager;
427 
CarSensorEventListenerToService(CarSensorManager manager)428         public CarSensorEventListenerToService(CarSensorManager manager) {
429             mManager = new WeakReference<CarSensorManager>(manager);
430         }
431 
432         @Override
onSensorChanged(List<CarSensorEvent> events)433         public void onSensorChanged(List<CarSensorEvent> events) {
434             CarSensorManager manager = mManager.get();
435             if (manager != null) {
436                 manager.handleOnSensorChanged(events);
437             }
438         }
439     }
440 
441     /**
442      * Represent listeners for a sensor.
443      */
444     private class CarSensorListeners {
445         private final LinkedList<CarSensorEventListener> mListeners =
446                 new LinkedList<CarSensorEventListener>();
447 
448         private int mUpdateRate;
449         private long mLastUpdateTime = -1;
450 
CarSensorListeners(int rate)451         CarSensorListeners(int rate) {
452             mUpdateRate = rate;
453         }
454 
contains(CarSensorEventListener listener)455         boolean contains(CarSensorEventListener listener) {
456             return mListeners.contains(listener);
457         }
458 
remove(CarSensorEventListener listener)459         void remove(CarSensorEventListener listener) {
460             mListeners.remove(listener);
461         }
462 
isEmpty()463         boolean isEmpty() {
464             return mListeners.isEmpty();
465         }
466 
467         /**
468          * Add given listener to the list and update rate if necessary.
469          * @param listener if null, add part is skipped.
470          * @param updateRate
471          * @return true if rate was updated. Otherwise, returns false.
472          */
addAndUpdateRate(CarSensorEventListener listener, int updateRate)473         boolean addAndUpdateRate(CarSensorEventListener listener, int updateRate) {
474             if (!mListeners.contains(listener)) {
475                 mListeners.add(listener);
476             }
477             if (mUpdateRate > updateRate) {
478                 mUpdateRate = updateRate;
479                 return true;
480             }
481             return false;
482         }
483 
onSensorChanged(CarSensorEvent event)484         void onSensorChanged(CarSensorEvent event) {
485             // throw away old sensor data as oneway binder call can change order.
486             long updateTime = event.timeStampNs;
487             if (updateTime < mLastUpdateTime) {
488                 Log.w(CarLibLog.TAG_SENSOR, "dropping old sensor data");
489                 return;
490             }
491             mLastUpdateTime = updateTime;
492             for (CarSensorEventListener listener: mListeners) {
493                 listener.onSensorChanged(event);
494             }
495         }
496     }
497 }
498