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