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