blob: 5baf08e14edbb9bfed193b68a848b9fa3004109b [file] [log] [blame]
keunyoungca515072015-07-10 12:21:47 -07001/*
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
Keun-young Parke54ac272016-02-16 19:02:18 -080017package android.car.hardware;
keunyoungca515072015-07-10 12:21:47 -070018
19import android.Manifest;
Keun-young Parkaf2cc992016-10-07 11:46:45 -070020import android.annotation.IntDef;
Keun-young Parke54ac272016-02-16 19:02:18 -080021import android.annotation.RequiresPermission;
22import android.car.Car;
23import android.car.CarApiUtil;
24import android.car.CarLibLog;
25import android.car.CarManagerBase;
26import android.car.CarNotConnectedException;
keunyoungca515072015-07-10 12:21:47 -070027import android.content.Context;
28import android.os.Handler;
Vitalii Tomkiv235f8ac2016-04-04 11:26:49 -070029import android.os.Handler.Callback;
Keun-young Parke54ac272016-02-16 19:02:18 -080030import android.os.IBinder;
keunyoungca515072015-07-10 12:21:47 -070031import android.os.Message;
32import android.os.RemoteException;
keunyoungca515072015-07-10 12:21:47 -070033import android.util.Log;
34
Keun-young Parkaf2cc992016-10-07 11:46:45 -070035import java.lang.annotation.Retention;
36import java.lang.annotation.RetentionPolicy;
keunyoungca515072015-07-10 12:21:47 -070037import java.lang.ref.WeakReference;
38import java.util.HashMap;
39import java.util.Iterator;
40import java.util.LinkedList;
keunyoungcc449f72015-08-12 10:46:27 -070041import java.util.List;
keunyoungca515072015-07-10 12:21:47 -070042
43/**
44 * API for monitoring car sensor data.
45 */
Keun-young Park4cf69112016-10-04 10:02:59 -070046public final class CarSensorManager implements CarManagerBase {
Keun-young Park4afc6ee2016-03-04 18:18:19 -080047 /** @hide */
48 public static final int SENSOR_TYPE_RESERVED1 = 1;
keunyoungca515072015-07-10 12:21:47 -070049 /**
50 * This sensor represents vehicle speed in m/s.
51 * Sensor data in {@link CarSensorEvent} is a float which will be >= 0.
52 * This requires {@link Car#PERMISSION_SPEED} permission.
53 */
54 public static final int SENSOR_TYPE_CAR_SPEED = 2;
55 /**
56 * Represents engine RPM of the car. Sensor data in {@link CarSensorEvent} is a float.
57 */
58 public static final int SENSOR_TYPE_RPM = 3;
59 /**
60 * Total travel distance of the car in Kilometer. Sensor data is a float.
61 * This requires {@link Car#PERMISSION_MILEAGE} permission.
62 */
63 public static final int SENSOR_TYPE_ODOMETER = 4;
64 /**
65 * Indicates fuel level of the car.
66 * In {@link CarSensorEvent}, floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_PERCENTILE}]
67 * represents fuel level in percentile (0 to 100) while
68 * floatValues[{@link CarSensorEvent#INDEX_FUEL_LEVEL_IN_DISTANCE}] represents estimated range
69 * in Kilometer with the remaining fuel.
70 * Note that the gas mileage used for the estimation may not represent the current driving
71 * condition.
72 * This requires {@link Car#PERMISSION_FUEL} permission.
73 */
74 public static final int SENSOR_TYPE_FUEL_LEVEL = 5;
75 /**
76 * Represents the current status of parking brake. Sensor data in {@link CarSensorEvent} is an
keunyoungcc449f72015-08-12 10:46:27 -070077 * intValues[0]. Value of 1 represents parking brake applied while 0 means the other way
Jason Tholstrupd72b5352016-09-22 16:32:14 -070078 * around. For this sensor, rate in {@link #registerListener(OnSensorChangedListener, int, int)}
keunyoungca515072015-07-10 12:21:47 -070079 * will be ignored and all changes will be notified.
80 */
81 public static final int SENSOR_TYPE_PARKING_BRAKE = 6;
82 /**
83 * This represents the current position of transmission gear. Sensor data in
keunyoungcc449f72015-08-12 10:46:27 -070084 * {@link CarSensorEvent} is an intValues[0]. For the meaning of the value, check
keunyoungca515072015-07-10 12:21:47 -070085 * {@link CarSensorEvent#GEAR_NEUTRAL} and other GEAR_*.
86 */
87 public static final int SENSOR_TYPE_GEAR = 7;
Jason Tholstrup9eae32f2016-05-10 14:39:05 -070088 /** @hide */
89 public static final int SENSOR_TYPE_RESERVED8 = 8;
keunyoungca515072015-07-10 12:21:47 -070090 /**
keunyoungcc449f72015-08-12 10:46:27 -070091 * Day/night sensor. Sensor data is intValues[0].
keunyoungca515072015-07-10 12:21:47 -070092 */
Jason Tholstrup9eae32f2016-05-10 14:39:05 -070093 public static final int SENSOR_TYPE_NIGHT = 9;
Keun-young Park4afc6ee2016-03-04 18:18:19 -080094 /** @hide */
Jason Tholstrup9eae32f2016-05-10 14:39:05 -070095 public static final int SENSOR_TYPE_RESERVED10 = 10;
keunyoungca515072015-07-10 12:21:47 -070096 /**
97 * Represents the current driving status of car. Different user interaction should be used
keunyoungcc449f72015-08-12 10:46:27 -070098 * depending on the current driving status. Driving status is intValues[0].
keunyoungca515072015-07-10 12:21:47 -070099 */
Jason Tholstrup9eae32f2016-05-10 14:39:05 -0700100 public static final int SENSOR_TYPE_DRIVING_STATUS = 11;
keunyoungca515072015-07-10 12:21:47 -0700101 /**
102 * Environment like temperature and pressure.
103 */
Jason Tholstrup9eae32f2016-05-10 14:39:05 -0700104 public static final int SENSOR_TYPE_ENVIRONMENT = 12;
Keun-young Park064ddd82015-12-21 23:57:50 +0000105 /** @hide */
keunyoungcc449f72015-08-12 10:46:27 -0700106 public static final int SENSOR_TYPE_RESERVED13 = 13;
Keun-young Park064ddd82015-12-21 23:57:50 +0000107 /** @hide */
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800108 public static final int SENSOR_TYPE_RESERVED14 = 14;
Jason Tholstrup9eae32f2016-05-10 14:39:05 -0700109 /** @hide */
110 public static final int SENSOR_TYPE_RESERVED15 = 15;
111 /** @hide */
112 public static final int SENSOR_TYPE_RESERVED16 = 16;
113 /** @hide */
114 public static final int SENSOR_TYPE_RESERVED17 = 17;
115 /** @hide */
116 public static final int SENSOR_TYPE_RESERVED18 = 18;
117 /** @hide */
118 public static final int SENSOR_TYPE_RESERVED19 = 19;
119 /** @hide */
120 public static final int SENSOR_TYPE_RESERVED20 = 20;
121 /** @hide */
122 public static final int SENSOR_TYPE_RESERVED21 = 21;
Keun-young Park064ddd82015-12-21 23:57:50 +0000123
124 /**
125 * Sensor type bigger than this is invalid. Always update this after adding a new sensor.
126 * @hide
127 */
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800128 private static final int SENSOR_TYPE_MAX = SENSOR_TYPE_ENVIRONMENT;
keunyoungca515072015-07-10 12:21:47 -0700129
Keun-young Park064ddd82015-12-21 23:57:50 +0000130 /**
131 * Sensors defined in this range [{@link #SENSOR_TYPE_VENDOR_EXTENSION_START},
132 * {@link #SENSOR_TYPE_VENDOR_EXTENSION_END}] is for each car vendor's to use.
133 * This should be only used for system app to access sensors not defined as standard types.
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800134 * So the sensor supported in this range can vary depending on car models / manufacturers.
Keun-young Park064ddd82015-12-21 23:57:50 +0000135 * 3rd party apps should not use sensors in this range as they are not compatible across
136 * different cars. Additionally 3rd party apps trying to access sensor in this range will get
137 * security exception as their access is restricted to system apps.
138 *
139 * @hide
140 */
141 public static final int SENSOR_TYPE_VENDOR_EXTENSION_START = 0x60000000;
142 public static final int SENSOR_TYPE_VENDOR_EXTENSION_END = 0x6fffffff;
143
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700144 /** @hide */
145 @IntDef({
146 SENSOR_TYPE_CAR_SPEED,
147 SENSOR_TYPE_RPM,
148 SENSOR_TYPE_ODOMETER,
149 SENSOR_TYPE_FUEL_LEVEL,
150 SENSOR_TYPE_PARKING_BRAKE,
151 SENSOR_TYPE_GEAR,
152 SENSOR_TYPE_NIGHT,
153 SENSOR_TYPE_DRIVING_STATUS,
154 SENSOR_TYPE_ENVIRONMENT
155 })
156 @Retention(RetentionPolicy.SOURCE)
157 public @interface SensorType {}
158
keunyoungcc449f72015-08-12 10:46:27 -0700159 /** Read sensor in default normal rate set for each sensors. This is default rate. */
keunyoungca515072015-07-10 12:21:47 -0700160 public static final int SENSOR_RATE_NORMAL = 3;
keunyoungcc449f72015-08-12 10:46:27 -0700161 public static final int SENSOR_RATE_UI = 2;
162 public static final int SENSOR_RATE_FAST = 1;
163 /** Read sensor at the maximum rate. Actual rate will be different depending on the sensor. */
keunyoungca515072015-07-10 12:21:47 -0700164 public static final int SENSOR_RATE_FASTEST = 0;
165
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700166 /** @hide */
167 @IntDef({
168 SENSOR_RATE_NORMAL,
169 SENSOR_RATE_UI,
170 SENSOR_RATE_FAST,
171 SENSOR_RATE_FASTEST
172 })
173 @Retention(RetentionPolicy.SOURCE)
174 public @interface SensorRate {}
175
keunyoungcc449f72015-08-12 10:46:27 -0700176 private static final int MSG_SENSOR_EVENTS = 0;
keunyoungca515072015-07-10 12:21:47 -0700177
keunyoungca515072015-07-10 12:21:47 -0700178 private final ICarSensor mService;
keunyoungca515072015-07-10 12:21:47 -0700179
180 private CarSensorEventListenerToService mCarSensorEventListenerToService;
181
182 /**
183 * To keep record of locally active sensors. Key is sensor type. This is used as a basic lock
184 * for all client accesses.
185 */
186 private final HashMap<Integer, CarSensorListeners> mActiveSensorListeners =
187 new HashMap<Integer, CarSensorListeners>();
188
189 /** Handles call back into projected apps. */
190 private final Handler mHandler;
191 private final Callback mHandlerCallback = new Callback() {
192 @Override
193 public boolean handleMessage(Message msg) {
194 switch (msg.what) {
keunyoungcc449f72015-08-12 10:46:27 -0700195 case MSG_SENSOR_EVENTS:
keunyoungca515072015-07-10 12:21:47 -0700196 synchronized(mActiveSensorListeners) {
keunyoungcc449f72015-08-12 10:46:27 -0700197 List<CarSensorEvent> events = (List<CarSensorEvent>) msg.obj;
198 for (CarSensorEvent event: events) {
199 CarSensorListeners listeners =
200 mActiveSensorListeners.get(event.sensorType);
201 if (listeners != null) {
202 listeners.onSensorChanged(event);
203 }
keunyoungca515072015-07-10 12:21:47 -0700204 }
205 }
206 break;
207 default:
208 break;
209 }
210 return true;
211 }
212 };
213
214
215 /** @hide */
Jason Tholstrup3ee334d2016-08-26 14:30:20 -0700216 public CarSensorManager(IBinder service, Context context, Handler handler) {
Keun-young Parke54ac272016-02-16 19:02:18 -0800217 mService = ICarSensor.Stub.asInterface(service);
Jason Tholstrup3ee334d2016-08-26 14:30:20 -0700218 mHandler = new Handler(handler.getLooper(), mHandlerCallback);
keunyoungca515072015-07-10 12:21:47 -0700219 }
220
221 /** @hide */
222 @Override
223 public void onCarDisconnected() {
224 synchronized(mActiveSensorListeners) {
225 mActiveSensorListeners.clear();
226 mCarSensorEventListenerToService = null;
227 }
228 }
229
keunyoungca515072015-07-10 12:21:47 -0700230 /**
231 * Give the list of CarSensors available in the connected car.
232 * @return array of all sensor types supported.
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700233 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700234 */
235 public int[] getSupportedSensors() throws CarNotConnectedException {
236 try {
237 return mService.getSupportedSensors();
238 } catch (IllegalStateException e) {
239 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
240 } catch (RemoteException e) {
Vitalii Tomkiv235f8ac2016-04-04 11:26:49 -0700241 throw new CarNotConnectedException(e);
keunyoungca515072015-07-10 12:21:47 -0700242 }
243 return new int[0];
244 }
245
246 /**
247 * Tells if given sensor is supported or not.
248 * @param sensorType
249 * @return true if the sensor is supported.
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700250 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700251 */
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700252 public boolean isSensorSupported(@SensorType int sensorType) throws CarNotConnectedException {
keunyoungca515072015-07-10 12:21:47 -0700253 int[] sensors = getSupportedSensors();
254 for (int sensorSupported: sensors) {
255 if (sensorType == sensorSupported) {
256 return true;
257 }
258 }
259 return false;
260 }
261
262 /**
263 * Check if given sensorList is including the sensorType.
264 * @param sensorList
265 * @param sensorType
266 * @return
267 */
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700268 public static boolean isSensorSupported(int[] sensorList, @SensorType int sensorType) {
keunyoungca515072015-07-10 12:21:47 -0700269 for (int sensorSupported: sensorList) {
270 if (sensorType == sensorSupported) {
271 return true;
272 }
273 }
274 return false;
275 }
276
277 /**
278 * Listener for car sensor data change.
279 * Callbacks are called in the Looper context.
280 */
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700281 public interface OnSensorChangedListener {
keunyoungca515072015-07-10 12:21:47 -0700282 /**
283 * Called when there is a new sensor data from car.
284 * @param event Incoming sensor event for the given sensor type.
285 */
286 void onSensorChanged(final CarSensorEvent event);
287 }
288
289 /**
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700290 * Register {@link OnSensorChangedListener} to get repeated sensor updates. Multiple listeners
keunyoungca515072015-07-10 12:21:47 -0700291 * can be registered for a single sensor or the same listener can be used for different sensors.
292 * If the same listener is registered again for the same sensor, it will be either ignored or
293 * updated depending on the rate.
294 * <p>
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800295 * Requires {@link Car#PERMISSION_SPEED} for {@link #SENSOR_TYPE_CAR_SPEED},
296 * {@link Car#PERMISSION_MILEAGE} for {@link #SENSOR_TYPE_ODOMETER},
297 * or {@link Car#PERMISSION_FUEL} for {@link #SENSOR_TYPE_FUEL_LEVEL}.
keunyoungca515072015-07-10 12:21:47 -0700298 *
299 * @param listener
300 * @param sensorType sensor type to subscribe.
301 * @param rate how fast the sensor events are delivered. It should be one of
302 * {@link #SENSOR_RATE_FASTEST} or {@link #SENSOR_RATE_NORMAL}. Rate may not be respected
303 * especially when the same sensor is registered with different listener with different
304 * rates.
305 * @return if the sensor was successfully enabled.
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700306 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700307 * @throws IllegalArgumentException for wrong argument like wrong rate
308 * @throws SecurityException if missing the appropriate permission
309 */
310 @RequiresPermission(anyOf={Manifest.permission.ACCESS_FINE_LOCATION, Car.PERMISSION_SPEED,
311 Car.PERMISSION_MILEAGE, Car.PERMISSION_FUEL}, conditional=true)
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700312 public boolean registerListener(OnSensorChangedListener listener, @SensorType int sensorType,
313 @SensorRate int rate) throws CarNotConnectedException, IllegalArgumentException {
keunyoungca515072015-07-10 12:21:47 -0700314 assertSensorType(sensorType);
315 if (rate != SENSOR_RATE_FASTEST && rate != SENSOR_RATE_NORMAL) {
316 throw new IllegalArgumentException("wrong rate " + rate);
317 }
318 synchronized(mActiveSensorListeners) {
319 if (mCarSensorEventListenerToService == null) {
320 mCarSensorEventListenerToService = new CarSensorEventListenerToService(this);
321 }
322 boolean needsServerUpdate = false;
323 CarSensorListeners listeners;
324 listeners = mActiveSensorListeners.get(sensorType);
325 if (listeners == null) {
326 listeners = new CarSensorListeners(rate);
327 mActiveSensorListeners.put(sensorType, listeners);
328 needsServerUpdate = true;
329 }
330 if (listeners.addAndUpdateRate(listener, rate)) {
331 needsServerUpdate = true;
332 }
333 if (needsServerUpdate) {
334 if (!registerOrUpdateSensorListener(sensorType, rate)) {
335 return false;
336 }
337 }
338 }
339 return true;
340 }
341
342 /**
343 * Stop getting sensor update for the given listener. If there are multiple registrations for
344 * this listener, all listening will be stopped.
345 * @param listener
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700346 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700347 */
Keun-young Park150d8de2016-10-07 15:48:11 -0700348 public void unregisterListener(OnSensorChangedListener listener) {
keunyoungca515072015-07-10 12:21:47 -0700349 //TODO: removing listener should reset update rate
350 synchronized(mActiveSensorListeners) {
351 Iterator<Integer> sensorIterator = mActiveSensorListeners.keySet().iterator();
352 while (sensorIterator.hasNext()) {
353 Integer sensor = sensorIterator.next();
354 doUnregisterListenerLocked(listener, sensor, sensorIterator);
355 }
356 }
357 }
358
359 /**
360 * Stop getting sensor update for the given listener and sensor. If the same listener is used
361 * for other sensors, those subscriptions will not be affected.
362 * @param listener
363 * @param sensorType
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700364 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700365 */
Keun-young Park150d8de2016-10-07 15:48:11 -0700366 public void unregisterListener(OnSensorChangedListener listener, @SensorType int sensorType) {
keunyoungca515072015-07-10 12:21:47 -0700367 synchronized(mActiveSensorListeners) {
368 doUnregisterListenerLocked(listener, sensorType, null);
369 }
370 }
371
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700372 private void doUnregisterListenerLocked(OnSensorChangedListener listener, Integer sensor,
Keun-young Park150d8de2016-10-07 15:48:11 -0700373 Iterator<Integer> sensorIterator) {
keunyoungca515072015-07-10 12:21:47 -0700374 CarSensorListeners listeners = mActiveSensorListeners.get(sensor);
375 if (listeners != null) {
376 if (listeners.contains(listener)) {
377 listeners.remove(listener);
378 }
379 if (listeners.isEmpty()) {
380 try {
381 mService.unregisterSensorListener(sensor.intValue(),
382 mCarSensorEventListenerToService);
383 } catch (RemoteException e) {
Keun-young Park150d8de2016-10-07 15:48:11 -0700384 //ignore
keunyoungca515072015-07-10 12:21:47 -0700385 }
386 if (sensorIterator == null) {
387 mActiveSensorListeners.remove(sensor);
388 } else {
389 sensorIterator.remove();
390 }
391 }
392 }
393 }
394
395 private boolean registerOrUpdateSensorListener(int sensor, int rate)
396 throws CarNotConnectedException {
397 try {
398 if (!mService.registerOrUpdateSensorListener(sensor, rate,
Keun-young Parke54ac272016-02-16 19:02:18 -0800399 mCarSensorEventListenerToService)) {
keunyoungca515072015-07-10 12:21:47 -0700400 return false;
401 }
402 } catch (IllegalStateException e) {
403 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
404 } catch (RemoteException e) {
Vitalii Tomkiv235f8ac2016-04-04 11:26:49 -0700405 throw new CarNotConnectedException(e);
keunyoungca515072015-07-10 12:21:47 -0700406 }
407 return true;
408 }
409
410 /**
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800411 * Get the most recent CarSensorEvent for the given type. Note that latest sensor data from car
412 * will not be available if it was never subscribed before. This call will return immediately
413 * with null if there is no data available.
keunyoungca515072015-07-10 12:21:47 -0700414 * @param type A sensor to request
415 * @return null if there was no sensor update since connected to the car.
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700416 * @throws CarNotConnectedException if the connection to the car service has been lost.
keunyoungca515072015-07-10 12:21:47 -0700417 */
Keun-young Parkaf2cc992016-10-07 11:46:45 -0700418 public CarSensorEvent getLatestSensorEvent(@SensorType int type)
419 throws CarNotConnectedException {
keunyoungca515072015-07-10 12:21:47 -0700420 assertSensorType(type);
421 try {
422 return mService.getLatestSensorEvent(type);
423 } catch (IllegalStateException e) {
424 CarApiUtil.checkCarNotConnectedExceptionFromCarService(e);
425 } catch(RemoteException e) {
426 handleCarServiceRemoteExceptionAndThrow(e);
427 }
428 return null;
429 }
430
431 private void handleCarServiceRemoteExceptionAndThrow(RemoteException e)
432 throws CarNotConnectedException {
433 if (Log.isLoggable(CarLibLog.TAG_SENSOR, Log.INFO)) {
434 Log.i(CarLibLog.TAG_SENSOR, "RemoteException from car service:" + e.getMessage());
435 }
436 throw new CarNotConnectedException();
437 }
438
439 private void assertSensorType(int sensorType) {
Keun-young Park064ddd82015-12-21 23:57:50 +0000440 if (sensorType == 0 || !((sensorType <= SENSOR_TYPE_MAX) ||
441 ((sensorType >= SENSOR_TYPE_VENDOR_EXTENSION_START) &&
442 (sensorType <= SENSOR_TYPE_VENDOR_EXTENSION_END)))) {
keunyoungca515072015-07-10 12:21:47 -0700443 throw new IllegalArgumentException("invalid sensor type " + sensorType);
444 }
445 }
446
keunyoungcc449f72015-08-12 10:46:27 -0700447 private void handleOnSensorChanged(List<CarSensorEvent> events) {
448 mHandler.sendMessage(mHandler.obtainMessage(MSG_SENSOR_EVENTS, events));
keunyoungca515072015-07-10 12:21:47 -0700449 }
450
451 private static class CarSensorEventListenerToService extends ICarSensorEventListener.Stub {
452 private final WeakReference<CarSensorManager> mManager;
453
454 public CarSensorEventListenerToService(CarSensorManager manager) {
455 mManager = new WeakReference<CarSensorManager>(manager);
456 }
457
458 @Override
keunyoungcc449f72015-08-12 10:46:27 -0700459 public void onSensorChanged(List<CarSensorEvent> events) {
keunyoungca515072015-07-10 12:21:47 -0700460 CarSensorManager manager = mManager.get();
461 if (manager != null) {
keunyoungcc449f72015-08-12 10:46:27 -0700462 manager.handleOnSensorChanged(events);
keunyoungca515072015-07-10 12:21:47 -0700463 }
464 }
465 }
466
467 /**
468 * Represent listeners for a sensor.
469 */
470 private class CarSensorListeners {
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700471 private final LinkedList<OnSensorChangedListener> mListeners =
472 new LinkedList<OnSensorChangedListener>();
keunyoungca515072015-07-10 12:21:47 -0700473
474 private int mUpdateRate;
475 private long mLastUpdateTime = -1;
476
477 CarSensorListeners(int rate) {
478 mUpdateRate = rate;
479 }
480
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700481 boolean contains(OnSensorChangedListener listener) {
keunyoungca515072015-07-10 12:21:47 -0700482 return mListeners.contains(listener);
483 }
484
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700485 void remove(OnSensorChangedListener listener) {
keunyoungca515072015-07-10 12:21:47 -0700486 mListeners.remove(listener);
487 }
488
489 boolean isEmpty() {
490 return mListeners.isEmpty();
491 }
492
493 /**
494 * Add given listener to the list and update rate if necessary.
495 * @param listener if null, add part is skipped.
496 * @param updateRate
497 * @return true if rate was updated. Otherwise, returns false.
498 */
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700499 boolean addAndUpdateRate(OnSensorChangedListener listener, int updateRate) {
keunyoungca515072015-07-10 12:21:47 -0700500 if (!mListeners.contains(listener)) {
501 mListeners.add(listener);
502 }
503 if (mUpdateRate > updateRate) {
504 mUpdateRate = updateRate;
505 return true;
506 }
507 return false;
508 }
509
510 void onSensorChanged(CarSensorEvent event) {
511 // throw away old sensor data as oneway binder call can change order.
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700512 long updateTime = event.timestamp;
keunyoungca515072015-07-10 12:21:47 -0700513 if (updateTime < mLastUpdateTime) {
514 Log.w(CarLibLog.TAG_SENSOR, "dropping old sensor data");
515 return;
516 }
517 mLastUpdateTime = updateTime;
Jason Tholstrupd72b5352016-09-22 16:32:14 -0700518 for (OnSensorChangedListener listener: mListeners) {
keunyoungca515072015-07-10 12:21:47 -0700519 listener.onSensorChanged(event);
520 }
521 }
522 }
523}