1/*
2 * Copyright (C) 2015 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 "VehicleNetwork"
18
19#include <utils/Log.h>
20
21#include <IVehicleNetwork.h>
22#include "VehicleNetworkProtoUtil.h"
23
24namespace android {
25
26static status_t copyString(const std::string& in, uint8_t** out, int32_t* len) {
27    *len = in.length();
28    if (*len == 0) {
29        *out = NULL;
30        return NO_ERROR;
31    }
32    *out = new uint8_t[*len];
33    ASSERT_OR_HANDLE_NO_MEMORY(*out, return NO_MEMORY);
34    memcpy(*out, in.data(), *len);
35    return NO_ERROR;
36}
37
38status_t VehicleNetworkProtoUtil::toVehiclePropValue(const vehicle_prop_value_t& in,
39        VehiclePropValue& out, bool /*inPlace*/) {
40    out.set_prop(in.prop);
41    out.set_value_type(in.value_type);
42    out.set_timestamp(in.timestamp);
43    out.set_zone(in.zone);
44    switch (in.value_type) {
45        case VEHICLE_VALUE_TYPE_STRING: {
46            //TODO fix ugly copy here for inplace mode
47            if (in.value.str_value.len > 0) {
48                out.set_string_value((char*)in.value.str_value.data, in.value.str_value.len);
49            }
50        } break;
51        case VEHICLE_VALUE_TYPE_BYTES: {
52            if (in.value.bytes_value.len > 0) {
53                out.set_bytes_value(in.value.bytes_value.data, in.value.bytes_value.len);
54            }
55        } break;
56        case VEHICLE_VALUE_TYPE_FLOAT:
57        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
58        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
59        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
60            int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_FLOAT + 1;
61            for (int i = 0; i < expectedSize; i++) {
62                out.add_float_values(in.value.float_array[i]);
63            }
64        } break;
65        case VEHICLE_VALUE_TYPE_INT64: {
66            out.set_int64_value(in.value.int64_value);
67        } break;
68        case VEHICLE_VALUE_TYPE_BOOLEAN:
69        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: {
70            out.add_int32_values(in.value.int32_value);
71        } break;
72        case VEHICLE_VALUE_TYPE_INT32:
73        case VEHICLE_VALUE_TYPE_INT32_VEC2:
74        case VEHICLE_VALUE_TYPE_INT32_VEC3:
75        case VEHICLE_VALUE_TYPE_INT32_VEC4: {
76            int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_INT32 + 1;
77            for (int i = 0; i < expectedSize; i++) {
78                out.add_int32_values(in.value.int32_array[i]);
79            }
80        } break;
81        case VEHICLE_VALUE_TYPE_ZONED_INT32:
82        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
83        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
84        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
85            int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
86            for (int i = 0; i < expectedSize; i++) {
87                out.add_int32_values(in.value.int32_array[i]);
88            }
89        } break;
90        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
91        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
92        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
93        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
94            int expectedSize = in.value_type - VEHICLE_VALUE_TYPE_ZONED_FLOAT + 1;
95            for (int i = 0; i < expectedSize; i++) {
96                out.add_float_values(in.value.float_array[i]);
97            }
98        } break;
99    }
100    return NO_ERROR;
101}
102
103status_t VehicleNetworkProtoUtil::fromVehiclePropValue(const VehiclePropValue& in,
104        vehicle_prop_value_t& out, bool /*inPlace*/, bool canIgnoreNoData) {
105    out.prop = in.prop();
106    out.value_type = in.value_type();
107    out.timestamp = in.timestamp();
108    out.zone = in.zone();
109    switch (out.value_type) {
110        case VEHICLE_VALUE_TYPE_STRING: {
111            if (!in.has_string_value()) {
112                // set to NULL so that client can just delete this safely.
113                out.value.str_value.data = NULL;
114                out.value.str_value.len = 0;
115                if (canIgnoreNoData) {
116                    return NO_ERROR;
117                } else {
118                    ALOGE("fromVehiclePropValue, no string data");
119                    return BAD_VALUE;
120                }
121            }
122            //TODO fix copy...
123            status_t r = copyString(in.string_value(), &(out.value.str_value.data),
124                    &(out.value.str_value.len));
125            if (r != NO_ERROR) {
126                out.value.str_value.data = NULL;
127                out.value.str_value.len = 0;
128                ALOGE("copyString for string failed %d", r);
129                return r;
130            }
131        } break;
132        case VEHICLE_VALUE_TYPE_BYTES: {
133            if (!in.has_bytes_value()) {
134                out.value.bytes_value.data = NULL;
135                out.value.bytes_value.len = 0;
136                if (canIgnoreNoData) {
137                    return NO_ERROR;
138                } else {
139                    ALOGE("fromVehiclePropValue, no byte data");
140                    return BAD_VALUE;
141                }
142            }
143            status_t r = copyString(in.bytes_value(), &(out.value.bytes_value.data),
144                    &(out.value.bytes_value.len));
145            if (r != NO_ERROR) {
146                out.value.bytes_value.data = NULL;
147                out.value.bytes_value.len = 0;
148                ALOGE("copyString for bytes failed %d", r);
149                return r;
150            }
151        } break;
152        case VEHICLE_VALUE_TYPE_FLOAT:
153        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
154        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
155        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
156            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_FLOAT + 1;
157            if (in.float_values_size() != expectedSize) {
158                if (canIgnoreNoData) {
159                    return NO_ERROR;
160                }
161                ALOGE("float value, wrong size %d, expecting %d", in.float_values_size(),
162                        expectedSize);
163                return BAD_VALUE;
164            }
165            for (int i = 0; i < expectedSize; i++) {
166                out.value.float_array[i] = in.float_values(i);
167            }
168        } break;
169        case VEHICLE_VALUE_TYPE_INT64: {
170            if (!in.has_int64_value()) {
171                if (canIgnoreNoData) {
172                    return NO_ERROR;
173                }
174                ALOGE("no int64 value");
175                return BAD_VALUE;
176            }
177            out.value.int64_value = in.int64_value();
178        } break;
179        case VEHICLE_VALUE_TYPE_BOOLEAN:
180        case VEHICLE_VALUE_TYPE_ZONED_BOOLEAN: {
181            if (in.int32_values_size() != 1) {
182                if (canIgnoreNoData) {
183                    return NO_ERROR;
184                }
185                ALOGE("no int32 value");
186                return BAD_VALUE;
187            }
188            out.value.int32_value = in.int32_values(0);
189        } break;
190        case VEHICLE_VALUE_TYPE_INT32:
191        case VEHICLE_VALUE_TYPE_INT32_VEC2:
192        case VEHICLE_VALUE_TYPE_INT32_VEC3:
193        case VEHICLE_VALUE_TYPE_INT32_VEC4: {
194            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_INT32 + 1;
195            if (in.int32_values_size() != expectedSize) {
196                if (canIgnoreNoData) {
197                    return NO_ERROR;
198                }
199                ALOGE("int32 value, wrong size %d, expecting %d", in.int32_values_size(),
200                        expectedSize);
201                return BAD_VALUE;
202            }
203            for (int i = 0; i < expectedSize; i++) {
204                out.value.int32_array[i] = in.int32_values(i);
205            }
206        } break;
207
208        case VEHICLE_VALUE_TYPE_ZONED_INT32:
209        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
210        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
211        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
212            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_ZONED_INT32 + 1;
213            if (in.int32_values_size() != expectedSize) {
214                if (canIgnoreNoData) {
215                    return NO_ERROR;
216                }
217                ALOGE("int32 value, wrong size %d, expecting %d", in.int32_values_size(),
218                        expectedSize);
219                return BAD_VALUE;
220            }
221            for (int i = 0; i < expectedSize; i++) {
222                out.value.int32_array[i] = in.int32_values(i);
223            }
224        } break;
225        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
226        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
227        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
228        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4:{
229            int expectedSize = out.value_type - VEHICLE_VALUE_TYPE_ZONED_FLOAT + 1;
230            if (in.float_values_size() != expectedSize) {
231                if (canIgnoreNoData) {
232                    return NO_ERROR;
233                }
234                ALOGE("float value, wrong size %d, expecting %d", in.float_values_size(),
235                        expectedSize);
236                return BAD_VALUE;
237            }
238            for (int i = 0; i < expectedSize; i++) {
239                out.value.float_array[i] = in.float_values(i);
240            }
241        } break;
242        default: {
243            if (canIgnoreNoData) {
244                return NO_ERROR;
245            }
246            ALOGE("fromVehiclePropValue unknown type 0x%x", out.value_type);
247            return BAD_VALUE;
248        }
249    }
250    return NO_ERROR;
251}
252
253status_t VehicleNetworkProtoUtil::toVehiclePropValues(const List<vehicle_prop_value_t*>& in,
254            VehiclePropValues& out) {
255    status_t r;
256    for (auto& v : in) {
257        VehiclePropValue* value = out.add_values();
258        r = toVehiclePropValue(*v, *value);
259        if (r != NO_ERROR) {
260            out.clear_values();
261            return r;
262        }
263    }
264    return NO_ERROR;
265}
266
267status_t VehicleNetworkProtoUtil::fromVehiclePropValues(const VehiclePropValues& in,
268            List<vehicle_prop_value_t*>& out) {
269    status_t r;
270    for (int i = 0; i < in.values_size(); i++) {
271        vehicle_prop_value_t* v =  new vehicle_prop_value_t();
272        memset(v, 0, sizeof(vehicle_prop_value_t));
273        ASSERT_OR_HANDLE_NO_MEMORY(v, r = NO_MEMORY;goto error);
274        r = fromVehiclePropValue(in.values(i), *v);
275        if (r != NO_ERROR) {
276            delete v;
277            goto error;
278        }
279        out.push_back(v);
280    }
281    return NO_ERROR;
282error:
283    // clean up everything in List
284    for (auto pv : out) {
285        VehiclePropValueUtil::deleteMembers(pv);
286    }
287    return r;
288}
289
290status_t VehicleNetworkProtoUtil::toVehiclePropConfig(const vehicle_prop_config_t& in,
291        VehiclePropConfig& out) {
292    out.set_prop(in.prop);
293    out.set_access(in.access);
294    out.set_change_mode(in.change_mode);
295    out.set_value_type(in.value_type);
296    out.set_permission_model(in.permission_model);
297    out.set_zones(in.vehicle_zone_flags);
298    for (unsigned int i = 0; i < sizeof(in.config_array) / sizeof(int32_t); i++) {
299        out.add_config_array(in.config_array[i]);
300    }
301    if (in.config_string.data != NULL && in.config_string.len != 0) {
302        out.set_config_string((char*)in.config_string.data, in.config_string.len);
303    } else {
304        out.clear_config_string();
305    }
306    switch (in.value_type) {
307        case VEHICLE_VALUE_TYPE_FLOAT:
308        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
309        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
310        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
311            out.add_float_maxs(in.float_max_value);
312            out.add_float_mins(in.float_min_value);
313        } break;
314        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
315        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
316        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
317        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
318            int numZones = VehicleNetworkUtil::countNumberOfZones(in.vehicle_zone_flags);
319            if (in.float_min_values == NULL) {
320                if (in.float_max_values == NULL) {
321                    // all the same min/max
322                    for (int i = 0; i < numZones; i++) {
323                        out.add_float_maxs(in.float_max_value);
324                        out.add_float_mins(in.float_min_value);
325                    }
326                } else { // invalid combination
327                    ALOGW("Zoned property 0x%x, min_values NULL while max_values not NULL",
328                            in.prop);
329                    return BAD_VALUE;
330                }
331            } else {
332                if (in.float_max_values != NULL) {
333                    for (int i = 0; i < numZones; i++) {
334                        out.add_float_maxs(in.float_max_values[i]);
335                        out.add_float_mins(in.float_min_values[i]);
336                    }
337                } else { // invalid combination
338                    ALOGW("Zoned property 0x%x, max_values NULL while min_values not NULL",
339                            in.prop);
340                    return BAD_VALUE;
341                }
342            }
343        } break;
344        case VEHICLE_VALUE_TYPE_INT64: {
345            out.add_int64_maxs(in.int64_max_value);
346            out.add_int64_mins(in.int64_min_value);
347        } break;
348        case VEHICLE_VALUE_TYPE_INT32:
349        case VEHICLE_VALUE_TYPE_INT32_VEC2:
350        case VEHICLE_VALUE_TYPE_INT32_VEC3:
351        case VEHICLE_VALUE_TYPE_INT32_VEC4:  {
352            out.add_int32_maxs(in.int32_max_value);
353            out.add_int32_mins(in.int32_min_value);
354        } break;
355        case VEHICLE_VALUE_TYPE_ZONED_INT32:
356        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
357        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
358        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
359            int numZones = VehicleNetworkUtil::countNumberOfZones(in.vehicle_zone_flags);
360            if (in.int32_min_values == NULL) {
361                if (in.int32_max_values == NULL) {
362                    // all the same min/max
363                    for (int i = 0; i < numZones; i++) {
364                        out.add_int32_maxs(in.int32_max_value);
365                        out.add_int32_mins(in.int32_min_value);
366                    }
367                } else { // invalid combination
368                    ALOGW("Zoned property 0x%x, min_values NULL while max_values not NULL",
369                            in.prop);
370                    return BAD_VALUE;
371                }
372            } else {
373                if (in.int32_max_values != NULL) {
374                    for (int i = 0; i < numZones; i++) {
375                        out.add_int32_maxs(in.int32_max_values[i]);
376                        out.add_int32_mins(in.int32_min_values[i]);
377                    }
378                } else { // invalid combination
379                    ALOGW("Zoned property 0x%x, max_values NULL while min_values not NULL",
380                            in.prop);
381                    return BAD_VALUE;
382                }
383            }
384        } break;
385    }
386    out.set_sample_rate_max(in.max_sample_rate);
387    out.set_sample_rate_min(in.min_sample_rate);
388    return NO_ERROR;
389}
390
391status_t VehicleNetworkProtoUtil::fromVehiclePropConfig(const VehiclePropConfig& in,
392        vehicle_prop_config_t& out) {
393    out.prop = in.prop();
394    out.access = in.access();
395    out.change_mode = in.change_mode();
396    out.value_type = in.value_type();
397    out.permission_model = in.permission_model();
398    out.vehicle_zone_flags = in.zones();
399    int maxConfigSize = sizeof(out.config_array) / sizeof(int32_t);
400    int configSize = in.config_array_size();
401    if (configSize > maxConfigSize) {
402        return BAD_VALUE;
403    }
404    int i = 0;
405    for (; i < configSize; i++) {
406        out.config_array[i] = in.config_array(i);
407    }
408    for (; i < maxConfigSize; i++) {
409        out.config_array[i] = 0;
410    }
411    if (in.has_config_string()) {
412        status_t r = copyString(in.config_string(), &(out.config_string.data),
413                &(out.config_string.len));
414        if (r != NO_ERROR) {
415            return r;
416        }
417    } else {
418        out.config_string.data = NULL;
419        out.config_string.len = 0;
420    }
421    switch (out.value_type) {
422        case VEHICLE_VALUE_TYPE_FLOAT:
423        case VEHICLE_VALUE_TYPE_FLOAT_VEC2:
424        case VEHICLE_VALUE_TYPE_FLOAT_VEC3:
425        case VEHICLE_VALUE_TYPE_FLOAT_VEC4: {
426            if ((in.float_maxs_size() == 1) && (in.float_mins_size() == 1)) {
427                out.float_max_value = in.float_maxs(0);
428                out.float_min_value = in.float_mins(0);
429            } else {
430                ALOGW("no float max/min for property 0x%x", out.prop);
431                out.float_max_value = 0;
432                out.float_min_value = 0;
433            }
434        } break;
435        case VEHICLE_VALUE_TYPE_ZONED_FLOAT:
436        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC2:
437        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC3:
438        case VEHICLE_VALUE_TYPE_ZONED_FLOAT_VEC4: {
439            int numZones = VehicleNetworkUtil::countNumberOfZones(out.vehicle_zone_flags);
440            int maxSize = in.float_maxs_size();
441            int minSize = in.float_mins_size();
442            if (maxSize != minSize) {
443                ALOGW("Zoned property 0x%x, config maxSize %d minSize %d", out.prop, maxSize,
444                        minSize);
445                return BAD_VALUE;
446            }
447            if (maxSize == 0) {
448                out.float_max_value = 0;
449                out.float_min_value = 0;
450                out.float_max_values = NULL;
451                out.float_min_values = NULL;
452            } else if (maxSize == 1) { // one for all
453                out.float_max_value = in.float_maxs(0);
454                out.float_min_value = in.float_mins(0);
455                out.float_max_values = NULL;
456                out.float_min_values = NULL;
457            } else if (numZones > 1){
458                if (numZones != maxSize) {
459                    ALOGW("Zoned property 0x%x, config maxSize %d num Zones %d", out.prop, maxSize,
460                                            numZones);
461                    return BAD_VALUE;
462                }
463                out.float_max_values = new float[numZones];
464                ASSERT_OR_HANDLE_NO_MEMORY(out.float_max_values, return NO_MEMORY);
465                out.float_min_values = new float[numZones];
466                ASSERT_OR_HANDLE_NO_MEMORY(out.float_min_values, return NO_MEMORY);
467                for (int i = 0; i < numZones; i++) {
468                    out.float_max_values[i] = in.float_maxs(i);
469                    out.float_min_values[i] = in.float_mins(i);
470                }
471            }
472        } break;
473        case VEHICLE_VALUE_TYPE_INT64: {
474            if ((in.int64_maxs_size() == 1) && (in.int64_mins_size() == 1)) {
475                out.int64_max_value = in.int64_maxs(0);
476                out.int64_min_value = in.int64_mins(0);
477            } else {
478                ALOGW("no int64 max/min for property 0x%x", out.prop);
479                out.int64_max_value = 0;
480                out.int64_min_value = 0;
481            }
482        } break;
483        case VEHICLE_VALUE_TYPE_INT32:
484        case VEHICLE_VALUE_TYPE_INT32_VEC2:
485        case VEHICLE_VALUE_TYPE_INT32_VEC3:
486        case VEHICLE_VALUE_TYPE_INT32_VEC4: {
487            if ((in.int32_maxs_size() == 1) && (in.int32_mins_size() == 1)) {
488                out.int32_max_value = in.int32_maxs(0);
489                out.int32_min_value = in.int32_mins(0);
490            } else {
491                ALOGW("no int32 max/min for property 0x%x", out.prop);
492                out.int32_max_value = 0;
493                out.int32_min_value = 0;
494            }
495        } break;
496        case VEHICLE_VALUE_TYPE_ZONED_INT32:
497        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC2:
498        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC3:
499        case VEHICLE_VALUE_TYPE_ZONED_INT32_VEC4: {
500            int numZones = VehicleNetworkUtil::countNumberOfZones(out.vehicle_zone_flags);
501            int maxSize = in.int32_maxs_size();
502            int minSize = in.int32_mins_size();
503            if (maxSize != minSize) {
504                ALOGW("Zoned property 0x%x, config maxSize %d minSize %d", out.prop, maxSize,
505                        minSize);
506                return BAD_VALUE;
507            }
508            if (maxSize == 0) {
509                out.int32_max_value = 0;
510                out.int32_min_value = 0;
511                out.int32_max_values = NULL;
512                out.int32_min_values = NULL;
513            } else if (maxSize == 1) { // one for all
514                out.int32_max_value = in.int32_maxs(0);
515                out.int32_min_value = in.int32_mins(0);
516                out.int32_max_values = NULL;
517                out.int32_min_values = NULL;
518            } else if (numZones > 1){
519                if (numZones != maxSize) {
520                    ALOGW("Zoned property 0x%x, config maxSize %d num Zones %d", out.prop, maxSize,
521                                            numZones);
522                    return BAD_VALUE;
523                }
524                out.int32_max_values = new int32_t[numZones];
525                ASSERT_OR_HANDLE_NO_MEMORY(out.int32_max_values, return NO_MEMORY);
526                out.int32_min_values = new int32_t[numZones];
527                ASSERT_OR_HANDLE_NO_MEMORY(out.int32_min_values, return NO_MEMORY);
528                for (int i = 0; i < numZones; i++) {
529                    out.int32_max_values[i] = in.int32_maxs(i);
530                    out.int32_min_values[i] = in.int32_mins(i);
531                }
532            }
533        } break;
534    }
535    out.max_sample_rate = in.sample_rate_max();
536    out.min_sample_rate = in.sample_rate_min();
537    return NO_ERROR;
538}
539
540status_t VehicleNetworkProtoUtil::toVehiclePropConfigs(List<vehicle_prop_config_t const*> &in,
541        VehiclePropConfigs& out) {
542    status_t r;
543    for (auto& inEntry : in) {
544        VehiclePropConfig* config = out.add_configs();
545        r = toVehiclePropConfig(*inEntry, *config);
546        if (r != NO_ERROR) {
547            out.clear_configs();
548            return r;
549        }
550    }
551    return NO_ERROR;
552}
553
554status_t VehicleNetworkProtoUtil::fromVehiclePropConfigs(const VehiclePropConfigs& in,
555        List<vehicle_prop_config_t const*>& out) {
556    int32_t n = in.configs_size();
557    status_t r;
558    for (int32_t i = 0; i < n; i++) {
559        vehicle_prop_config_t* entry = new vehicle_prop_config_t();
560        ASSERT_OR_HANDLE_NO_MEMORY(entry, r = NO_MEMORY; goto error);
561        memset(entry, 0, sizeof(vehicle_prop_config_t));
562        r = fromVehiclePropConfig(in.configs(i), *entry);
563        if (r != NO_ERROR) {
564            goto error;
565        }
566        out.push_back(entry);
567    }
568    return NO_ERROR;
569error:
570    for (auto& e : out) {
571        vehicle_prop_config_t* eDelete = const_cast<vehicle_prop_config_t*>(e);
572        VehiclePropertiesUtil::deleteMembers(eDelete);
573        delete eDelete;
574    }
575    out.clear();
576    return r;
577}
578
579status_t VehiclePropValueBinderUtil::writeToParcel(Parcel& parcel,
580        const vehicle_prop_value_t& value) {
581    parcel.writeInt32(1); // 0 means no value. For compatibility with aidl based code.
582    std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
583    ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
584    VehicleNetworkProtoUtil::toVehiclePropValue(value, *v.get());
585    int size = v->ByteSize();
586    WritableBlobHolder blob(new Parcel::WritableBlob());
587    ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
588    parcel.writeInt32(size);
589    parcel.writeBlob(size, false, blob.blob);
590    v->SerializeToArray(blob.blob->data(), size);
591    return NO_ERROR;
592}
593
594status_t VehiclePropValueBinderUtil::readFromParcel(const Parcel& parcel,
595        vehicle_prop_value_t* value, bool deleteMembers, bool canIgnoreNoData) {
596    if (parcel.readInt32() == 0) { // no result
597        ALOGE("readFromParcel, null data");
598        return BAD_VALUE;
599    }
600    ReadableBlobHolder blob(new Parcel::ReadableBlob());
601    ASSERT_OR_HANDLE_NO_MEMORY(blob.blob, return NO_MEMORY);
602    int32_t size = parcel.readInt32();
603    status_t status = parcel.readBlob(size, blob.blob);
604    if (status != NO_ERROR) {
605        ALOGE("readFromParcel, cannot read blob");
606        return status;
607    }
608    std::unique_ptr<VehiclePropValue> v(new VehiclePropValue());
609    ASSERT_OR_HANDLE_NO_MEMORY(v.get(), return NO_MEMORY);
610    if (!v->ParseFromArray(blob.blob->data(), size)) {
611        ALOGE("readFromParcel, cannot parse");
612        return BAD_VALUE;
613    }
614    if (deleteMembers) {
615        VehiclePropValueUtil::deleteMembers(value);
616    }
617    return VehicleNetworkProtoUtil::fromVehiclePropValue(*v.get(), *value, false /*inPlace*/,
618            canIgnoreNoData);
619}
620
621}; //namespace android
622
623