Home | History | Annotate | Download | only in hal
      1 /*
      2  * Copyright (C) 2016 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 package com.android.car.hal;
     17 
     18 import static com.android.car.hal.CarPropertyUtils.toCarPropertyValue;
     19 import static com.android.car.hal.CarPropertyUtils.toVehiclePropValue;
     20 import static java.lang.Integer.toHexString;
     21 
     22 import android.annotation.Nullable;
     23 import android.car.hardware.CarPropertyConfig;
     24 import android.car.hardware.CarPropertyValue;
     25 import android.car.hardware.property.CarPropertyEvent;
     26 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
     27 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
     28 import android.util.Log;
     29 
     30 import com.android.car.CarLog;
     31 import com.android.internal.annotations.GuardedBy;
     32 
     33 import java.io.PrintWriter;
     34 import java.util.ArrayList;
     35 import java.util.Collection;
     36 import java.util.LinkedList;
     37 import java.util.List;
     38 import java.util.concurrent.ConcurrentHashMap;
     39 
     40 /**
     41  * Common interface for HAL services that send Vehicle Properties back and forth via ICarProperty.
     42  * Services that communicate by passing vehicle properties back and forth via ICarProperty should
     43  * extend this class.
     44  */
     45 public abstract class PropertyHalServiceBase extends HalServiceBase {
     46     private final boolean mDbg;
     47     private final ConcurrentHashMap<Integer, CarPropertyConfig<?>> mProps =
     48             new ConcurrentHashMap<>();
     49     private final String mTag;
     50     private final VehicleHal mVehicleHal;
     51 
     52     @GuardedBy("mLock")
     53     private PropertyHalListener mListener;
     54     private final Object mLock = new Object();
     55 
     56     public interface PropertyHalListener {
     57         void onPropertyChange(CarPropertyEvent event);
     58         void onPropertySetError(int property, int area);
     59     }
     60 
     61     protected PropertyHalServiceBase(VehicleHal vehicleHal, String tag, boolean dbg) {
     62         mVehicleHal = vehicleHal;
     63         mTag = "PropertyHalServiceBase." + tag;
     64         mDbg = dbg;
     65 
     66         if (mDbg) {
     67             Log.d(mTag, "started PropertyHalServiceBase!");
     68         }
     69     }
     70 
     71     public void setListener(PropertyHalListener listener) {
     72         synchronized (mLock) {
     73             mListener = listener;
     74         }
     75     }
     76 
     77     public List<CarPropertyConfig> getPropertyList() {
     78         return new ArrayList<>(mProps.values());
     79     }
     80 
     81     /**
     82      * Returns property or null if property is not ready yet.
     83      */
     84     @Nullable
     85     public CarPropertyValue getProperty(int mgrPropId, int areaId) {
     86         int halPropId = managerToHalPropId(mgrPropId);
     87         if (halPropId == NOT_SUPPORTED_PROPERTY) {
     88             throw new IllegalArgumentException("Invalid property Id : 0x" + toHexString(mgrPropId));
     89         }
     90 
     91         VehiclePropValue value = null;
     92         try {
     93             value = mVehicleHal.get(halPropId, areaId);
     94         } catch (PropertyTimeoutException e) {
     95             Log.e(CarLog.TAG_PROPERTY, "get, property not ready 0x" + toHexString(halPropId), e);
     96         }
     97 
     98         return value == null ? null : toCarPropertyValue(value, mgrPropId);
     99     }
    100 
    101     public void setProperty(CarPropertyValue prop) {
    102         int halPropId = managerToHalPropId(prop.getPropertyId());
    103         if (halPropId == NOT_SUPPORTED_PROPERTY) {
    104             throw new IllegalArgumentException("Invalid property Id : 0x"
    105                     + toHexString(prop.getPropertyId()));
    106         }
    107         VehiclePropValue halProp = toVehiclePropValue(prop, halPropId);
    108         try {
    109             mVehicleHal.set(halProp);
    110         } catch (PropertyTimeoutException e) {
    111             Log.e(CarLog.TAG_PROPERTY, "set, property not ready 0x" + toHexString(halPropId), e);
    112             throw new RuntimeException(e);
    113         }
    114     }
    115 
    116     @Override
    117     public void init() {
    118         if (mDbg) {
    119             Log.d(mTag, "init()");
    120         }
    121         // Subscribe to each of the properties
    122         for (Integer prop : mProps.keySet()) {
    123             mVehicleHal.subscribeProperty(this, prop);
    124         }
    125     }
    126 
    127     @Override
    128     public void release() {
    129         if (mDbg) {
    130             Log.d(mTag, "release()");
    131         }
    132 
    133         for (Integer prop : mProps.keySet()) {
    134             mVehicleHal.unsubscribeProperty(this, prop);
    135         }
    136 
    137         // Clear the property list
    138         mProps.clear();
    139 
    140         synchronized (mLock) {
    141             mListener = null;
    142         }
    143     }
    144 
    145     @Override
    146     public Collection<VehiclePropConfig> takeSupportedProperties(
    147             Collection<VehiclePropConfig> allProperties) {
    148         List<VehiclePropConfig> taken = new LinkedList<>();
    149 
    150         for (VehiclePropConfig p : allProperties) {
    151             int mgrPropId = halToManagerPropId(p.prop);
    152 
    153             if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
    154                 continue;  // The property is not handled by this HAL.
    155             }
    156 
    157             CarPropertyConfig config = CarPropertyUtils.toCarPropertyConfig(p, mgrPropId);
    158 
    159             taken.add(p);
    160             mProps.put(p.prop, config);
    161 
    162             if (mDbg) {
    163                 Log.d(mTag, "takeSupportedProperties: " + toHexString(p.prop));
    164             }
    165         }
    166         return taken;
    167     }
    168 
    169     @Override
    170     public void handleHalEvents(List<VehiclePropValue> values) {
    171         PropertyHalListener listener;
    172         synchronized (mLock) {
    173             listener = mListener;
    174         }
    175         if (listener != null) {
    176             for (VehiclePropValue v : values) {
    177                 int prop = v.prop;
    178                 int mgrPropId = halToManagerPropId(prop);
    179 
    180                 if (mgrPropId == NOT_SUPPORTED_PROPERTY) {
    181                     Log.e(mTag, "Property is not supported: 0x" + toHexString(prop));
    182                     continue;
    183                 }
    184 
    185                 CarPropertyEvent event;
    186                 CarPropertyValue<?> propVal = toCarPropertyValue(v, mgrPropId);
    187                 event = new CarPropertyEvent(CarPropertyEvent.PROPERTY_EVENT_PROPERTY_CHANGE,
    188                         propVal);
    189 
    190                 listener.onPropertyChange(event);
    191                 if (mDbg) {
    192                     Log.d(mTag, "handleHalEvents event: " + event);
    193                 }
    194             }
    195         }
    196     }
    197 
    198     @Override
    199     public void handlePropertySetError(int property, int area) {
    200         PropertyHalListener listener;
    201         synchronized (mLock) {
    202             listener = mListener;
    203         }
    204         if (listener != null) {
    205             listener.onPropertySetError(property, area);
    206         }
    207     }
    208 
    209     @Override
    210     public void dump(PrintWriter writer) {
    211         writer.println(mTag);
    212         writer.println("  Properties available:");
    213         for (CarPropertyConfig prop : mProps.values()) {
    214             writer.println("    " + prop.toString());
    215         }
    216     }
    217 
    218     /**
    219      * Converts manager property ID to Vehicle HAL property ID.
    220      * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
    221      */
    222     abstract protected int managerToHalPropId(int managerPropId);
    223 
    224     /**
    225      * Converts Vehicle HAL property ID to manager property ID.
    226      * If property is not supported, it will return {@link #NOT_SUPPORTED_PROPERTY}.
    227      */
    228     abstract protected int halToManagerPropId(int halPropId);
    229 }
    230