Home | History | Annotate | Download | only in test
      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 
     17 package com.android.car.vehiclehal.test;
     18 
     19 import static java.lang.Integer.toHexString;
     20 import static junit.framework.Assert.assertEquals;
     21 import static junit.framework.Assert.assertNotNull;
     22 import static junit.framework.Assert.fail;
     23 
     24 import com.google.android.collect.Lists;
     25 
     26 import android.hardware.automotive.vehicle.V2_0.IVehicle;
     27 import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
     28 import android.hardware.automotive.vehicle.V2_0.StatusCode;
     29 import android.hardware.automotive.vehicle.V2_0.SubscribeOptions;
     30 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
     31 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
     32 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
     33 import android.os.RemoteException;
     34 
     35 import java.util.ArrayList;
     36 import java.util.HashMap;
     37 import java.util.List;
     38 import java.util.Map;
     39 
     40 /**
     41  * Mocked implementation of {@link IVehicle}.
     42  */
     43 public class MockedVehicleHal extends IVehicle.Stub {
     44     /**
     45      * Interface for handler of each property.
     46      */
     47     public interface VehicleHalPropertyHandler {
     48         default void onPropertySet(VehiclePropValue value) {}
     49         default VehiclePropValue onPropertyGet(VehiclePropValue value) { return null; }
     50         default void onPropertySubscribe(int property, int zones, float sampleRate) {}
     51         default void onPropertyUnsubscribe(int property) {}
     52 
     53         VehicleHalPropertyHandler NOP = new VehicleHalPropertyHandler() {};
     54     }
     55 
     56     private final Map<Integer, VehicleHalPropertyHandler> mPropertyHandlerMap = new HashMap<>();
     57     private final Map<Integer, VehiclePropConfig> mConfigs = new HashMap<>();
     58     private final Map<Integer, List<IVehicleCallback>> mSubscribers = new HashMap<>();
     59 
     60     public synchronized void addProperties(VehiclePropConfig... configs) {
     61         for (VehiclePropConfig config : configs) {
     62             addProperty(config, new DefaultPropertyHandler(config, null));
     63         }
     64     }
     65 
     66     public synchronized void addProperty(VehiclePropConfig config,
     67             VehicleHalPropertyHandler handler) {
     68         mPropertyHandlerMap.put(config.prop, handler);
     69         mConfigs.put(config.prop, config);
     70     }
     71 
     72     public synchronized void addStaticProperty(VehiclePropConfig config,
     73             VehiclePropValue value) {
     74         addProperty(config, new StaticPropertyHandler(value));
     75     }
     76 
     77     public synchronized void injectEvent(VehiclePropValue value) {
     78         List<IVehicleCallback> callbacks = mSubscribers.get(value.prop);
     79         assertNotNull("Injecting event failed for property: " + value.prop
     80                         + ". No listeners found", callbacks);
     81         for (IVehicleCallback callback : callbacks) {
     82             try {
     83                 callback.onPropertyEvent(Lists.newArrayList(value));
     84             } catch (RemoteException e) {
     85                 e.printStackTrace();
     86                 fail("Remote exception while injecting events.");
     87             }
     88         }
     89     }
     90 
     91     public synchronized void injectError(int errorCode, int propertyId, int areaId) {
     92         List<IVehicleCallback> callbacks = mSubscribers.get(propertyId);
     93         assertNotNull("Injecting error failed for property: " + propertyId
     94                         + ". No listeners found", callbacks);
     95         for (IVehicleCallback callback : callbacks) {
     96             try {
     97                 callback.onPropertySetError(errorCode, propertyId, areaId);
     98             } catch (RemoteException e) {
     99                 e.printStackTrace();
    100                 fail("Remote exception while injecting errors.");
    101             }
    102         }
    103     }
    104 
    105     @Override
    106     public synchronized ArrayList<VehiclePropConfig> getAllPropConfigs() {
    107         return new ArrayList<>(mConfigs.values());
    108     }
    109 
    110     @Override
    111     public synchronized void getPropConfigs(ArrayList<Integer> props, getPropConfigsCallback cb) {
    112         ArrayList<VehiclePropConfig> res = new ArrayList<>();
    113         for (Integer prop : props) {
    114             VehiclePropConfig config = mConfigs.get(prop);
    115             if (config == null) {
    116                 cb.onValues(StatusCode.INVALID_ARG, new ArrayList<>());
    117                 return;
    118             }
    119             res.add(config);
    120         }
    121         cb.onValues(StatusCode.OK, res);
    122     }
    123 
    124     @Override
    125     public synchronized void get(VehiclePropValue requestedPropValue, getCallback cb) {
    126         VehicleHalPropertyHandler handler = mPropertyHandlerMap.get(requestedPropValue.prop);
    127         if (handler == null) {
    128             cb.onValues(StatusCode.INVALID_ARG, null);
    129         } else {
    130             cb.onValues(StatusCode.OK, handler.onPropertyGet(requestedPropValue));
    131         }
    132     }
    133 
    134     @Override
    135     public synchronized int set(VehiclePropValue propValue) {
    136         VehicleHalPropertyHandler handler = mPropertyHandlerMap.get(propValue.prop);
    137         if (handler == null) {
    138             return StatusCode.INVALID_ARG;
    139         } else {
    140             handler.onPropertySet(propValue);
    141             return StatusCode.OK;
    142         }
    143     }
    144 
    145     @Override
    146     public synchronized int subscribe(IVehicleCallback callback,
    147             ArrayList<SubscribeOptions> options) {
    148         for (SubscribeOptions opt : options) {
    149             VehicleHalPropertyHandler handler = mPropertyHandlerMap.get(opt.propId);
    150             if (handler == null) {
    151                 return StatusCode.INVALID_ARG;
    152             }
    153 
    154             handler.onPropertySubscribe(opt.propId, opt.vehicleAreas, opt.sampleRate);
    155             List<IVehicleCallback>  subscribers = mSubscribers.get(opt.propId);
    156             if (subscribers == null) {
    157                 subscribers = new ArrayList<>();
    158                 mSubscribers.put(opt.propId, subscribers);
    159             }
    160             subscribers.add(callback);
    161         }
    162         return StatusCode.OK;
    163     }
    164 
    165     @Override
    166     public synchronized int unsubscribe(IVehicleCallback callback, int propId) {
    167         VehicleHalPropertyHandler handler = mPropertyHandlerMap.get(propId);
    168         if (handler == null) {
    169             return StatusCode.INVALID_ARG;
    170         }
    171 
    172         handler.onPropertyUnsubscribe(propId);
    173         List<IVehicleCallback>  subscribers = mSubscribers.get(propId);
    174         if (subscribers != null) {
    175             subscribers.remove(callback);
    176             if (subscribers.size() == 0) {
    177                 mSubscribers.remove(propId);
    178             }
    179         }
    180         return StatusCode.OK;
    181     }
    182 
    183     @Override
    184     public String debugDump() {
    185         return null;
    186     }
    187 
    188     public static class FailingPropertyHandler implements VehicleHalPropertyHandler {
    189         @Override
    190         public void onPropertySet(VehiclePropValue value) {
    191             fail("Unexpected onPropertySet call");
    192         }
    193 
    194         @Override
    195         public VehiclePropValue onPropertyGet(VehiclePropValue value) {
    196             fail("Unexpected onPropertyGet call");
    197             return null;
    198         }
    199 
    200         @Override
    201         public void onPropertySubscribe(int property, int zones, float sampleRate) {
    202             fail("Unexpected onPropertySubscribe call");
    203         }
    204 
    205         @Override
    206         public void onPropertyUnsubscribe(int property) {
    207             fail("Unexpected onPropertyUnsubscribe call");
    208         }
    209     }
    210 
    211     public static class StaticPropertyHandler extends FailingPropertyHandler {
    212         private final VehiclePropValue mValue;
    213 
    214         public StaticPropertyHandler(VehiclePropValue value) {
    215             mValue = value;
    216         }
    217 
    218         @Override
    219         public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
    220             return mValue;
    221         }
    222     }
    223 
    224     public static class DefaultPropertyHandler implements VehicleHalPropertyHandler {
    225         private final VehiclePropConfig mConfig;
    226         private VehiclePropValue mValue;
    227         private boolean mSubscribed = false;
    228 
    229         public DefaultPropertyHandler(VehiclePropConfig config, VehiclePropValue initialValue) {
    230             mConfig = config;
    231             mValue = initialValue;
    232         }
    233 
    234         @Override
    235         public synchronized void onPropertySet(VehiclePropValue value) {
    236             assertEquals(mConfig.prop, value.prop);
    237             assertEquals(VehiclePropertyAccess.WRITE, mConfig.access & VehiclePropertyAccess.WRITE);
    238             mValue = value;
    239         }
    240 
    241         @Override
    242         public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
    243             assertEquals(mConfig.prop, value.prop);
    244             assertEquals(VehiclePropertyAccess.READ, mConfig.access & VehiclePropertyAccess.READ);
    245             return mValue;
    246         }
    247 
    248         @Override
    249         public synchronized void onPropertySubscribe(int property, int zones, float sampleRate) {
    250             assertEquals(mConfig.prop, property);
    251             mSubscribed = true;
    252         }
    253 
    254         @Override
    255         public synchronized void onPropertyUnsubscribe(int property) {
    256             assertEquals(mConfig.prop, property);
    257             if (!mSubscribed) {
    258                 throw new IllegalArgumentException("Property was not subscribed 0x"
    259                         + toHexString( property));
    260             }
    261             mSubscribed = false;
    262         }
    263     }
    264 }
    265