Home | History | Annotate | Download | only in car
      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