blob: ed97beaf8577b9b054886e91169b5ab3c69a608c [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.hal;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BOOLEAN;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_BYTES;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_STRING;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_BOOLEAN;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3;
import static com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4;
import static com.android.car.vehiclenetwork.VehiclePropValueUtil.getVectorValueType;
import static java.lang.Integer.toHexString;
import android.car.VehicleAreaType;
import android.car.VehicleZoneUtil;
import android.car.hardware.CarPropertyConfig;
import android.car.hardware.CarPropertyValue;
import com.google.protobuf.ByteString;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfig;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
import java.util.List;
/**
* Utility functions to work with {@link CarPropertyConfig} and {@link CarPropertyValue}
*/
/*package*/ final class CarPropertyUtils {
/* Utility class has no public constructor */
private CarPropertyUtils() {}
/** Converts {@link VehiclePropValue} to {@link CarPropertyValue} */
static CarPropertyValue<?> toCarPropertyValue(
VehiclePropValue halValue, int propertyId) {
Class<?> clazz = getJavaClass(halValue.getValueType());
int areaId = halValue.getZone();
if (Boolean.class == clazz) {
return new CarPropertyValue<>(propertyId, areaId, halValue.getInt32Values(0) == 1);
} else if (String.class == clazz) {
return new CarPropertyValue<>(propertyId, areaId, halValue.getStringValue());
} else if (Long.class == clazz) {
return new CarPropertyValue<>(propertyId, areaId, halValue.getInt64Value());
} else if (byte[].class == clazz) {
byte[] halData = halValue.getBytesValue().toByteArray();
return new CarPropertyValue<>(propertyId, areaId, halData);
} else /* All list properties */ {
Object[] values = getRawValueList(clazz, halValue).toArray();
return new CarPropertyValue<>(propertyId, areaId,
values.length == 1 ? values[0] : values);
}
}
/** Converts {@link CarPropertyValue} to {@link VehiclePropValue} */
static VehiclePropValue toVehiclePropValue(CarPropertyValue hvacProp, int halPropId) {
VehiclePropValue.Builder builder = VehiclePropValue.newBuilder();
builder.setProp(halPropId);
if (hvacProp.getAreaId() != 0) {
builder.setZone(hvacProp.getAreaId());
}
Object o = hvacProp.getValue();
boolean hasArea = hvacProp.getAreaId() != 0;
int vectorLength = (o instanceof Object[] ? ((Object[]) o).length : 0);
int halType;
if (o instanceof Boolean) {
halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_BOOLEAN : VEHICLE_VALUE_TYPE_BOOLEAN;
builder.addInt32Values(((Boolean )o) ? 1 : 0);
} else if (o instanceof Integer) {
halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_INT32;
builder.addInt32Values((Integer) o);
} else if (o instanceof Float) {
halType = hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_FLOAT;
builder.addFloatValues((Float) o);
} else if (o instanceof Integer[]) {
halType = getVectorValueType(
hasArea ? VEHICLE_VALUE_TYPE_ZONED_INT32 : VEHICLE_VALUE_TYPE_ZONED_INT32,
vectorLength);
for (Integer i : (Integer[]) o) {
builder.addInt32Values(i);
}
} else if (o instanceof Float[]) {
halType = getVectorValueType(
hasArea ? VEHICLE_VALUE_TYPE_ZONED_FLOAT : VEHICLE_VALUE_TYPE_ZONED_FLOAT,
vectorLength);
for (Float f : (Float[]) o) {
builder.addFloatValues(f);
}
} else if (o instanceof String) {
halType = VEHICLE_VALUE_TYPE_STRING;
builder.setStringValue((String) o);
} else if (o instanceof byte[]) {
halType = VEHICLE_VALUE_TYPE_BYTES; // We don't have zoned type in vehicle.h
builder.setBytesValue(ByteString.copyFrom((byte[]) o));
} else {
throw new IllegalArgumentException("Unexpected type in: " + hvacProp);
}
builder.setValueType(halType);
return builder.build();
}
/**
* Converts {@link VehiclePropConfig} to {@link CarPropertyConfig}.
*/
static CarPropertyConfig<?> toCarPropertyConfig(VehiclePropConfig p, int propertyId) {
int[] areas = VehicleZoneUtil.listAllZones(p.getZones());
// TODO: handle other vehicle area types.
int areaType = areas.length == 0
? VehicleAreaType.VEHICLE_AREA_TYPE_NONE : VehicleAreaType.VEHICLE_AREA_TYPE_ZONE;
Class<?> clazz = getJavaClass(p.getValueType());
if (clazz == Boolean.class || clazz == byte[].class || clazz == String.class) {
return CarPropertyConfig
.newBuilder(clazz, propertyId, areaType, /* capacity */ 1)
.addAreas(areas)
.build();
} else {
List mins;
List maxs;
if (classMatched(Integer.class, clazz)) {
mins = p.getInt32MinsList();
maxs = p.getInt32MaxsList();
} else if (classMatched(Float.class, clazz)) {
mins = p.getFloatMinsList();
maxs = p.getFloatMaxsList();
} else {
throw new IllegalArgumentException("Unexpected type: " + clazz);
}
CarPropertyConfig.Builder builder = CarPropertyConfig
.newBuilder(clazz, propertyId, areaType, /* capacity */ mins.size());
for (int i = 0; i < mins.size(); i++) {
int areaId = areas.length == 0 ? 0 : areas[i];
builder.addAreaConfig(areaId, mins.get(i), maxs.get(i));
}
return builder.build();
}
}
private static Class<?> getJavaClass(int halType) {
switch (halType) {
case VEHICLE_VALUE_TYPE_BOOLEAN:
case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN:
return Boolean.class;
case VEHICLE_VALUE_TYPE_FLOAT:
case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
return Float.class;
case VEHICLE_VALUE_TYPE_INT32:
case VEHICLE_VALUE_TYPE_ZONED_INT32:
return Integer.class;
case VEHICLE_VALUE_TYPE_INT32_VEC2:
case VEHICLE_VALUE_TYPE_INT32_VEC3:
case VEHICLE_VALUE_TYPE_INT32_VEC4:
case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4:
return Integer[].class;
case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
case VEHICLE_VALUE_TYPE_FLOAT_VEC4:
case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:
return Float[].class;
case VEHICLE_VALUE_TYPE_STRING:
return String.class;
case VEHICLE_VALUE_TYPE_BYTES:
return byte[].class;
default:
throw new IllegalArgumentException("Unexpected type: " + toHexString(halType));
}
}
private static List getRawValueList(Class<?> clazz, VehiclePropValue vehiclePropValue) {
if (classMatched(Float.class, clazz)) {
return vehiclePropValue.getFloatValuesList();
} else if (classMatched(Integer.class, clazz)) {
return vehiclePropValue.getInt32ValuesList();
} else {
throw new IllegalArgumentException("Unexpected type: " + clazz);
}
}
private static boolean classMatched(Class<?> class1, Class<?> class2) {
return class1 == class2 || class1.getComponentType() == class2;
}
}