1 /* 2 * Copyright (C) 2018 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.vehiclehal.test; 17 18 import static java.lang.Integer.toHexString; 19 20 import android.car.hardware.CarPropertyValue; 21 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType; 22 23 import com.android.car.vehiclehal.VehiclePropValueBuilder; 24 25 import org.json.JSONArray; 26 import org.json.JSONException; 27 import org.json.JSONObject; 28 29 import java.io.BufferedReader; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.InputStreamReader; 33 import java.nio.charset.StandardCharsets; 34 import java.util.ArrayList; 35 import java.util.List; 36 37 38 class VhalJsonReader { 39 40 /** 41 * Name of fields presented in JSON file. All of them are required. 42 */ 43 private static final String JSON_FIELD_PROP = "prop"; 44 private static final String JSON_FIELD_AREA_ID = "areaId"; 45 private static final String JSON_FIELD_TIMESTAMP = "timestamp"; 46 private static final String JSON_FIELD_VALUE = "value"; 47 private static final String JSON_FIELD_INT32_VALUES = "int32Values"; 48 private static final String JSON_FIELD_INT64_VALUES = "int64Values"; 49 private static final String JSON_FIELD_FLOAT_VALUES = "floatValues"; 50 private static final String JSON_FIELD_STRING_VALUE = "stringValue"; 51 readFromJson(InputStream in)52 public static List<CarPropertyValue> readFromJson(InputStream in) 53 throws IOException, JSONException { 54 JSONArray rawEvents = new JSONArray(readJsonString(in)); 55 List<CarPropertyValue> events = new ArrayList<>(); 56 for (int i = 0; i < rawEvents.length(); i++) { 57 events.add(getEvent(rawEvents.getJSONObject(i))); 58 } 59 return events; 60 } 61 readJsonString(InputStream in)62 private static String readJsonString(InputStream in) throws IOException { 63 StringBuilder builder = new StringBuilder(); 64 try (BufferedReader reader = new BufferedReader( 65 new InputStreamReader(in, StandardCharsets.UTF_8))) { 66 reader.lines().forEach(builder::append); 67 } 68 return builder.toString(); 69 } 70 getEvent(JSONObject rawEvent)71 private static CarPropertyValue<?> getEvent(JSONObject rawEvent) throws JSONException { 72 int prop = rawEvent.getInt(JSON_FIELD_PROP); 73 int areaId = rawEvent.getInt(JSON_FIELD_AREA_ID); 74 long timestamp = rawEvent.getLong(JSON_FIELD_TIMESTAMP); 75 76 switch (prop & VehiclePropertyType.MASK) { 77 case VehiclePropertyType.BOOLEAN: 78 return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, 79 timestamp, rawEvent.getInt(JSON_FIELD_VALUE) != 0); 80 case VehiclePropertyType.INT32: 81 return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, 82 timestamp, rawEvent.getInt(JSON_FIELD_VALUE)); 83 case VehiclePropertyType.INT64: 84 return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, 85 timestamp, rawEvent.getLong(JSON_FIELD_VALUE)); 86 case VehiclePropertyType.FLOAT: 87 return new CarPropertyValue<>(prop, areaId, 88 CarPropertyValue.STATUS_AVAILABLE, timestamp, 89 (float) rawEvent.getDouble(JSON_FIELD_VALUE)); 90 case VehiclePropertyType.STRING: 91 return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, 92 timestamp, rawEvent.getString(JSON_FIELD_VALUE)); 93 // TODO: CarPropertyValue API has not supported VehiclePropertyType.MIXED type yet. 94 // Here is a temporary solution to use VehiclePropValue.RawValue 95 case VehiclePropertyType.MIXED: 96 VehiclePropValueBuilder builder = VehiclePropValueBuilder.newBuilder(prop); 97 JSONObject rawValueJson = rawEvent.getJSONObject(JSON_FIELD_VALUE); 98 copyValuesArray( 99 builder, rawValueJson.optJSONArray(JSON_FIELD_INT32_VALUES), Integer.class); 100 copyValuesArray( 101 builder, rawValueJson.optJSONArray(JSON_FIELD_INT64_VALUES), Long.class); 102 copyValuesArray( 103 builder, rawValueJson.optJSONArray(JSON_FIELD_FLOAT_VALUES), Float.class); 104 builder.setStringValue(rawValueJson.getString(JSON_FIELD_STRING_VALUE)); 105 106 return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, 107 timestamp, builder.build().value); 108 default: 109 throw new IllegalArgumentException("Property type 0x" 110 + toHexString(prop & VehiclePropertyType.MASK) 111 + " is not supported in the test."); 112 } 113 } 114 copyValuesArray(VehiclePropValueBuilder builder, JSONArray jsonArray, Class clazz)115 private static void copyValuesArray(VehiclePropValueBuilder builder, JSONArray jsonArray, 116 Class clazz) throws JSONException { 117 if (jsonArray == null) { 118 return; 119 } 120 for (int i = 0; i < jsonArray.length(); i++) { 121 if (clazz == Integer.class) { 122 builder.addIntValue(jsonArray.getInt(i)); 123 } else if (clazz == Long.class) { 124 // It is really "add" the value 125 builder.setInt64Value(jsonArray.getLong(i)); 126 } else if (clazz == Float.class) { 127 builder.addFloatValue((float) jsonArray.getDouble(i)); 128 } // TODO: Add support for byte array if required 129 } 130 } 131 } 132