1 /* 2 * Copyright (C) 2021 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 android.car.VehicleAreaType; 20 import android.car.hardware.CarPropertyConfig; 21 import android.car.hardware.property.AreaIdConfig; 22 import android.hardware.automotive.vehicle.VehicleArea; 23 import android.hardware.automotive.vehicle.VehicleProperty; 24 import android.hardware.automotive.vehicle.VehiclePropertyChangeMode; 25 import android.hardware.automotive.vehicle.VehiclePropertyType; 26 27 import java.util.ArrayList; 28 import java.util.List; 29 import java.util.Set; 30 31 /** 32 * HalPropConfig represents a vehicle property config. 33 */ 34 public abstract class HalPropConfig { 35 private static final Set<Integer> CONFIG_ARRAY_DEFINES_SUPPORTED_ENUM_VALUES = 36 Set.of( 37 VehicleProperty.GEAR_SELECTION, 38 VehicleProperty.CURRENT_GEAR, 39 VehicleProperty.DISTANCE_DISPLAY_UNITS, 40 VehicleProperty.EV_BATTERY_DISPLAY_UNITS, 41 VehicleProperty.TIRE_PRESSURE_DISPLAY_UNITS, 42 VehicleProperty.FUEL_VOLUME_DISPLAY_UNITS, 43 VehicleProperty.HVAC_TEMPERATURE_DISPLAY_UNITS, 44 VehicleProperty.VEHICLE_SPEED_DISPLAY_UNITS); 45 /** 46 * Get the property ID. 47 */ getPropId()48 public abstract int getPropId(); 49 50 /** 51 * Get the access mode. 52 */ getAccess()53 public abstract int getAccess(); 54 55 /** 56 * Get the change mode. 57 */ getChangeMode()58 public abstract int getChangeMode(); 59 60 /** 61 * Get the area configs. 62 */ getAreaConfigs()63 public abstract HalAreaConfig[] getAreaConfigs(); 64 65 /** 66 * Get the config array. 67 */ getConfigArray()68 public abstract int[] getConfigArray(); 69 70 /** 71 * Get the config string. 72 */ getConfigString()73 public abstract String getConfigString(); 74 75 /** 76 * Get the min sample rate. 77 */ getMinSampleRate()78 public abstract float getMinSampleRate(); 79 80 /** 81 * Get the max sample rate. 82 */ getMaxSampleRate()83 public abstract float getMaxSampleRate(); 84 85 /** 86 * Converts to AIDL or HIDL VehiclePropConfig. 87 */ toVehiclePropConfig()88 public abstract Object toVehiclePropConfig(); 89 90 /** 91 * Converts {@link HalPropConfig} to {@link CarPropertyConfig}. 92 * 93 * @param mgrPropertyId The Property ID used by Car Property Manager, different from the 94 * property ID used by VHAL. 95 */ toCarPropertyConfig(int mgrPropertyId)96 public CarPropertyConfig<?> toCarPropertyConfig(int mgrPropertyId) { 97 int propId = getPropId(); 98 int areaType = getVehicleAreaType(propId & VehicleArea.MASK); 99 Class<?> clazz = CarPropertyUtils.getJavaClass(propId & VehiclePropertyType.MASK); 100 CarPropertyConfig.Builder carPropertyConfigBuilder = CarPropertyConfig.newBuilder(clazz, 101 mgrPropertyId, areaType).setAccess(getAccess()).setChangeMode( 102 getChangeMode()).setConfigString(getConfigString()); 103 104 float maxSampleRate = 0f; 105 float minSampleRate = 0f; 106 if (getChangeMode() == CarPropertyConfig.VEHICLE_PROPERTY_CHANGE_MODE_CONTINUOUS) { 107 maxSampleRate = getMaxSampleRate(); 108 minSampleRate = getMinSampleRate(); 109 } 110 carPropertyConfigBuilder.setMinSampleRate(minSampleRate).setMaxSampleRate(maxSampleRate); 111 112 int[] configIntArray = getConfigArray(); 113 ArrayList<Integer> configArray = new ArrayList<>(configIntArray.length); 114 long[] supportedEnumValues = null; 115 boolean shouldConfigArrayDefineSupportedEnumValues = 116 CONFIG_ARRAY_DEFINES_SUPPORTED_ENUM_VALUES.contains(propId); 117 if (shouldConfigArrayDefineSupportedEnumValues) { 118 supportedEnumValues = new long[configIntArray.length]; 119 } 120 for (int i = 0; i < configIntArray.length; i++) { 121 configArray.add(configIntArray[i]); 122 if (shouldConfigArrayDefineSupportedEnumValues) { 123 supportedEnumValues[i] = (long) configIntArray[i]; 124 } 125 } 126 carPropertyConfigBuilder.setConfigArray(configArray); 127 128 HalAreaConfig[] halAreaConfigs = getAreaConfigs(); 129 if (halAreaConfigs.length == 0) { 130 carPropertyConfigBuilder.addAreaIdConfig(generateAreaIdConfig(clazz, /*areaId=*/0, 131 /*minInt32Value=*/0, /*maxInt32Value=*/0, 132 /*minFloatValue=*/0, /*maxFloatValue=*/0, 133 /*minInt64Value=*/0, /*maxInt64Value=*/0, 134 supportedEnumValues)); 135 } else { 136 for (HalAreaConfig halAreaConfig : halAreaConfigs) { 137 if (!shouldConfigArrayDefineSupportedEnumValues) { 138 supportedEnumValues = halAreaConfig.getSupportedEnumValues(); 139 } 140 carPropertyConfigBuilder.addAreaIdConfig( 141 generateAreaIdConfig(clazz, halAreaConfig.getAreaId(), 142 halAreaConfig.getMinInt32Value(), halAreaConfig.getMaxInt32Value(), 143 halAreaConfig.getMinFloatValue(), halAreaConfig.getMaxFloatValue(), 144 halAreaConfig.getMinInt64Value(), halAreaConfig.getMaxInt64Value(), 145 supportedEnumValues)); 146 } 147 } 148 return carPropertyConfigBuilder.build(); 149 } 150 generateAreaIdConfig(Class<?> clazz, int areaId, int minInt32Value, int maxInt32Value, float minFloatValue, float maxFloatValue, long minInt64Value, long maxInt64Value, long[] supportedEnumValues)151 private AreaIdConfig generateAreaIdConfig(Class<?> clazz, int areaId, int minInt32Value, 152 int maxInt32Value, float minFloatValue, float maxFloatValue, long minInt64Value, 153 long maxInt64Value, long[] supportedEnumValues) { 154 AreaIdConfig.Builder areaIdConfigBuilder = new AreaIdConfig.Builder(areaId); 155 if (classMatched(Integer.class, clazz)) { 156 if ((minInt32Value != 0 || maxInt32Value != 0)) { 157 areaIdConfigBuilder.setMinValue(minInt32Value).setMaxValue(maxInt32Value); 158 } 159 if (getChangeMode() == VehiclePropertyChangeMode.ON_CHANGE) { 160 if (supportedEnumValues != null && supportedEnumValues.length > 0) { 161 List<Integer> managerSupportedEnumValues = new ArrayList<>( 162 supportedEnumValues.length); 163 for (int i = 0; i < supportedEnumValues.length; i++) { 164 managerSupportedEnumValues.add((int) supportedEnumValues[i]); 165 } 166 areaIdConfigBuilder.setSupportedEnumValues(managerSupportedEnumValues); 167 } else if (PropertyHalServiceIds.getAllPossibleSupportedEnumValues(getPropId()) 168 != null) { 169 areaIdConfigBuilder.setSupportedEnumValues(new ArrayList( 170 PropertyHalServiceIds.getAllPossibleSupportedEnumValues(getPropId()))); 171 } 172 } 173 } else if (classMatched(Float.class, clazz) && (minFloatValue != 0 || maxFloatValue != 0)) { 174 areaIdConfigBuilder.setMinValue(minFloatValue).setMaxValue(maxFloatValue); 175 } else if (classMatched(Long.class, clazz) && (minInt64Value != 0 || maxInt64Value != 0)) { 176 areaIdConfigBuilder.setMinValue(minInt64Value).setMaxValue(maxInt64Value); 177 } 178 return areaIdConfigBuilder.build(); 179 } 180 getVehicleAreaType(int halArea)181 private static @VehicleAreaType.VehicleAreaTypeValue int getVehicleAreaType(int halArea) { 182 switch (halArea) { 183 case VehicleArea.GLOBAL: 184 return VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; 185 case VehicleArea.SEAT: 186 return VehicleAreaType.VEHICLE_AREA_TYPE_SEAT; 187 case VehicleArea.DOOR: 188 return VehicleAreaType.VEHICLE_AREA_TYPE_DOOR; 189 case VehicleArea.WINDOW: 190 return VehicleAreaType.VEHICLE_AREA_TYPE_WINDOW; 191 case VehicleArea.MIRROR: 192 return VehicleAreaType.VEHICLE_AREA_TYPE_MIRROR; 193 case VehicleArea.WHEEL: 194 return VehicleAreaType.VEHICLE_AREA_TYPE_WHEEL; 195 default: 196 throw new RuntimeException("Unsupported area type " + halArea); 197 } 198 } 199 classMatched(Class<?> class1, Class<?> class2)200 private static boolean classMatched(Class<?> class1, Class<?> class2) { 201 return class1 == class2 || class1.getComponentType() == class2; 202 } 203 } 204