Home | History | Annotate | Download | only in car
      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;
     18 
     19 import static com.android.car.CarServiceUtils.toByteArray;
     20 
     21 import static org.junit.Assert.assertEquals;
     22 import static org.junit.Assert.assertNotNull;
     23 
     24 import android.car.Car;
     25 import android.car.hardware.CarPropertyConfig;
     26 import android.car.hardware.CarVendorExtensionManager;
     27 import android.hardware.automotive.vehicle.V2_0.StatusCode;
     28 import android.hardware.automotive.vehicle.V2_0.VehicleArea;
     29 import android.hardware.automotive.vehicle.V2_0.VehicleAreaSeat;
     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.VehiclePropertyGroup;
     33 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType;
     34 import android.os.SystemClock;
     35 import android.support.test.filters.MediumTest;
     36 import android.support.test.runner.AndroidJUnit4;
     37 import android.util.Log;
     38 import android.util.SparseArray;
     39 
     40 import com.android.car.vehiclehal.test.MockedVehicleHal;
     41 import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
     42 
     43 import org.junit.Assert;
     44 import org.junit.Test;
     45 import org.junit.runner.RunWith;
     46 
     47 import java.util.Arrays;
     48 import java.util.List;
     49 import java.util.Random;
     50 
     51 /**
     52  * Tests for {@link CarVendorExtensionManager}
     53  */
     54 @RunWith(AndroidJUnit4.class)
     55 @MediumTest
     56 public class CarVendorExtensionManagerTest extends MockedCarTestBase {
     57 
     58     private static final String TAG = CarVendorExtensionManager.class.getSimpleName();
     59 
     60     private static final int CUSTOM_GLOBAL_INT_PROP_ID =
     61             0x1 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.INT32 | VehicleArea.GLOBAL;
     62 
     63     private static final int CUSTOM_ZONED_FLOAT_PROP_ID =
     64             0x2 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.FLOAT | VehicleArea.SEAT;
     65 
     66     private static final int CUSTOM_BYTES_PROP_ID_1 =
     67             0x3 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.BYTES | VehicleArea.SEAT;
     68 
     69     private static final int CUSTOM_BYTES_PROP_ID_2 =
     70             0x4 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.BYTES | VehicleArea.GLOBAL;
     71 
     72     private static final int CUSTOM_STRING_PROP_ID =
     73             0x5 | VehiclePropertyGroup.VENDOR | VehiclePropertyType.STRING | VehicleArea.GLOBAL;
     74 
     75     private static final float EPS = 1e-9f;
     76     private static final int MILLION = 1000 * 1000;
     77 
     78     private static final int MIN_PROP_INT32 = 0x0000005;
     79     private static final int MAX_PROP_INT32 = 0xDeadBee;
     80 
     81     private static final float MIN_PROP_FLOAT = 10.42f;
     82     private static final float MAX_PROP_FLOAT = 42.10f;
     83 
     84 //    private static final MockedVehicleHal mVehicleHal = new MockedVehicleHal();
     85 
     86     private static final VehiclePropConfig mConfigs[] = new VehiclePropConfig[] {
     87             VehiclePropConfigBuilder.newBuilder(CUSTOM_GLOBAL_INT_PROP_ID)
     88                     .addAreaConfig(0, MIN_PROP_INT32, MAX_PROP_INT32)
     89                     .build(),
     90             VehiclePropConfigBuilder.newBuilder(CUSTOM_ZONED_FLOAT_PROP_ID)
     91                     .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0)
     92                     .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
     93                     .addAreaConfig(VehicleAreaSeat.ROW_2_RIGHT, MIN_PROP_FLOAT, MAX_PROP_FLOAT)
     94                     .build(),
     95             VehiclePropConfigBuilder.newBuilder(CUSTOM_BYTES_PROP_ID_1)
     96                     .addAreaConfig(VehicleAreaSeat.ROW_1_LEFT | VehicleAreaSeat.ROW_1_RIGHT, 0, 0)
     97                     .build(),
     98             VehiclePropConfigBuilder.newBuilder(CUSTOM_BYTES_PROP_ID_2).build(),
     99             VehiclePropConfigBuilder.newBuilder(CUSTOM_STRING_PROP_ID).build(),
    100     };
    101 
    102     private CarVendorExtensionManager mManager;
    103 
    104     @Override
    105     public void setUp() throws Exception {
    106         super.setUp();
    107 
    108         mManager = (CarVendorExtensionManager) getCar().getCarManager(Car.VENDOR_EXTENSION_SERVICE);
    109         assertNotNull(mManager);
    110     }
    111 
    112     @Test
    113     public void testPropertyList() throws Exception {
    114         List<CarPropertyConfig> configs = mManager.getProperties();
    115         assertEquals(mConfigs.length, configs.size());
    116 
    117         SparseArray<CarPropertyConfig> configById = new SparseArray<>(configs.size());
    118         for (CarPropertyConfig config : configs) {
    119             configById.put(config.getPropertyId(), config);
    120         }
    121 
    122         CarPropertyConfig prop1 = configById.get(CUSTOM_GLOBAL_INT_PROP_ID);
    123         assertNotNull(prop1);
    124         assertEquals(Integer.class, prop1.getPropertyType());
    125         assertEquals(MIN_PROP_INT32, prop1.getMinValue());
    126         assertEquals(MAX_PROP_INT32, prop1.getMaxValue());
    127     }
    128 
    129     @Test
    130     public void testIntGlobalProperty() throws Exception {
    131         final int value = 0xbeef;
    132         mManager.setGlobalProperty(Integer.class, CUSTOM_GLOBAL_INT_PROP_ID, value);
    133         int actualValue = mManager.getGlobalProperty(Integer.class, CUSTOM_GLOBAL_INT_PROP_ID);
    134         assertEquals(value, actualValue);
    135     }
    136 
    137     @Test
    138     public void testFloatZonedProperty() throws Exception {
    139         final float value = MIN_PROP_FLOAT + 1;
    140         mManager.setProperty(
    141                 Float.class,
    142                 CUSTOM_ZONED_FLOAT_PROP_ID,
    143                 VehicleAreaSeat.ROW_1_RIGHT,
    144                 value);
    145 
    146         float actualValue = mManager.getProperty(
    147                 Float.class, CUSTOM_ZONED_FLOAT_PROP_ID, VehicleAreaSeat.ROW_1_RIGHT);
    148         assertEquals(value, actualValue, EPS);
    149     }
    150 
    151     @Test
    152     public void testByteArrayProperty() throws Exception {
    153         final byte[] expectedData = new byte[] { 1, 2, 3, 4, -1, 127, -127, 0 };
    154 
    155         // Write to CUSTOM_BYTES_PROP_ID_1 and read this value from CUSTOM_BYTES_PROP_ID_2
    156         mManager.setGlobalProperty(
    157                 byte[].class,
    158                 CUSTOM_BYTES_PROP_ID_1,
    159                 expectedData);
    160 
    161         byte[] actualData = mManager.getGlobalProperty(
    162                 byte[].class,
    163                 CUSTOM_BYTES_PROP_ID_2);
    164 
    165         assertEquals(Arrays.toString(expectedData), Arrays.toString(actualData));
    166     }
    167 
    168     @Test
    169     public void testLargeByteArrayProperty() throws Exception {
    170         // Allocate array of byte which is greater than binder transaction buffer limitation.
    171         byte[] expectedData = new byte[2 * MILLION];
    172 
    173         new Random(SystemClock.elapsedRealtimeNanos())
    174             .nextBytes(expectedData);
    175 
    176         // Write to CUSTOM_BYTES_PROP_ID_1 and read this value from CUSTOM_BYTES_PROP_ID_2
    177         mManager.setGlobalProperty(
    178                 byte[].class,
    179                 CUSTOM_BYTES_PROP_ID_1,
    180                 expectedData);
    181 
    182         byte[] actualData = mManager.getGlobalProperty(
    183                 byte[].class,
    184                 CUSTOM_BYTES_PROP_ID_2);
    185 
    186         Assert.assertArrayEquals(expectedData, actualData);
    187     }
    188 
    189     @Test
    190     public void testLargeStringProperty() throws Exception {
    191         // Allocate string which is greater than binder transaction buffer limitation.
    192         String expectedString = generateRandomString(2 * MILLION,
    193                 "abcdefghijKLMN!@#$%^&*()[]{}:\"\t\n\r!'");
    194 
    195         mManager.setGlobalProperty(
    196                 String.class,
    197                 CUSTOM_STRING_PROP_ID,
    198                 expectedString);
    199 
    200         String actualString = mManager.getGlobalProperty(
    201                 String.class,
    202                 CUSTOM_STRING_PROP_ID);
    203 
    204         assertEquals(expectedString, actualString);
    205     }
    206 
    207     @Test
    208     public void testStringProperty() throws Exception {
    209         final String expectedString = "!";  // Test some utf as well.
    210 
    211         mManager.setGlobalProperty(
    212                 String.class,
    213                 CUSTOM_STRING_PROP_ID,
    214                 expectedString);
    215 
    216         String actualString = mManager.getGlobalProperty(
    217                 String.class,
    218                 CUSTOM_STRING_PROP_ID);
    219 
    220         assertEquals(expectedString, actualString);
    221     }
    222 
    223     private static String generateRandomString(int length, String allowedSymbols) {
    224         Random r = new Random(SystemClock.elapsedRealtimeNanos());
    225         StringBuilder sb = new StringBuilder(length);
    226         char[] chars = allowedSymbols.toCharArray();
    227         for (int i = 0; i < length; i++) {
    228             sb.append(chars[r.nextInt(chars.length)]);
    229         }
    230         return sb.toString();
    231     }
    232 
    233     @Override
    234     protected synchronized MockedVehicleHal createMockedVehicleHal() {
    235         MockedVehicleHal hal = new VendorExtMockedVehicleHal();
    236         hal.addProperties(mConfigs);
    237         return hal;
    238     }
    239 
    240     private static class VendorExtMockedVehicleHal extends MockedVehicleHal {
    241         private final SparseArray<VehiclePropValue> mValues = new SparseArray<>();
    242 
    243         private byte[] mBytes = null;
    244 
    245         @Override
    246         public synchronized int set(VehiclePropValue propValue) {
    247             if (propValue.prop == CUSTOM_BYTES_PROP_ID_1) {
    248                 mBytes = toByteArray(propValue.value.bytes);
    249             }
    250 
    251             mValues.put(propValue.prop, propValue);
    252             return StatusCode.OK;
    253         }
    254 
    255         @Override
    256         public synchronized void get(VehiclePropValue requestedPropValue, getCallback cb) {
    257             if (!isVendorProperty(requestedPropValue.prop)) {
    258                 super.get(requestedPropValue, cb);
    259                 return;
    260             }
    261             VehiclePropValue result = new VehiclePropValue();
    262             result.prop = requestedPropValue.prop;
    263             result.areaId = requestedPropValue.areaId;
    264 
    265             if (requestedPropValue.prop == CUSTOM_BYTES_PROP_ID_2 && mBytes != null) {
    266                 Log.d(TAG, "Returning byte array property, value size " + mBytes.length);
    267                 result.value.bytes.ensureCapacity(mBytes.length);
    268                 for (byte b : mBytes) {
    269                     result.value.bytes.add(b);
    270                 }
    271             } else {
    272                 VehiclePropValue existingValue = mValues.get(requestedPropValue.prop);
    273                 if (existingValue != null) {
    274                     result = existingValue;
    275                 } else {
    276                     result = requestedPropValue;
    277                 }
    278             }
    279             cb.onValues(StatusCode.OK, result);
    280         }
    281 
    282         private boolean isVendorProperty(int prop) {
    283             return VehiclePropertyGroup.VENDOR == (prop & VehiclePropertyGroup.VENDOR);
    284         }
    285     }
    286 }
    287