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 static java.lang.Integer.toHexString;
     20 
     21 import android.annotation.Nullable;
     22 import android.car.hardware.CarSensorEvent;
     23 import android.car.hardware.CarSensorManager;
     24 import android.hardware.automotive.vehicle.V2_0.VehicleGear;
     25 import android.hardware.automotive.vehicle.V2_0.VehicleIgnitionState;
     26 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
     27 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
     28 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
     29 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
     30 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
     31 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
     32 import android.util.Log;
     33 import android.util.SparseIntArray;
     34 import com.android.car.CarLog;
     35 import com.android.car.CarSensorEventFactory;
     36 import java.io.PrintWriter;
     37 import java.util.LinkedList;
     38 import java.util.List;
     39 
     40 /**
     41  * Sensor HAL implementation for physical sensors in car.
     42  */
     43 public class SensorHalService extends SensorHalServiceBase {
     44     private static final String TAG = CarLog.concatTag(CarLog.TAG_SENSOR, SensorHalService.class);
     45     private static final boolean DBG_EVENTS = false;
     46 
     47     /**
     48      * Listener for monitoring sensor event. Only sensor service will implement this.
     49      */
     50     public interface SensorListener {
     51         /**
     52          * Sensor events are available.
     53          * @param events
     54          */
     55         void onSensorEvents(List<CarSensorEvent> events);
     56     }
     57 
     58     // Manager property Id to HAL property Id mapping.
     59     private final static ManagerToHalPropIdMap mManagerToHalPropIdMap =
     60             ManagerToHalPropIdMap.create(
     61                     CarSensorManager.SENSOR_TYPE_CAR_SPEED, VehicleProperty.PERF_VEHICLE_SPEED,
     62                     CarSensorManager.SENSOR_TYPE_RPM, VehicleProperty.ENGINE_RPM,
     63                     CarSensorManager.SENSOR_TYPE_ODOMETER, VehicleProperty.PERF_ODOMETER,
     64                     CarSensorManager.SENSOR_TYPE_GEAR, VehicleProperty.GEAR_SELECTION,
     65                     CarSensorManager.SENSOR_TYPE_NIGHT, VehicleProperty.NIGHT_MODE,
     66                     CarSensorManager.SENSOR_TYPE_PARKING_BRAKE, VehicleProperty.PARKING_BRAKE_ON,
     67                     CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, VehicleProperty.DRIVING_STATUS,
     68                     CarSensorManager.SENSOR_TYPE_FUEL_LEVEL, VehicleProperty.FUEL_LEVEL_LOW,
     69                     CarSensorManager.SENSOR_TYPE_IGNITION_STATE, VehicleProperty.IGNITION_STATE);
     70 
     71     private final static SparseIntArray mMgrGearToHalMap = initSparseIntArray(
     72             VehicleGear.GEAR_NEUTRAL, CarSensorEvent.GEAR_NEUTRAL,
     73             VehicleGear.GEAR_REVERSE, CarSensorEvent.GEAR_REVERSE,
     74             VehicleGear.GEAR_PARK, CarSensorEvent.GEAR_PARK,
     75             VehicleGear.GEAR_DRIVE, CarSensorEvent.GEAR_DRIVE,
     76             VehicleGear.GEAR_LOW, CarSensorEvent.GEAR_FIRST, // Also GEAR_1 - the value is the same.
     77             VehicleGear.GEAR_2, CarSensorEvent.GEAR_SECOND,
     78             VehicleGear.GEAR_3, CarSensorEvent.GEAR_THIRD,
     79             VehicleGear.GEAR_4, CarSensorEvent.GEAR_FOURTH,
     80             VehicleGear.GEAR_5, CarSensorEvent.GEAR_FIFTH,
     81             VehicleGear.GEAR_6, CarSensorEvent.GEAR_SIXTH,
     82             VehicleGear.GEAR_7, CarSensorEvent.GEAR_SEVENTH,
     83             VehicleGear.GEAR_8, CarSensorEvent.GEAR_EIGHTH,
     84             VehicleGear.GEAR_9, CarSensorEvent.GEAR_NINTH);
     85 
     86     private final static SparseIntArray mMgrIgnitionStateToHalMap = initSparseIntArray(
     87             VehicleIgnitionState.UNDEFINED, CarSensorEvent.IGNITION_STATE_UNDEFINED,
     88             VehicleIgnitionState.LOCK, CarSensorEvent.IGNITION_STATE_LOCK,
     89             VehicleIgnitionState.OFF, CarSensorEvent.IGNITION_STATE_OFF,
     90             VehicleIgnitionState.ACC, CarSensorEvent.IGNITION_STATE_ACC,
     91             VehicleIgnitionState.ON, CarSensorEvent.IGNITION_STATE_ON,
     92             VehicleIgnitionState.START, CarSensorEvent.IGNITION_STATE_START);
     93 
     94     private SensorListener mSensorListener;
     95 
     96     public SensorHalService(VehicleHal hal) {
     97         super(hal);
     98     }
     99 
    100     public synchronized void registerSensorListener(SensorListener listener) {
    101         mSensorListener = listener;
    102     }
    103 
    104     @Override
    105     protected int getTokenForProperty(VehiclePropConfig halProperty) {
    106         int sensor = mManagerToHalPropIdMap.getManagerPropId(halProperty.prop);
    107         if (sensor != SENSOR_TYPE_INVALID
    108             && halProperty.changeMode != VehiclePropertyChangeMode.STATIC
    109             && ((halProperty.access & VehiclePropertyAccess.READ) != 0)) {
    110             return sensor;
    111         }
    112         return SENSOR_TYPE_INVALID;
    113     }
    114 
    115     // Should be used only inside handleHalEvents method.
    116     private final LinkedList<CarSensorEvent> mEventsToDispatch = new LinkedList<>();
    117     @Override
    118     public void handleHalEvents(List<VehiclePropValue> values) {
    119         for (VehiclePropValue v : values) {
    120             CarSensorEvent event = createCarSensorEvent(v);
    121             if (event != null) {
    122                 mEventsToDispatch.add(event);
    123             }
    124         }
    125         SensorListener sensorListener;
    126         synchronized (this) {
    127             sensorListener = mSensorListener;
    128         }
    129         if (DBG_EVENTS) Log.d(TAG, "handleHalEvents, listener: " + sensorListener);
    130         if (sensorListener != null) {
    131             sensorListener.onSensorEvents(mEventsToDispatch);
    132         }
    133         mEventsToDispatch.clear();
    134     }
    135 
    136     @Nullable
    137     private Integer mapHalEnumValueToMgr(int propId, int halValue) {
    138         int mgrValue = halValue;
    139 
    140         switch (propId) {
    141             case VehicleProperty.GEAR_SELECTION:
    142                 mgrValue = mMgrGearToHalMap.get(halValue, -1);
    143                 break;
    144             case VehicleProperty.IGNITION_STATE:
    145                 mgrValue =  mMgrIgnitionStateToHalMap.get(halValue, -1);
    146             default:
    147                 break; // Do nothing
    148         }
    149         return mgrValue == -1 ? null : mgrValue;
    150     }
    151 
    152     @Nullable
    153     private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
    154         int property = v.prop;
    155         int sensorType = mManagerToHalPropIdMap.getManagerPropId(property);
    156         if (sensorType == SENSOR_TYPE_INVALID) {
    157             throw new RuntimeException("no sensor defined for property 0x" + toHexString(property));
    158         }
    159 
    160         int dataType = property & VehiclePropertyType.MASK;
    161 
    162         CarSensorEvent event = null;
    163         switch (dataType) {
    164             case VehiclePropertyType.BOOLEAN:
    165                 event = CarSensorEventFactory.createBooleanEvent(sensorType, v.timestamp,
    166                         v.value.int32Values.get(0) == 1);
    167                 break;
    168             case VehiclePropertyType.INT32:
    169                 Integer mgrVal = mapHalEnumValueToMgr(property, v.value.int32Values.get(0));
    170                 event =  mgrVal == null ? null
    171                         : CarSensorEventFactory.createIntEvent(sensorType, v.timestamp, mgrVal);
    172                 break;
    173             case VehiclePropertyType.FLOAT: {
    174                 event = CarSensorEventFactory.createFloatEvent(sensorType, v.timestamp,
    175                         v.value.floatValues.get(0));
    176                 break;
    177             }
    178             default:
    179                 Log.w(TAG, "createCarSensorEvent: unsupported type: 0x" + toHexString(dataType));
    180         }
    181         if (DBG_EVENTS) Log.i(TAG, "Sensor event created: " + event);
    182         return event;
    183     }
    184 
    185     @Nullable
    186     public CarSensorEvent getCurrentSensorValue(int sensorType) {
    187         VehiclePropValue propValue = getCurrentSensorVehiclePropValue(sensorType);
    188         return (null != propValue) ? createCarSensorEvent(propValue) : null;
    189     }
    190 
    191     @Override
    192     protected float fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate) {
    193         switch (prop.changeMode) {
    194             case VehiclePropertyChangeMode.ON_CHANGE:
    195             case VehiclePropertyChangeMode.ON_SET:
    196                 return 0;
    197         }
    198         float rate = 1.0f;
    199         switch (carSensorManagerRate) {
    200             case CarSensorManager.SENSOR_RATE_FASTEST:
    201                 rate = prop.maxSampleRate;
    202                 break;
    203             case CarSensorManager.SENSOR_RATE_FAST:
    204                 rate = 10f;  // every 100ms
    205                 break;
    206             case CarSensorManager.SENSOR_RATE_UI:
    207                 rate = 5f;   // every 200ms
    208                 break;
    209             default: // fall back to default.
    210                 break;
    211         }
    212         if (rate > prop.maxSampleRate) {
    213             rate = prop.maxSampleRate;
    214         }
    215         if (rate < prop.minSampleRate) {
    216             rate = prop.minSampleRate;
    217         }
    218         return rate;
    219     }
    220 
    221     @Override
    222     public void dump(PrintWriter writer) {
    223         writer.println("*Sensor HAL*");
    224         writer.println("**Supported properties**");
    225         for (int i = 0; i < mSensorToPropConfig.size(); i++) {
    226             writer.println(mSensorToPropConfig.valueAt(i).toString());
    227         }
    228     }
    229 
    230     private static SparseIntArray initSparseIntArray(int... keyValuePairs) {
    231         int inputLength = keyValuePairs.length;
    232         if (inputLength % 2 != 0) {
    233             throw new IllegalArgumentException("Odd number of key-value elements");
    234         }
    235 
    236         SparseIntArray map = new SparseIntArray(inputLength / 2);
    237         for (int i = 0; i < keyValuePairs.length; i += 2) {
    238             map.put(keyValuePairs[i], keyValuePairs[i + 1]);
    239         }
    240         return map;
    241     }
    242 }
    243