blob: fe80c54d52bb7ba2a1bae06c972c97661e56fd2d [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
Keun-young Parke54ac272016-02-16 19:02:18 -080019import android.car.hardware.CarSensorEvent;
20import android.car.hardware.CarSensorManager;
Keun-young Parkba485482016-03-24 13:24:31 -070021import android.os.ServiceSpecificException;
keunyoungcc449f72015-08-12 10:46:27 -070022import android.util.Log;
23import android.util.SparseArray;
24
25import com.android.car.CarLog;
26import com.android.car.CarSensorEventFactory;
keunyoungfe30ba02015-09-17 17:56:35 -070027import com.android.car.vehiclenetwork.VehicleNetworkConsts;
28import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess;
29import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode;
30import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
31import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
keunyoungcc449f72015-08-12 10:46:27 -070032
33import java.io.PrintWriter;
34import java.util.LinkedList;
35import java.util.List;
36
37/**
38 * Sensor HAL implementation for physical sensors in car.
39 */
40public class SensorHalService extends SensorHalServiceBase {
41
keunyoung1ab8e182015-09-24 09:25:22 -070042 private static final boolean DBG_EVENTS = false;
keunyoungcc449f72015-08-12 10:46:27 -070043
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;
keunyoungfe30ba02015-09-17 17:56:35 -070049 private final SparseArray<VehiclePropConfig> mSensorToHalProperty =
50 new SparseArray<VehiclePropConfig>();
keunyoungcc449f72015-08-12 10:46:27 -070051
52 public SensorHalService(VehicleHal hal) {
53 mHal = hal;
54 }
55
56 @Override
57 public synchronized void init() {
keunyoungcc449f72015-08-12 10:46:27 -070058 mIsReady = true;
59 }
60
61 @Override
keunyoungfe30ba02015-09-17 17:56:35 -070062 public synchronized List<VehiclePropConfig> takeSupportedProperties(
63 List<VehiclePropConfig> allProperties) {
64 LinkedList<VehiclePropConfig> supportedProperties = new LinkedList<VehiclePropConfig>();
65 for (VehiclePropConfig halProperty : allProperties) {
66 int sensor = getSensorTypeFromHalProperty(halProperty.getProp());
keunyoungcc449f72015-08-12 10:46:27 -070067 if (sensor != SENSOR_TYPE_INVALD &&
keunyoungfe30ba02015-09-17 17:56:35 -070068 halProperty.getChangeMode() !=
69 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_STATIC &&
70 (halProperty.getAccess() == VehiclePropAccess.VEHICLE_PROP_ACCESS_READ
71 || halProperty.getAccess() ==
72 VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE)) {
keunyoungcc449f72015-08-12 10:46:27 -070073 supportedProperties.add(halProperty);
74 mSensorToHalProperty.append(sensor, halProperty);
75 }
76 }
77 return supportedProperties;
78 }
79
80 @Override
81 public synchronized void release() {
82 mSensorToHalProperty.clear();
83 mIsReady = false;
84 }
85
keunyoungfe30ba02015-09-17 17:56:35 -070086 // should be used only insidehandleHalEvents.
87 private final LinkedList<CarSensorEvent> mEventsToDispatch = new LinkedList<CarSensorEvent>();
keunyoungcc449f72015-08-12 10:46:27 -070088 @Override
keunyoungfe30ba02015-09-17 17:56:35 -070089 public void handleHalEvents(List<VehiclePropValue> values) {
90 for (VehiclePropValue v : values) {
91 CarSensorEvent event = createCarSensorEvent(v);
92 if (event != null) {
93 mEventsToDispatch.add(event);
94 }
keunyoungcc449f72015-08-12 10:46:27 -070095 }
keunyoungfe30ba02015-09-17 17:56:35 -070096 SensorHalServiceBase.SensorListener sensorListener = null;
97 synchronized (this) {
98 sensorListener = mSensorListener;
keunyoungcc449f72015-08-12 10:46:27 -070099 }
keunyoungfe30ba02015-09-17 17:56:35 -0700100 if (sensorListener != null) {
101 sensorListener.onSensorEvents(mEventsToDispatch);
102 }
103 mEventsToDispatch.clear();
104 }
105
106 private CarSensorEvent createCarSensorEvent(VehiclePropValue v) {
107 int property = v.getProp();
keunyoungcc449f72015-08-12 10:46:27 -0700108 int sensorType = getSensorTypeFromHalProperty(property);
109 if (sensorType == SENSOR_TYPE_INVALD) {
110 throw new RuntimeException("handleBooleanHalEvent no sensor defined for property " +
111 property);
112 }
keunyoungcc449f72015-08-12 10:46:27 -0700113 switch (property) {
keunyoungfe30ba02015-09-17 17:56:35 -0700114 // boolean
115 case VehicleNetworkConsts.VEHICLE_PROPERTY_NIGHT_MODE:
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800116 case VehicleNetworkConsts.VEHICLE_PROPERTY_PARKING_BRAKE_ON:
117 case VehicleNetworkConsts.VEHICLE_PROPERTY_FUEL_LEVEL_LOW: {
keunyoungfe30ba02015-09-17 17:56:35 -0700118 if (DBG_EVENTS) {
119 Log.i(CarLog.TAG_SENSOR, "boolean event, property:" +
keunyoungd32f4e62015-09-21 11:33:06 -0700120 Integer.toHexString(property) + " value:" + v.getInt32Values(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700121 }
122 return CarSensorEventFactory.createBooleanEvent(sensorType, v.getTimestamp(),
keunyoungd32f4e62015-09-21 11:33:06 -0700123 v.getInt32Values(0) == 1);
keunyoungfe30ba02015-09-17 17:56:35 -0700124 }
125 // int
126 case VehicleNetworkConsts.VEHICLE_PROPERTY_GEAR_SELECTION:
127 case VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS: {
128 if (DBG_EVENTS) {
129 Log.i(CarLog.TAG_SENSOR, "int event, property:" +
keunyoungd32f4e62015-09-21 11:33:06 -0700130 Integer.toHexString(property) + " value:" + v.getInt32Values(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700131 }
132 return CarSensorEventFactory.createIntEvent(sensorType, v.getTimestamp(),
keunyoungd32f4e62015-09-21 11:33:06 -0700133 v.getInt32Values(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700134 }
135 // float
136 case VehicleNetworkConsts.VEHICLE_PROPERTY_PERF_VEHICLE_SPEED: {
137 if (DBG_EVENTS) {
138 Log.i(CarLog.TAG_SENSOR, "float event, property:" +
keunyoungd32f4e62015-09-21 11:33:06 -0700139 Integer.toHexString(property) + " value:" + v.getFloatValues(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700140 }
141 return CarSensorEventFactory.createFloatEvent(sensorType, v.getTimestamp(),
keunyoungd32f4e62015-09-21 11:33:06 -0700142 v.getFloatValues(0));
keunyoungfe30ba02015-09-17 17:56:35 -0700143 }
keunyoungcc449f72015-08-12 10:46:27 -0700144 }
keunyoungfe30ba02015-09-17 17:56:35 -0700145 return null;
keunyoungcc449f72015-08-12 10:46:27 -0700146 }
147
148 @Override
149 public synchronized void registerSensorListener(SensorHalServiceBase.SensorListener listener) {
150 mSensorListener = listener;
keunyoungcc449f72015-08-12 10:46:27 -0700151 }
152
153 @Override
154 public synchronized boolean isReady() {
155 return mIsReady;
156 }
157
158 @Override
159 public synchronized int[] getSupportedSensors() {
160 int[] supportedSensors = new int[mSensorToHalProperty.size()];
161 for (int i = 0; i < supportedSensors.length; i++) {
162 supportedSensors[i] = mSensorToHalProperty.keyAt(i);
163 }
164 return supportedSensors;
165 }
166
167 @Override
168 public synchronized boolean requestSensorStart(int sensorType, int rate) {
keunyoungfe30ba02015-09-17 17:56:35 -0700169 VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
170 if (config == null) {
keunyoungcc449f72015-08-12 10:46:27 -0700171 return false;
172 }
173 //TODO calculate sampling rate properly
keunyoungd32f4e62015-09-21 11:33:06 -0700174 mHal.subscribeProperty(this, config.getProp(), fixSamplingRateForProperty(config, rate));
keunyoungfe30ba02015-09-17 17:56:35 -0700175 return true;
keunyoungcc449f72015-08-12 10:46:27 -0700176 }
177
Keun-young Park05f44812016-02-10 15:32:48 -0800178 public CarSensorEvent getCurrentSensorValue(int sensorType) {
179 VehiclePropConfig config;
180 synchronized (this) {
181 config = mSensorToHalProperty.get(sensorType);
182 }
183 if (config == null) {
Keun-young Park9ec05472016-04-26 21:18:18 -0700184 Log.e(CarLog.TAG_SENSOR, "sensor type not available 0x" +
185 Integer.toHexString(sensorType));
Keun-young Park05f44812016-02-10 15:32:48 -0800186 return null;
187 }
Keun-young Parkba485482016-03-24 13:24:31 -0700188 try {
189 VehiclePropValue value = mHal.getVehicleNetwork().getProperty(config.getProp());
190 return createCarSensorEvent(value);
191 } catch (ServiceSpecificException e) {
192 Log.e(CarLog.TAG_SENSOR, "property not ready 0x" +
193 Integer.toHexString(config.getProp()), e);
194 return null;
195 }
Keun-young Park05f44812016-02-10 15:32:48 -0800196 }
197
keunyoungfe30ba02015-09-17 17:56:35 -0700198 private float fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate) {
Keun-young Park85dc7bd2016-05-13 13:23:06 -0700199 switch (prop.getChangeMode()) {
200 case VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE:
201 case VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_SET:
202 return 0;
keunyoungcc449f72015-08-12 10:46:27 -0700203 }
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 }
keunyoungfe30ba02015-09-17 17:56:35 -0700216 if (rate > prop.getSampleRateMax()) {
217 rate = prop.getSampleRateMax();
keunyoungcc449f72015-08-12 10:46:27 -0700218 }
keunyoungfe30ba02015-09-17 17:56:35 -0700219 if (rate < prop.getSampleRateMin()) {
220 rate = prop.getSampleRateMin();
keunyoungcc449f72015-08-12 10:46:27 -0700221 }
222 return rate;
223 }
224
225 @Override
226 public synchronized void requestSensorStop(int sensorType) {
keunyoungfe30ba02015-09-17 17:56:35 -0700227 VehiclePropConfig config = mSensorToHalProperty.get(sensorType);
228 if (config == null) {
keunyoungcc449f72015-08-12 10:46:27 -0700229 return;
230 }
keunyoungd32f4e62015-09-21 11:33:06 -0700231 mHal.unsubscribeProperty(this, config.getProp());
keunyoungcc449f72015-08-12 10:46:27 -0700232 }
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) {
keunyoungfe30ba02015-09-17 17:56:35 -0700242 case VehicleNetworkConsts.VEHICLE_PROPERTY_PERF_VEHICLE_SPEED:
keunyoungcc449f72015-08-12 10:46:27 -0700243 return CarSensorManager.SENSOR_TYPE_CAR_SPEED;
keunyoungfe30ba02015-09-17 17:56:35 -0700244 case VehicleNetworkConsts.VEHICLE_PROPERTY_GEAR_SELECTION:
keunyoungcc449f72015-08-12 10:46:27 -0700245 return CarSensorManager.SENSOR_TYPE_GEAR;
keunyoungfe30ba02015-09-17 17:56:35 -0700246 case VehicleNetworkConsts.VEHICLE_PROPERTY_NIGHT_MODE:
keunyoungcc449f72015-08-12 10:46:27 -0700247 return CarSensorManager.SENSOR_TYPE_NIGHT;
keunyoungfe30ba02015-09-17 17:56:35 -0700248 case VehicleNetworkConsts.VEHICLE_PROPERTY_PARKING_BRAKE_ON:
keunyoungcc449f72015-08-12 10:46:27 -0700249 return CarSensorManager.SENSOR_TYPE_PARKING_BRAKE;
keunyoungfe30ba02015-09-17 17:56:35 -0700250 case VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS:
keunyoungcc449f72015-08-12 10:46:27 -0700251 return CarSensorManager.SENSOR_TYPE_DRIVING_STATUS;
Keun-young Park4afc6ee2016-03-04 18:18:19 -0800252 case VehicleNetworkConsts.VEHICLE_PROPERTY_FUEL_LEVEL_LOW:
253 return CarSensorManager.SENSOR_TYPE_FUEL_LEVEL;
keunyoungcc449f72015-08-12 10:46:27 -0700254 default:
keunyoungcc449f72015-08-12 10:46:27 -0700255 return SENSOR_TYPE_INVALD;
256 }
257 }
258
259 @Override
260 public void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700261 writer.println("*Sensor HAL*");
262 writer.println("**Supported properties**");
keunyoungcc449f72015-08-12 10:46:27 -0700263 for (int i = 0; i < mSensorToHalProperty.size(); i++) {
264 writer.println(mSensorToHalProperty.valueAt(i).toString());
265 }
266 }
267}