blob: b7d48b463e35628c9c6189fbd27743fc79df3dd2 [file] [log] [blame]
Steven Moreland860b1942018-08-16 14:59:28 -07001/*
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"
Jiyong Parkce50e262018-10-29 09:54:20 +090019#include "logging.h"
20
Daniel Norman85aed542019-08-21 12:01:14 -070021#include <android-base/stringprintf.h>
Jeongik Cha1a7ab642019-07-29 17:31:02 +090022#include <android-base/strings.h>
23
Jiyong Parkce50e262018-10-29 09:54:20 +090024#include <functional>
25#include <unordered_map>
Steven Moreland860b1942018-08-16 14:59:28 -070026
Jeongik Cha1a7ab642019-07-29 17:31:02 +090027using android::base::Join;
28using android::base::Split;
Daniel Norman85aed542019-08-21 12:01:14 -070029using android::base::StringPrintf;
Jeongik Chab5d962f2018-11-17 09:12:28 +090030using std::ostringstream;
31
Steven Moreland860b1942018-08-16 14:59:28 -070032namespace android {
33namespace aidl {
34namespace cpp {
35
Jeongik Cha1a7ab642019-07-29 17:31:02 +090036namespace {
Devin Moore21b26772020-08-26 16:37:56 -070037std::string RawParcelMethod(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
Jeongik Cha1a7ab642019-07-29 17:31:02 +090038 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
Devin Moore21b26772020-08-26 16:37:56 -070067 const bool nullable = type.IsNullable();
68 const bool isVector = type.IsArray() || typenames.IsList(type);
69 const bool utf8 = type.IsUtf8InCpp();
Jeongik Cha1a7ab642019-07-29 17:31:02 +090070
Devin Moore21b26772020-08-26 16:37:56 -070071 if (auto enum_decl = typenames.GetEnumDeclaration(type); enum_decl != nullptr) {
Daniel Normanee8674f2019-09-20 16:07:00 -070072 if (isVector) {
73 return "EnumVector";
74 } else {
75 return RawParcelMethod(enum_decl->GetBackingType(), typenames, readMethod);
76 }
77 }
78
Jeongik Cha1a7ab642019-07-29 17:31:02 +090079 if (isVector) {
Devin Moore21b26772020-08-26 16:37:56 -070080 string element_name;
81 if (typenames.IsList(type)) {
82 CHECK(type.GetTypeParameters().size() == 1);
83 element_name = type.GetTypeParameters().at(0)->GetName();
84 } else {
85 element_name = type.GetName();
86 }
87 if (kBuiltinVector.find(element_name) != kBuiltinVector.end()) {
88 CHECK(AidlTypenames::IsBuiltinTypename(element_name));
Jeongik Cha1a7ab642019-07-29 17:31:02 +090089 if (utf8) {
Devin Moore21b26772020-08-26 16:37:56 -070090 CHECK(element_name == "String");
Jeongik Cha1a7ab642019-07-29 17:31:02 +090091 return readMethod ? "Utf8VectorFromUtf16Vector" : "Utf8VectorAsUtf16Vector";
92 }
Devin Moore21b26772020-08-26 16:37:56 -070093 return kBuiltinVector[element_name];
Jeongik Cha1a7ab642019-07-29 17:31:02 +090094 }
Devin Moore21b26772020-08-26 16:37:56 -070095 CHECK(!typenames.IsList(type));
Jeongik Cha1a7ab642019-07-29 17:31:02 +090096 } else {
Devin Moore21b26772020-08-26 16:37:56 -070097 const string& type_name = type.GetName();
98 if (kBuiltin.find(type_name) != kBuiltin.end()) {
99 CHECK(AidlTypenames::IsBuiltinTypename(type_name));
100 if (type_name == "IBinder" && nullable && readMethod) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900101 return "NullableStrongBinder";
102 }
Devin Moore21b26772020-08-26 16:37:56 -0700103 if (type_name == "ParcelFileDescriptor" && nullable && !readMethod) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900104 return "NullableParcelable";
105 }
106 if (utf8) {
Devin Moore21b26772020-08-26 16:37:56 -0700107 CHECK(type_name == "String");
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900108 return readMethod ? "Utf8FromUtf16" : "Utf8AsUtf16";
109 }
Devin Moore21b26772020-08-26 16:37:56 -0700110 return kBuiltin[type_name];
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900111 }
112 }
Devin Moore21b26772020-08-26 16:37:56 -0700113 CHECK(!AidlTypenames::IsBuiltinTypename(type.GetName()));
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900114 auto definedType = typenames.TryGetDefinedType(type.GetName());
115 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
116 if (isVector) {
117 return "StrongBinderVector";
118 }
119 if (nullable && readMethod) {
120 return "NullableStrongBinder";
121 }
122 return "StrongBinder";
123 }
124
125 // The type must be either primitive or interface or parcelable,
126 // so it cannot be nullptr.
127 CHECK(definedType != nullptr) << type.GetName() << " is not found.";
128
129 // Parcelable
130 if (isVector) {
131 return "ParcelableVector";
132 }
133 if (nullable && !readMethod) {
134 return "NullableParcelable";
135 }
136 return "Parcelable";
137}
138
139std::string GetRawCppName(const AidlTypeSpecifier& type) {
140 return "::" + Join(type.GetSplitName(), "::");
141}
142
Daniel Normanee8674f2019-09-20 16:07:00 -0700143std::string WrapIfNullable(const std::string type_str, const AidlTypeSpecifier& raw_type,
144 const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700145 const auto& type = typenames.IsList(raw_type) ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900146
147 if (raw_type.IsNullable() && !AidlTypenames::IsPrimitiveTypename(type.GetName()) &&
Daniel Normanee8674f2019-09-20 16:07:00 -0700148 type.GetName() != "IBinder" && typenames.GetEnumDeclaration(type) == nullptr) {
Jooyung Han43122462020-01-23 13:03:10 +0900149 return "::std::optional<" + type_str + ">";
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900150 }
151 return type_str;
152}
153
154std::string GetCppName(const AidlTypeSpecifier& raw_type, const AidlTypenames& typenames) {
155 // map from AIDL built-in type name to the corresponding Cpp type name
156 static map<string, string> m = {
157 {"boolean", "bool"},
158 {"byte", "int8_t"},
159 {"char", "char16_t"},
160 {"double", "double"},
161 {"FileDescriptor", "::android::base::unique_fd"},
162 {"float", "float"},
163 {"IBinder", "::android::sp<::android::IBinder>"},
164 {"int", "int32_t"},
165 {"long", "int64_t"},
166 {"ParcelFileDescriptor", "::android::os::ParcelFileDescriptor"},
167 {"String", "::android::String16"},
168 {"void", "void"},
169 };
Devin Mooref12cc112020-08-26 16:25:00 -0700170 CHECK(!typenames.IsList(raw_type) || raw_type.GetTypeParameters().size() == 1);
171 const auto& type = typenames.IsList(raw_type) ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900172 const string& aidl_name = type.GetName();
173 if (m.find(aidl_name) != m.end()) {
174 CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
175 if (aidl_name == "byte" && type.IsArray()) {
176 return "uint8_t";
177 } else if (raw_type.IsUtf8InCpp()) {
178 CHECK(aidl_name == "String");
Daniel Normanee8674f2019-09-20 16:07:00 -0700179 return WrapIfNullable("::std::string", raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900180 }
Daniel Normanee8674f2019-09-20 16:07:00 -0700181 return WrapIfNullable(m[aidl_name], raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900182 }
183 auto definedType = typenames.TryGetDefinedType(type.GetName());
184 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
185 return "::android::sp<" + GetRawCppName(type) + ">";
186 }
187
Daniel Normanee8674f2019-09-20 16:07:00 -0700188 return WrapIfNullable(GetRawCppName(type), raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900189}
190} // namespace
Steven Moreland860b1942018-08-16 14:59:28 -0700191std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700192 if (type.IsArray()) {
193 return raw_value;
194 }
195
Daniel Norman37d43dd2019-09-09 17:22:34 -0700196 if (type.GetName() == "long") {
197 return raw_value + "L";
198 }
199
Will McVickerd7d18df2019-09-12 13:40:50 -0700200 if (type.GetName() == "String" && !type.IsUtf8InCpp()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700201 return "::android::String16(" + raw_value + ")";
202 }
203
204 return raw_value;
205};
206
Jeongik Chab5d962f2018-11-17 09:12:28 +0900207std::string GetTransactionIdFor(const AidlMethod& method) {
208 ostringstream output;
209
Jeongik Chaf1470e22019-05-20 18:45:05 +0900210 output << "::android::IBinder::FIRST_CALL_TRANSACTION + ";
Jeongik Chab5d962f2018-11-17 09:12:28 +0900211 output << method.GetId() << " /* " << method.GetName() << " */";
212 return output.str();
213}
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900214
215std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700216 if (type.IsArray() || typenames.IsList(type)) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900217 std::string cpp_name = GetCppName(type, typenames);
218 if (type.IsNullable()) {
Jooyung Han43122462020-01-23 13:03:10 +0900219 return "::std::optional<::std::vector<" + cpp_name + ">>";
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900220 }
221 return "::std::vector<" + cpp_name + ">";
Devin Moore53fc99c2020-08-12 08:07:52 -0700222 } else if (type.IsGeneric()) {
223 std::vector<std::string> type_params;
224 for (const auto& parameter : type.GetTypeParameters()) {
225 type_params.push_back(CppNameOf(*parameter, typenames));
226 }
227 return StringPrintf("%s<%s>", GetCppName(type, typenames).c_str(),
228 base::Join(type_params, ", ").c_str());
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900229 }
230 return GetCppName(type, typenames);
231}
232
Jiyong Park4f3e8c02019-11-22 14:28:47 +0900233bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700234 if (type.IsArray() || typenames.IsList(type)) {
Jiyong Park4f3e8c02019-11-22 14:28:47 +0900235 return false;
236 }
237
238 const std::string cpp_name = GetCppName(type, typenames);
239 if (cpp_name == "::android::base::unique_fd") {
240 return true;
241 }
242 return false;
243}
244
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900245std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
246 return "read" + RawParcelMethod(type, typenames, true /* readMethod */);
247}
248
Daniel Norman85aed542019-08-21 12:01:14 -0700249std::string ParcelReadCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
250 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700251 if (auto enum_decl = typenames.GetEnumDeclaration(type);
252 enum_decl != nullptr && !type.IsArray()) {
253 return StringPrintf("reinterpret_cast<%s *>(%s)",
254 CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
Daniel Norman85aed542019-08-21 12:01:14 -0700255 variable_name.c_str());
256 }
257
258 return variable_name;
259}
260
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900261std::string ParcelWriteMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
262 return "write" + RawParcelMethod(type, typenames, false /* readMethod */);
263}
264
Daniel Norman85aed542019-08-21 12:01:14 -0700265std::string ParcelWriteCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
266 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700267 if (auto enum_decl = typenames.GetEnumDeclaration(type);
268 enum_decl != nullptr && !type.IsArray()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700269 return StringPrintf("static_cast<%s>(%s)",
270 CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
271 variable_name.c_str());
272 }
273
274 if (typenames.GetInterface(type) != nullptr) {
275 return GetRawCppName(type) + "::asBinder(" + variable_name + ")";
276 }
277
278 return variable_name;
279}
280
Devin Moore2f2077a2020-08-28 11:27:53 -0700281void AddHeaders(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
282 std::set<std::string>* headers) {
283 CHECK(!typenames.IsList(type) || type.GetTypeParameters().size() == 1);
284 bool isVector = type.IsArray() || typenames.IsList(type);
285 bool isNullable = type.IsNullable();
286 bool utf8 = type.IsUtf8InCpp();
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900287
288 if (isVector) {
Devin Moore2f2077a2020-08-28 11:27:53 -0700289 headers->insert("vector");
290 }
291 if (type.IsGeneric()) {
292 for (const auto& parameter : type.GetTypeParameters()) {
293 AddHeaders(*parameter, typenames, headers);
294 }
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900295 }
296 if (isNullable) {
297 if (type.GetName() != "IBinder") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700298 headers->insert("optional");
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900299 }
300 }
Devin Moore2f2077a2020-08-28 11:27:53 -0700301 if (typenames.IsList(type)) {
302 // Nothing else to do for List.
303 return;
304 }
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900305 if (type.GetName() == "String") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700306 headers->insert(utf8 ? "string" : "utils/String16.h");
307 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900308 }
309 if (type.GetName() == "IBinder") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700310 headers->insert("binder/IBinder.h");
311 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900312 }
313 if (type.GetName() == "FileDescriptor") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700314 headers->insert("android-base/unique_fd.h");
315 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900316 }
317 if (type.GetName() == "ParcelFileDescriptor") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700318 headers->insert("binder/ParcelFileDescriptor.h");
319 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900320 }
321
322 static const std::set<string> need_cstdint{"byte", "int", "long"};
323 if (need_cstdint.find(type.GetName()) != need_cstdint.end()) {
Devin Moore2f2077a2020-08-28 11:27:53 -0700324 headers->insert("cstdint");
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900325 return;
326 }
Devin Moore2f2077a2020-08-28 11:27:53 -0700327
328 if (AidlTypenames::IsPrimitiveTypename(type.GetName())) {
329 return;
330 }
331
332 auto definedType = typenames.TryGetDefinedType(type.GetName());
333 AIDL_FATAL_IF(definedType == nullptr, type) << "Unexpected type: " << type.GetName();
334
Daniel Norman85aed542019-08-21 12:01:14 -0700335 if (definedType->AsInterface() != nullptr || definedType->AsStructuredParcelable() != nullptr ||
336 definedType->AsEnumDeclaration() != nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900337 AddHeaders(*definedType, headers);
338 } else if (definedType->AsParcelable() != nullptr) {
339 const std::string cpp_header = definedType->AsParcelable()->GetCppHeader();
340 AIDL_FATAL_IF(cpp_header.empty(), definedType->AsParcelable())
341 << "Parcelable " << definedType->AsParcelable()->GetCanonicalName()
342 << " has no C++ header defined.";
Devin Moore2f2077a2020-08-28 11:27:53 -0700343 headers->insert(cpp_header);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900344 }
345}
346
Devin Moore2f2077a2020-08-28 11:27:53 -0700347void AddHeaders(const AidlDefinedType& definedType, std::set<std::string>* headers) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900348 vector<string> name = definedType.GetSplitPackage();
349 name.push_back(definedType.GetName());
350 const std::string cpp_header = Join(name, '/') + ".h";
Devin Moore2f2077a2020-08-28 11:27:53 -0700351 headers->insert(cpp_header);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900352}
353
Steven Moreland860b1942018-08-16 14:59:28 -0700354} // namespace cpp
355} // namespace aidl
356} // namespace android