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 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.car.hardware.CarPropertyConfig;
     23 import android.car.hardware.CarPropertyValue;
     24 import android.car.hardware.hvac.CarHvacEvent;
     25 import android.car.hardware.hvac.CarHvacManager.HvacPropertyId;
     26 import android.os.ServiceSpecificException;
     27 import android.util.Log;
     28 import android.util.SparseIntArray;
     29 
     30 import com.android.car.CarLog;
     31 import com.android.car.vehiclenetwork.VehicleNetworkConsts;
     32 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
     33 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
     34 
     35 import java.io.PrintWriter;
     36 import java.util.ArrayList;
     37 import java.util.HashMap;
     38 import java.util.LinkedList;
     39 import java.util.List;
     40 
     41 public class HvacHalService extends HalServiceBase {
     42     private static final boolean   DBG = true;
     43     private static final String    TAG = CarLog.TAG_HVAC + ".HvacHalService";
     44     private HvacHalListener        mListener;
     45     private final VehicleHal       mVehicleHal;
     46 
     47     private final HashMap<Integer, CarPropertyConfig<?>> mProps = new HashMap<>();
     48     private final SparseIntArray mHalPropToValueType = new SparseIntArray();
     49 
     50     public interface HvacHalListener {
     51         void onPropertyChange(CarHvacEvent event);
     52         void onError(int zone, int property);
     53     }
     54 
     55     public HvacHalService(VehicleHal vehicleHal) {
     56         mVehicleHal = vehicleHal;
     57         if (DBG) {
     58             Log.d(TAG, "started HvacHalService!");
     59         }
     60     }
     61 
     62     public void setListener(HvacHalListener listener) {
     63         synchronized (this) {
     64             mListener = listener;
     65         }
     66     }
     67 
     68     public List<CarPropertyConfig> getHvacProperties() {
     69         List<CarPropertyConfig> propList;
     70         synchronized (mProps) {
     71             propList = new ArrayList<>(mProps.values());
     72         }
     73         return propList;
     74     }
     75 
     76     public CarPropertyValue getHvacProperty(int hvacPropertyId, int areaId) {
     77         int halProp = hvacToHalPropId(hvacPropertyId);
     78 
     79         VehiclePropValue value = null;
     80         try {
     81             VehiclePropValue valueRequest = VehiclePropValue.newBuilder()
     82                     .setProp(halProp)
     83                     .setZone(areaId)
     84                     .setValueType(mHalPropToValueType.get(halProp))
     85                     .build();
     86 
     87             value = mVehicleHal.getVehicleNetwork().getProperty(valueRequest);
     88         } catch (ServiceSpecificException e) {
     89             Log.e(CarLog.TAG_HVAC, "property not ready 0x" + toHexString(halProp), e);
     90         }
     91 
     92         return value == null ? null : toCarPropertyValue(value, hvacPropertyId);
     93     }
     94 
     95     public void setHvacProperty(CarPropertyValue prop) {
     96         VehiclePropValue halProp = toVehiclePropValue(prop, hvacToHalPropId(prop.getPropertyId()));
     97         mVehicleHal.getVehicleNetwork().setProperty(halProp);
     98     }
     99 
    100     @Override
    101     public void init() {
    102         if (DBG) {
    103             Log.d(TAG, "init()");
    104         }
    105         synchronized (mProps) {
    106             // Subscribe to each of the HVAC properties
    107             for (Integer prop : mProps.keySet()) {
    108                 mVehicleHal.subscribeProperty(this, prop, 0);
    109             }
    110         }
    111     }
    112 
    113     @Override
    114     public void release() {
    115         if (DBG) {
    116             Log.d(TAG, "release()");
    117         }
    118         synchronized (mProps) {
    119             for (Integer prop : mProps.keySet()) {
    120                 mVehicleHal.unsubscribeProperty(this, prop);
    121             }
    122 
    123             // Clear the property list
    124             mProps.clear();
    125         }
    126         mListener = null;
    127     }
    128 
    129     @Override
    130     public synchronized List<VehiclePropConfig> takeSupportedProperties(
    131             List<VehiclePropConfig> allProperties) {
    132         List<VehiclePropConfig> taken = new LinkedList<>();
    133 
    134         for (VehiclePropConfig p : allProperties) {
    135             int hvacPropId;
    136             try {
    137                 hvacPropId = halToHvacPropId(p.getProp());
    138             } catch (IllegalArgumentException e) {
    139                 Log.i(TAG, "Property not supported by HVAC: 0x" + toHexString(p.getProp()));
    140                 continue;
    141             }
    142             CarPropertyConfig hvacConfig = CarPropertyUtils.toCarPropertyConfig(p, hvacPropId);
    143 
    144             taken.add(p);
    145             mProps.put(p.getProp(), hvacConfig);
    146             mHalPropToValueType.put(p.getProp(), p.getValueType());
    147 
    148             if (DBG) {
    149                 Log.d(TAG, "takeSupportedProperties:  " + toHexString(p.getProp()));
    150             }
    151         }
    152         return taken;
    153     }
    154 
    155     @Override
    156     public void handleHalEvents(List<VehiclePropValue> values) {
    157         HvacHalListener listener;
    158         synchronized (this) {
    159             listener = mListener;
    160         }
    161         if (listener != null) {
    162             dispatchEventToListener(listener, values);
    163         }
    164     }
    165 
    166     private void dispatchEventToListener(HvacHalListener listener, List<VehiclePropValue> values) {
    167         for (VehiclePropValue v : values) {
    168             int prop = v.getProp();
    169 
    170             int hvacPropId;
    171             try {
    172                 hvacPropId = halToHvacPropId(prop);
    173             } catch (IllegalArgumentException ex) {
    174                 Log.e(TAG, "Property is not supported: 0x" + toHexString(prop), ex);
    175                 continue;
    176             }
    177 
    178             CarHvacEvent event;
    179             CarPropertyValue<?> hvacProperty = toCarPropertyValue(v, hvacPropId);
    180             event = new CarHvacEvent(CarHvacEvent.HVAC_EVENT_PROPERTY_CHANGE, hvacProperty);
    181 
    182             listener.onPropertyChange(event);
    183             if (DBG) {
    184                 Log.d(TAG, "handleHalEvents event: " + event);
    185             }
    186         }
    187     }
    188 
    189     @Override
    190     public void dump(PrintWriter writer) {
    191         writer.println("*HVAC HAL*");
    192         writer.println("  Properties available:");
    193         for (CarPropertyConfig prop : mProps.values()) {
    194             writer.println("    " + prop.toString());
    195         }
    196     }
    197 
    198     // Convert the HVAC public API property ID to HAL property ID
    199     private static int hvacToHalPropId(int hvacPropId) {
    200         switch (hvacPropId) {
    201             case HvacPropertyId.ZONED_FAN_SPEED_SETPOINT:
    202                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_FAN_SPEED;
    203             case HvacPropertyId.ZONED_FAN_POSITION:
    204                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_FAN_DIRECTION;
    205             case HvacPropertyId.ZONED_TEMP_ACTUAL:
    206                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_TEMPERATURE_CURRENT;
    207             case HvacPropertyId.ZONED_TEMP_SETPOINT:
    208                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET;
    209             case HvacPropertyId.WINDOW_DEFROSTER_ON:
    210                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_DEFROSTER;
    211             case HvacPropertyId.ZONED_AC_ON:
    212                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_AC_ON;
    213             case HvacPropertyId.ZONED_AIR_RECIRCULATION_ON:
    214                 return VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_RECIRC_ON;
    215             default:
    216                 throw new IllegalArgumentException("hvacPropId " + hvacPropId + " is not supported");
    217         }
    218     }
    219 
    220     // Convert he HAL specific property ID to HVAC public API
    221     private static int halToHvacPropId(int halPropId) {
    222         switch (halPropId) {
    223             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_FAN_SPEED:
    224                 return HvacPropertyId.ZONED_FAN_SPEED_SETPOINT;
    225             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_FAN_DIRECTION:
    226                 return HvacPropertyId.ZONED_FAN_POSITION;
    227             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_TEMPERATURE_CURRENT:
    228                 return HvacPropertyId.ZONED_TEMP_ACTUAL;
    229             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_TEMPERATURE_SET:
    230                 return HvacPropertyId.ZONED_TEMP_SETPOINT;
    231             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_DEFROSTER:
    232                 return HvacPropertyId.WINDOW_DEFROSTER_ON;
    233             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_AC_ON:
    234                 return HvacPropertyId.ZONED_AC_ON;
    235             case VehicleNetworkConsts.VEHICLE_PROPERTY_HVAC_RECIRC_ON:
    236                 return HvacPropertyId.ZONED_AIR_RECIRCULATION_ON;
    237             default:
    238                 throw new IllegalArgumentException("halPropId " + halPropId + " is not supported");
    239         }
    240     }
    241 }
    242