blob: d2c27147345bd781c15d7f7110c32f7b64d7aac7 [file] [log] [blame]
keunyoungcc449f72015-08-12 10:46:27 -07001/*
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
17package com.android.car.hal;
18
Pavel Maltsev0d07c762016-11-03 16:40:15 -070019import static android.hardware.vehicle.V2_0.VehicleProperty.DRIVING_STATUS;
20import static android.hardware.vehicle.V2_0.VehicleProperty.FUEL_LEVEL_LOW;
21import static android.hardware.vehicle.V2_0.VehicleProperty.GEAR_SELECTION;
22import static android.hardware.vehicle.V2_0.VehicleProperty.NIGHT_MODE;
23import static android.hardware.vehicle.V2_0.VehicleProperty.PARKING_BRAKE_ON;
24import static android.hardware.vehicle.V2_0.VehicleProperty.PERF_VEHICLE_SPEED;
25import static java.lang.Integer.toHexString;
26
27import android.annotation.Nullable;
Keun-young Parke54ac272016-02-16 19:02:18 -080028import android.car.hardware.CarSensorEvent;
29import android.car.hardware.CarSensorManager;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070030import android.hardware.vehicle.V2_0.VehiclePropConfig;
31import android.hardware.vehicle.V2_0.VehiclePropValue;
32import android.hardware.vehicle.V2_0.VehicleProperty;
33import android.hardware.vehicle.V2_0.VehiclePropertyAccess;
34import android.hardware.vehicle.V2_0.VehiclePropertyChangeMode;
keunyoungcc449f72015-08-12 10:46:27 -070035import android.util.Log;
36import android.util.SparseArray;
37
38import com.android.car.CarLog;
39import com.android.car.CarSensorEventFactory;
40
41import java.io.PrintWriter;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070042import java.util.Collection;
keunyoungcc449f72015-08-12 10:46:27 -070043import java.util.LinkedList;
44import java.util.List;
45
46/**
47 * Sensor HAL implementation for physical sensors in car.
48 */
49public class SensorHalService extends SensorHalServiceBase {
50
keunyoung1ab8e182015-09-24 09:25:22 -070051 private static final boolean DBG_EVENTS = false;
keunyoungcc449f72015-08-12 10:46:27 -070052
Pavel Maltsev0d07c762016-11-03 16:40:15 -070053 private static final int SENSOR_TYPE_INVALID = -1;
keunyoungcc449f72015-08-12 10:46:27 -070054
55 private final VehicleHal mHal;
56 private boolean mIsReady = false;
57 private SensorHalServiceBase.SensorListener mSensorListener;
Pavel Maltsev0d07c762016-11-03 16:40:15 -070058 private final SparseArray<VehiclePropConfig> mSensorToHalProperty = new SparseArray<>();
keunyoungcc449f72015-08-12 10:46:27 -070059
60 public SensorHalService(VehicleHal hal) {
61 mHal = hal;
62 }
63
64 @Override
65 public synchronized void init() {
keunyoungcc449f72015-08-12 10:46:27 -070066 mIsReady = true;
67 }
68
69 @Override
Pavel Maltsev0d07c762016-11-03 16:40:15 -070070 public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
71 Collection<VehiclePropConfig> allProperties) {
72 LinkedList<VehiclePropConfig> supportedProperties = new LinkedList<>();
keunyoungfe30ba02015-09-17 17:56:35 -070073 for (VehiclePropConfig halProperty : allProperties) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -070074 int sensor = getSensorTypeFromHalProperty(halProperty.prop);
75 if (sensor != SENSOR_TYPE_INVALID
76 && halProperty.changeMode != VehiclePropertyChangeMode.STATIC
77 && ((halProperty.access & VehiclePropertyAccess.READ) != 0)) {
keunyoungcc449f72015-08-12 10:46:27 -070078 supportedProperties.add(halProperty);
79 mSensorToHalProperty.append(sensor, halProperty);
80 }
81 }
82 return supportedProperties;
83 }
84
85 @Override
86 public synchronized void release() {
87 mSensorToHalProperty.clear();
88 mIsReady = false;
89 }
90
Pavel Maltsev0d07c762016-11-03 16:40:15 -070091 // Should be used only inside handleHalEvents method.
92 private final LinkedList<CarSensorEvent> mEventsToDispatch = new LinkedList<>();
keunyoungcc449f72015-08-12 10:46:27 -070093 @Override
keunyoungfe30ba02015-09-17 17:56:35 -070094 public void handleHalEvents(List<VehiclePropValue> values) {
95 for (VehiclePropValue v : values) {
96 CarSensorEvent event = createCarSensorEvent(v);
97 if (event != null) {
98 mEventsToDispatch.add(event);
99 }
keunyoungcc449f72015-08-12 10:46:27 -0700100 }
keunyoungfe30ba02015-09-17 17:56:35 -0700101 SensorHalServiceBase.SensorListener sensorListener = null;
102 synchronized (this) {
103 sensorListener = mSensorListener;
keunyoungcc449f72015-08-12 10:46:27 -0700104 }
keunyoungfe30ba02015-09-17 17:56:35 -0700105 if (sensorListener != null) {
106 sensorListener.onSensorEvents(mEventsToDispatch);
107 }
108 mEventsToDispatch.clear();
109 }
110
111 private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700112 int property = v.prop;
keunyoungcc449f72015-08-12 10:46:27 -0700113 int sensorType = getSensorTypeFromHalProperty(property);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700114 if (sensorType == SENSOR_TYPE_INVALID) {
keunyoungcc449f72015-08-12 10:46:27 -0700115 throw new RuntimeException("handleBooleanHalEvent no sensor defined for property " +
116 property);
117 }
keunyoungcc449f72015-08-12 10:46:27 -0700118 switch (property) {
keunyoungfe30ba02015-09-17 17:56:35 -0700119 // boolean
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700120 case VehicleProperty.NIGHT_MODE:
121 case VehicleProperty.PARKING_BRAKE_ON:
122 case VehicleProperty.FUEL_LEVEL_LOW: {
keunyoungfe30ba02015-09-17 17:56:35 -0700123 if (DBG_EVENTS) {
124 Log.i(CarLog.TAG_SENSOR, "boolean event, property:" +
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700125 toHexString(property) + " value:" + v.value.int32Values.get(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700126 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700127 return CarSensorEventFactory.createBooleanEvent(sensorType, v.timestamp,
128 v.value.int32Values.get(0) == 1);
keunyoungfe30ba02015-09-17 17:56:35 -0700129 }
130 // int
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700131 case VehicleProperty.GEAR_SELECTION:
132 case VehicleProperty.DRIVING_STATUS: {
keunyoungfe30ba02015-09-17 17:56:35 -0700133 if (DBG_EVENTS) {
134 Log.i(CarLog.TAG_SENSOR, "int event, property:" +
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700135 toHexString(property) + " value:" + v.value.int32Values.get(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700136 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700137 return CarSensorEventFactory.createIntEvent(sensorType, v.timestamp,
138 v.value.int32Values.get(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700139 }
140 // float
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700141 case VehicleProperty.PERF_VEHICLE_SPEED: {
keunyoungfe30ba02015-09-17 17:56:35 -0700142 if (DBG_EVENTS) {
143 Log.i(CarLog.TAG_SENSOR, "float event, property:" +
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700144 toHexString(property) + " value:" + v.value.floatValues.get(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700145 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700146 return CarSensorEventFactory.createFloatEvent(sensorType, v.timestamp,
147 v.value.floatValues.get(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700148 }
keunyoungcc449f72015-08-12 10:46:27 -0700149 }
keunyoungfe30ba02015-09-17 17:56:35 -0700150 return null;
keunyoungcc449f72015-08-12 10:46:27 -0700151 }
152
153 @Override
154 public synchronized void registerSensorListener(SensorHalServiceBase.SensorListener listener) {
155 mSensorListener = listener;
keunyoungcc449f72015-08-12 10:46:27 -0700156 }
157
158 @Override
159 public synchronized boolean isReady() {
160 return mIsReady;
161 }
162
163 @Override
164 public synchronized int[] getSupportedSensors() {
165 int[] supportedSensors = new int[mSensorToHalProperty.size()];
166 for (int i = 0; i < supportedSensors.length; i++) {
167 supportedSensors[i] = mSensorToHalProperty.keyAt(i);
168 }
169 return supportedSensors;
170 }
171
172 @Override
173 public synchronized boolean requestSensorStart(int sensorType, int rate) {
keunyoungfe30ba02015-09-17 17:56:35 -0700174 VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
175 if (config == null) {
keunyoungcc449f72015-08-12 10:46:27 -0700176 return false;
177 }
Keun-young Parkf9215202016-10-10 12:34:08 -0700178 //TODO calculate sampling rate properly, bug: 32095903
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700179 mHal.subscribeProperty(this, config.prop, fixSamplingRateForProperty(config, rate));
keunyoungfe30ba02015-09-17 17:56:35 -0700180 return true;
keunyoungcc449f72015-08-12 10:46:27 -0700181 }
182
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700183 @Nullable
Keun-young Park05f44812016-02-10 15:32:48 -0800184 public CarSensorEvent getCurrentSensorValue(int sensorType) {
185 VehiclePropConfig config;
186 synchronized (this) {
187 config = mSensorToHalProperty.get(sensorType);
188 }
189 if (config == null) {
Keun-young Park9ec05472016-04-26 21:18:18 -0700190 Log.e(CarLog.TAG_SENSOR, "sensor type not available 0x" +
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700191 toHexString(sensorType));
Keun-young Park05f44812016-02-10 15:32:48 -0800192 return null;
193 }
Keun-young Parkba485482016-03-24 13:24:31 -0700194 try {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700195 VehiclePropValue value = mHal.get(config.prop);
Keun-young Parkba485482016-03-24 13:24:31 -0700196 return createCarSensorEvent(value);
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700197 } catch (PropertyTimeoutException e) {
198 Log.e(CarLog.TAG_SENSOR, "property not ready 0x" + toHexString(config.prop), e);
Keun-young Parkba485482016-03-24 13:24:31 -0700199 return null;
200 }
Keun-young Park05f44812016-02-10 15:32:48 -0800201 }
202
keunyoungfe30ba02015-09-17 17:56:35 -0700203 private float fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700204 switch (prop.changeMode) {
205 case VehiclePropertyChangeMode.ON_CHANGE:
206 case VehiclePropertyChangeMode.ON_SET:
Keun-young Park85dc7bd2016-05-13 13:23:06 -0700207 return 0;
keunyoungcc449f72015-08-12 10:46:27 -0700208 }
209 float rate = 1.0f;
210 switch (carSensorManagerRate) {
211 case CarSensorManager.SENSOR_RATE_FASTEST:
212 case CarSensorManager.SENSOR_RATE_FAST:
213 rate = 10f;
214 break;
215 case CarSensorManager.SENSOR_RATE_UI:
216 rate = 5f;
217 break;
218 default: // fall back to default.
219 break;
220 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700221 if (rate > prop.maxSampleRate) {
222 rate = prop.maxSampleRate;
keunyoungcc449f72015-08-12 10:46:27 -0700223 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700224 if (rate < prop.minSampleRate) {
225 rate = prop.minSampleRate;
keunyoungcc449f72015-08-12 10:46:27 -0700226 }
227 return rate;
228 }
229
230 @Override
231 public synchronized void requestSensorStop(int sensorType) {
keunyoungfe30ba02015-09-17 17:56:35 -0700232 VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
233 if (config == null) {
keunyoungcc449f72015-08-12 10:46:27 -0700234 return;
235 }
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700236 mHal.unsubscribeProperty(this, config.prop);
keunyoungcc449f72015-08-12 10:46:27 -0700237 }
238
239 /**
240 * Covert hal property to sensor type. This is also used to check if specific property
241 * is supported by sensor hal or not.
242 * @param halPropertyType
243 * @return
244 */
245 static int getSensorTypeFromHalProperty(int halPropertyType) {
246 switch (halPropertyType) {
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700247 case PERF_VEHICLE_SPEED:
keunyoungcc449f72015-08-12 10:46:27 -0700248 return CarSensorManager.SENSOR_TYPE_CAR_SPEED;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700249 case GEAR_SELECTION:
keunyoungcc449f72015-08-12 10:46:27 -0700250 return CarSensorManager.SENSOR_TYPE_GEAR;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700251 case NIGHT_MODE:
keunyoungcc449f72015-08-12 10:46:27 -0700252 return CarSensorManager.SENSOR_TYPE_NIGHT;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700253 case PARKING_BRAKE_ON:
keunyoungcc449f72015-08-12 10:46:27 -0700254 return CarSensorManager.SENSOR_TYPE_PARKING_BRAKE;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700255 case DRIVING_STATUS:
keunyoungcc449f72015-08-12 10:46:27 -0700256 return CarSensorManager.SENSOR_TYPE_DRIVING_STATUS;
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700257 case FUEL_LEVEL_LOW:
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800258 return CarSensorManager.SENSOR_TYPE_FUEL_LEVEL;
keunyoungcc449f72015-08-12 10:46:27 -0700259 default:
Pavel Maltsev0d07c762016-11-03 16:40:15 -0700260 return SENSOR_TYPE_INVALID;
keunyoungcc449f72015-08-12 10:46:27 -0700261 }
262 }
263
264 @Override
265 public void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700266 writer.println("*Sensor HAL*");
267 writer.println("**Supported properties**");
keunyoungcc449f72015-08-12 10:46:27 -0700268 for (int i = 0; i < mSensorToHalProperty.size(); i++) {
269 writer.println(mSensorToHalProperty.valueAt(i).toString());
270 }
271 }
272}