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.hardware.automotive.vehicle.V2_0.VehiclePropConfig; 24 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 25 import android.util.Log; 26 import android.util.SparseArray; 27 import com.android.car.CarLog; 28 import java.util.Collection; 29 import java.util.LinkedList; 30 import java.util.List; 31 32 /** 33 * Common base for all SensorHal implementation. 34 * It is wholly based on subscription and there is no explicit API for polling, but each sensor 35 * should report its initial state immediately after {@link #requestSensorStart(int, int)} call. 36 * It is ok to report sensor data {@link SensorListener#onSensorData(CarSensorEvent)} inside 37 * the {@link #requestSensorStart(int, int)} call. 38 */ 39 public abstract class SensorHalServiceBase extends HalServiceBase implements SensorBase { 40 private static final String TAG = CarLog.concatTag(CarLog.TAG_SENSOR, 41 SensorHalServiceBase.class); 42 protected static final boolean DBG = false; 43 44 private boolean mIsReady = false; 45 46 protected static final int SENSOR_TYPE_INVALID = NOT_SUPPORTED_PROPERTY; 47 protected final VehicleHal mHal; 48 protected final SparseArray<VehiclePropConfig> mSensorToPropConfig = new SparseArray<>(); 49 SensorHalServiceBase(VehicleHal hal)50 public SensorHalServiceBase(VehicleHal hal) { 51 mHal = hal; 52 } 53 54 55 @Override takeSupportedProperties( Collection<VehiclePropConfig> allProperties)56 public synchronized Collection<VehiclePropConfig> takeSupportedProperties( 57 Collection<VehiclePropConfig> allProperties) { 58 if (DBG) Log.d(TAG, "takeSupportedProperties"); 59 LinkedList<VehiclePropConfig> supportedProperties = new LinkedList<>(); 60 for (VehiclePropConfig halProperty : allProperties) { 61 int sensor = getTokenForProperty(halProperty); 62 boolean mapped = sensor != SENSOR_TYPE_INVALID; 63 if (DBG) { 64 Log.d(TAG, "takeSupportedProperties, hal property " 65 + " 0x" + toHexString(halProperty.prop) + 66 (mapped ? (" mapped to " + sensor) : " ignored")); 67 } 68 if (mapped) { 69 supportedProperties.add(halProperty); 70 mSensorToPropConfig.append(sensor, halProperty); 71 } 72 } 73 return supportedProperties; 74 } 75 76 @Override init()77 public synchronized void init() { 78 mIsReady = true; 79 } 80 81 @Override release()82 public synchronized void release() { 83 mIsReady = false; 84 } 85 86 /** 87 * Sensor HAL should be ready after init call. 88 * @return 89 */ 90 @Override isReady()91 public synchronized boolean isReady() { 92 return mIsReady; 93 } 94 95 /** 96 * This should work after {@link #init()}. 97 * @return 98 */ 99 @Override getSupportedSensors()100 public synchronized int[] getSupportedSensors() { 101 int[] supportedSensors = new int[mSensorToPropConfig.size()]; 102 for (int i = 0; i < supportedSensors.length; i++) { 103 supportedSensors[i] = mSensorToPropConfig.keyAt(i); 104 } 105 return supportedSensors; 106 } 107 108 @Override requestSensorStart(int sensorType, int rate)109 public synchronized boolean requestSensorStart(int sensorType, int rate) { 110 if (DBG) Log.d(TAG, "requestSensorStart, sensorType: " + sensorType + ", rate: " + rate); 111 VehiclePropConfig config = mSensorToPropConfig.get(sensorType); 112 if (config == null) { 113 Log.e(TAG, "requesting to start sensor " + sensorType + ", but VHAL config not found"); 114 return false; 115 } 116 //TODO calculate sampling rate properly, bug: 32095903 117 mHal.subscribeProperty(this, config.prop, fixSamplingRateForProperty(config, rate)); 118 return true; 119 } 120 121 @Override requestSensorStop(int sensorType)122 public synchronized void requestSensorStop(int sensorType) { 123 if (DBG) Log.d(TAG, "requestSensorStop, sensorType: " + sensorType); 124 VehiclePropConfig config = mSensorToPropConfig.get(sensorType); 125 if (config == null) { 126 return; 127 } 128 mHal.unsubscribeProperty(this, config.prop); 129 } 130 131 @Nullable getCurrentSensorVehiclePropValue(int sensorType)132 public VehiclePropValue getCurrentSensorVehiclePropValue(int sensorType) { 133 VehiclePropConfig config; 134 synchronized (this) { 135 config = mSensorToPropConfig.get(sensorType); 136 } 137 if (config == null) { 138 Log.e(TAG, "sensor type not available 0x" + toHexString(sensorType)); 139 return null; 140 } 141 try { 142 return mHal.get(config.prop); 143 } catch (PropertyTimeoutException e) { 144 Log.e(TAG, "property not ready 0x" + toHexString(config.prop), e); 145 return null; 146 } 147 } 148 149 150 @Override handleHalEvents(List<VehiclePropValue> values)151 public void handleHalEvents(List<VehiclePropValue> values) { 152 // default no-op impl. Necessary to not propagate this HAL specific event to logical 153 // sensor provider. 154 throw new RuntimeException("should not be called"); 155 } 156 fixSamplingRateForProperty(VehiclePropConfig prop, int carSensorManagerRate)157 protected abstract float fixSamplingRateForProperty(VehiclePropConfig prop, 158 int carSensorManagerRate); 159 160 /** 161 * Returns a unique token to be used to map this property to a higher-level sensor 162 * This token will be stored in mSensorToPropConfig to allow callers to go from unique 163 * sensor identifiers to VehiclePropConfig objects 164 * @param config 165 * @return SENSOR_TYPE_INVALID or a locally unique token 166 */ getTokenForProperty(VehiclePropConfig config)167 protected abstract int getTokenForProperty(VehiclePropConfig config); 168 } 169