1 /*
2  * Copyright (C) 2017 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.vehiclehal;
18 
19 import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
20 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
21 import android.hardware.automotive.vehicle.V2_0.DiagnosticFloatSensorIndex;
22 import android.hardware.automotive.vehicle.V2_0.DiagnosticIntegerSensorIndex;
23 import android.util.SparseArray;
24 import java.util.BitSet;
25 import java.util.Iterator;
26 
27 /**
28  * A builder class for a VehiclePropValue that encapsulates a diagnostic event. This is the Java
29  * equivalent of Obd2SensorStore.cpp in the native layer.
30  *
31  * @hide
32  */
33 public class DiagnosticEventBuilder {
34     /**
35      * An array-like container that knows to return a default value for any unwritten-to index.
36      *
37      * @param <T> the element type
38      */
39     class DefaultedArray<T> implements Iterable<T> {
40         private final SparseArray<T> mElements = new SparseArray<>();
41         private final int mSize;
42         private final T mDefaultValue;
43 
DefaultedArray(int size, T defaultValue)44         DefaultedArray(int size, T defaultValue) {
45             mSize = size;
46             mDefaultValue = defaultValue;
47         }
48 
checkIndex(int index)49         private int checkIndex(int index) {
50             if (index < 0 || index >= mSize)
51                 throw new IndexOutOfBoundsException(
52                         String.format("Index: %d, Size: %d", index, mSize));
53             return index;
54         }
55 
set(int index, T element)56         DefaultedArray<T> set(int index, T element) {
57             checkIndex(index);
58             mElements.put(index, element);
59             return this;
60         }
61 
get(int index)62         T get(int index) {
63             checkIndex(index);
64             return mElements.get(index, mDefaultValue);
65         }
66 
size()67         int size() {
68             return mSize;
69         }
70 
clear()71         void clear() {
72             mElements.clear();
73         }
74 
75         @Override
iterator()76         public Iterator<T> iterator() {
77             return new Iterator<T>() {
78                 private int mIndex = 0;
79 
80                 @Override
81                 public boolean hasNext() {
82                     return (mIndex >= 0) && (mIndex < mSize);
83                 }
84 
85                 @Override
86                 public T next() {
87                     int index = mIndex++;
88                     return get(index);
89                 }
90             };
91         }
92     }
93 
94     private final int mPropertyId;
95     private final int mNumIntSensors;
96     private final DefaultedArray<Integer> mIntValues;
97     private final DefaultedArray<Float> mFloatValues;
98     private final BitSet mBitmask;
99     private String mDtc = null;
100 
DiagnosticEventBuilder(VehiclePropConfig propConfig)101     public DiagnosticEventBuilder(VehiclePropConfig propConfig) {
102         this(propConfig.prop, propConfig.configArray.get(0), propConfig.configArray.get(1));
103     }
104 
DiagnosticEventBuilder(int propertyId)105     public DiagnosticEventBuilder(int propertyId) {
106         this(propertyId, 0, 0);
107     }
108 
DiagnosticEventBuilder( int propertyId, int numVendorIntSensors, int numVendorFloatSensors)109     public DiagnosticEventBuilder(
110             int propertyId, int numVendorIntSensors, int numVendorFloatSensors) {
111         mPropertyId = propertyId;
112         mNumIntSensors = DiagnosticIntegerSensorIndex.LAST_SYSTEM_INDEX + 1 + numVendorIntSensors;
113         final int numFloatSensors =
114                 DiagnosticFloatSensorIndex.LAST_SYSTEM_INDEX + 1 + numVendorFloatSensors;
115         mBitmask = new BitSet(mNumIntSensors + numFloatSensors);
116         mIntValues = new DefaultedArray<>(mNumIntSensors, 0);
117         mFloatValues = new DefaultedArray<>(numFloatSensors, 0.0f);
118     }
119 
clear()120     public DiagnosticEventBuilder clear() {
121         mIntValues.clear();
122         mFloatValues.clear();
123         mBitmask.clear();
124         mDtc = null;
125         return this;
126     }
127 
addIntSensor(int index, int value)128     public DiagnosticEventBuilder addIntSensor(int index, int value) {
129         mIntValues.set(index, value);
130         mBitmask.set(index);
131         return this;
132     }
133 
addFloatSensor(int index, float value)134     public DiagnosticEventBuilder addFloatSensor(int index, float value) {
135         mFloatValues.set(index, value);
136         mBitmask.set(mNumIntSensors + index);
137         return this;
138     }
139 
setDTC(String dtc)140     public DiagnosticEventBuilder setDTC(String dtc) {
141         mDtc = dtc;
142         return this;
143     }
144 
build()145     public VehiclePropValue build() {
146         return build(0);
147     }
148 
build(long timestamp)149     public VehiclePropValue build(long timestamp) {
150         VehiclePropValueBuilder propValueBuilder = VehiclePropValueBuilder.newBuilder(mPropertyId);
151         if (0 == timestamp) {
152             propValueBuilder.setTimestamp();
153         } else {
154             propValueBuilder.setTimestamp(timestamp);
155         }
156         mIntValues.forEach(propValueBuilder::addIntValue);
157         mFloatValues.forEach(propValueBuilder::addFloatValue);
158         return propValueBuilder.addByteValue(mBitmask.toByteArray()).setStringValue(mDtc).build();
159     }
160 }
161