blob: 40552c8e8879f7889f1ea00d73945d6f9997e9da [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"
Jiyong Park717fc692020-11-25 16:31:32 +090018#include "aidl_to_cpp_common.h"
Steven Moreland860b1942018-08-16 14:59:28 -070019#include "aidl_language.h"
Jiyong Parkce50e262018-10-29 09:54:20 +090020#include "logging.h"
21
Daniel Norman85aed542019-08-21 12:01:14 -070022#include <android-base/stringprintf.h>
Jeongik Cha1a7ab642019-07-29 17:31:02 +090023#include <android-base/strings.h>
24
Jiyong Parkce50e262018-10-29 09:54:20 +090025#include <functional>
26#include <unordered_map>
Steven Moreland860b1942018-08-16 14:59:28 -070027
Jeongik Cha1a7ab642019-07-29 17:31:02 +090028using android::base::Join;
29using android::base::Split;
Daniel Norman85aed542019-08-21 12:01:14 -070030using android::base::StringPrintf;
Jeongik Chab5d962f2018-11-17 09:12:28 +090031using std::ostringstream;
32
Steven Moreland860b1942018-08-16 14:59:28 -070033namespace android {
34namespace aidl {
35namespace cpp {
36
Jeongik Cha1a7ab642019-07-29 17:31:02 +090037namespace {
Devin Moore21b26772020-08-26 16:37:56 -070038std::string RawParcelMethod(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
Jeongik Cha1a7ab642019-07-29 17:31:02 +090039 bool readMethod) {
40 static map<string, string> kBuiltin = {
41 {"byte", "Byte"},
42 {"boolean", "Bool"},
43 {"char", "Char"},
44 {"double", "Double"},
45 {"FileDescriptor", "UniqueFileDescriptor"},
46 {"float", "Float"},
47 {"IBinder", "StrongBinder"},
48 {"int", "Int32"},
49 {"long", "Int64"},
50 {"ParcelFileDescriptor", "Parcelable"},
51 {"String", "String16"},
Jeongik Cha225519b2020-08-29 01:55:32 +090052 {"ParcelableHolder", "Parcelable"},
Jeongik Cha1a7ab642019-07-29 17:31:02 +090053 };
54
55 static map<string, string> kBuiltinVector = {
56 {"FileDescriptor", "UniqueFileDescriptorVector"},
57 {"double", "DoubleVector"},
58 {"char", "CharVector"},
59 {"boolean", "BoolVector"},
60 {"byte", "ByteVector"},
61 {"float", "FloatVector"},
62 {"IBinder", "StrongBinderVector"},
63 {"String", "String16Vector"},
64 {"int", "Int32Vector"},
65 {"long", "Int64Vector"},
66 {"ParcelFileDescriptor", "ParcelableVector"},
67 };
68
Devin Moore21b26772020-08-26 16:37:56 -070069 const bool nullable = type.IsNullable();
70 const bool isVector = type.IsArray() || typenames.IsList(type);
71 const bool utf8 = type.IsUtf8InCpp();
Jeongik Cha1a7ab642019-07-29 17:31:02 +090072
Devin Moore21b26772020-08-26 16:37:56 -070073 if (auto enum_decl = typenames.GetEnumDeclaration(type); enum_decl != nullptr) {
Daniel Normanee8674f2019-09-20 16:07:00 -070074 if (isVector) {
75 return "EnumVector";
76 } else {
77 return RawParcelMethod(enum_decl->GetBackingType(), typenames, readMethod);
78 }
79 }
80
Jeongik Cha1a7ab642019-07-29 17:31:02 +090081 if (isVector) {
Devin Moore21b26772020-08-26 16:37:56 -070082 string element_name;
83 if (typenames.IsList(type)) {
Steven Moreland21780812020-09-11 01:29:45 +000084 AIDL_FATAL_IF(type.GetTypeParameters().size() != 1, type);
Devin Moore21b26772020-08-26 16:37:56 -070085 element_name = type.GetTypeParameters().at(0)->GetName();
86 } else {
87 element_name = type.GetName();
88 }
89 if (kBuiltinVector.find(element_name) != kBuiltinVector.end()) {
Steven Moreland21780812020-09-11 01:29:45 +000090 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(element_name), type);
Jeongik Cha1a7ab642019-07-29 17:31:02 +090091 if (utf8) {
Steven Moreland21780812020-09-11 01:29:45 +000092 AIDL_FATAL_IF(element_name != "String", type);
Jeongik Cha1a7ab642019-07-29 17:31:02 +090093 return readMethod ? "Utf8VectorFromUtf16Vector" : "Utf8VectorAsUtf16Vector";
94 }
Devin Moore21b26772020-08-26 16:37:56 -070095 return kBuiltinVector[element_name];
Jeongik Cha1a7ab642019-07-29 17:31:02 +090096 }
Jooyung Han55f96ad2020-12-13 10:08:33 +090097 auto definedType = typenames.TryGetDefinedType(element_name);
98 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +090099 return "StrongBinderVector";
100 }
Jooyung Han55f96ad2020-12-13 10:08:33 +0900101 return "ParcelableVector";
102 }
103
104 const string& type_name = type.GetName();
105 if (kBuiltin.find(type_name) != kBuiltin.end()) {
106 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(type_name), type);
107 if (type_name == "IBinder" && nullable && readMethod) {
108 return "NullableStrongBinder";
109 }
110 if (type_name == "ParcelFileDescriptor" && nullable && !readMethod) {
111 return "NullableParcelable";
112 }
113 if (utf8) {
114 AIDL_FATAL_IF(type_name != "String", type);
115 return readMethod ? "Utf8FromUtf16" : "Utf8AsUtf16";
116 }
117 return kBuiltin[type_name];
118 }
119
120 AIDL_FATAL_IF(AidlTypenames::IsBuiltinTypename(type.GetName()), type);
121 auto definedType = typenames.TryGetDefinedType(type.GetName());
122 // The type must be either primitive or interface or parcelable,
123 // so it cannot be nullptr.
124 AIDL_FATAL_IF(definedType == nullptr, type) << type.GetName() << " is not found.";
125
126 if (definedType->AsInterface() != nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900127 if (nullable && readMethod) {
128 return "NullableStrongBinder";
129 }
130 return "StrongBinder";
131 }
132
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900133 // Parcelable
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900134 if (nullable && !readMethod) {
135 return "NullableParcelable";
136 }
137 return "Parcelable";
138}
139
140std::string GetRawCppName(const AidlTypeSpecifier& type) {
141 return "::" + Join(type.GetSplitName(), "::");
142}
143
Daniel Normanee8674f2019-09-20 16:07:00 -0700144std::string WrapIfNullable(const std::string type_str, const AidlTypeSpecifier& raw_type,
145 const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700146 const auto& type = typenames.IsList(raw_type) ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900147
148 if (raw_type.IsNullable() && !AidlTypenames::IsPrimitiveTypename(type.GetName()) &&
Daniel Normanee8674f2019-09-20 16:07:00 -0700149 type.GetName() != "IBinder" && typenames.GetEnumDeclaration(type) == nullptr) {
Jooyung Han43122462020-01-23 13:03:10 +0900150 return "::std::optional<" + type_str + ">";
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900151 }
152 return type_str;
153}
154
155std::string GetCppName(const AidlTypeSpecifier& raw_type, const AidlTypenames& typenames) {
156 // map from AIDL built-in type name to the corresponding Cpp type name
157 static map<string, string> m = {
158 {"boolean", "bool"},
159 {"byte", "int8_t"},
160 {"char", "char16_t"},
161 {"double", "double"},
162 {"FileDescriptor", "::android::base::unique_fd"},
163 {"float", "float"},
164 {"IBinder", "::android::sp<::android::IBinder>"},
165 {"int", "int32_t"},
166 {"long", "int64_t"},
167 {"ParcelFileDescriptor", "::android::os::ParcelFileDescriptor"},
168 {"String", "::android::String16"},
169 {"void", "void"},
Jeongik Cha225519b2020-08-29 01:55:32 +0900170 {"ParcelableHolder", "::android::os::ParcelableHolder"},
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900171 };
Steven Moreland21780812020-09-11 01:29:45 +0000172 AIDL_FATAL_IF(typenames.IsList(raw_type) && raw_type.GetTypeParameters().size() != 1, raw_type);
Devin Mooref12cc112020-08-26 16:25:00 -0700173 const auto& type = typenames.IsList(raw_type) ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900174 const string& aidl_name = type.GetName();
175 if (m.find(aidl_name) != m.end()) {
Steven Moreland21780812020-09-11 01:29:45 +0000176 AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), raw_type);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900177 if (aidl_name == "byte" && type.IsArray()) {
178 return "uint8_t";
179 } else if (raw_type.IsUtf8InCpp()) {
Steven Moreland21780812020-09-11 01:29:45 +0000180 AIDL_FATAL_IF(aidl_name != "String", type);
Daniel Normanee8674f2019-09-20 16:07:00 -0700181 return WrapIfNullable("::std::string", raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900182 }
Daniel Normanee8674f2019-09-20 16:07:00 -0700183 return WrapIfNullable(m[aidl_name], raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900184 }
185 auto definedType = typenames.TryGetDefinedType(type.GetName());
186 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
187 return "::android::sp<" + GetRawCppName(type) + ">";
188 }
189
Daniel Normanee8674f2019-09-20 16:07:00 -0700190 return WrapIfNullable(GetRawCppName(type), raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900191}
192} // namespace
Steven Moreland860b1942018-08-16 14:59:28 -0700193std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700194 if (type.IsArray()) {
195 return raw_value;
196 }
197
Daniel Norman37d43dd2019-09-09 17:22:34 -0700198 if (type.GetName() == "long") {
199 return raw_value + "L";
200 }
201
Will McVickerd7d18df2019-09-12 13:40:50 -0700202 if (type.GetName() == "String" && !type.IsUtf8InCpp()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700203 return "::android::String16(" + raw_value + ")";
204 }
205
Jooyung Han690f5842020-12-04 13:02:04 +0900206 if (auto defined_type = type.GetDefinedType(); defined_type) {
207 auto enum_type = defined_type->AsEnumDeclaration();
208 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
209 return GetRawCppName(type) + "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
210 }
211
Steven Moreland860b1942018-08-16 14:59:28 -0700212 return raw_value;
213};
214
Jiyong Park717fc692020-11-25 16:31:32 +0900215std::string GetTransactionIdFor(const AidlInterface& iface, const AidlMethod& method) {
216 return ClassName(iface, ClassNames::SERVER) + "::TRANSACTION_" + method.GetName();
Jeongik Chab5d962f2018-11-17 09:12:28 +0900217}
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900218
219std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700220 if (type.IsArray() || typenames.IsList(type)) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900221 std::string cpp_name = GetCppName(type, typenames);
222 if (type.IsNullable()) {
Jooyung Han43122462020-01-23 13:03:10 +0900223 return "::std::optional<::std::vector<" + cpp_name + ">>";
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900224 }
225 return "::std::vector<" + cpp_name + ">";
Devin Moore53fc99c2020-08-12 08:07:52 -0700226 } else if (type.IsGeneric()) {
227 std::vector<std::string> type_params;
228 for (const auto& parameter : type.GetTypeParameters()) {
229 type_params.push_back(CppNameOf(*parameter, typenames));
230 }
231 return StringPrintf("%s<%s>", GetCppName(type, typenames).c_str(),
232 base::Join(type_params, ", ").c_str());
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900233 }
234 return GetCppName(type, typenames);
235}
236
Jiyong Park4f3e8c02019-11-22 14:28:47 +0900237bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
Devin Mooref12cc112020-08-26 16:25:00 -0700238 if (type.IsArray() || typenames.IsList(type)) {
Jiyong Park4f3e8c02019-11-22 14:28:47 +0900239 return false;
240 }
241
242 const std::string cpp_name = GetCppName(type, typenames);
243 if (cpp_name == "::android::base::unique_fd") {
244 return true;
245 }
246 return false;
247}
248
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900249std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
250 return "read" + RawParcelMethod(type, typenames, true /* readMethod */);
251}
252
Daniel Norman85aed542019-08-21 12:01:14 -0700253std::string ParcelReadCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
254 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700255 if (auto enum_decl = typenames.GetEnumDeclaration(type);
256 enum_decl != nullptr && !type.IsArray()) {
257 return StringPrintf("reinterpret_cast<%s *>(%s)",
258 CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
Daniel Norman85aed542019-08-21 12:01:14 -0700259 variable_name.c_str());
260 }
261
262 return variable_name;
263}
264
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900265std::string ParcelWriteMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
266 return "write" + RawParcelMethod(type, typenames, false /* readMethod */);
267}
268
Daniel Norman85aed542019-08-21 12:01:14 -0700269std::string ParcelWriteCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
270 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700271 if (auto enum_decl = typenames.GetEnumDeclaration(type);
272 enum_decl != nullptr && !type.IsArray()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700273 return StringPrintf("static_cast<%s>(%s)",
274 CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
275 variable_name.c_str());
276 }
277
278 if (typenames.GetInterface(type) != nullptr) {
279 return GetRawCppName(type) + "::asBinder(" + variable_name + ")";
280 }
281
282 return variable_name;
283}
284
Devin Moore2f2077a2020-08-28 11:27:53 -0700285void AddHeaders(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
286 std::set<std::string>* headers) {
Steven Moreland21780812020-09-11 01:29:45 +0000287 AIDL_FATAL_IF(typenames.IsList(type) && type.GetTypeParameters().size() != 1, type);
Devin Moore2f2077a2020-08-28 11:27:53 -0700288 bool isVector = type.IsArray() || typenames.IsList(type);
289 bool isNullable = type.IsNullable();
290 bool utf8 = type.IsUtf8InCpp();
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900291
292 if (isVector) {
Devin Moore2f2077a2020-08-28 11:27:53 -0700293 headers->insert("vector");
294 }
295 if (type.IsGeneric()) {
296 for (const auto& parameter : type.GetTypeParameters()) {
297 AddHeaders(*parameter, typenames, headers);
298 }
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900299 }
300 if (isNullable) {
301 if (type.GetName() != "IBinder") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700302 headers->insert("optional");
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900303 }
304 }
Devin Moore2f2077a2020-08-28 11:27:53 -0700305 if (typenames.IsList(type)) {
306 // Nothing else to do for List.
307 return;
308 }
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900309 if (type.GetName() == "String") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700310 headers->insert(utf8 ? "string" : "utils/String16.h");
311 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900312 }
313 if (type.GetName() == "IBinder") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700314 headers->insert("binder/IBinder.h");
315 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900316 }
317 if (type.GetName() == "FileDescriptor") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700318 headers->insert("android-base/unique_fd.h");
319 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900320 }
321 if (type.GetName() == "ParcelFileDescriptor") {
Devin Moore2f2077a2020-08-28 11:27:53 -0700322 headers->insert("binder/ParcelFileDescriptor.h");
323 return;
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900324 }
Jeongik Cha225519b2020-08-29 01:55:32 +0900325 if (type.GetName() == "ParcelableHolder") {
326 headers->insert("binder/ParcelableHolder.h");
327 return;
328 }
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900329
330 static const std::set<string> need_cstdint{"byte", "int", "long"};
331 if (need_cstdint.find(type.GetName()) != need_cstdint.end()) {
Devin Moore2f2077a2020-08-28 11:27:53 -0700332 headers->insert("cstdint");
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900333 return;
334 }
Devin Moore2f2077a2020-08-28 11:27:53 -0700335
336 if (AidlTypenames::IsPrimitiveTypename(type.GetName())) {
337 return;
338 }
339
340 auto definedType = typenames.TryGetDefinedType(type.GetName());
341 AIDL_FATAL_IF(definedType == nullptr, type) << "Unexpected type: " << type.GetName();
342
Daniel Norman85aed542019-08-21 12:01:14 -0700343 if (definedType->AsInterface() != nullptr || definedType->AsStructuredParcelable() != nullptr ||
Jooyung Han14af79b2020-10-12 03:30:41 +0900344 definedType->AsEnumDeclaration() != nullptr || definedType->AsUnionDeclaration() != nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900345 AddHeaders(*definedType, headers);
346 } else if (definedType->AsParcelable() != nullptr) {
347 const std::string cpp_header = definedType->AsParcelable()->GetCppHeader();
348 AIDL_FATAL_IF(cpp_header.empty(), definedType->AsParcelable())
349 << "Parcelable " << definedType->AsParcelable()->GetCanonicalName()
350 << " has no C++ header defined.";
Devin Moore2f2077a2020-08-28 11:27:53 -0700351 headers->insert(cpp_header);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900352 }
353}
354
Devin Moore2f2077a2020-08-28 11:27:53 -0700355void AddHeaders(const AidlDefinedType& definedType, std::set<std::string>* headers) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900356 vector<string> name = definedType.GetSplitPackage();
357 name.push_back(definedType.GetName());
358 const std::string cpp_header = Join(name, '/') + ".h";
Devin Moore2f2077a2020-08-28 11:27:53 -0700359 headers->insert(cpp_header);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900360}
361
Steven Moreland860b1942018-08-16 14:59:28 -0700362} // namespace cpp
363} // namespace aidl
364} // namespace android