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 #ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
18 #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
19 
20 #include <LargeParcelableBase.h>
21 #include <VehicleHalTypes.h>
22 #include <VehicleUtils.h>
23 
24 #include <memory>
25 #include <vector>
26 
27 namespace android {
28 namespace hardware {
29 namespace automotive {
30 namespace vehicle {
31 
32 // Turns the values into a stable large parcelable that could be sent via binder.
33 // If values is small enough, it would be put into output.payloads, otherwise a shared memory file
34 // would be created and output.sharedMemoryFd would be filled in.
35 template <class T1, class T2>
vectorToStableLargeParcelable(std::vector<T1> && values,T2 * output)36 ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>&& values, T2* output) {
37     output->payloads = std::move(values);
38     auto result = android::automotive::car_binder_lib::LargeParcelableBase::
39             parcelableToStableLargeParcelable(*output);
40     if (!result.ok()) {
41         return toScopedAStatus(
42                 result, aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
43     }
44     auto& fd = result.value();
45     if (fd != nullptr) {
46         // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
47         // 'sharedMemoryFd' field.
48         output->payloads.clear();
49         output->sharedMemoryFd = std::move(*fd);
50     } else {
51         output->sharedMemoryFd = ndk::ScopedFileDescriptor();
52         // Do not modify payloads.
53     }
54     return ndk::ScopedAStatus::ok();
55 }
56 
57 template <class T1, class T2>
vectorToStableLargeParcelable(const std::vector<T1> & values,T2 * output)58 ndk::ScopedAStatus vectorToStableLargeParcelable(const std::vector<T1>& values, T2* output) {
59     // Because 'values' is passed in as const reference, we have to do a copy here.
60     std::vector<T1> valuesCopy = values;
61 
62     return vectorToStableLargeParcelable(std::move(valuesCopy), output);
63 }
64 
65 template <class T>
66 android::base::expected<
67         android::automotive::car_binder_lib::LargeParcelableBase::BorrowedOwnedObject<T>,
68         ndk::ScopedAStatus>
fromStableLargeParcelable(const T & largeParcelable)69 fromStableLargeParcelable(const T& largeParcelable) {
70     auto result = android::automotive::car_binder_lib::LargeParcelableBase::
71             stableLargeParcelableToParcelable(largeParcelable);
72 
73     if (!result.ok()) {
74         return android::base::unexpected(toScopedAStatus(
75                 result, aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG,
76                 "failed to parse large parcelable"));
77     }
78 
79     return std::move(result.value());
80 }
81 
82 }  // namespace vehicle
83 }  // namespace automotive
84 }  // namespace hardware
85 }  // namespace android
86 
87 #endif  // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_
88