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.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 
     50     public SensorHalServiceBase(VehicleHal hal) {
     51         mHal = hal;
     52     }
     53 
     54 
     55     @Override
     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
     77     public synchronized void init() {
     78         mIsReady = true;
     79     }
     80 
     81     @Override
     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
     91     public synchronized boolean isReady() {
     92         return mIsReady;
     93     }
     94 
     95     /**
     96      * This should work after {@link #init()}.
     97      * @return
     98      */
     99     @Override
    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
    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
    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
    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
    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 
    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      */
    167     protected abstract int getTokenForProperty(VehiclePropConfig config);
    168 }
    169