1 /*
2  * Copyright (C) 2021 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 #define LOG_TAG "VehicleObjectPool"
18 
19 #include <VehicleObjectPool.h>
20 
21 #include <VehicleUtils.h>
22 
23 #include <assert.h>
24 #include <utils/Log.h>
25 
26 namespace android {
27 namespace hardware {
28 namespace automotive {
29 namespace vehicle {
30 
31 using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
32 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
33 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
34 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
35 
obtain(VehiclePropertyType type)36 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type) {
37     if (isComplexType(type)) {
38         return obtain(type, 0);
39     }
40     return obtain(type, 1);
41 }
42 
obtain(VehiclePropertyType type,size_t vectorSize)43 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type,
44                                                                   size_t vectorSize) {
45     if (isSingleValueType(type)) {
46         vectorSize = 1;
47     } else if (isComplexType(type)) {
48         vectorSize = 0;
49     }
50     return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize)
51                                           : obtainRecyclable(type, vectorSize);
52 }
53 
obtain(const VehiclePropValue & src)54 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) {
55     int propId = src.prop;
56     VehiclePropertyType type = getPropType(propId);
57     size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
58     auto dest = obtain(type, vectorSize);
59 
60     dest->prop = propId;
61     dest->areaId = src.areaId;
62     dest->status = src.status;
63     dest->timestamp = src.timestamp;
64     copyVehicleRawValue(&dest->value, src.value);
65 
66     return dest;
67 }
68 
obtainInt32(int32_t value)69 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(int32_t value) {
70     auto val = obtain(VehiclePropertyType::INT32);
71     val->value.int32Values[0] = value;
72     return val;
73 }
74 
obtainInt64(int64_t value)75 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(int64_t value) {
76     auto val = obtain(VehiclePropertyType::INT64);
77     val->value.int64Values[0] = value;
78     return val;
79 }
80 
obtainFloat(float value)81 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(float value) {
82     auto val = obtain(VehiclePropertyType::FLOAT);
83     val->value.floatValues[0] = value;
84     return val;
85 }
86 
obtainString(const char * cstr)87 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(const char* cstr) {
88     auto val = obtain(VehiclePropertyType::STRING);
89     val->value.stringValue = cstr;
90     return val;
91 }
92 
obtainComplex()93 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
94     return obtain(VehiclePropertyType::MIXED);
95 }
96 
obtainRecyclable(VehiclePropertyType type,size_t vectorSize)97 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
98         VehiclePropertyType type, size_t vectorSize) {
99     std::scoped_lock<std::mutex> lock(mLock);
100     assert(vectorSize > 0);
101 
102     // VehiclePropertyType is not overlapping with vectorSize.
103     int32_t key = static_cast<int32_t>(type) | static_cast<int32_t>(vectorSize);
104     auto it = mValueTypePools.find(key);
105 
106     if (it == mValueTypePools.end()) {
107         auto newPool(std::make_unique<InternalPool>(type, vectorSize, mMaxPoolObjectsSize,
108                                                     getVehiclePropValueSize));
109         it = mValueTypePools.emplace(key, std::move(newPool)).first;
110     }
111     return it->second->obtain();
112 }
113 
obtainBoolean(bool value)114 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(bool value) {
115     return obtainInt32(value);
116 }
117 
obtainDisposable(VehiclePropertyType valueType,size_t vectorSize) const118 VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
119         VehiclePropertyType valueType, size_t vectorSize) const {
120     return RecyclableType{createVehiclePropValueVec(valueType, vectorSize).release(),
121                           mDisposableDeleter};
122 }
123 
recycle(VehiclePropValue * o)124 void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) {
125     if (o == nullptr) {
126         ALOGE("Attempt to recycle nullptr");
127         return;
128     }
129 
130     if (!check(&o->value)) {
131         ALOGE("Discarding value for prop 0x%x because it contains "
132               "data that is not consistent with this pool. "
133               "Expected type: %d, vector size: %zu",
134               o->prop, toInt(mPropType), mVectorSize);
135         delete o;
136     } else {
137         ObjectPool<VehiclePropValue>::recycle(o);
138     }
139 }
140 
check(RawPropValues * v)141 bool VehiclePropValuePool::InternalPool::check(RawPropValues* v) {
142     return check(&v->int32Values, (VehiclePropertyType::INT32 == mPropType ||
143                                    VehiclePropertyType::INT32_VEC == mPropType ||
144                                    VehiclePropertyType::BOOLEAN == mPropType)) &&
145            check(&v->floatValues, (VehiclePropertyType::FLOAT == mPropType ||
146                                    VehiclePropertyType::FLOAT_VEC == mPropType)) &&
147            check(&v->int64Values, (VehiclePropertyType::INT64 == mPropType ||
148                                    VehiclePropertyType::INT64_VEC == mPropType)) &&
149            check(&v->byteValues, VehiclePropertyType::BYTES == mPropType) &&
150            v->stringValue.size() == 0;
151 }
152 
createObject()153 VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
154     return createVehiclePropValueVec(mPropType, mVectorSize).release();
155 }
156 
157 }  // namespace vehicle
158 }  // namespace automotive
159 }  // namespace hardware
160 }  // namespace android
161