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 */ onSensorEvents(List<CarSensorEvent> events)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 SensorHalService(VehicleHal hal)96 public SensorHalService(VehicleHal hal) { 97 super(hal); 98 } 99 registerSensorListener(SensorListener listener)100 public synchronized void registerSensorListener(SensorListener listener) { 101 mSensorListener = listener; 102 } 103 104 @Override getTokenForProperty(VehiclePropConfig halProperty)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 handleHalEvents(List<VehiclePropValue> values)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 mapHalEnumValueToMgr(int propId, int halValue)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 createCarSensorEvent(VehiclePropValue v)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 getCurrentSensorValue(int sensorType)186 public CarSensorEvent getCurrentSensorValue(int sensorType) { 187 VehiclePropValue propValue = getCurrentSensorVehiclePropValue(sensorType); 188 return (null != propValue) ? createCarSensorEvent(propValue) : null; 189 } 190 191 @Override fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate)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 dump(PrintWriter writer)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 initSparseIntArray(int... keyValuePairs)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