Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 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 | |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 20 | import android.car.hardware.CarPropertyValue; |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 21 | import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType; |
| 22 | |
Chao Yan | 17357d1 | 2018-06-21 19:07:09 -0700 | [diff] [blame] | 23 | import com.android.car.vehiclehal.VehiclePropValueBuilder; |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 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"; |
Chao Yan | 17357d1 | 2018-06-21 19:07:09 -0700 | [diff] [blame] | 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"; |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 51 | |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 52 | public static List<CarPropertyValue> readFromJson(InputStream in) |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 53 | throws IOException, JSONException { |
| 54 | JSONArray rawEvents = new JSONArray(readJsonString(in)); |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 55 | List<CarPropertyValue> events = new ArrayList<>(); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 56 | for (int i = 0; i < rawEvents.length(); i++) { |
| 57 | events.add(getEvent(rawEvents.getJSONObject(i))); |
| 58 | } |
| 59 | return events; |
| 60 | } |
| 61 | |
| 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 | |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 71 | private static CarPropertyValue<?> getEvent(JSONObject rawEvent) throws JSONException { |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 72 | int prop = rawEvent.getInt(JSON_FIELD_PROP); |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 73 | int areaId = rawEvent.getInt(JSON_FIELD_AREA_ID); |
| 74 | long timestamp = rawEvent.getLong(JSON_FIELD_TIMESTAMP); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 75 | |
| 76 | switch (prop & VehiclePropertyType.MASK) { |
| 77 | case VehiclePropertyType.BOOLEAN: |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 78 | return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, |
| 79 | timestamp, rawEvent.getInt(JSON_FIELD_VALUE) != 0); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 80 | case VehiclePropertyType.INT32: |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 81 | return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, |
| 82 | timestamp, rawEvent.getInt(JSON_FIELD_VALUE)); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 83 | case VehiclePropertyType.INT64: |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 84 | return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, |
| 85 | timestamp, rawEvent.getLong(JSON_FIELD_VALUE)); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 86 | case VehiclePropertyType.FLOAT: |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 87 | return new CarPropertyValue<>(prop, areaId, |
| 88 | CarPropertyValue.STATUS_AVAILABLE, timestamp, |
| 89 | (float) rawEvent.getDouble(JSON_FIELD_VALUE)); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 90 | case VehiclePropertyType.STRING: |
Chao Yan | a916068 | 2018-06-14 11:05:45 -0700 | [diff] [blame] | 91 | return new CarPropertyValue<>(prop, areaId, CarPropertyValue.STATUS_AVAILABLE, |
| 92 | timestamp, rawEvent.getString(JSON_FIELD_VALUE)); |
Chao Yan | 17357d1 | 2018-06-21 19:07:09 -0700 | [diff] [blame] | 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); |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 108 | default: |
| 109 | throw new IllegalArgumentException("Property type 0x" |
| 110 | + toHexString(prop & VehiclePropertyType.MASK) |
| 111 | + " is not supported in the test."); |
| 112 | } |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 113 | } |
Chao Yan | 17357d1 | 2018-06-21 19:07:09 -0700 | [diff] [blame] | 114 | |
| 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 | } |
Chao Yan | f2c109c | 2018-05-11 12:16:14 -0700 | [diff] [blame] | 131 | } |