1 /*
2  * Copyright (C) 2022 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 #pragma once
17 
18 #include <lib/shared/ibinder/ibinder.h>
19 #include <lk/macros.h>
20 #include <utils/StrongPointer.h>
21 
22 #define IBINDER_DEFINE_IFACE_CONTAINER(aidl_iface, iface) \
23     struct iface##_container {                            \
24         android::sp<aidl_iface> binder;                   \
25         struct iface cbinder;                             \
26         std::atomic<uint32_t> ref_count;                  \
27     };
28 
29 #define IBINDER_DEFINE_PARCELABLE_CONTAINER(parcel_type, parcel_struct) \
30     struct parcel_struct##_container {                                  \
31         parcel_type* parcel;                                            \
32         struct parcel_struct cparcel;                                   \
33         std::atomic<uint32_t> ref_count;                                \
34     };
35 
36 #define IBINDER_DEFINE_ADD_REF_IFACE(iface)                                    \
37     void iface##_add_ref(struct iface* self) {                                 \
38         auto container = containerof(self, struct iface##_container, cbinder); \
39         container->ref_count.fetch_add(1, std::memory_order_relaxed);          \
40     }
41 
42 #define IBINDER_DEFINE_ADD_REF_PARCELABLE(parcel_struct)                      \
43     void parcel_struct##_add_ref(struct parcel_struct* self) {                \
44         auto container =                                                      \
45                 containerof(self, struct parcel_struct##_container, cparcel); \
46         container->ref_count.fetch_add(1, std::memory_order_relaxed);         \
47     }
48 
49 #define IBINDER_DEFINE_RELEASE_IFACE(iface)                                 \
50     void iface##_release(struct iface** pself) {                            \
51         assert(pself != nullptr);                                           \
52         assert(*pself != nullptr);                                          \
53         auto container =                                                    \
54                 containerof(*pself, struct iface##_container, cbinder);     \
55                                                                             \
56         if (container->ref_count.fetch_sub(1, std::memory_order_release) == \
57             1) {                                                            \
58             std::atomic_thread_fence(std::memory_order_acquire);            \
59             delete container;                                               \
60         }                                                                   \
61         *pself = nullptr;                                                   \
62     }
63 
64 #define IBINDER_DEFINE_RELEASE_PARCELABLE(parcel_struct)                       \
65     void parcel_struct##_release(struct parcel_struct** pself) {               \
66         assert(pself != nullptr);                                              \
67         assert(*pself != nullptr);                                             \
68         auto container = containerof(*pself, struct parcel_struct##_container, \
69                                      cparcel);                                 \
70                                                                                \
71         if (container->ref_count.fetch_sub(1, std::memory_order_release) ==    \
72             1) {                                                               \
73             std::atomic_thread_fence(std::memory_order_acquire);               \
74             delete container->parcel;                                          \
75             delete container;                                                  \
76         }                                                                      \
77         *pself = nullptr;                                                      \
78     }
79 
80 #define IBINDER_DEFINE_GET_CPP_IFACE(aidl, iface)                              \
81     android::sp<aidl>& iface##_to_##aidl(struct iface* self) {                 \
82         auto container = containerof(self, struct iface##_container, cbinder); \
83         return container->binder;                                              \
84     }
85 
86 #define IBINDER_DEFINE_GET_CPP_PARCELABLE(parcel_type, parcel_struct)         \
87     parcel_type* parcel_struct##_to_##parcel_type(                            \
88             struct parcel_struct* self) {                                     \
89         auto container =                                                      \
90                 containerof(self, struct parcel_struct##_container, cparcel); \
91         return container->parcel;                                             \
92     }
93 
94 #define IBINDER_DEFINE_IFACE(aidl_iface, iface)        \
95     IBINDER_DEFINE_IFACE_CONTAINER(aidl_iface, iface); \
96     IBINDER_DEFINE_ADD_REF_IFACE(iface);               \
97     IBINDER_DEFINE_RELEASE_IFACE(iface);               \
98     IBINDER_DEFINE_GET_CPP_IFACE(aidl_iface, iface);
99 
100 #define IBINDER_DEFINE_PARCELABLE(parcel_type, parcel)        \
101     static inline parcel parcel##_builder();                  \
102     IBINDER_DEFINE_PARCELABLE_CONTAINER(parcel_type, parcel); \
103     IBINDER_DEFINE_ADD_REF_PARCELABLE(parcel);                \
104     IBINDER_DEFINE_RELEASE_PARCELABLE(parcel);                \
105     IBINDER_DEFINE_GET_CPP_PARCELABLE(parcel_type, parcel)
106