Home | History | Annotate | Download | only in hal
      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.hal;
     18 
     19 import android.car.hardware.CarSensorEvent;
     20 import android.car.hardware.CarSensorManager;
     21 import android.os.ServiceSpecificException;
     22 import android.util.Log;
     23 import android.util.SparseArray;
     24 
     25 import com.android.car.CarLog;
     26 import com.android.car.CarSensorEventFactory;
     27 import com.android.car.vehiclenetwork.VehicleNetworkConsts;
     28 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess;
     29 import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode;
     30 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
     31 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
     32 
     33 import java.io.PrintWriter;
     34 import java.util.LinkedList;
     35 import java.util.List;
     36 
     37 /**
     38  * Sensor HAL implementation for physical sensors in car.
     39  */
     40 public class SensorHalService extends SensorHalServiceBase {
     41 
     42     private static final boolean DBG_EVENTS = false;
     43 
     44     private static final int SENSOR_TYPE_INVALD = -1;
     45 
     46     private final VehicleHal mHal;
     47     private boolean mIsReady = false;
     48     private SensorHalServiceBase.SensorListener mSensorListener;
     49     private final SparseArray<VehiclePropConfig> mSensorToHalProperty =
     50             new SparseArray<VehiclePropConfig>();
     51 
     52     public SensorHalService(VehicleHal hal) {
     53         mHal = hal;
     54     }
     55 
     56     @Override
     57     public synchronized void init() {
     58         //TODO
     59         mIsReady = true;
     60     }
     61 
     62     @Override
     63     public synchronized List<VehiclePropConfig> takeSupportedProperties(
     64             List<VehiclePropConfig> allProperties) {
     65         LinkedList<VehiclePropConfig> supportedProperties = new LinkedList<VehiclePropConfig>();
     66         for (VehiclePropConfig halProperty : allProperties) {
     67             int sensor = getSensorTypeFromHalProperty(halProperty.getProp());
     68             if (sensor != SENSOR_TYPE_INVALD &&
     69                 halProperty.getChangeMode() !=
     70                     VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_STATIC &&
     71                 (halProperty.getAccess() == VehiclePropAccess.VEHICLE_PROP_ACCESS_READ
     72                     || halProperty.getAccess() ==
     73                     VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE)) {
     74                 supportedProperties.add(halProperty);
     75                 mSensorToHalProperty.append(sensor, halProperty);
     76             }
     77         }
     78         return supportedProperties;
     79     }
     80 
     81     @Override
     82     public synchronized void release() {
     83         mSensorToHalProperty.clear();
     84         mIsReady = false;
     85     }
     86 
     87     // should be used only insidehandleHalEvents.
     88     private final LinkedList<CarSensorEvent> mEventsToDispatch = new LinkedList<CarSensorEvent>();
     89     @Override
     90     public void handleHalEvents(List<VehiclePropValue> values) {
     91         for (VehiclePropValue v : values) {
     92             CarSensorEvent event = createCarSensorEvent(v);
     93             if (event != null) {
     94                 mEventsToDispatch.add(event);
     95             }
     96         }
     97         SensorHalServiceBase.SensorListener sensorListener = null;
     98         synchronized (this) {
     99             sensorListener = mSensorListener;
    100         }
    101         if (sensorListener != null) {
    102             sensorListener.onSensorEvents(mEventsToDispatch);
    103         }
    104         mEventsToDispatch.clear();
    105     }
    106 
    107     private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
    108         int property = v.getProp();
    109         int sensorType = getSensorTypeFromHalProperty(property);
    110         if (sensorType == SENSOR_TYPE_INVALD) {
    111             throw new RuntimeException("handleBooleanHalEvent no sensor defined for property " +
    112                     property);
    113         }
    114         switch (property) {
    115             // boolean
    116             case VehicleNetworkConsts.VEHICLE_PROPERTY_NIGHT_MODE:
    117             case VehicleNetworkConsts.VEHICLE_PROPERTY_PARKING_BRAKE_ON:
    118             case VehicleNetworkConsts.VEHICLE_PROPERTY_FUEL_LEVEL_LOW: {
    119                 if (DBG_EVENTS) {
    120                     Log.i(CarLog.TAG_SENSOR, "boolean event, property:" +
    121                             Integer.toHexString(property) + " value:" + v.getInt32Values(0));
    122                 }
    123                 return CarSensorEventFactory.createBooleanEvent(sensorType, v.getTimestamp(),
    124                         v.getInt32Values(0) == 1);
    125             }
    126             // int
    127             case VehicleNetworkConsts.VEHICLE_PROPERTY_GEAR_SELECTION:
    128             case VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS: {
    129                 if (DBG_EVENTS) {
    130                     Log.i(CarLog.TAG_SENSOR, "int event, property:" +
    131                             Integer.toHexString(property) + " value:" + v.getInt32Values(0));
    132                 }
    133                 return CarSensorEventFactory.createIntEvent(sensorType, v.getTimestamp(),
    134                         v.getInt32Values(0));
    135             }
    136             // float
    137             case VehicleNetworkConsts.VEHICLE_PROPERTY_PERF_VEHICLE_SPEED: {
    138                 if (DBG_EVENTS) {
    139                     Log.i(CarLog.TAG_SENSOR, "float event, property:" +
    140                             Integer.toHexString(property) + " value:" + v.getFloatValues(0));
    141                 }
    142                 return CarSensorEventFactory.createFloatEvent(sensorType, v.getTimestamp(),
    143                         v.getFloatValues(0));
    144             }
    145         }
    146         return null;
    147     }
    148 
    149     @Override
    150     public synchronized void registerSensorListener(SensorHalServiceBase.SensorListener listener) {
    151         mSensorListener = listener;
    152         if (mIsReady) {
    153             listener.onSensorHalReady(this);
    154         }
    155     }
    156 
    157     @Override
    158     public synchronized boolean isReady() {
    159         return mIsReady;
    160     }
    161 
    162     @Override
    163     public synchronized int[] getSupportedSensors() {
    164         int[] supportedSensors = new int[mSensorToHalProperty.size()];
    165         for (int i = 0; i < supportedSensors.length; i++) {
    166             supportedSensors[i] = mSensorToHalProperty.keyAt(i);
    167         }
    168         return supportedSensors;
    169     }
    170 
    171     @Override
    172     public synchronized boolean requestSensorStart(int sensorType, int rate) {
    173         VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
    174         if (config == null) {
    175             return false;
    176         }
    177         //TODO calculate sampling rate properly
    178         mHal.subscribeProperty(this, config.getProp(), fixSamplingRateForProperty(config, rate));
    179         return true;
    180     }
    181 
    182     public CarSensorEvent getCurrentSensorValue(int sensorType) {
    183         VehiclePropConfig config;
    184         synchronized (this) {
    185             config = mSensorToHalProperty.get(sensorType);
    186         }
    187         if (config == null) {
    188             return null;
    189         }
    190         try {
    191             VehiclePropValue value = mHal.getVehicleNetwork().getProperty(config.getProp());
    192             return createCarSensorEvent(value);
    193         } catch (ServiceSpecificException e) {
    194             Log.e(CarLog.TAG_SENSOR, "property not ready 0x" +
    195                     Integer.toHexString(config.getProp()), e);
    196             return null;
    197         }
    198     }
    199 
    200     private float fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate) {
    201         if (prop.getChangeMode() ==  VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE) {
    202             return 0;
    203         }
    204         float rate = 1.0f;
    205         switch (carSensorManagerRate) {
    206             case CarSensorManager.SENSOR_RATE_FASTEST:
    207             case CarSensorManager.SENSOR_RATE_FAST:
    208                 rate = 10f;
    209                 break;
    210             case CarSensorManager.SENSOR_RATE_UI:
    211                 rate = 5f;
    212                 break;
    213             default: // fall back to default.
    214                 break;
    215         }
    216         if (rate > prop.getSampleRateMax()) {
    217             rate = prop.getSampleRateMax();
    218         }
    219         if (rate < prop.getSampleRateMin()) {
    220             rate = prop.getSampleRateMin();
    221         }
    222         return rate;
    223     }
    224 
    225     @Override
    226     public synchronized void requestSensorStop(int sensorType) {
    227         VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
    228         if (config == null) {
    229             return;
    230         }
    231         mHal.unsubscribeProperty(this, config.getProp());
    232     }
    233 
    234     /**
    235      * Covert hal property to sensor type. This is also used to check if specific property
    236      * is supported by sensor hal or not.
    237      * @param halPropertyType
    238      * @return
    239      */
    240     static int getSensorTypeFromHalProperty(int halPropertyType) {
    241         switch (halPropertyType) {
    242             case VehicleNetworkConsts.VEHICLE_PROPERTY_PERF_VEHICLE_SPEED:
    243                 return CarSensorManager.SENSOR_TYPE_CAR_SPEED;
    244             case VehicleNetworkConsts.VEHICLE_PROPERTY_GEAR_SELECTION:
    245                 return CarSensorManager.SENSOR_TYPE_GEAR;
    246             case VehicleNetworkConsts.VEHICLE_PROPERTY_NIGHT_MODE:
    247                 return CarSensorManager.SENSOR_TYPE_NIGHT;
    248             case VehicleNetworkConsts.VEHICLE_PROPERTY_PARKING_BRAKE_ON:
    249                 return CarSensorManager.SENSOR_TYPE_PARKING_BRAKE;
    250             case VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS:
    251                 return CarSensorManager.SENSOR_TYPE_DRIVING_STATUS;
    252             case VehicleNetworkConsts.VEHICLE_PROPERTY_FUEL_LEVEL_LOW:
    253                 return CarSensorManager.SENSOR_TYPE_FUEL_LEVEL;
    254             default:
    255                 return SENSOR_TYPE_INVALD;
    256         }
    257     }
    258 
    259     @Override
    260     public void dump(PrintWriter writer) {
    261         writer.println("*Sensor HAL*");
    262         writer.println("**Supported properties**");
    263         for (int i = 0; i < mSensorToHalProperty.size(); i++) {
    264             writer.println(mSensorToHalProperty.valueAt(i).toString());
    265         }
    266     }
    267 }
    268