1 /*
2  * Copyright (C) 2018, 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 #include "aidl_to_cpp.h"
18 #include "aidl_language.h"
19 #include "logging.h"
20 
21 #include <android-base/stringprintf.h>
22 #include <android-base/strings.h>
23 
24 #include <functional>
25 #include <unordered_map>
26 
27 using android::base::Join;
28 using android::base::Split;
29 using android::base::StringPrintf;
30 using std::ostringstream;
31 
32 namespace android {
33 namespace aidl {
34 namespace cpp {
35 
36 namespace {
RawParcelMethod(const AidlTypeSpecifier & raw_type,const AidlTypenames & typenames,bool readMethod)37 std::string RawParcelMethod(const AidlTypeSpecifier& raw_type, const AidlTypenames& typenames,
38                             bool readMethod) {
39   static map<string, string> kBuiltin = {
40       {"byte", "Byte"},
41       {"boolean", "Bool"},
42       {"char", "Char"},
43       {"double", "Double"},
44       {"FileDescriptor", "UniqueFileDescriptor"},
45       {"float", "Float"},
46       {"IBinder", "StrongBinder"},
47       {"int", "Int32"},
48       {"long", "Int64"},
49       {"ParcelFileDescriptor", "Parcelable"},
50       {"String", "String16"},
51   };
52 
53   static map<string, string> kBuiltinVector = {
54       {"FileDescriptor", "UniqueFileDescriptorVector"},
55       {"double", "DoubleVector"},
56       {"char", "CharVector"},
57       {"boolean", "BoolVector"},
58       {"byte", "ByteVector"},
59       {"float", "FloatVector"},
60       {"IBinder", "StrongBinderVector"},
61       {"String", "String16Vector"},
62       {"int", "Int32Vector"},
63       {"long", "Int64Vector"},
64       {"ParcelFileDescriptor", "ParcelableVector"},
65   };
66 
67   const bool nullable = raw_type.IsNullable();
68   const bool isVector =
69       raw_type.IsArray() || (raw_type.IsGeneric() && raw_type.GetName() == "List");
70   const bool utf8 = raw_type.IsUtf8InCpp();
71   const auto& type = raw_type.IsGeneric() ? *raw_type.GetTypeParameters().at(0) : raw_type;
72   const string& aidl_name = type.GetName();
73 
74   if (auto enum_decl = typenames.GetEnumDeclaration(raw_type); enum_decl != nullptr) {
75     if (isVector) {
76       return "EnumVector";
77     } else {
78       return RawParcelMethod(enum_decl->GetBackingType(), typenames, readMethod);
79     }
80   }
81 
82   if (isVector) {
83     if (kBuiltinVector.find(aidl_name) != kBuiltinVector.end()) {
84       CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
85       if (utf8) {
86         CHECK(aidl_name == "String");
87         return readMethod ? "Utf8VectorFromUtf16Vector" : "Utf8VectorAsUtf16Vector";
88       }
89       return kBuiltinVector[aidl_name];
90     }
91   } else {
92     if (kBuiltin.find(aidl_name) != kBuiltin.end()) {
93       CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
94       if (aidl_name == "IBinder" && nullable && readMethod) {
95         return "NullableStrongBinder";
96       }
97       if (aidl_name == "ParcelFileDescriptor" && nullable && !readMethod) {
98         return "NullableParcelable";
99       }
100       if (utf8) {
101         CHECK(aidl_name == "String");
102         return readMethod ? "Utf8FromUtf16" : "Utf8AsUtf16";
103       }
104       return kBuiltin[aidl_name];
105     }
106   }
107   CHECK(!AidlTypenames::IsBuiltinTypename(aidl_name));
108   auto definedType = typenames.TryGetDefinedType(type.GetName());
109   if (definedType != nullptr && definedType->AsInterface() != nullptr) {
110     if (isVector) {
111       return "StrongBinderVector";
112     }
113     if (nullable && readMethod) {
114       return "NullableStrongBinder";
115     }
116     return "StrongBinder";
117   }
118 
119   // The type must be either primitive or interface or parcelable,
120   // so it cannot be nullptr.
121   CHECK(definedType != nullptr) << type.GetName() << " is not found.";
122 
123   // Parcelable
124   if (isVector) {
125     return "ParcelableVector";
126   }
127   if (nullable && !readMethod) {
128     return "NullableParcelable";
129   }
130   return "Parcelable";
131 }
132 
GetRawCppName(const AidlTypeSpecifier & type)133 std::string GetRawCppName(const AidlTypeSpecifier& type) {
134   return "::" + Join(type.GetSplitName(), "::");
135 }
136 
WrapIfNullable(const std::string type_str,const AidlTypeSpecifier & raw_type,const AidlTypenames & typenames)137 std::string WrapIfNullable(const std::string type_str, const AidlTypeSpecifier& raw_type,
138                            const AidlTypenames& typenames) {
139   const auto& type = raw_type.IsGeneric() ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
140 
141   if (raw_type.IsNullable() && !AidlTypenames::IsPrimitiveTypename(type.GetName()) &&
142       type.GetName() != "IBinder" && typenames.GetEnumDeclaration(type) == nullptr) {
143     return "::std::optional<" + type_str + ">";
144   }
145   return type_str;
146 }
147 
GetCppName(const AidlTypeSpecifier & raw_type,const AidlTypenames & typenames)148 std::string GetCppName(const AidlTypeSpecifier& raw_type, const AidlTypenames& typenames) {
149   // map from AIDL built-in type name to the corresponding Cpp type name
150   static map<string, string> m = {
151       {"boolean", "bool"},
152       {"byte", "int8_t"},
153       {"char", "char16_t"},
154       {"double", "double"},
155       {"FileDescriptor", "::android::base::unique_fd"},
156       {"float", "float"},
157       {"IBinder", "::android::sp<::android::IBinder>"},
158       {"int", "int32_t"},
159       {"long", "int64_t"},
160       {"ParcelFileDescriptor", "::android::os::ParcelFileDescriptor"},
161       {"String", "::android::String16"},
162       {"void", "void"},
163   };
164 
165   CHECK(!raw_type.IsGeneric() ||
166         (raw_type.GetName() == "List" && raw_type.GetTypeParameters().size() == 1));
167   const auto& type = raw_type.IsGeneric() ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
168   const string& aidl_name = type.GetName();
169   if (m.find(aidl_name) != m.end()) {
170     CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
171     if (aidl_name == "byte" && type.IsArray()) {
172       return "uint8_t";
173     } else if (raw_type.IsUtf8InCpp()) {
174       CHECK(aidl_name == "String");
175       return WrapIfNullable("::std::string", raw_type, typenames);
176     }
177     return WrapIfNullable(m[aidl_name], raw_type, typenames);
178   }
179   auto definedType = typenames.TryGetDefinedType(type.GetName());
180   if (definedType != nullptr && definedType->AsInterface() != nullptr) {
181     return "::android::sp<" + GetRawCppName(type) + ">";
182   }
183 
184   return WrapIfNullable(GetRawCppName(type), raw_type, typenames);
185 }
186 }  // namespace
ConstantValueDecorator(const AidlTypeSpecifier & type,const std::string & raw_value)187 std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
188   if (type.IsArray()) {
189     return raw_value;
190   }
191 
192   if (type.GetName() == "long") {
193     return raw_value + "L";
194   }
195 
196   if (type.GetName() == "String" && !type.IsUtf8InCpp()) {
197     return "::android::String16(" + raw_value + ")";
198   }
199 
200   return raw_value;
201 };
202 
GetTransactionIdFor(const AidlMethod & method)203 std::string GetTransactionIdFor(const AidlMethod& method) {
204   ostringstream output;
205 
206   output << "::android::IBinder::FIRST_CALL_TRANSACTION + ";
207   output << method.GetId() << " /* " << method.GetName() << " */";
208   return output.str();
209 }
210 
CppNameOf(const AidlTypeSpecifier & type,const AidlTypenames & typenames)211 std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
212   if (type.IsArray() || type.IsGeneric()) {
213     std::string cpp_name = GetCppName(type, typenames);
214     if (type.IsNullable()) {
215       return "::std::optional<::std::vector<" + cpp_name + ">>";
216     }
217     return "::std::vector<" + cpp_name + ">";
218   }
219   return GetCppName(type, typenames);
220 }
221 
IsNonCopyableType(const AidlTypeSpecifier & type,const AidlTypenames & typenames)222 bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
223   if (type.IsArray() || type.IsGeneric()) {
224     return false;
225   }
226 
227   const std::string cpp_name = GetCppName(type, typenames);
228   if (cpp_name == "::android::base::unique_fd") {
229     return true;
230   }
231   return false;
232 }
233 
ParcelReadMethodOf(const AidlTypeSpecifier & type,const AidlTypenames & typenames)234 std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
235   return "read" + RawParcelMethod(type, typenames, true /* readMethod */);
236 }
237 
ParcelReadCastOf(const AidlTypeSpecifier & type,const AidlTypenames & typenames,const std::string & variable_name)238 std::string ParcelReadCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
239                              const std::string& variable_name) {
240   if (auto enum_decl = typenames.GetEnumDeclaration(type);
241       enum_decl != nullptr && !type.IsArray()) {
242     return StringPrintf("reinterpret_cast<%s *>(%s)",
243                         CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
244                         variable_name.c_str());
245   }
246 
247   return variable_name;
248 }
249 
ParcelWriteMethodOf(const AidlTypeSpecifier & type,const AidlTypenames & typenames)250 std::string ParcelWriteMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
251   return "write" + RawParcelMethod(type, typenames, false /* readMethod */);
252 }
253 
ParcelWriteCastOf(const AidlTypeSpecifier & type,const AidlTypenames & typenames,const std::string & variable_name)254 std::string ParcelWriteCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
255                               const std::string& variable_name) {
256   if (auto enum_decl = typenames.GetEnumDeclaration(type);
257       enum_decl != nullptr && !type.IsArray()) {
258     return StringPrintf("static_cast<%s>(%s)",
259                         CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
260                         variable_name.c_str());
261   }
262 
263   if (typenames.GetInterface(type) != nullptr) {
264     return GetRawCppName(type) + "::asBinder(" + variable_name + ")";
265   }
266 
267   return variable_name;
268 }
269 
AddHeaders(const AidlTypeSpecifier & raw_type,const AidlTypenames & typenames,std::set<std::string> & headers)270 void AddHeaders(const AidlTypeSpecifier& raw_type, const AidlTypenames& typenames,
271                 std::set<std::string>& headers) {
272   bool isVector = raw_type.IsArray() || raw_type.IsGeneric();
273   bool isNullable = raw_type.IsNullable();
274   bool utf8 = raw_type.IsUtf8InCpp();
275 
276   CHECK(!raw_type.IsGeneric() ||
277         (raw_type.GetName() == "List" && raw_type.GetTypeParameters().size() == 1));
278   const auto& type = raw_type.IsGeneric() ? *raw_type.GetTypeParameters().at(0) : raw_type;
279   auto definedType = typenames.TryGetDefinedType(type.GetName());
280 
281   if (isVector) {
282     headers.insert("vector");
283   }
284   if (isNullable) {
285     if (type.GetName() != "IBinder") {
286       headers.insert("optional");
287     }
288   }
289   if (type.GetName() == "String") {
290     headers.insert(utf8 ? "string" : "utils/String16.h");
291   }
292   if (type.GetName() == "IBinder") {
293     headers.insert("binder/IBinder.h");
294   }
295   if (type.GetName() == "FileDescriptor") {
296     headers.insert("android-base/unique_fd.h");
297   }
298   if (type.GetName() == "ParcelFileDescriptor") {
299     headers.insert("binder/ParcelFileDescriptor.h");
300   }
301 
302   static const std::set<string> need_cstdint{"byte", "int", "long"};
303   if (need_cstdint.find(type.GetName()) != need_cstdint.end()) {
304     headers.insert("cstdint");
305   }
306 
307   if (definedType == nullptr) {
308     return;
309   }
310   if (definedType->AsInterface() != nullptr || definedType->AsStructuredParcelable() != nullptr ||
311       definedType->AsEnumDeclaration() != nullptr) {
312     AddHeaders(*definedType, headers);
313   } else if (definedType->AsParcelable() != nullptr) {
314     const std::string cpp_header = definedType->AsParcelable()->GetCppHeader();
315     AIDL_FATAL_IF(cpp_header.empty(), definedType->AsParcelable())
316         << "Parcelable " << definedType->AsParcelable()->GetCanonicalName()
317         << " has no C++ header defined.";
318     headers.insert(cpp_header);
319   }
320 }
321 
AddHeaders(const AidlDefinedType & definedType,std::set<std::string> & headers)322 void AddHeaders(const AidlDefinedType& definedType, std::set<std::string>& headers) {
323   vector<string> name = definedType.GetSplitPackage();
324   name.push_back(definedType.GetName());
325   const std::string cpp_header = Join(name, '/') + ".h";
326   headers.insert(cpp_header);
327 }
328 
329 }  // namespace cpp
330 }  // namespace aidl
331 }  // namespace android
332