blob: 9f2963e74e6c8e9bee0f610eeec5bbf1cce7771e [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 {
37std::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
Daniel Normanee8674f2019-09-20 16:07:00 -070074 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
Jeongik Cha1a7ab642019-07-29 17:31:02 +090082 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
133std::string GetRawCppName(const AidlTypeSpecifier& type) {
134 return "::" + Join(type.GetSplitName(), "::");
135}
136
Daniel Normanee8674f2019-09-20 16:07:00 -0700137std::string WrapIfNullable(const std::string type_str, const AidlTypeSpecifier& raw_type,
138 const AidlTypenames& typenames) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900139 const auto& type = raw_type.IsGeneric() ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
140
141 if (raw_type.IsNullable() && !AidlTypenames::IsPrimitiveTypename(type.GetName()) &&
Daniel Normanee8674f2019-09-20 16:07:00 -0700142 type.GetName() != "IBinder" && typenames.GetEnumDeclaration(type) == nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900143 return "::std::unique_ptr<" + type_str + ">";
144 }
145 return type_str;
146}
147
148std::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");
Daniel Normanee8674f2019-09-20 16:07:00 -0700175 return WrapIfNullable("::std::string", raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900176 }
Daniel Normanee8674f2019-09-20 16:07:00 -0700177 return WrapIfNullable(m[aidl_name], raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900178 }
179 auto definedType = typenames.TryGetDefinedType(type.GetName());
180 if (definedType != nullptr && definedType->AsInterface() != nullptr) {
181 return "::android::sp<" + GetRawCppName(type) + ">";
182 }
183
Daniel Normanee8674f2019-09-20 16:07:00 -0700184 return WrapIfNullable(GetRawCppName(type), raw_type, typenames);
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900185}
186} // namespace
Steven Moreland860b1942018-08-16 14:59:28 -0700187std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
Will McVickerd7d18df2019-09-12 13:40:50 -0700188 if (type.IsArray()) {
189 return raw_value;
190 }
191
Daniel Norman37d43dd2019-09-09 17:22:34 -0700192 if (type.GetName() == "long") {
193 return raw_value + "L";
194 }
195
Will McVickerd7d18df2019-09-12 13:40:50 -0700196 if (type.GetName() == "String" && !type.IsUtf8InCpp()) {
Steven Moreland860b1942018-08-16 14:59:28 -0700197 return "::android::String16(" + raw_value + ")";
198 }
199
200 return raw_value;
201};
202
Jeongik Chab5d962f2018-11-17 09:12:28 +0900203std::string GetTransactionIdFor(const AidlMethod& method) {
204 ostringstream output;
205
Jeongik Chaf1470e22019-05-20 18:45:05 +0900206 output << "::android::IBinder::FIRST_CALL_TRANSACTION + ";
Jeongik Chab5d962f2018-11-17 09:12:28 +0900207 output << method.GetId() << " /* " << method.GetName() << " */";
208 return output.str();
209}
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900210
211std::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::unique_ptr<::std::vector<" + cpp_name + ">>";
216 }
217 return "::std::vector<" + cpp_name + ">";
218 }
219 return GetCppName(type, typenames);
220}
221
Jiyong Parkf1a557f2019-11-22 14:28:47 +0900222bool 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
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900234std::string ParcelReadMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
235 return "read" + RawParcelMethod(type, typenames, true /* readMethod */);
236}
237
Daniel Norman85aed542019-08-21 12:01:14 -0700238std::string ParcelReadCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
239 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700240 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(),
Daniel Norman85aed542019-08-21 12:01:14 -0700244 variable_name.c_str());
245 }
246
247 return variable_name;
248}
249
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900250std::string ParcelWriteMethodOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
251 return "write" + RawParcelMethod(type, typenames, false /* readMethod */);
252}
253
Daniel Norman85aed542019-08-21 12:01:14 -0700254std::string ParcelWriteCastOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
255 const std::string& variable_name) {
Daniel Normanee8674f2019-09-20 16:07:00 -0700256 if (auto enum_decl = typenames.GetEnumDeclaration(type);
257 enum_decl != nullptr && !type.IsArray()) {
Daniel Norman85aed542019-08-21 12:01:14 -0700258 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
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900270void 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("memory");
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 }
Daniel Norman85aed542019-08-21 12:01:14 -0700310 if (definedType->AsInterface() != nullptr || definedType->AsStructuredParcelable() != nullptr ||
311 definedType->AsEnumDeclaration() != nullptr) {
Jeongik Cha1a7ab642019-07-29 17:31:02 +0900312 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
322void 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
Steven Moreland860b1942018-08-16 14:59:28 -0700329} // namespace cpp
330} // namespace aidl
331} // namespace android