1/*
2 * Copyright (C) 2016 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 "automotive.vehicle@2.0-impl"
18
19#include "VehicleObjectPool.h"
20
21#include <log/log.h>
22
23#include "VehicleUtils.h"
24
25namespace android {
26namespace hardware {
27namespace automotive {
28namespace vehicle {
29namespace V2_0 {
30
31VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
32        VehiclePropertyType type, size_t vecSize) {
33    return isDisposable(type, vecSize)
34           ? obtainDisposable(type, vecSize)
35           : obtainRecylable(type, vecSize);
36}
37
38VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
39        const VehiclePropValue& src) {
40    if (src.prop == toInt(VehicleProperty::INVALID)) {
41        ALOGE("Unable to obtain an object from pool for unknown property");
42        return RecyclableType();
43    }
44    VehiclePropertyType type = getPropType(src.prop);
45    size_t vecSize = getVehicleRawValueVectorSize(src.value, type);;
46    auto dest = obtain(type, vecSize);
47
48    dest->prop = src.prop;
49    dest->areaId = src.areaId;
50    dest->status = src.status;
51    dest->timestamp = src.timestamp;
52    copyVehicleRawValue(&dest->value, src.value);
53
54    return dest;
55}
56
57VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(
58        int32_t value) {
59    auto val = obtain(VehiclePropertyType::INT32);
60    val->value.int32Values[0] = value;
61    return val;
62}
63
64VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(
65        int64_t value) {
66    auto val = obtain(VehiclePropertyType::INT64);
67    val->value.int64Values[0] = value;
68    return val;
69}
70
71VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(
72        float value)  {
73    auto val = obtain(VehiclePropertyType::FLOAT);
74    val->value.floatValues[0] = value;
75    return val;
76}
77
78VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(
79        const char* cstr) {
80    auto val = obtain(VehiclePropertyType::STRING);
81    val->value.stringValue = cstr;
82    return val;
83}
84
85VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
86    return obtain(VehiclePropertyType::MIXED);
87}
88
89VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecylable(
90        VehiclePropertyType type, size_t vecSize) {
91    // VehiclePropertyType is not overlapping with vectorSize.
92    int32_t key = static_cast<int32_t>(type)
93                  | static_cast<int32_t>(vecSize);
94
95    std::lock_guard<std::mutex> g(mLock);
96    auto it = mValueTypePools.find(key);
97
98    if (it == mValueTypePools.end()) {
99        auto newPool(std::make_unique<InternalPool>(type, vecSize));
100        it = mValueTypePools.emplace(key, std::move(newPool)).first;
101    }
102    return it->second->obtain();
103}
104
105VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(
106        bool value)  {
107    return obtainInt32(value);
108}
109
110VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
111        VehiclePropertyType valueType, size_t vectorSize) const {
112    return RecyclableType {
113        createVehiclePropValue(valueType, vectorSize).release(),
114        mDisposableDeleter
115    };
116}
117
118VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
119        VehiclePropertyType type) {
120    return obtain(type, 1);
121}
122
123
124void 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, mPropType, mVectorSize);
135        delete o;
136    } else {
137        ObjectPool<VehiclePropValue>::recycle(o);
138    }
139}
140
141bool VehiclePropValuePool::InternalPool::check(VehiclePropValue::RawValue* 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->bytes, VehiclePropertyType::BYTES == mPropType) && v->stringValue.size() == 0;
150}
151
152VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
153    return createVehiclePropValue(mPropType, mVectorSize).release();
154}
155
156}  // namespace V2_0
157}  // namespace vehicle
158}  // namespace automotive
159}  // namespace hardware
160}  // namespace android
161