1 /*
2 * Copyright (C) 2015, 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_language.h"
18 #include "aidl_typenames.h"
19 #include "parser.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <algorithm>
25 #include <iostream>
26 #include <set>
27 #include <sstream>
28 #include <string>
29 #include <utility>
30
31 #include <android-base/parsedouble.h>
32 #include <android-base/parseint.h>
33 #include <android-base/strings.h>
34
35 #include "aidl_language_y-module.h"
36 #include "logging.h"
37
38 #include "aidl.h"
39
40 #ifdef _WIN32
isatty(int fd)41 int isatty(int fd)
42 {
43 return (fd == 0);
44 }
45 #endif
46
47 using android::aidl::IoDelegate;
48 using android::base::Join;
49 using android::base::Split;
50 using std::cerr;
51 using std::pair;
52 using std::set;
53 using std::string;
54 using std::unique_ptr;
55 using std::vector;
56
57 namespace {
IsJavaKeyword(const char * str)58 bool IsJavaKeyword(const char* str) {
59 static const std::vector<std::string> kJavaKeywords{
60 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
61 "char", "class", "const", "continue", "default", "do", "double",
62 "else", "enum", "extends", "final", "finally", "float", "for",
63 "goto", "if", "implements", "import", "instanceof", "int", "interface",
64 "long", "native", "new", "package", "private", "protected", "public",
65 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
66 "this", "throw", "throws", "transient", "try", "void", "volatile",
67 "while", "true", "false", "null",
68 };
69 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
70 }
71
AddHideComment(CodeWriter * writer)72 void AddHideComment(CodeWriter* writer) {
73 writer->Write("/* @hide */\n");
74 }
75
HasHideComment(const std::string & comment)76 inline bool HasHideComment(const std::string& comment) {
77 return std::regex_search(comment, std::regex("@hide\\b"));
78 }
79 } // namespace
80
AidlLocation(const std::string & file,Point begin,Point end,Source source)81 AidlLocation::AidlLocation(const std::string& file, Point begin, Point end, Source source)
82 : file_(file), begin_(begin), end_(end), source_(source) {}
83
operator <<(std::ostream & os,const AidlLocation & l)84 std::ostream& operator<<(std::ostream& os, const AidlLocation& l) {
85 os << l.file_;
86 if (l.LocationKnown()) {
87 os << ":" << l.begin_.line << "." << l.begin_.column << "-";
88 if (l.begin_.line != l.end_.line) {
89 os << l.end_.line << ".";
90 }
91 os << l.end_.column;
92 }
93 return os;
94 }
95
AidlNode(const AidlLocation & location)96 AidlNode::AidlNode(const AidlLocation& location) : location_(location) {}
97
PrintLine() const98 std::string AidlNode::PrintLine() const {
99 std::stringstream ss;
100 ss << location_.file_ << ":" << location_.begin_.line;
101 return ss.str();
102 }
103
PrintLocation() const104 std::string AidlNode::PrintLocation() const {
105 std::stringstream ss;
106 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
107 << location_.end_.line << ":" << location_.end_.column;
108 return ss.str();
109 }
110
AllSchemas()111 const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
112 static const std::vector<Schema> kSchemas{
113 {AidlAnnotation::Type::NULLABLE, "nullable", {}},
114 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}},
115 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}},
116 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
117 "UnsupportedAppUsage",
118 {{"expectedSignature", "String"},
119 {"implicitMember", "String"},
120 {"maxTargetSdk", "int"},
121 {"publicAlternatives", "String"},
122 {"trackingBug", "long"}}},
123 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}},
124 {AidlAnnotation::Type::HIDE, "Hide", {}},
125 {AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}},
126 {AidlAnnotation::Type::JAVA_PASSTHROUGH, "JavaPassthrough", {{"annotation", "String"}}},
127 {AidlAnnotation::Type::JAVA_DEBUG, "JavaDebug", {}},
128 {AidlAnnotation::Type::IMMUTABLE, "Immutable", {}},
129 };
130 return kSchemas;
131 }
132
TypeToString(Type type)133 std::string AidlAnnotation::TypeToString(Type type) {
134 for (const Schema& schema : AllSchemas()) {
135 if (type == schema.type) return schema.name;
136 }
137 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
138 __builtin_unreachable();
139 }
140
Parse(const AidlLocation & location,const string & name,std::map<std::string,std::shared_ptr<AidlConstantValue>> * parameter_list)141 AidlAnnotation* AidlAnnotation::Parse(
142 const AidlLocation& location, const string& name,
143 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
144 const Schema* schema = nullptr;
145 for (const Schema& a_schema : AllSchemas()) {
146 if (a_schema.name == name) {
147 schema = &a_schema;
148 }
149 }
150
151 if (schema == nullptr) {
152 std::ostringstream stream;
153 stream << "'" << name << "' is not a recognized annotation. ";
154 stream << "It must be one of:";
155 for (const Schema& s : AllSchemas()) {
156 stream << " " << s.name;
157 }
158 stream << ".";
159 AIDL_ERROR(location) << stream.str();
160 return nullptr;
161 }
162 if (parameter_list == nullptr) {
163 return new AidlAnnotation(location, *schema, {});
164 }
165
166 return new AidlAnnotation(location, *schema, std::move(*parameter_list));
167 }
168
AidlAnnotation(const AidlLocation & location,const Schema & schema,std::map<std::string,std::shared_ptr<AidlConstantValue>> && parameters)169 AidlAnnotation::AidlAnnotation(
170 const AidlLocation& location, const Schema& schema,
171 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
172 : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
173
CheckValid() const174 bool AidlAnnotation::CheckValid() const {
175 for (const auto& name_and_param : parameters_) {
176 const std::string& param_name = name_and_param.first;
177 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
178 if (!param->CheckValid()) {
179 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
180 << GetName() << ".";
181 return false;
182 }
183 auto parameter_mapping_it = schema_.supported_parameters.find(param_name);
184 if (parameter_mapping_it == schema_.supported_parameters.end()) {
185 std::ostringstream stream;
186 stream << "Parameter " << param_name << " not supported ";
187 stream << "for annotation " << GetName() << ". ";
188 stream << "It must be one of:";
189 for (const auto& kv : schema_.supported_parameters) {
190 stream << " " << kv.first;
191 }
192 AIDL_ERROR(this) << stream.str();
193 return false;
194 }
195 AidlTypeSpecifier type{AIDL_LOCATION_HERE, parameter_mapping_it->second, false, nullptr, ""};
196 const std::string param_value = param->ValueString(type, AidlConstantValueDecorator);
197 // Assume error on empty string.
198 if (param_value == "") {
199 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
200 << GetName() << ".";
201 return false;
202 }
203 }
204 return true;
205 }
206
AnnotationParams(const ConstantValueDecorator & decorator) const207 std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
208 const ConstantValueDecorator& decorator) const {
209 std::map<std::string, std::string> raw_params;
210 for (const auto& name_and_param : parameters_) {
211 const std::string& param_name = name_and_param.first;
212 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
213 if (schema_.supported_parameters.find(param_name) == schema_.supported_parameters.end()) {
214 std::ostringstream stream;
215 stream << "Parameter " << param_name << " not supported ";
216 stream << "for annotation " << GetName() << ". ";
217 stream << "It must be one of:";
218 for (const auto& kv : schema_.supported_parameters) {
219 stream << " " << kv.first;
220 }
221 AIDL_ERROR(this) << stream.str();
222 continue;
223 }
224 AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
225 nullptr, ""};
226 if (!param->CheckValid()) {
227 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
228 << GetName() << ".";
229 continue;
230 }
231
232 raw_params.emplace(param_name, param->ValueString(type, decorator));
233 }
234 return raw_params;
235 }
236
ToString(const ConstantValueDecorator & decorator) const237 std::string AidlAnnotation::ToString(const ConstantValueDecorator& decorator) const {
238 if (parameters_.empty()) {
239 return "@" + GetName();
240 } else {
241 vector<string> param_strings;
242 for (const auto& [name, value] : AnnotationParams(decorator)) {
243 param_strings.emplace_back(name + "=" + value);
244 }
245 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
246 }
247 }
248
GetAnnotation(const vector<AidlAnnotation> & annotations,AidlAnnotation::Type type)249 static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
250 AidlAnnotation::Type type) {
251 for (const auto& a : annotations) {
252 if (a.GetType() == type) {
253 return &a;
254 }
255 }
256 return nullptr;
257 }
258
AidlAnnotatable(const AidlLocation & location)259 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
260
IsNullable() const261 bool AidlAnnotatable::IsNullable() const {
262 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
263 }
264
IsUtf8InCpp() const265 bool AidlAnnotatable::IsUtf8InCpp() const {
266 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
267 }
268
IsVintfStability() const269 bool AidlAnnotatable::IsVintfStability() const {
270 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
271 }
272
IsImmutable() const273 bool AidlAnnotatable::IsImmutable() const {
274 return GetAnnotation(annotations_, AidlAnnotation::Type::IMMUTABLE);
275 }
276
UnsupportedAppUsage() const277 const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
278 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
279 }
280
JavaPassthrough() const281 const AidlAnnotation* AidlAnnotatable::JavaPassthrough() const {
282 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_PASSTHROUGH);
283 }
284
BackingType(const AidlTypenames & typenames) const285 const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
286 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
287 if (annotation != nullptr) {
288 auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
289 if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
290 const string& type = it->second;
291
292 AIDL_FATAL_IF(type.size() < 2, this) << type;
293 AIDL_FATAL_IF(type[0] != '"', this) << type;
294 AIDL_FATAL_IF(type[type.length() - 1] != '"', this) << type;
295 string unquoted_type = type.substr(1, type.length() - 2);
296
297 AidlTypeSpecifier* type_specifier =
298 new AidlTypeSpecifier(AIDL_LOCATION_HERE, unquoted_type, false, nullptr, "");
299 type_specifier->Resolve(typenames);
300 return type_specifier;
301 }
302 }
303 return nullptr;
304 }
305
IsStableApiParcelable(Options::Language lang) const306 bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
307 return lang == Options::Language::JAVA &&
308 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
309 }
310
IsHide() const311 bool AidlAnnotatable::IsHide() const {
312 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
313 }
314
IsJavaDebug() const315 bool AidlAnnotatable::IsJavaDebug() const {
316 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEBUG);
317 }
318
DumpAnnotations(CodeWriter * writer) const319 void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
320 if (annotations_.empty()) return;
321
322 writer->Write("%s\n", AidlAnnotatable::ToString().c_str());
323 }
324
CheckValid(const AidlTypenames &) const325 bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
326 std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
327 for (const auto& annotation : GetAnnotations()) {
328 if (!annotation.CheckValid()) {
329 return false;
330 }
331
332 std::vector<std::string> supported_annot_strings;
333 for (AidlAnnotation::Type type : supported_annotations) {
334 supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
335 }
336
337 if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
338 AIDL_ERROR(this) << "'" << annotation.GetName()
339 << "' is not a supported annotation for this node. "
340 << "It must be one of: "
341 << android::base::Join(supported_annot_strings, ", ");
342 return false;
343 }
344 }
345
346 return true;
347 }
348
ToString() const349 string AidlAnnotatable::ToString() const {
350 vector<string> ret;
351 for (const auto& a : annotations_) {
352 ret.emplace_back(a.ToString(AidlConstantValueDecorator));
353 }
354 std::sort(ret.begin(), ret.end());
355 return Join(ret, " ");
356 }
357
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,bool is_array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const string & comments)358 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
359 bool is_array,
360 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
361 const string& comments)
362 : AidlAnnotatable(location),
363 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
364 unresolved_name_(unresolved_name),
365 is_array_(is_array),
366 comments_(comments),
367 split_name_(Split(unresolved_name, ".")) {}
368
ArrayBase() const369 AidlTypeSpecifier AidlTypeSpecifier::ArrayBase() const {
370 AIDL_FATAL_IF(!is_array_, this);
371 // Declaring array of generic type cannot happen, it is grammar error.
372 AIDL_FATAL_IF(IsGeneric(), this);
373
374 AidlTypeSpecifier array_base = *this;
375 array_base.is_array_ = false;
376 return array_base;
377 }
378
IsHidden() const379 bool AidlTypeSpecifier::IsHidden() const {
380 return HasHideComment(GetComments());
381 }
382
ToString() const383 string AidlTypeSpecifier::ToString() const {
384 string ret = GetName();
385 if (IsGeneric()) {
386 vector<string> arg_names;
387 for (const auto& ta : GetTypeParameters()) {
388 arg_names.emplace_back(ta->ToString());
389 }
390 ret += "<" + Join(arg_names, ",") + ">";
391 }
392 if (IsArray()) {
393 ret += "[]";
394 }
395 return ret;
396 }
397
Signature() const398 string AidlTypeSpecifier::Signature() const {
399 string ret = ToString();
400 string annotations = AidlAnnotatable::ToString();
401 if (annotations != "") {
402 ret = annotations + " " + ret;
403 }
404 return ret;
405 }
406
Resolve(const AidlTypenames & typenames)407 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
408 CHECK(!IsResolved());
409 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
410 if (result.is_resolved) {
411 fully_qualified_name_ = result.canonical_name;
412 split_name_ = Split(fully_qualified_name_, ".");
413 }
414 return result.is_resolved;
415 }
416
GetSupportedAnnotations() const417 std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
418 // kHide and kUnsupportedAppUsage are both method return annotations
419 // which we don't distinguish from other type specifiers.
420 return {AidlAnnotation::Type::NULLABLE, AidlAnnotation::Type::UTF8_IN_CPP,
421 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE,
422 AidlAnnotation::Type::JAVA_PASSTHROUGH};
423 }
424
CheckValid(const AidlTypenames & typenames) const425 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
426 if (!AidlAnnotatable::CheckValid(typenames)) {
427 return false;
428 }
429 if (IsGeneric()) {
430 const string& type_name = GetName();
431
432 auto& types = GetTypeParameters();
433 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
434 if (type_name == "List" || type_name == "Map") {
435 if (std::any_of(types.begin(), types.end(), [](auto& type_ptr) {
436 return AidlTypenames::IsPrimitiveTypename(type_ptr->GetName());
437 })) {
438 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
439 return false;
440 }
441 }
442 const auto defined_type = typenames.TryGetDefinedType(type_name);
443 const auto parameterizable =
444 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
445 const bool is_user_defined_generic_type =
446 parameterizable != nullptr && parameterizable->IsGeneric();
447 const size_t num_params = GetTypeParameters().size();
448 if (type_name == "List") {
449 if (num_params > 1) {
450 AIDL_ERROR(this) << " List cannot have type parameters more than one, but got "
451 << "'" << ToString() << "'";
452 return false;
453 }
454 } else if (type_name == "Map") {
455 if (num_params != 0 && num_params != 2) {
456 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
457 << "'" << ToString() << "'";
458 return false;
459 }
460 if (num_params == 2) {
461 const string& key_type = GetTypeParameters()[0]->GetName();
462 if (key_type != "String") {
463 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
464 << "'" << key_type << "'";
465 return false;
466 }
467 }
468 } else if (is_user_defined_generic_type) {
469 const size_t allowed = parameterizable->GetTypeParameters().size();
470 if (num_params != allowed) {
471 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
472 << num_params;
473 return false;
474 }
475 } else {
476 AIDL_ERROR(this) << type_name << " is not a generic type.";
477 return false;
478 }
479 }
480
481 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
482 GetTypeParameters().size() == 1 &&
483 GetTypeParameters()[0]->GetName() == "String";
484 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
485 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
486 return false;
487 }
488
489 if (GetName() == "void") {
490 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
491 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
492 return false;
493 }
494 }
495
496 if (IsArray()) {
497 const auto defined_type = typenames.TryGetDefinedType(GetName());
498 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
499 AIDL_ERROR(this) << "Binder type cannot be an array";
500 return false;
501 }
502 }
503
504 if (IsNullable()) {
505 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
506 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
507 return false;
508 }
509 const auto defined_type = typenames.TryGetDefinedType(GetName());
510 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
511 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
512 return false;
513 }
514 }
515 return true;
516 }
517
AidlConstantValueDecorator(const AidlTypeSpecifier &,const std::string & raw_value)518 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& /*type*/,
519 const std::string& raw_value) {
520 return raw_value;
521 }
522
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)523 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
524 AidlTypeSpecifier* type, const std::string& name)
525 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
526 default_user_specified_ = false;
527 }
528
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)529 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
530 AidlTypeSpecifier* type, const std::string& name,
531 AidlConstantValue* default_value)
532 : AidlNode(location),
533 type_(type),
534 name_(name),
535 default_user_specified_(true),
536 default_value_(default_value) {}
537
CheckValid(const AidlTypenames & typenames) const538 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
539 bool valid = true;
540 valid &= type_->CheckValid(typenames);
541
542 if (type_->GetName() == "void") {
543 AIDL_ERROR(this) << "Declaration " << name_
544 << " is void, but declarations cannot be of void type.";
545 valid = false;
546 }
547
548 if (default_value_ == nullptr) return valid;
549 valid &= default_value_->CheckValid();
550
551 if (!valid) return false;
552
553 return !ValueString(AidlConstantValueDecorator).empty();
554 }
555
ToString() const556 string AidlVariableDeclaration::ToString() const {
557 string ret = type_->Signature() + " " + name_;
558 if (default_value_ != nullptr && default_user_specified_) {
559 ret += " = " + ValueString(AidlConstantValueDecorator);
560 }
561 return ret;
562 }
563
Signature() const564 string AidlVariableDeclaration::Signature() const {
565 return type_->Signature() + " " + name_;
566 }
567
ValueString(const ConstantValueDecorator & decorator) const568 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
569 if (default_value_ != nullptr) {
570 return default_value_->ValueString(GetType(), decorator);
571 } else {
572 return "";
573 }
574 }
575
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)576 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
577 AidlTypeSpecifier* type, const std::string& name)
578 : AidlVariableDeclaration(location, type, name),
579 direction_(direction),
580 direction_specified_(true) {}
581
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)582 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
583 const std::string& name)
584 : AidlVariableDeclaration(location, type, name),
585 direction_(AidlArgument::IN_DIR),
586 direction_specified_(false) {}
587
GetDirectionSpecifier() const588 string AidlArgument::GetDirectionSpecifier() const {
589 string ret;
590 if (direction_specified_) {
591 switch(direction_) {
592 case AidlArgument::IN_DIR:
593 ret += "in";
594 break;
595 case AidlArgument::OUT_DIR:
596 ret += "out";
597 break;
598 case AidlArgument::INOUT_DIR:
599 ret += "inout";
600 break;
601 }
602 }
603 return ret;
604 }
605
ToString() const606 string AidlArgument::ToString() const {
607 if (direction_specified_) {
608 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
609 } else {
610 return AidlVariableDeclaration::ToString();
611 }
612 }
613
Signature() const614 std::string AidlArgument::Signature() const {
615 class AidlInterface;
616 class AidlInterface;
617 class AidlParcelable;
618 class AidlStructuredParcelable;
619 class AidlParcelable;
620 class AidlStructuredParcelable;
621 if (direction_specified_) {
622 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::Signature();
623 } else {
624 return AidlVariableDeclaration::Signature();
625 }
626 }
627
AidlMember(const AidlLocation & location)628 AidlMember::AidlMember(const AidlLocation& location) : AidlNode(location) {}
629
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)630 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
631 AidlTypeSpecifier* type, const std::string& name,
632 AidlConstantValue* value)
633 : AidlMember(location), type_(type), name_(name), value_(value) {}
634
CheckValid(const AidlTypenames & typenames) const635 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
636 bool valid = true;
637 valid &= type_->CheckValid(typenames);
638 valid &= value_->CheckValid();
639 if (!valid) return false;
640
641 const static set<string> kSupportedConstTypes = {"String", "int"};
642 if (kSupportedConstTypes.find(type_->ToString()) == kSupportedConstTypes.end()) {
643 AIDL_ERROR(this) << "Constant of type " << type_->ToString() << " is not supported.";
644 return false;
645 }
646
647 return true;
648 }
649
ToString() const650 string AidlConstantDeclaration::ToString() const {
651 return "const " + type_->ToString() + " " + name_ + " = " +
652 ValueString(AidlConstantValueDecorator);
653 }
654
Signature() const655 string AidlConstantDeclaration::Signature() const {
656 return type_->Signature() + " " + name_;
657 }
658
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments)659 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
660 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
661 const std::string& comments)
662 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
663 has_id_ = false;
664 }
665
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const std::string & comments,int id,bool is_user_defined)666 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
667 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
668 const std::string& comments, int id, bool is_user_defined)
669 : AidlMember(location),
670 oneway_(oneway),
671 comments_(comments),
672 type_(type),
673 name_(name),
674 arguments_(std::move(*args)),
675 id_(id),
676 is_user_defined_(is_user_defined) {
677 has_id_ = true;
678 delete args;
679 for (const unique_ptr<AidlArgument>& a : arguments_) {
680 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
681 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
682 }
683 }
684
IsHidden() const685 bool AidlMethod::IsHidden() const {
686 return HasHideComment(GetComments());
687 }
688
Signature() const689 string AidlMethod::Signature() const {
690 vector<string> arg_signatures;
691 for (const auto& arg : GetArguments()) {
692 arg_signatures.emplace_back(arg->GetType().ToString());
693 }
694 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
695 }
696
ToString() const697 string AidlMethod::ToString() const {
698 vector<string> arg_strings;
699 for (const auto& arg : GetArguments()) {
700 arg_strings.emplace_back(arg->Signature());
701 }
702 string ret = (IsOneway() ? "oneway " : "") + GetType().Signature() + " " + GetName() + "(" +
703 Join(arg_strings, ", ") + ")";
704 if (HasId()) {
705 ret += " = " + std::to_string(GetId());
706 }
707 return ret;
708 }
709
AidlDefinedType(const AidlLocation & location,const std::string & name,const std::string & comments,const std::string & package)710 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
711 const std::string& comments, const std::string& package)
712 : AidlAnnotatable(location),
713 name_(name),
714 comments_(comments),
715 package_(package),
716 split_package_(package.empty() ? std::vector<std::string>()
717 : android::base::Split(package, ".")) {}
718
CheckValid(const AidlTypenames & typenames) const719 bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
720 if (!AidlAnnotatable::CheckValid(typenames)) {
721 return false;
722 }
723
724 return true;
725 }
726
IsHidden() const727 bool AidlDefinedType::IsHidden() const {
728 return HasHideComment(GetComments());
729 }
730
GetCanonicalName() const731 std::string AidlDefinedType::GetCanonicalName() const {
732 if (package_.empty()) {
733 return GetName();
734 }
735 return GetPackage() + "." + GetName();
736 }
737
DumpHeader(CodeWriter * writer) const738 void AidlDefinedType::DumpHeader(CodeWriter* writer) const {
739 if (this->IsHidden()) {
740 AddHideComment(writer);
741 }
742 DumpAnnotations(writer);
743 }
744
AidlParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const std::string & comments,const std::string & cpp_header,std::vector<std::string> * type_params)745 AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
746 const std::string& package, const std::string& comments,
747 const std::string& cpp_header, std::vector<std::string>* type_params)
748 : AidlDefinedType(location, name, comments, package),
749 AidlParameterizable<std::string>(type_params),
750 cpp_header_(cpp_header) {
751 // Strip off quotation marks if we actually have a cpp header.
752 if (cpp_header_.length() >= 2) {
753 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
754 }
755 }
756 template <typename T>
AidlParameterizable(const AidlParameterizable & other)757 AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
758 // Copying is not supported if it has type parameters.
759 // It doesn't make a problem because only ArrayBase() makes a copy,
760 // and it can be called only if a type is not generic.
761 CHECK(!other.IsGeneric());
762 }
763
764 template <typename T>
CheckValid() const765 bool AidlParameterizable<T>::CheckValid() const {
766 return true;
767 };
768
769 template <>
CheckValid() const770 bool AidlParameterizable<std::string>::CheckValid() const {
771 if (!IsGeneric()) {
772 return true;
773 }
774 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
775 if (set.size() != GetTypeParameters().size()) {
776 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
777 return false;
778 }
779 return true;
780 }
781
GetSupportedAnnotations() const782 std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
783 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
784 AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE,
785 AidlAnnotation::Type::JAVA_PASSTHROUGH, AidlAnnotation::Type::IMMUTABLE};
786 }
787
CheckValid(const AidlTypenames & typenames) const788 bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
789 if (!AidlDefinedType::CheckValid(typenames)) {
790 return false;
791 }
792 if (!AidlParameterizable<std::string>::CheckValid()) {
793 return false;
794 }
795
796 return true;
797 }
798
Dump(CodeWriter * writer) const799 void AidlParcelable::Dump(CodeWriter* writer) const {
800 DumpHeader(writer);
801 writer->Write("parcelable %s ;\n", GetName().c_str());
802 }
803
AidlStructuredParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const std::string & comments,std::vector<std::unique_ptr<AidlVariableDeclaration>> * variables)804 AidlStructuredParcelable::AidlStructuredParcelable(
805 const AidlLocation& location, const std::string& name, const std::string& package,
806 const std::string& comments, std::vector<std::unique_ptr<AidlVariableDeclaration>>* variables)
807 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/),
808 variables_(std::move(*variables)) {}
809
Dump(CodeWriter * writer) const810 void AidlStructuredParcelable::Dump(CodeWriter* writer) const {
811 DumpHeader(writer);
812 writer->Write("parcelable %s {\n", GetName().c_str());
813 writer->Indent();
814 for (const auto& field : GetFields()) {
815 if (field->GetType().IsHidden()) {
816 AddHideComment(writer);
817 }
818 writer->Write("%s;\n", field->ToString().c_str());
819 }
820 writer->Dedent();
821 writer->Write("}\n");
822 }
823
GetSupportedAnnotations() const824 std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
825 return {AidlAnnotation::Type::VINTF_STABILITY,
826 AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
827 AidlAnnotation::Type::HIDE,
828 AidlAnnotation::Type::JAVA_PASSTHROUGH,
829 AidlAnnotation::Type::JAVA_DEBUG,
830 AidlAnnotation::Type::IMMUTABLE};
831 }
832
CheckValid(const AidlTypenames & typenames) const833 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
834 bool success = true;
835 if (!AidlParcelable::CheckValid(typenames)) {
836 return false;
837 }
838
839 for (const auto& v : GetFields()) {
840 success = success && v->CheckValid(typenames);
841 if (IsImmutable()) {
842 success = success && typenames.CanBeImmutable(v->GetType());
843 }
844 }
845
846 return success;
847 }
848
849 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const850 bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
851 Options::Language lang) const {
852 if (lang == Options::Language::NDK && IsArray() && GetName() == "IBinder") {
853 AIDL_ERROR(this) << "The NDK backend does not support array of IBinder";
854 return false;
855 }
856 if (lang == Options::Language::NDK && IsArray() && IsNullable()) {
857 if (GetName() == "ParcelFileDescriptor") {
858 AIDL_ERROR(this) << "The NDK backend does not support nullable array of ParcelFileDescriptor";
859 return false;
860 }
861
862 const auto defined_type = typenames.TryGetDefinedType(GetName());
863 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
864 AIDL_ERROR(this) << "The NDK backend does not support nullable array of parcelable";
865 return false;
866 }
867 }
868 if (lang != Options::Language::JAVA) {
869 if (this->GetName() == "List" && !this->IsGeneric()) {
870 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
871 return false;
872 }
873 }
874 if (this->GetName() == "FileDescriptor" && lang == Options::Language::NDK) {
875 AIDL_ERROR(this) << "FileDescriptor isn't supported with the NDK.";
876 return false;
877 }
878 if (this->IsGeneric()) {
879 if (this->GetName() == "List") {
880 if (this->GetTypeParameters().size() != 1) {
881 AIDL_ERROR(this) << "List must have only one type parameter.";
882 return false;
883 }
884 if (lang == Options::Language::CPP) {
885 const string& contained_type = this->GetTypeParameters()[0]->GetName();
886 if (!(contained_type == "String" || contained_type == "IBinder")) {
887 AIDL_ERROR(this) << "List<" << contained_type
888 << "> is not supported. List in cpp supports only String and IBinder.";
889 return false;
890 }
891 } else if (lang == Options::Language::JAVA) {
892 const string& contained_type = this->GetTypeParameters()[0]->GetName();
893 if (AidlTypenames::IsBuiltinTypename(contained_type)) {
894 if (contained_type != "String" && contained_type != "IBinder" &&
895 contained_type != "ParcelFileDescriptor") {
896 AIDL_ERROR(this) << "List<" << contained_type
897 << "> is not supported. List in Java supports only String, IBinder, "
898 "and ParcelFileDescriptor.";
899 return false;
900 }
901 }
902 }
903 }
904 }
905 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
906 if (lang != Options::Language::JAVA) {
907 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
908 return false;
909 }
910 }
911 if (lang == Options::Language::JAVA) {
912 const string name = this->GetName();
913 // List[], Map[], CharSequence[] are not supported.
914 if (AidlTypenames::IsBuiltinTypename(name) && this->IsArray()) {
915 if (name == "List" || name == "Map" || name == "CharSequence") {
916 AIDL_ERROR(this) << "List[], Map[], CharSequence[] are not supported.";
917 return false;
918 }
919 }
920 }
921
922 return true;
923 }
924
925 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames &,Options::Language lang) const926 bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
927 Options::Language lang) const {
928 if (lang != Options::Language::JAVA) {
929 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
930 if (unstructured_parcelable != nullptr) {
931 if (unstructured_parcelable->GetCppHeader().empty()) {
932 AIDL_ERROR(unstructured_parcelable)
933 << "Unstructured parcelable must have C++ header defined.";
934 return false;
935 }
936 }
937 }
938 return true;
939 }
940
941 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const942 bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
943 Options::Language lang) const {
944 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
945 return false;
946 }
947 for (const auto& v : this->GetFields()) {
948 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
949 return false;
950 }
951 }
952 return true;
953 }
954
AidlEnumerator(const AidlLocation & location,const std::string & name,AidlConstantValue * value,const std::string & comments)955 AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
956 AidlConstantValue* value, const std::string& comments)
957 : AidlNode(location), name_(name), value_(value), comments_(comments) {}
958
CheckValid(const AidlTypeSpecifier & enum_backing_type) const959 bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
960 if (GetValue() == nullptr) {
961 return false;
962 }
963 if (!GetValue()->CheckValid()) {
964 return false;
965 }
966 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
967 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
968 return false;
969 }
970 return true;
971 }
972
ValueString(const AidlTypeSpecifier & backing_type,const ConstantValueDecorator & decorator) const973 string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
974 const ConstantValueDecorator& decorator) const {
975 return GetValue()->ValueString(backing_type, decorator);
976 }
977
AidlEnumDeclaration(const AidlLocation & location,const std::string & name,std::vector<std::unique_ptr<AidlEnumerator>> * enumerators,const std::string & package,const std::string & comments)978 AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
979 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
980 const std::string& package, const std::string& comments)
981 : AidlDefinedType(location, name, comments, package), enumerators_(std::move(*enumerators)) {}
982
SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type)983 void AidlEnumDeclaration::SetBackingType(std::unique_ptr<const AidlTypeSpecifier> type) {
984 backing_type_ = std::move(type);
985 }
986
Autofill()987 bool AidlEnumDeclaration::Autofill() {
988 const AidlEnumerator* previous = nullptr;
989 for (const auto& enumerator : enumerators_) {
990 if (enumerator->GetValue() == nullptr) {
991 if (previous == nullptr) {
992 enumerator->SetValue(
993 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(GetLocation(), "0")));
994 } else {
995 auto prev_value = std::unique_ptr<AidlConstantValue>(
996 AidlConstantValue::ShallowIntegralCopy(*previous->GetValue()));
997 if (prev_value == nullptr) {
998 return false;
999 }
1000 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
1001 GetLocation(), std::move(prev_value), "+",
1002 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(GetLocation(), "1"))));
1003 }
1004 }
1005 previous = enumerator.get();
1006 }
1007 return true;
1008 }
1009
GetSupportedAnnotations() const1010 std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
1011 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::BACKING,
1012 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH};
1013 }
1014
CheckValid(const AidlTypenames & typenames) const1015 bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1016 if (!AidlDefinedType::CheckValid(typenames)) {
1017 return false;
1018 }
1019 if (backing_type_ == nullptr) {
1020 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1021 return false;
1022 }
1023 bool success = true;
1024 for (const auto& enumerator : enumerators_) {
1025 success = success && enumerator->CheckValid(GetBackingType());
1026 }
1027 return success;
1028 }
1029
Dump(CodeWriter * writer) const1030 void AidlEnumDeclaration::Dump(CodeWriter* writer) const {
1031 DumpHeader(writer);
1032 writer->Write("enum %s {\n", GetName().c_str());
1033 writer->Indent();
1034 for (const auto& enumerator : GetEnumerators()) {
1035 writer->Write("%s = %s,\n", enumerator->GetName().c_str(),
1036 enumerator->ValueString(GetBackingType(), AidlConstantValueDecorator).c_str());
1037 }
1038 writer->Dedent();
1039 writer->Write("}\n");
1040 }
1041
1042 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const1043 bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1044 Options::Language lang) const {
1045 for (const auto& m : this->GetMethods()) {
1046 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1047 return false;
1048 }
1049 for (const auto& arg : m->GetArguments()) {
1050 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1051 return false;
1052 }
1053 }
1054 }
1055 return true;
1056 }
1057
AidlInterface(const AidlLocation & location,const std::string & name,const std::string & comments,bool oneway,std::vector<std::unique_ptr<AidlMember>> * members,const std::string & package)1058 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
1059 const std::string& comments, bool oneway,
1060 std::vector<std::unique_ptr<AidlMember>>* members,
1061 const std::string& package)
1062 : AidlDefinedType(location, name, comments, package) {
1063 for (auto& member : *members) {
1064 AidlMember* local = member.release();
1065 AidlMethod* method = local->AsMethod();
1066 AidlConstantDeclaration* constant = local->AsConstantDeclaration();
1067
1068 CHECK(method == nullptr || constant == nullptr);
1069
1070 if (method) {
1071 method->ApplyInterfaceOneway(oneway);
1072 methods_.emplace_back(method);
1073 } else if (constant) {
1074 constants_.emplace_back(constant);
1075 } else {
1076 AIDL_FATAL(this) << "Member is neither method nor constant!";
1077 }
1078 }
1079
1080 delete members;
1081 }
1082
Dump(CodeWriter * writer) const1083 void AidlInterface::Dump(CodeWriter* writer) const {
1084 DumpHeader(writer);
1085 writer->Write("interface %s {\n", GetName().c_str());
1086 writer->Indent();
1087 for (const auto& method : GetMethods()) {
1088 if (method->IsHidden()) {
1089 AddHideComment(writer);
1090 }
1091 writer->Write("%s;\n", method->ToString().c_str());
1092 }
1093 for (const auto& constdecl : GetConstantDeclarations()) {
1094 if (constdecl->GetType().IsHidden()) {
1095 AddHideComment(writer);
1096 }
1097 writer->Write("%s;\n", constdecl->ToString().c_str());
1098 }
1099 writer->Dedent();
1100 writer->Write("}\n");
1101 }
1102
GetSupportedAnnotations() const1103 std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
1104 return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
1105 AidlAnnotation::Type::HIDE, AidlAnnotation::Type::JAVA_PASSTHROUGH};
1106 }
1107
CheckValid(const AidlTypenames & typenames) const1108 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1109 if (!AidlDefinedType::CheckValid(typenames)) {
1110 return false;
1111 }
1112 // Has to be a pointer due to deleting copy constructor. No idea why.
1113 map<string, const AidlMethod*> method_names;
1114 for (const auto& m : GetMethods()) {
1115 if (!m->GetType().CheckValid(typenames)) {
1116 return false;
1117 }
1118
1119 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1120 if (m->GetType().GetName() == "ParcelableHolder") {
1121 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1122 return false;
1123 }
1124 if (m->IsOneway() && m->GetType().GetName() != "void") {
1125 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1126 return false;
1127 }
1128
1129 set<string> argument_names;
1130 for (const auto& arg : m->GetArguments()) {
1131 auto it = argument_names.find(arg->GetName());
1132 if (it != argument_names.end()) {
1133 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1134 << arg->GetName() << "'";
1135 return false;
1136 }
1137 argument_names.insert(arg->GetName());
1138
1139 if (!arg->GetType().CheckValid(typenames)) {
1140 return false;
1141 }
1142
1143 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1144 if (arg->GetType().GetName() == "ParcelableHolder") {
1145 AIDL_ERROR(arg) << "ParcelableHolder cannot be an argument type";
1146 return false;
1147 }
1148 if (m->IsOneway() && arg->IsOut()) {
1149 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1150 return false;
1151 }
1152 const bool can_be_out = typenames.CanBeOutParameter(arg->GetType());
1153 if (!arg->DirectionWasSpecified() && can_be_out) {
1154 AIDL_ERROR(arg) << "'" << arg->GetType().ToString()
1155 << "' can be an out type, so you must declare it as in, out, or inout.";
1156 return false;
1157 }
1158
1159 if (arg->GetDirection() != AidlArgument::IN_DIR && !can_be_out) {
1160 AIDL_ERROR(arg) << "'" << arg->ToString() << "' can only be an in parameter.";
1161 return false;
1162 }
1163
1164 // check that the name doesn't match a keyword
1165 if (IsJavaKeyword(arg->GetName().c_str())) {
1166 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1167 return false;
1168 }
1169
1170 // Reserve a namespace for internal use
1171 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1172 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1173 return false;
1174 }
1175 }
1176
1177 auto it = method_names.find(m->GetName());
1178 // prevent duplicate methods
1179 if (it == method_names.end()) {
1180 method_names[m->GetName()] = m.get();
1181 } else {
1182 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1183 AIDL_ERROR(it->second) << "previously defined here.";
1184 return false;
1185 }
1186
1187 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
1188 "getTransactionName(int)"};
1189
1190 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1191 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
1192 return false;
1193 }
1194 }
1195
1196 bool success = true;
1197 set<string> constant_names;
1198 for (const std::unique_ptr<AidlConstantDeclaration>& constant : GetConstantDeclarations()) {
1199 if (constant_names.count(constant->GetName()) > 0) {
1200 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
1201 success = false;
1202 }
1203 constant_names.insert(constant->GetName());
1204 success = success && constant->CheckValid(typenames);
1205 }
1206
1207 return success;
1208 }
1209
AidlImport(const AidlLocation & location,const std::string & needed_class)1210 AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class)
1211 : AidlNode(location), needed_class_(needed_class) {}
1212