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.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BOOLEAN; 19 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT; 20 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2; 21 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3; 22 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4; 23 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32; 24 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2; 25 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3; 26 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4; 27 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_STRING; 28 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN; 29 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT; 30 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2; 31 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3; 32 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4; 33 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32; 34 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2; 35 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3; 36 import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4; 37 import static com.android.car.vehiclenetwork.VehiclePropValueUtil.getVectorValueType; 38 import static java.lang.Integer.toHexString; 39 40 import android.car.VehicleZoneUtil; 41 import android.car.VehicleAreaType; 42 import android.car.hardware.CarPropertyConfig; 43 import android.car.hardware.CarPropertyValue; 44 45 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig; 46 import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 47 48 import java.util.List; 49 50 /** 51 * Utility functions to work with {@link CarPropertyConfig} and {@link CarPropertyValue} 52 */ 53 /*package*/ final class CarPropertyUtils { 54 55 /* Utility class has no public constructor */ CarPropertyUtils()56 private CarPropertyUtils() {} 57 58 /** Converts {@link VehiclePropValue} to {@link CarPropertyValue} */ toCarPropertyValue( VehiclePropValue halValue, int propertyId)59 static CarPropertyValue<?> toCarPropertyValue( 60 VehiclePropValue halValue, int propertyId) { 61 Class<?> clazz = getJavaClass(halValue.getValueType()); 62 int areaId = halValue.getZone(); 63 if (Boolean.class == clazz) { 64 return new CarPropertyValue<>(propertyId, areaId, halValue.getInt32Values(0) == 1); 65 } else if (String.class == clazz) { 66 return new CarPropertyValue<>(propertyId, areaId, halValue.getStringValue()); 67 } else if (Long.class == clazz) { 68 return new CarPropertyValue<>(propertyId, areaId, halValue.getInt64Value()); 69 } else /* All list properties */ { 70 Object[] values = getRawValueList(clazz, halValue).toArray(); 71 return new CarPropertyValue<>(propertyId, areaId, 72 values.length == 1 ? values[0] : values); 73 } 74 } 75 76 /** Converts {@link CarPropertyValue} to {@link VehiclePropValue} */ toVehiclePropValue(CarPropertyValue hvacProp, int halPropId)77 static VehiclePropValue toVehiclePropValue(CarPropertyValue hvacProp, int halPropId) { 78 VehiclePropValue.Builder builder = VehiclePropValue.newBuilder(); 79 builder.setProp(halPropId); 80 81 if (hvacProp.getAreaId() != 0) { 82 builder.setZone(hvacProp.getAreaId()); 83 } 84 85 Object o = hvacProp.getValue(); 86 87 boolean hasArea = hvacProp.getAreaId() != 0; 88 int vectorLength = (o instanceof Object[] ? ((Object[]) o).length : 0); 89 int halType; 90 if (o instanceof Boolean) { 91 halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_BOOLEAN : VEHICLE_VALUE_TYPE_BOOLEAN; 92 builder.addInt32Values(((Boolean )o) ? 1 : 0); 93 } else if (o instanceof Integer) { 94 halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_INT32; 95 builder.addInt32Values((Integer) o); 96 } else if (o instanceof Float) { 97 halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_FLOAT; 98 builder.addFloatValues((Float) o); 99 } else if (o instanceof Integer[]) { 100 halType = getVectorValueType( 101 hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_ZONED_INT32, 102 vectorLength); 103 for (Integer i : (Integer[]) o) { 104 builder.addInt32Values(i); 105 } 106 } else if (o instanceof Float[]) { 107 halType = getVectorValueType( 108 hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_ZONED_FLOAT, 109 vectorLength); 110 for (Float f : (Float[]) o) { 111 builder.addFloatValues(f); 112 } 113 } else if (o instanceof String) { 114 halType = VEHICLE_VALUE_TYPE_STRING; 115 builder.setStringValue((String) o); 116 } else { 117 throw new IllegalArgumentException("Unexpected type in: " + hvacProp); 118 } 119 builder.setValueType(halType); 120 return builder.build(); 121 } 122 123 /** 124 * Converts {@link VehiclePropConfig} to {@link CarPropertyConfig}. 125 */ toCarPropertyConfig(VehiclePropConfig p, int propertyId)126 static CarPropertyConfig<?> toCarPropertyConfig(VehiclePropConfig p, int propertyId) { 127 int[] areas = VehicleZoneUtil.listAllZones(p.getZones()); 128 129 // TODO: handle other vehicle area types. 130 int areaType = areas.length == 0 131 ? VehicleAreaType.VEHICLE_AREA_TYPE_NONE : VehicleAreaType.VEHICLE_AREA_TYPE_ZONE; 132 133 Class<?> clazz = getJavaClass(p.getValueType()); 134 if (clazz == Boolean.class) { 135 return CarPropertyConfig 136 .newBuilder(clazz, propertyId, areaType, /* capacity */ 1) 137 .addAreas(areas) 138 .build(); 139 } else { 140 List mins; 141 List maxs; 142 if (classMatched(Integer.class, clazz)) { 143 mins = p.getInt32MinsList(); 144 maxs = p.getInt32MaxsList(); 145 } else if (classMatched(Float.class, clazz)) { 146 mins = p.getFloatMinsList(); 147 maxs = p.getFloatMaxsList(); 148 } else { 149 throw new IllegalArgumentException("Unexpected type: " + clazz); 150 } 151 CarPropertyConfig.Builder builder = CarPropertyConfig 152 .newBuilder(clazz, propertyId, areaType, /* capacity */ mins.size()); 153 for (int i = 0; i < mins.size(); i++) { 154 int areaId = areas.length == 0 ? 0 : areas[i]; 155 builder.addAreaConfig(areaId, mins.get(i), maxs.get(i)); 156 } 157 return builder.build(); 158 } 159 } 160 getJavaClass(int halType)161 private static Class<?> getJavaClass(int halType) { 162 switch (halType) { 163 case VEHICLE_VALUE_TYPE_BOOLEAN: 164 case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: 165 return Boolean.class; 166 case VEHICLE_VALUE_TYPE_FLOAT: 167 case VEHICLE_VALUE_TYPE_ZONED_FLOAT: 168 return Float.class; 169 case VEHICLE_VALUE_TYPE_INT32: 170 case VEHICLE_VALUE_TYPE_ZONED_INT32: 171 return Integer.class; 172 case VEHICLE_VALUE_TYPE_INT32_VEC2: 173 case VEHICLE_VALUE_TYPE_INT32_VEC3: 174 case VEHICLE_VALUE_TYPE_INT32_VEC4: 175 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2: 176 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3: 177 case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: 178 return Integer[].class; 179 case VEHICLE_VALUE_TYPE_FLOAT_VEC2: 180 case VEHICLE_VALUE_TYPE_FLOAT_VEC3: 181 case VEHICLE_VALUE_TYPE_FLOAT_VEC4: 182 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2: 183 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3: 184 case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: 185 return Float[].class; 186 case VEHICLE_VALUE_TYPE_STRING: 187 return String.class; 188 default: 189 throw new IllegalArgumentException("Unexpected type: " + toHexString(halType)); 190 } 191 } 192 getRawValueList(Class<?> clazz, VehiclePropValue vehiclePropValue)193 private static List getRawValueList(Class<?> clazz, VehiclePropValue vehiclePropValue) { 194 if (classMatched(Float.class, clazz)) { 195 return vehiclePropValue.getFloatValuesList(); 196 } else if (classMatched(Integer.class, clazz)) { 197 return vehiclePropValue.getInt32ValuesList(); 198 } else { 199 throw new IllegalArgumentException("Unexpected type: " + clazz); 200 } 201 } 202 classMatched(Class<?> class1, Class<?> class2)203 private static boolean classMatched(Class<?> class1, Class<?> class2) { 204 return class1 == class2 || class1.getComponentType() == class2; 205 } 206 } 207