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 com.android.car; 18 19 import android.car.Car; 20 import android.car.hardware.CarSensorConfig; 21 import android.car.hardware.CarSensorEvent; 22 import android.car.hardware.CarSensorManager; 23 import android.car.hardware.ICarSensor; 24 import android.car.hardware.ICarSensorEventListener; 25 import android.content.Context; 26 import android.content.pm.PackageManager; 27 import android.os.Binder; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.IBinder; 31 import android.os.Looper; 32 import android.os.Message; 33 import android.os.Process; 34 import android.os.RemoteException; 35 import android.os.SystemClock; 36 import android.util.ArrayMap; 37 import android.util.Log; 38 import android.util.SparseArray; 39 import android.util.SparseBooleanArray; 40 41 import static com.android.car.Listeners.ClientWithRate; 42 import com.android.car.hal.SensorBase; 43 import com.android.car.hal.SensorHalService.SensorListener; 44 import com.google.android.collect.Lists; 45 46 import com.android.car.hal.SensorHalService; 47 import com.android.car.hal.SensorHalServiceBase; 48 import com.android.internal.annotations.GuardedBy; 49 50 import java.io.PrintWriter; 51 import java.util.Arrays; 52 import java.util.ConcurrentModificationException; 53 import java.util.LinkedList; 54 import java.util.List; 55 import java.util.concurrent.TimeUnit; 56 import java.util.concurrent.atomic.AtomicBoolean; 57 import java.util.concurrent.locks.ReentrantLock; 58 59 60 public class CarSensorService extends ICarSensor.Stub 61 implements CarServiceBase, SensorHalService.SensorListener { 62 63 /** 64 * Abstraction for logical sensor which is not physical sensor but presented as sensor to 65 * upper layer. Currently {@link CarSensorManager#SENSOR_TYPE_NIGHT} and 66 * {@link CarSensorManager#SENSOR_TYPE_DRIVING_STATUS} falls into this category. 67 * Implementation can call {@link CarSensorService#onSensorData(CarSensorEvent)} when there 68 * is state change for the given sensor after {@link SensorHalServiceBase#init()} 69 * is called. 70 */ 71 public static abstract class LogicalSensor implements SensorBase { 72 private final LinkedList<CarSensorEvent> mDispatchQ = new LinkedList<>(); 73 74 /** Sensor service is ready and all vehicle sensors are available. */ onSensorServiceReady()75 public abstract void onSensorServiceReady(); 76 77 /** 78 * Utility to help service to send one event as listener only takes list form. 79 * @param listener 80 * @param event 81 */ dispatchCarSensorEvent(SensorListener listener, CarSensorEvent event)82 protected void dispatchCarSensorEvent(SensorListener listener, CarSensorEvent event) { 83 synchronized (mDispatchQ) { 84 mDispatchQ.add(event); 85 listener.onSensorEvents(mDispatchQ); 86 mDispatchQ.clear(); 87 } 88 } 89 } 90 91 /** 92 * When set, sensor service sets its own dispatching rate limit. 93 * VehicleNetworkService is already doing this, so not necessary to set it for now. 94 */ 95 private static final boolean ENABLE_DISPATCHING_LIMIT = false; 96 97 /** {@link #mSensorLock} is not waited forever for handling disconnection */ 98 private static final long MAX_SENSOR_LOCK_WAIT_MS = 1000; 99 100 /** lock to access sensor structures */ 101 private final ReentrantLock mSensorLock = new ReentrantLock(); 102 /** hold clients callback */ 103 @GuardedBy("mSensorLock") 104 private final LinkedList<SensorClient> mClients = new LinkedList<>(); 105 106 /** key: sensor type. */ 107 @GuardedBy("mSensorLock") 108 private final SparseArray<Listeners<SensorClient>> mSensorListeners = new SparseArray<>(); 109 /** key: sensor type. */ 110 @GuardedBy("mSensorLock") 111 private final SparseArray<SensorRecord> mSensorRecords = new SparseArray<>(); 112 113 private final SensorHalService mSensorHal; 114 private int[] mCarProvidedSensors; 115 private int[] mSupportedSensors; 116 private final AtomicBoolean mSensorDiscovered = new AtomicBoolean(false); 117 118 private final Context mContext; 119 120 private final DrivingStatePolicy mDrivingStatePolicy; 121 private boolean mUseDefaultDrivingPolicy = true; 122 private final DayNightModePolicy mDayNightModePolicy; 123 private boolean mUseDefaultDayNightModePolicy = true; 124 125 private final HandlerThread mHandlerThread; 126 private final SensorDispatchHandler mSensorDispatchHandler; 127 CarSensorService(Context context, SensorHalService sensorHal)128 public CarSensorService(Context context, SensorHalService sensorHal) { 129 mContext = context; 130 if (ENABLE_DISPATCHING_LIMIT) { 131 mHandlerThread = new HandlerThread("SENSOR", Process.THREAD_PRIORITY_AUDIO); 132 mHandlerThread.start(); 133 mSensorDispatchHandler = new SensorDispatchHandler(mHandlerThread.getLooper()); 134 } else { 135 mHandlerThread = null; 136 mSensorDispatchHandler = null; 137 } 138 // This triggers sensor hal init as well. 139 mSensorHal = sensorHal; 140 mDrivingStatePolicy = new DrivingStatePolicy(context, this); 141 mDayNightModePolicy = new DayNightModePolicy(context); 142 } 143 144 @Override init()145 public void init() { 146 mSensorLock.lock(); 147 try { 148 mSensorHal.registerSensorListener(this); 149 mCarProvidedSensors = mSensorHal.getSupportedSensors(); 150 mSupportedSensors = refreshSupportedSensorsLocked(); 151 152 addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, 153 getInitialDrivingStatus()); 154 addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_NIGHT, getInitialNightMode()); 155 addNewSensorRecordLocked(CarSensorManager.SENSOR_TYPE_IGNITION_STATE, 156 getInitialIgnitionState()); 157 158 notifyDefaultPoliciesLocked(); 159 } finally { 160 mSensorLock.unlock(); 161 } 162 } 163 getInitialIgnitionState()164 private CarSensorEvent getInitialIgnitionState() { 165 return mSensorHal.getCurrentSensorValue(CarSensorManager.SENSOR_TYPE_IGNITION_STATE); 166 } 167 getInitialNightMode()168 private CarSensorEvent getInitialNightMode() { 169 CarSensorEvent event = null; 170 if (mUseDefaultDayNightModePolicy) { 171 mDayNightModePolicy.init(); 172 mDayNightModePolicy.registerSensorListener(this); 173 } else { 174 event = mSensorHal.getCurrentSensorValue(CarSensorManager.SENSOR_TYPE_NIGHT); 175 Log.i(CarLog.TAG_SENSOR, "initial daynight: " 176 + ((event == null) ? "not ready" : + event.intValues[0])); 177 } 178 if (event == null) { 179 event = DayNightModePolicy.getDefaultValue(CarSensorManager.SENSOR_TYPE_NIGHT); 180 if (!mUseDefaultDayNightModePolicy) { 181 Log.w(CarLog.TAG_SENSOR, "Default daynight set as sensor not ready"); 182 } 183 } 184 return event; 185 } 186 getInitialDrivingStatus()187 private CarSensorEvent getInitialDrivingStatus() { 188 CarSensorEvent event = null; 189 if (mUseDefaultDrivingPolicy) { 190 mDrivingStatePolicy.init(); 191 mDrivingStatePolicy.registerSensorListener(this); 192 } else { 193 event = mSensorHal.getCurrentSensorValue( 194 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS); 195 Log.i(CarLog.TAG_SENSOR, "initial driving status:" + ((event == null)? 196 "not ready" : " 0x" + Integer.toHexString(event.intValues[0]))); 197 } 198 if (event == null) { 199 event = DrivingStatePolicy.getDefaultValue( 200 CarSensorManager.SENSOR_TYPE_DRIVING_STATUS); 201 if (!mUseDefaultDrivingPolicy) { 202 Log.w(CarLog.TAG_SENSOR, "Default driving status set as sensor not ready"); 203 } 204 } 205 return event; 206 } 207 addNewSensorRecordLocked(int type, CarSensorEvent event)208 private void addNewSensorRecordLocked(int type, CarSensorEvent event) { 209 SensorRecord record = new SensorRecord(); 210 record.lastEvent = event; 211 mSensorRecords.put(type,record); 212 } 213 214 @Override release()215 public void release() { 216 if (mHandlerThread != null) { 217 mHandlerThread.quit(); 218 } 219 tryHoldSensorLock(); 220 try { 221 if (mUseDefaultDrivingPolicy) { 222 mDrivingStatePolicy.release(); 223 } 224 if (mUseDefaultDayNightModePolicy) { 225 mDayNightModePolicy.release(); 226 } 227 for (int i = mSensorListeners.size() - 1; i >= 0; --i) { 228 Listeners listener = mSensorListeners.valueAt(i); 229 listener.release(); 230 } 231 mSensorListeners.clear(); 232 mSensorRecords.clear(); 233 mClients.clear(); 234 } finally { 235 releaseSensorLockSafely(); 236 } 237 } 238 tryHoldSensorLock()239 private void tryHoldSensorLock() { 240 try { 241 mSensorLock.tryLock(MAX_SENSOR_LOCK_WAIT_MS, TimeUnit.MILLISECONDS); 242 } catch (InterruptedException e) { 243 //ignore 244 } 245 } 246 releaseSensorLockSafely()247 private void releaseSensorLockSafely() { 248 if (mSensorLock.isHeldByCurrentThread()) { 249 mSensorLock.unlock(); 250 } 251 } 252 notifyDefaultPoliciesLocked()253 private void notifyDefaultPoliciesLocked() { 254 if (mUseDefaultDrivingPolicy) { 255 mDrivingStatePolicy.onSensorServiceReady(); 256 } 257 if (mUseDefaultDayNightModePolicy) { 258 mDayNightModePolicy.onSensorServiceReady(); 259 } 260 } 261 processSensorData(List<CarSensorEvent> events)262 private void processSensorData(List<CarSensorEvent> events) { 263 ArrayMap<SensorClient, List<CarSensorEvent>> eventsByClient = new ArrayMap<>(); 264 265 mSensorLock.lock(); 266 for (CarSensorEvent event: events) { 267 SensorRecord record = mSensorRecords.get(event.sensorType); 268 if (record != null) { 269 if (record.lastEvent == null) { 270 record.lastEvent = event; 271 } else if (record.lastEvent.timestamp < event.timestamp) { 272 record.lastEvent = event; 273 //TODO recycle event, bug: 32094595 274 } else { // wrong timestamp, throw away this. 275 //TODO recycle new event, bug: 32094595 276 continue; 277 } 278 279 Listeners<SensorClient> listeners = mSensorListeners.get(event.sensorType); 280 if (listeners == null) { 281 continue; 282 } 283 284 for (ClientWithRate<SensorClient> clientWithRate : listeners.getClients()) { 285 SensorClient client = clientWithRate.getClient(); 286 List<CarSensorEvent> clientEvents = eventsByClient.get(client); 287 if (clientEvents == null) { 288 clientEvents = new LinkedList<>(); 289 eventsByClient.put(client, clientEvents); 290 } 291 clientEvents.add(event); 292 } 293 } 294 } 295 mSensorLock.unlock(); 296 297 for (ArrayMap.Entry<SensorClient, List<CarSensorEvent>> entry : eventsByClient.entrySet()) { 298 SensorClient client = entry.getKey(); 299 List<CarSensorEvent> clientEvents = entry.getValue(); 300 301 client.dispatchSensorUpdate(clientEvents); 302 } 303 } 304 305 /** 306 * Received sensor data from car. 307 */ 308 @Override onSensorEvents(List<CarSensorEvent> events)309 public void onSensorEvents(List<CarSensorEvent> events) { 310 if (ENABLE_DISPATCHING_LIMIT) { 311 mSensorDispatchHandler.handleSensorEvents(events); 312 } else { 313 processSensorData(events); 314 } 315 } 316 317 @Override getSupportedSensors()318 public int[] getSupportedSensors() { 319 mSensorLock.lock(); 320 int[] supportedSensors = mSupportedSensors; 321 mSensorLock.unlock(); 322 return supportedSensors; 323 } 324 325 @Override registerOrUpdateSensorListener(int sensorType, int rate, ICarSensorEventListener listener)326 public boolean registerOrUpdateSensorListener(int sensorType, int rate, 327 ICarSensorEventListener listener) { 328 boolean shouldStartSensors = false; 329 SensorRecord sensorRecord = null; 330 SensorClient sensorClient = null; 331 Integer oldRate = null; 332 Listeners<SensorClient> sensorListeners = null; 333 mSensorLock.lock(); 334 try { 335 sensorRecord = mSensorRecords.get(sensorType); 336 if (sensorRecord == null) { 337 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.INFO)) { 338 Log.i(CarLog.TAG_SENSOR, "Requested sensor " + sensorType + " not supported"); 339 } 340 return false; 341 } 342 if (Binder.getCallingUid() != Process.myUid()) { 343 switch (getSensorPermission(sensorType)) { 344 case PackageManager.PERMISSION_DENIED: 345 throw new SecurityException("client does not have permission:" 346 + getPermissionName(sensorType) 347 + " pid:" + Binder.getCallingPid() 348 + " uid:" + Binder.getCallingUid()); 349 case PackageManager.PERMISSION_GRANTED: 350 break; 351 } 352 } 353 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 354 Log.d(CarLog.TAG_SENSOR, "registerOrUpdateSensorListener " + sensorType + " " + 355 listener); 356 } 357 sensorClient = findSensorClientLocked(listener); 358 ClientWithRate<SensorClient> sensorClientWithRate = null; 359 sensorListeners = mSensorListeners.get(sensorType); 360 if (sensorClient == null) { 361 sensorClient = new SensorClient(listener); 362 try { 363 listener.asBinder().linkToDeath(sensorClient, 0); 364 } catch (RemoteException e) { 365 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.INFO)) { 366 Log.i(CarLog.TAG_SENSOR, "Adding listener failed."); 367 } 368 return false; 369 } 370 mClients.add(sensorClient); 371 } 372 // If we have a cached event for this sensor, send the event. 373 SensorRecord record = mSensorRecords.get(sensorType); 374 if (record != null && record.lastEvent != null) { 375 sensorClient.dispatchSensorUpdate(Lists.newArrayList(record.lastEvent)); 376 } 377 if (sensorListeners == null) { 378 sensorListeners = new Listeners<>(rate); 379 mSensorListeners.put(sensorType, sensorListeners); 380 shouldStartSensors = true; 381 } else { 382 oldRate = sensorListeners.getRate(); 383 sensorClientWithRate = sensorListeners.findClientWithRate(sensorClient); 384 } 385 if (sensorClientWithRate == null) { 386 sensorClientWithRate = new ClientWithRate<>(sensorClient, rate); 387 sensorListeners.addClientWithRate(sensorClientWithRate); 388 } else { 389 sensorClientWithRate.setRate(rate); 390 } 391 if (sensorListeners.getRate() > rate) { 392 sensorListeners.setRate(rate); 393 shouldStartSensors = sensorSupportRate(sensorType); 394 } 395 sensorClient.addSensor(sensorType); 396 } finally { 397 mSensorLock.unlock(); 398 } 399 // start sensor outside lock as it can take time. 400 if (shouldStartSensors) { 401 if (!startSensor(sensorRecord, sensorType, rate)) { 402 // failed. so remove from active sensor list. 403 mSensorLock.lock(); 404 try { 405 sensorClient.removeSensor(sensorType); 406 if (oldRate != null) { 407 sensorListeners.setRate(oldRate); 408 } else { 409 mSensorListeners.remove(sensorType); 410 } 411 } finally { 412 mSensorLock.unlock(); 413 } 414 return false; 415 } 416 } 417 return true; 418 } 419 sensorSupportRate(int sensorType)420 private boolean sensorSupportRate(int sensorType) { 421 switch (sensorType) { 422 case CarSensorManager.SENSOR_TYPE_CAR_SPEED: 423 case CarSensorManager.SENSOR_TYPE_RPM: 424 case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE: 425 return true; 426 case CarSensorManager.SENSOR_TYPE_ODOMETER: 427 case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL: 428 case CarSensorManager.SENSOR_TYPE_PARKING_BRAKE: 429 case CarSensorManager.SENSOR_TYPE_GEAR: 430 case CarSensorManager.SENSOR_TYPE_NIGHT: 431 case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS: 432 case CarSensorManager.SENSOR_TYPE_ENVIRONMENT: 433 return false; 434 default: 435 Log.w(CarLog.TAG_SENSOR, "sensorSupportRate not listed sensor:" + sensorType); 436 return false; 437 } 438 } 439 getSensorPermission(int sensorType)440 private int getSensorPermission(int sensorType) { 441 String permission = getPermissionName(sensorType); 442 int result = PackageManager.PERMISSION_GRANTED; 443 if (permission != null) { 444 return mContext.checkCallingOrSelfPermission(permission); 445 } 446 // If no permission is required, return granted. 447 return result; 448 } 449 450 //TODO handle per property OEM permission. bug: 32094983 getPermissionName(int sensorType)451 private String getPermissionName(int sensorType) { 452 if ((sensorType >= CarSensorManager.SENSOR_TYPE_VENDOR_EXTENSION_START) && 453 (sensorType >= CarSensorManager.SENSOR_TYPE_VENDOR_EXTENSION_END)) { 454 return Car.PERMISSION_VENDOR_EXTENSION; 455 } 456 String permission = null; 457 switch (sensorType) { 458 case CarSensorManager.SENSOR_TYPE_CAR_SPEED: 459 case CarSensorManager.SENSOR_TYPE_WHEEL_TICK_DISTANCE: 460 permission = Car.PERMISSION_SPEED; 461 break; 462 case CarSensorManager.SENSOR_TYPE_ODOMETER: 463 permission = Car.PERMISSION_MILEAGE; 464 break; 465 case CarSensorManager.SENSOR_TYPE_FUEL_LEVEL: 466 permission = Car.PERMISSION_FUEL; 467 break; 468 case CarSensorManager.SENSOR_TYPE_ABS_ACTIVE: 469 case CarSensorManager.SENSOR_TYPE_TRACTION_CONTROL_ACTIVE: 470 permission = Car.PERMISSION_VEHICLE_DYNAMICS_STATE; 471 break; 472 default: 473 break; 474 } 475 return permission; 476 } 477 startSensor(SensorRecord record, int sensorType, int rate)478 private boolean startSensor(SensorRecord record, int sensorType, int rate) { 479 //TODO handle sensor rate properly. bug: 32095903 480 //Some sensors which report only when there is change should be always set with maximum 481 //rate. For now, set every sensor to the maximum. 482 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.VERBOSE)) { 483 Log.v(CarLog.TAG_SENSOR, "startSensor " + sensorType + " with rate " + rate); 484 } 485 SensorBase sensorHal = getSensorHal(sensorType); 486 if (sensorHal != null) { 487 if (!sensorHal.isReady()) { 488 Log.w(CarLog.TAG_SENSOR, "Sensor channel not available."); 489 return false; 490 } 491 if (record.enabled) { 492 return true; 493 } 494 if (sensorHal.requestSensorStart(sensorType, 0)) { 495 record.enabled = true; 496 return true; 497 } 498 } 499 Log.w(CarLog.TAG_SENSOR, "requestSensorStart failed, sensor type:" + sensorType); 500 return false; 501 } 502 503 @Override unregisterSensorListener(int sensorType, ICarSensorEventListener listener)504 public void unregisterSensorListener(int sensorType, ICarSensorEventListener listener) { 505 boolean shouldStopSensor = false; 506 boolean shouldRestartSensor = false; 507 SensorRecord record = null; 508 int newRate = 0; 509 mSensorLock.lock(); 510 try { 511 record = mSensorRecords.get(sensorType); 512 if (record == null) { 513 // unregister not supported sensor. ignore. 514 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 515 Log.d(CarLog.TAG_SENSOR, "unregister for unsupported sensor"); 516 } 517 return; 518 } 519 SensorClient sensorClient = findSensorClientLocked(listener); 520 if (sensorClient == null) { 521 // never registered or already unregistered. 522 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 523 Log.d(CarLog.TAG_SENSOR, "unregister for not existing client"); 524 } 525 return; 526 } 527 sensorClient.removeSensor(sensorType); 528 if (sensorClient.getNumberOfActiveSensor() == 0) { 529 sensorClient.release(); 530 mClients.remove(sensorClient); 531 } 532 Listeners<SensorClient> sensorListeners = mSensorListeners.get(sensorType); 533 if (sensorListeners == null) { 534 // sensor not active 535 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 536 Log.d(CarLog.TAG_SENSOR, "unregister for non-active sensor"); 537 } 538 return; 539 } 540 ClientWithRate<SensorClient> clientWithRate = 541 sensorListeners.findClientWithRate(sensorClient); 542 if (clientWithRate == null) { 543 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 544 Log.d(CarLog.TAG_SENSOR, "unregister for not registered sensor"); 545 } 546 return; 547 } 548 sensorListeners.removeClientWithRate(clientWithRate); 549 if (sensorListeners.getNumberOfClients() == 0) { 550 shouldStopSensor = true; 551 mSensorListeners.remove(sensorType); 552 } else if (sensorListeners.updateRate()) { // rate changed 553 newRate = sensorListeners.getRate(); 554 shouldRestartSensor = sensorSupportRate(sensorType); 555 } 556 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 557 Log.d(CarLog.TAG_SENSOR, "unregister succeeded"); 558 } 559 } finally { 560 mSensorLock.unlock(); 561 } 562 if (shouldStopSensor) { 563 stopSensor(record, sensorType); 564 } else if (shouldRestartSensor) { 565 startSensor(record, sensorType, newRate); 566 } 567 } 568 569 @Override getSensorConfig(int sensorType)570 public CarSensorConfig getSensorConfig(int sensorType) { 571 if (Binder.getCallingUid() != Process.myUid()) { 572 switch (getSensorPermission(sensorType)) { 573 case PackageManager.PERMISSION_DENIED: 574 throw new SecurityException("client does not have permission:" 575 + getPermissionName(sensorType) 576 + " pid:" + Binder.getCallingPid() 577 + " uid:" + Binder.getCallingUid()); 578 case PackageManager.PERMISSION_GRANTED: 579 break; 580 } 581 } 582 return(mSensorHal.getSensorConfig(sensorType)); 583 } 584 stopSensor(SensorRecord record, int sensorType)585 private void stopSensor(SensorRecord record, int sensorType) { 586 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 587 Log.d(CarLog.TAG_SENSOR, "stopSensor " + sensorType); 588 } 589 SensorBase sensorHal = getSensorHal(sensorType); 590 if (sensorHal == null || !sensorHal.isReady()) { 591 Log.w(CarLog.TAG_SENSOR, "Sensor channel not available."); 592 return; 593 } 594 if (!record.enabled) { 595 return; 596 } 597 record.enabled = false; 598 // make lastEvent invalid as old data can be sent to client when subscription is restarted 599 // later. 600 record.lastEvent = null; 601 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 602 Log.d(CarLog.TAG_SENSOR, "stopSensor requestStop " + sensorType); 603 } 604 sensorHal.requestSensorStop(sensorType); 605 } 606 getSensorHal(int sensorType)607 private SensorBase getSensorHal(int sensorType) { 608 try { 609 mSensorLock.lock(); 610 switch (sensorType) { 611 case CarSensorManager.SENSOR_TYPE_DRIVING_STATUS: 612 if (mUseDefaultDrivingPolicy) { 613 return mDrivingStatePolicy; 614 } 615 break; 616 case CarSensorManager.SENSOR_TYPE_NIGHT: 617 if (mUseDefaultDayNightModePolicy) { 618 return mDayNightModePolicy; 619 } 620 break; 621 } 622 return mSensorHal; 623 } finally { 624 mSensorLock.unlock(); 625 } 626 } 627 628 @Override getLatestSensorEvent(int sensorType)629 public CarSensorEvent getLatestSensorEvent(int sensorType) { 630 SensorRecord record = null; 631 mSensorLock.lock(); 632 try { 633 record = mSensorRecords.get(sensorType); 634 } finally { 635 mSensorLock.unlock(); 636 } 637 if (record != null) { 638 return record.lastEvent; 639 } 640 return null; 641 } 642 refreshSupportedSensorsLocked()643 private int[] refreshSupportedSensorsLocked() { 644 int numCarSensors = (mCarProvidedSensors == null) ? 0 : mCarProvidedSensors.length; 645 for (int i = 0; i < numCarSensors; i++) { 646 int sensor = mCarProvidedSensors[i]; 647 if (sensor == CarSensorManager.SENSOR_TYPE_DRIVING_STATUS) { 648 mUseDefaultDrivingPolicy = false; 649 } else if (sensor == CarSensorManager.SENSOR_TYPE_NIGHT) { 650 mUseDefaultDayNightModePolicy = false; 651 } 652 } 653 int totalNumSensors = numCarSensors; 654 if (mUseDefaultDrivingPolicy) { 655 totalNumSensors++; 656 } 657 if (mUseDefaultDayNightModePolicy) { 658 totalNumSensors++; 659 } 660 // Two logical sensors are always added. 661 int[] supportedSensors = new int[totalNumSensors]; 662 int index = 0; 663 if (mUseDefaultDrivingPolicy) { 664 supportedSensors[index] = CarSensorManager.SENSOR_TYPE_DRIVING_STATUS; 665 index++; 666 } 667 if (mUseDefaultDayNightModePolicy) { 668 supportedSensors[index] = CarSensorManager.SENSOR_TYPE_NIGHT; 669 index++; 670 } 671 672 for (int i = 0; i < numCarSensors; i++) { 673 int sensor = mCarProvidedSensors[i]; 674 675 if (mSensorRecords.get(sensor) == null) { 676 SensorRecord record = new SensorRecord(); 677 mSensorRecords.put(sensor, record); 678 } 679 supportedSensors[index] = sensor; 680 index++; 681 } 682 683 return supportedSensors; 684 } 685 isSensorRealLocked(int sensorType)686 private boolean isSensorRealLocked(int sensorType) { 687 if (mCarProvidedSensors != null) { 688 for (int sensor : mCarProvidedSensors) { 689 if (sensor == sensorType ) { 690 return true; 691 } 692 } 693 } 694 return false; 695 } 696 697 /** 698 * Find SensorClient from client list and return it. 699 * This should be called with mClients locked. 700 * @param listener 701 * @return null if not found. 702 */ findSensorClientLocked(ICarSensorEventListener listener)703 private SensorClient findSensorClientLocked(ICarSensorEventListener listener) { 704 IBinder binder = listener.asBinder(); 705 for (SensorClient sensorClient : mClients) { 706 if (sensorClient.isHoldingListenerBinder(binder)) { 707 return sensorClient; 708 } 709 } 710 return null; 711 } 712 removeClient(SensorClient sensorClient)713 private void removeClient(SensorClient sensorClient) { 714 mSensorLock.lock(); 715 try { 716 for (int sensor: sensorClient.getSensorArray()) { 717 unregisterSensorListener(sensor, 718 sensorClient.getICarSensorEventListener()); 719 } 720 mClients.remove(sensorClient); 721 } finally { 722 mSensorLock.unlock(); 723 } 724 } 725 726 private class SensorDispatchHandler extends Handler { 727 private static final long SENSOR_DISPATCH_MIN_INTERVAL_MS = 16; // over 60Hz 728 729 private static final int MSG_SENSOR_DATA = 0; 730 731 private long mLastSensorDispatchTime = -1; 732 private int mFreeListIndex = 0; 733 private final LinkedList<CarSensorEvent>[] mSensorDataList = new LinkedList[2]; 734 SensorDispatchHandler(Looper looper)735 private SensorDispatchHandler(Looper looper) { 736 super(looper); 737 for (int i = 0; i < mSensorDataList.length; i++) { 738 mSensorDataList[i] = new LinkedList<CarSensorEvent>(); 739 } 740 } 741 handleSensorEvents(List<CarSensorEvent> data)742 private synchronized void handleSensorEvents(List<CarSensorEvent> data) { 743 LinkedList<CarSensorEvent> list = mSensorDataList[mFreeListIndex]; 744 list.addAll(data); 745 requestDispatchLocked(); 746 } 747 handleSensorEvent(CarSensorEvent event)748 private synchronized void handleSensorEvent(CarSensorEvent event) { 749 LinkedList<CarSensorEvent> list = mSensorDataList[mFreeListIndex]; 750 list.add(event); 751 requestDispatchLocked(); 752 } 753 requestDispatchLocked()754 private void requestDispatchLocked() { 755 Message msg = obtainMessage(MSG_SENSOR_DATA); 756 long now = SystemClock.uptimeMillis(); 757 long delta = now - mLastSensorDispatchTime; 758 if (delta > SENSOR_DISPATCH_MIN_INTERVAL_MS) { 759 sendMessage(msg); 760 } else { 761 sendMessageDelayed(msg, SENSOR_DISPATCH_MIN_INTERVAL_MS - delta); 762 } 763 } 764 765 @Override handleMessage(Message msg)766 public void handleMessage(Message msg) { 767 switch (msg.what) { 768 case MSG_SENSOR_DATA: 769 doHandleSensorData(); 770 break; 771 default: 772 break; 773 } 774 } 775 doHandleSensorData()776 private void doHandleSensorData() { 777 List<CarSensorEvent> listToDispatch = null; 778 synchronized (this) { 779 mLastSensorDispatchTime = SystemClock.uptimeMillis(); 780 int nonFreeListIndex = mFreeListIndex ^ 0x1; 781 List<CarSensorEvent> nonFreeList = mSensorDataList[nonFreeListIndex]; 782 List<CarSensorEvent> freeList = mSensorDataList[mFreeListIndex]; 783 if (nonFreeList.size() > 0) { 784 Log.w(CarLog.TAG_SENSOR, "non free list not empty"); 785 // copy again, but this should not be normal case 786 nonFreeList.addAll(freeList); 787 listToDispatch = nonFreeList; 788 freeList.clear(); 789 } else if (freeList.size() > 0) { 790 listToDispatch = freeList; 791 mFreeListIndex = nonFreeListIndex; 792 } 793 } 794 // leave this part outside lock so that time-taking dispatching can be done without 795 // blocking sensor event notification. 796 if (listToDispatch != null) { 797 processSensorData(listToDispatch); 798 listToDispatch.clear(); 799 } 800 } 801 802 } 803 804 /** internal instance for pending client request */ 805 private class SensorClient implements Listeners.IListener { 806 /** callback for sensor events */ 807 private final ICarSensorEventListener mListener; 808 private final SparseBooleanArray mActiveSensors = new SparseBooleanArray(); 809 810 /** when false, it is already released */ 811 private volatile boolean mActive = true; 812 SensorClient(ICarSensorEventListener listener)813 SensorClient(ICarSensorEventListener listener) { 814 this.mListener = listener; 815 } 816 817 @Override equals(Object o)818 public boolean equals(Object o) { 819 if (o instanceof SensorClient && 820 mListener.asBinder() == ((SensorClient) o).mListener.asBinder()) { 821 return true; 822 } 823 return false; 824 } 825 isHoldingListenerBinder(IBinder listenerBinder)826 boolean isHoldingListenerBinder(IBinder listenerBinder) { 827 return mListener.asBinder() == listenerBinder; 828 } 829 addSensor(int sensor)830 void addSensor(int sensor) { 831 mActiveSensors.put(sensor, true); 832 } 833 removeSensor(int sensor)834 void removeSensor(int sensor) { 835 mActiveSensors.delete(sensor); 836 } 837 getNumberOfActiveSensor()838 int getNumberOfActiveSensor() { 839 return mActiveSensors.size(); 840 } 841 getSensorArray()842 int[] getSensorArray() { 843 int[] sensors = new int[mActiveSensors.size()]; 844 for (int i = sensors.length - 1; i >= 0; --i) { 845 sensors[i] = mActiveSensors.keyAt(i); 846 } 847 return sensors; 848 } 849 getICarSensorEventListener()850 ICarSensorEventListener getICarSensorEventListener() { 851 return mListener; 852 } 853 854 /** 855 * Client dead. should remove all sensor requests from client 856 */ 857 @Override binderDied()858 public void binderDied() { 859 mListener.asBinder().unlinkToDeath(this, 0); 860 removeClient(this); 861 } 862 dispatchSensorUpdate(List<CarSensorEvent> events)863 void dispatchSensorUpdate(List<CarSensorEvent> events) { 864 if (events.size() == 0) { 865 return; 866 } 867 if (mActive) { 868 try { 869 mListener.onSensorChanged(events); 870 } catch (RemoteException e) { 871 //ignore. crash will be handled by death handler 872 } 873 } else { 874 if (Log.isLoggable(CarLog.TAG_SENSOR, Log.DEBUG)) { 875 Log.d(CarLog.TAG_SENSOR, "sensor update while client is already released"); 876 } 877 } 878 } 879 880 @Override release()881 public void release() { 882 if (mActive) { 883 mListener.asBinder().unlinkToDeath(this, 0); 884 mActiveSensors.clear(); 885 mActive = false; 886 } 887 } 888 } 889 890 private static class SensorRecord { 891 /** Record the lastly received sensor event */ 892 CarSensorEvent lastEvent = null; 893 /** sensor was enabled by at least one client */ 894 boolean enabled = false; 895 } 896 897 @Override dump(PrintWriter writer)898 public void dump(PrintWriter writer) { 899 writer.println("*CarSensorService*"); 900 writer.println("supported sensors:" + Arrays.toString(mSupportedSensors)); 901 writer.println("**last events for sensors**"); 902 if (mSensorRecords != null) { 903 try { 904 int sensorRecordSize = mSensorRecords.size(); 905 for (int i = 0; i < sensorRecordSize; i++) { 906 int sensor = mSensorRecords.keyAt(i); 907 SensorRecord record = mSensorRecords.get(sensor); 908 if (record != null && record.lastEvent != null) { 909 writer.println("sensor: " + sensor 910 + " active: " + record.enabled); 911 writer.println(" " + record.lastEvent.toString()); 912 } 913 Listeners listeners = mSensorListeners.get(sensor); 914 if (listeners != null) { 915 writer.println(" rate: " + listeners.getRate()); 916 } 917 } 918 } catch (ConcurrentModificationException e) { 919 writer.println("concurrent modification happened"); 920 } 921 } else { 922 writer.println("null records"); 923 } 924 writer.println("**clients**"); 925 try { 926 for (SensorClient client: mClients) { 927 if (client != null) { 928 try { 929 writer.println("binder:" + client.mListener 930 + " active sensors:" + Arrays.toString(client.getSensorArray())); 931 } catch (ConcurrentModificationException e) { 932 writer.println("concurrent modification happened"); 933 } 934 } else { 935 writer.println("null client"); 936 } 937 } 938 } catch (ConcurrentModificationException e) { 939 writer.println("concurrent modification happened"); 940 } 941 writer.println("**sensor listeners**"); 942 try { 943 int sensorListenerSize = mSensorListeners.size(); 944 for (int i = 0; i < sensorListenerSize; i++) { 945 int sensor = mSensorListeners.keyAt(i); 946 Listeners sensorListeners = mSensorListeners.get(sensor); 947 if (sensorListeners != null) { 948 writer.println(" Sensor:" + sensor 949 + " num client:" + sensorListeners.getNumberOfClients() 950 + " rate:" + sensorListeners.getRate()); 951 } 952 } 953 } catch (ConcurrentModificationException e) { 954 writer.println("concurrent modification happened"); 955 } 956 writer.println("mUseDefaultDrivingPolicy:" + mUseDefaultDrivingPolicy + 957 ",mUseDefaultDayNightModePolicy" + mUseDefaultDayNightModePolicy); 958 writer.println("**driving policy**"); 959 if (mUseDefaultDrivingPolicy) { 960 mDrivingStatePolicy.dump(writer); 961 } 962 writer.println("**day/night policy**"); 963 if (mUseDefaultDayNightModePolicy) { 964 mDayNightModePolicy.dump(writer); 965 } 966 } 967 } 968