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.h"
36 #include "comments.h"
37 #include "logging.h"
38
39 #include "aidl.h"
40
41 #ifdef _WIN32
isatty(int fd)42 int isatty(int fd)
43 {
44 return (fd == 0);
45 }
46 #endif
47
48 using android::aidl::IoDelegate;
49 using android::base::Join;
50 using android::base::Split;
51 using std::cerr;
52 using std::pair;
53 using std::set;
54 using std::string;
55 using std::unique_ptr;
56 using std::vector;
57
58 namespace {
IsJavaKeyword(const char * str)59 bool IsJavaKeyword(const char* str) {
60 static const std::vector<std::string> kJavaKeywords{
61 "abstract", "assert", "boolean", "break", "byte", "case", "catch",
62 "char", "class", "const", "continue", "default", "do", "double",
63 "else", "enum", "extends", "final", "finally", "float", "for",
64 "goto", "if", "implements", "import", "instanceof", "int", "interface",
65 "long", "native", "new", "package", "private", "protected", "public",
66 "return", "short", "static", "strictfp", "super", "switch", "synchronized",
67 "this", "throw", "throws", "transient", "try", "void", "volatile",
68 "while", "true", "false", "null",
69 };
70 return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
71 }
72 } // namespace
73
AidlNode(const AidlLocation & location,const Comments & comments)74 AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
75 : location_(location), comments_(comments) {}
76
PrintLine() const77 std::string AidlNode::PrintLine() const {
78 std::stringstream ss;
79 ss << location_.file_ << ":" << location_.begin_.line;
80 return ss.str();
81 }
82
PrintLocation() const83 std::string AidlNode::PrintLocation() const {
84 std::stringstream ss;
85 ss << location_.file_ << ":" << location_.begin_.line << ":" << location_.begin_.column << ":"
86 << location_.end_.line << ":" << location_.end_.column;
87 return ss.str();
88 }
89
90 static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
91 Comments{}};
92 static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
93 Comments{}};
94 static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
95 static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
96 static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
97 Comments{}};
98
AllSchemas()99 const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
100 static const std::vector<Schema> kSchemas{
101 {AidlAnnotation::Type::NULLABLE, "nullable", CONTEXT_TYPE_SPECIFIER, {}},
102 {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
103 {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
104 {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
105 {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
106 "UnsupportedAppUsage",
107 CONTEXT_TYPE | CONTEXT_MEMBER,
108 {{"expectedSignature", kStringType},
109 {"implicitMember", kStringType},
110 {"maxTargetSdk", kIntType},
111 {"publicAlternatives", kStringType},
112 {"trackingBug", kLongType}}},
113 {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE,
114 "JavaOnlyStableParcelable",
115 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
116 {}},
117 {AidlAnnotation::Type::HIDE, "Hide", CONTEXT_TYPE | CONTEXT_MEMBER, {}},
118 {AidlAnnotation::Type::BACKING,
119 "Backing",
120 CONTEXT_TYPE_ENUM,
121 {{"type", kStringType, /* required= */ true}}},
122 {AidlAnnotation::Type::JAVA_PASSTHROUGH,
123 "JavaPassthrough",
124 CONTEXT_ALL,
125 {{"annotation", kStringType, /* required= */ true}},
126 /* repeatable= */ true},
127 {AidlAnnotation::Type::JAVA_DERIVE,
128 "JavaDerive",
129 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
130 {{"toString", kBooleanType}, {"equals", kBooleanType}}},
131 {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
132 "JavaOnlyImmutable",
133 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
134 CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
135 {}},
136 {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
137 {AidlAnnotation::Type::DESCRIPTOR,
138 "Descriptor",
139 CONTEXT_TYPE_INTERFACE,
140 {{"value", kStringType, /* required= */ true}}},
141 {AidlAnnotation::Type::RUST_DERIVE,
142 "RustDerive",
143 CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
144 {{"Copy", kBooleanType},
145 {"Clone", kBooleanType},
146 {"PartialOrd", kBooleanType},
147 {"Ord", kBooleanType},
148 {"PartialEq", kBooleanType},
149 {"Eq", kBooleanType},
150 {"Hash", kBooleanType}}},
151 {AidlAnnotation::Type::SUPPRESS_WARNINGS,
152 "SuppressWarnings",
153 CONTEXT_TYPE | CONTEXT_MEMBER,
154 {{"value", kStringArrayType, /* required= */ true}}},
155 };
156 return kSchemas;
157 }
158
TypeToString(Type type)159 std::string AidlAnnotation::TypeToString(Type type) {
160 for (const Schema& schema : AllSchemas()) {
161 if (type == schema.type) return schema.name;
162 }
163 AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
164 __builtin_unreachable();
165 }
166
Parse(const AidlLocation & location,const string & name,std::map<std::string,std::shared_ptr<AidlConstantValue>> * parameter_list,const Comments & comments)167 AidlAnnotation* AidlAnnotation::Parse(
168 const AidlLocation& location, const string& name,
169 std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list,
170 const Comments& comments) {
171 const Schema* schema = nullptr;
172 for (const Schema& a_schema : AllSchemas()) {
173 if (a_schema.name == name) {
174 schema = &a_schema;
175 }
176 }
177
178 if (schema == nullptr) {
179 std::ostringstream stream;
180 stream << "'" << name << "' is not a recognized annotation. ";
181 stream << "It must be one of:";
182 for (const Schema& s : AllSchemas()) {
183 stream << " " << s.name;
184 }
185 stream << ".";
186 AIDL_ERROR(location) << stream.str();
187 return nullptr;
188 }
189 if (parameter_list == nullptr) {
190 return new AidlAnnotation(location, *schema, {}, comments);
191 }
192
193 return new AidlAnnotation(location, *schema, std::move(*parameter_list), comments);
194 }
195
AidlAnnotation(const AidlLocation & location,const Schema & schema,std::map<std::string,std::shared_ptr<AidlConstantValue>> && parameters,const Comments & comments)196 AidlAnnotation::AidlAnnotation(
197 const AidlLocation& location, const Schema& schema,
198 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters,
199 const Comments& comments)
200 : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
201
202 struct ConstReferenceFinder : AidlVisitor {
203 const AidlConstantReference* found;
VisitConstReferenceFinder204 void Visit(const AidlConstantReference& ref) override {
205 if (!found) found = &ref;
206 }
FindConstReferenceFinder207 static const AidlConstantReference* Find(const AidlConstantValue& c) {
208 ConstReferenceFinder finder;
209 VisitTopDown(finder, c);
210 return finder.found;
211 }
212 };
213
214 // Checks if annotation complies with the schema
215 // - every parameter is known and has well-typed value.
216 // - every required parameter is present.
CheckValid() const217 bool AidlAnnotation::CheckValid() const {
218 for (const auto& name_and_param : parameters_) {
219 const std::string& param_name = name_and_param.first;
220 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
221
222 const ParamType* param_type = schema_.ParamType(param_name);
223 if (!param_type) {
224 std::ostringstream stream;
225 stream << "Parameter " << param_name << " not supported ";
226 stream << "for annotation " << GetName() << ". ";
227 stream << "It must be one of:";
228 for (const auto& param : schema_.parameters) {
229 stream << " " << param.name;
230 }
231 AIDL_ERROR(this) << stream.str();
232 return false;
233 }
234
235 const auto& found = ConstReferenceFinder::Find(*param);
236 if (found) {
237 AIDL_ERROR(found) << "Value must be a constant expression but contains reference to "
238 << found->GetFieldName() << ".";
239 return false;
240 }
241
242 if (!param->CheckValid()) {
243 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
244 << GetName() << ".";
245 return false;
246 }
247
248 const std::string param_value =
249 param->ValueString(param_type->type, AidlConstantValueDecorator);
250 // Assume error on empty string.
251 if (param_value == "") {
252 AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
253 << GetName() << ".";
254 return false;
255 }
256 }
257 bool success = true;
258 for (const auto& param : schema_.parameters) {
259 if (param.required && parameters_.count(param.name) == 0) {
260 AIDL_ERROR(this) << "Missing '" << param.name << "' on @" << GetName() << ".";
261 success = false;
262 }
263 }
264 return success;
265 }
266
267 // Checks if the annotation is applicable to the current context.
268 // For example, annotations like @VintfStability, @FixedSize is not applicable to AidlTypeSpecifier
269 // nodes.
CheckContext(TargetContext context) const270 bool AidlAnnotation::CheckContext(TargetContext context) const {
271 if (schema_.target_context & static_cast<uint32_t>(context)) {
272 return true;
273 }
274 const static map<TargetContext, string> context_name_map{
275 {CONTEXT_TYPE_INTERFACE, "interface"},
276 {CONTEXT_TYPE_ENUM, "enum"},
277 {CONTEXT_TYPE_STRUCTURED_PARCELABLE, "structured parcelable"},
278 {CONTEXT_TYPE_UNION, "union"},
279 {CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE, "parcelable"},
280 {CONTEXT_CONST, "constant"},
281 {CONTEXT_FIELD, "field"},
282 {CONTEXT_METHOD, "method"},
283 {CONTEXT_TYPE_SPECIFIER, "type"},
284 };
285 vector<string> available;
286 for (const auto& [context, name] : context_name_map) {
287 if (schema_.target_context & context) {
288 available.push_back(name);
289 }
290 }
291 AIDL_ERROR(this) << "@" << GetName() << " is not available. It can annotate {"
292 << Join(available, ", ") << "}.";
293 return false;
294 }
295
AnnotationParams(const ConstantValueDecorator & decorator) const296 std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
297 const ConstantValueDecorator& decorator) const {
298 std::map<std::string, std::string> raw_params;
299 for (const auto& name_and_param : parameters_) {
300 const std::string& param_name = name_and_param.first;
301 const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
302 const ParamType* param_type = schema_.ParamType(param_name);
303 AIDL_FATAL_IF(!param_type, this);
304 raw_params.emplace(param_name, param->ValueString(param_type->type, decorator));
305 }
306 return raw_params;
307 }
308
ToString() const309 std::string AidlAnnotation::ToString() const {
310 if (parameters_.empty()) {
311 return "@" + GetName();
312 } else {
313 vector<string> param_strings;
314 for (const auto& [name, value] : AnnotationParams(AidlConstantValueDecorator)) {
315 param_strings.emplace_back(name + "=" + value);
316 }
317 return "@" + GetName() + "(" + Join(param_strings, ", ") + ")";
318 }
319 }
320
TraverseChildren(std::function<void (const AidlNode &)> traverse) const321 void AidlAnnotation::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
322 for (const auto& [name, value] : parameters_) {
323 (void)name;
324 traverse(*value);
325 }
326 }
327
GetAnnotation(const vector<AidlAnnotation> & annotations,AidlAnnotation::Type type)328 static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
329 AidlAnnotation::Type type) {
330 for (const auto& a : annotations) {
331 if (a.GetType() == type) {
332 AIDL_FATAL_IF(a.Repeatable(), a)
333 << "Trying to get a single annotation when it is repeatable.";
334 return &a;
335 }
336 }
337 return nullptr;
338 }
339
AidlAnnotatable(const AidlLocation & location,const Comments & comments)340 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
341 : AidlCommentable(location, comments) {}
342
IsNullable() const343 bool AidlAnnotatable::IsNullable() const {
344 return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
345 }
346
IsUtf8InCpp() const347 bool AidlAnnotatable::IsUtf8InCpp() const {
348 return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
349 }
350
IsSensitiveData() const351 bool AidlAnnotatable::IsSensitiveData() const {
352 return GetAnnotation(annotations_, AidlAnnotation::Type::SENSITIVE_DATA);
353 }
354
IsVintfStability() const355 bool AidlAnnotatable::IsVintfStability() const {
356 return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
357 }
358
IsJavaOnlyImmutable() const359 bool AidlAnnotatable::IsJavaOnlyImmutable() const {
360 return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE);
361 }
362
IsFixedSize() const363 bool AidlAnnotatable::IsFixedSize() const {
364 return GetAnnotation(annotations_, AidlAnnotation::Type::FIXED_SIZE);
365 }
366
UnsupportedAppUsage() const367 const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
368 return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
369 }
370
RustDerive() const371 const AidlAnnotation* AidlAnnotatable::RustDerive() const {
372 return GetAnnotation(annotations_, AidlAnnotation::Type::RUST_DERIVE);
373 }
374
BackingType() const375 const AidlAnnotation* AidlAnnotatable::BackingType() const {
376 return GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
377 }
378
SuppressWarnings() const379 std::vector<std::string> AidlAnnotatable::SuppressWarnings() const {
380 auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::SUPPRESS_WARNINGS);
381 if (annot) {
382 auto names = annot->ParamValue<std::vector<std::string>>("value");
383 AIDL_FATAL_IF(!names.has_value(), this);
384 return std::move(names.value());
385 }
386 return {};
387 }
388
IsStableApiParcelable(Options::Language lang) const389 bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
390 return lang == Options::Language::JAVA &&
391 GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
392 }
393
IsHide() const394 bool AidlAnnotatable::IsHide() const {
395 return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
396 }
397
JavaDerive(const std::string & method) const398 bool AidlAnnotatable::JavaDerive(const std::string& method) const {
399 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DERIVE);
400 if (annotation != nullptr) {
401 return annotation->ParamValue<bool>(method).value_or(false);
402 }
403 return false;
404 }
405
GetDescriptor() const406 std::string AidlAnnotatable::GetDescriptor() const {
407 auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
408 if (annotation != nullptr) {
409 return annotation->ParamValue<std::string>("value").value();
410 }
411 return "";
412 }
413
CheckValid(const AidlTypenames &) const414 bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
415 for (const auto& annotation : GetAnnotations()) {
416 if (!annotation.CheckValid()) {
417 return false;
418 }
419 }
420
421 std::map<AidlAnnotation::Type, AidlLocation> declared;
422 for (const auto& annotation : GetAnnotations()) {
423 const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
424 if (!inserted && !annotation.Repeatable()) {
425 AIDL_ERROR(this) << "'" << annotation.GetName()
426 << "' is repeated, but not allowed. Previous location: " << iter->second;
427 return false;
428 }
429 }
430
431 return true;
432 }
433
ToString() const434 string AidlAnnotatable::ToString() const {
435 vector<string> ret;
436 for (const auto& a : annotations_) {
437 ret.emplace_back(a.ToString());
438 }
439 std::sort(ret.begin(), ret.end());
440 return Join(ret, " ");
441 }
442
AidlTypeSpecifier(const AidlLocation & location,const string & unresolved_name,bool is_array,vector<unique_ptr<AidlTypeSpecifier>> * type_params,const Comments & comments)443 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
444 bool is_array,
445 vector<unique_ptr<AidlTypeSpecifier>>* type_params,
446 const Comments& comments)
447 : AidlAnnotatable(location, comments),
448 AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
449 unresolved_name_(unresolved_name),
450 is_array_(is_array),
451 split_name_(Split(unresolved_name, ".")) {}
452
ArrayBase() const453 const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
454 AIDL_FATAL_IF(!is_array_, this);
455 // Declaring array of generic type cannot happen, it is grammar error.
456 AIDL_FATAL_IF(IsGeneric(), this);
457
458 if (!array_base_) {
459 array_base_.reset(new AidlTypeSpecifier(*this));
460 array_base_->is_array_ = false;
461 }
462 return *array_base_;
463 }
464
Signature() const465 string AidlTypeSpecifier::Signature() const {
466 string ret = GetName();
467 if (IsGeneric()) {
468 vector<string> arg_names;
469 for (const auto& ta : GetTypeParameters()) {
470 arg_names.emplace_back(ta->Signature());
471 }
472 ret += "<" + Join(arg_names, ",") + ">";
473 }
474 if (IsArray()) {
475 ret += "[]";
476 }
477 return ret;
478 }
479
ToString() const480 string AidlTypeSpecifier::ToString() const {
481 string ret = Signature();
482 string annotations = AidlAnnotatable::ToString();
483 if (annotations != "") {
484 ret = annotations + " " + ret;
485 }
486 return ret;
487 }
488
Resolve(const AidlTypenames & typenames)489 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
490 AIDL_FATAL_IF(IsResolved(), this);
491 AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
492 if (result.is_resolved) {
493 fully_qualified_name_ = result.canonical_name;
494 split_name_ = Split(fully_qualified_name_, ".");
495 defined_type_ = result.defined_type;
496 }
497 return result.is_resolved;
498 }
499
GetDefinedType() const500 const AidlDefinedType* AidlTypeSpecifier::GetDefinedType() const {
501 return defined_type_;
502 }
503
CheckValid(const AidlTypenames & typenames) const504 bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
505 if (!AidlAnnotatable::CheckValid(typenames)) {
506 return false;
507 }
508 if (IsGeneric()) {
509 const auto& types = GetTypeParameters();
510 for (const auto& arg : types) {
511 if (!arg->CheckValid(typenames)) {
512 return false;
513 }
514 }
515
516 const string& type_name = GetName();
517 // TODO(b/136048684) Disallow to use primitive types only if it is List or Map.
518 if (type_name == "List" || type_name == "Map") {
519 if (std::any_of(types.begin(), types.end(), [&](auto& type_ptr) {
520 return !type_ptr->IsArray() &&
521 (typenames.GetEnumDeclaration(*type_ptr) ||
522 AidlTypenames::IsPrimitiveTypename(type_ptr->GetName()));
523 })) {
524 AIDL_ERROR(this) << "A generic type cannot have any primitive type parameters.";
525 return false;
526 }
527 }
528 const auto defined_type = typenames.TryGetDefinedType(type_name);
529 const auto parameterizable =
530 defined_type != nullptr ? defined_type->AsParameterizable() : nullptr;
531 const bool is_user_defined_generic_type =
532 parameterizable != nullptr && parameterizable->IsGeneric();
533 const size_t num_params = GetTypeParameters().size();
534 if (type_name == "List") {
535 if (num_params > 1) {
536 AIDL_ERROR(this) << "List can only have one type parameter, but got: '" << Signature()
537 << "'";
538 return false;
539 }
540 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
541 if (contained_type.IsArray()) {
542 AIDL_ERROR(this)
543 << "List of arrays is not supported. List<T> supports parcelable/union, String, "
544 "IBinder, and ParcelFileDescriptor.";
545 return false;
546 }
547 const string& contained_type_name = contained_type.GetName();
548 if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
549 if (contained_type_name != "String" && contained_type_name != "IBinder" &&
550 contained_type_name != "ParcelFileDescriptor") {
551 AIDL_ERROR(this) << "List<" << contained_type_name
552 << "> is not supported. List<T> supports parcelable/union, String, "
553 "IBinder, and ParcelFileDescriptor.";
554 return false;
555 }
556 } else { // Defined types
557 if (typenames.GetInterface(contained_type)) {
558 AIDL_ERROR(this) << "List<" << contained_type_name
559 << "> is not supported. List<T> supports parcelable/union, String, "
560 "IBinder, and ParcelFileDescriptor.";
561 return false;
562 }
563 }
564 } else if (type_name == "Map") {
565 if (num_params != 0 && num_params != 2) {
566 AIDL_ERROR(this) << "Map must have 0 or 2 type parameters, but got "
567 << "'" << Signature() << "'";
568 return false;
569 }
570 if (num_params == 2) {
571 const string& key_type = GetTypeParameters()[0]->Signature();
572 if (key_type != "String") {
573 AIDL_ERROR(this) << "The type of key in map must be String, but it is "
574 << "'" << key_type << "'";
575 return false;
576 }
577 }
578 } else if (is_user_defined_generic_type) {
579 const size_t allowed = parameterizable->GetTypeParameters().size();
580 if (num_params != allowed) {
581 AIDL_ERROR(this) << type_name << " must have " << allowed << " type parameters, but got "
582 << num_params;
583 return false;
584 }
585 } else {
586 AIDL_ERROR(this) << type_name << " is not a generic type.";
587 return false;
588 }
589 }
590
591 const bool is_generic_string_list = GetName() == "List" && IsGeneric() &&
592 GetTypeParameters().size() == 1 &&
593 GetTypeParameters()[0]->GetName() == "String";
594 if (IsUtf8InCpp() && (GetName() != "String" && !is_generic_string_list)) {
595 AIDL_ERROR(this) << "@utf8InCpp can only be used on String, String[], and List<String>.";
596 return false;
597 }
598
599 if (GetName() == "void") {
600 if (IsArray() || IsNullable() || IsUtf8InCpp()) {
601 AIDL_ERROR(this) << "void type cannot be an array or nullable or utf8 string";
602 return false;
603 }
604 }
605
606 if (IsArray()) {
607 const auto defined_type = typenames.TryGetDefinedType(GetName());
608 if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
609 AIDL_ERROR(this) << "Binder type cannot be an array";
610 return false;
611 }
612 if (GetName() == "ParcelableHolder") {
613 AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
614 return false;
615 }
616 }
617
618 if (IsNullable()) {
619 if (AidlTypenames::IsPrimitiveTypename(GetName()) && !IsArray()) {
620 AIDL_ERROR(this) << "Primitive type cannot get nullable annotation";
621 return false;
622 }
623 const auto defined_type = typenames.TryGetDefinedType(GetName());
624 if (defined_type != nullptr && defined_type->AsEnumDeclaration() != nullptr && !IsArray()) {
625 AIDL_ERROR(this) << "Enum type cannot get nullable annotation";
626 return false;
627 }
628 if (GetName() == "ParcelableHolder") {
629 AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
630 return false;
631 }
632 }
633 return true;
634 }
635
AidlConstantValueDecorator(const AidlTypeSpecifier & type,const std::string & raw_value)636 std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
637 const std::string& raw_value) {
638 if (type.IsArray()) {
639 return raw_value;
640 }
641
642 if (auto defined_type = type.GetDefinedType(); defined_type) {
643 auto enum_type = defined_type->AsEnumDeclaration();
644 AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
645 return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
646 }
647 return raw_value;
648 }
649
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)650 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
651 AidlTypeSpecifier* type, const std::string& name)
652 : AidlVariableDeclaration(location, type, name, AidlConstantValue::Default(*type)) {
653 default_user_specified_ = false;
654 }
655
AidlVariableDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * default_value)656 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
657 AidlTypeSpecifier* type, const std::string& name,
658 AidlConstantValue* default_value)
659 : AidlMember(location, type->GetComments()),
660 type_(type),
661 name_(name),
662 default_user_specified_(true),
663 default_value_(default_value) {}
664
HasUsefulDefaultValue() const665 bool AidlVariableDeclaration::HasUsefulDefaultValue() const {
666 if (GetDefaultValue()) {
667 return true;
668 }
669 // null is accepted as a valid default value in all backends
670 if (GetType().IsNullable()) {
671 return true;
672 }
673 return false;
674 }
675
CheckValid(const AidlTypenames & typenames) const676 bool AidlVariableDeclaration::CheckValid(const AidlTypenames& typenames) const {
677 bool valid = true;
678 valid &= type_->CheckValid(typenames);
679
680 if (type_->GetName() == "void") {
681 AIDL_ERROR(this) << "Declaration " << name_
682 << " is void, but declarations cannot be of void type.";
683 valid = false;
684 }
685
686 if (default_value_ == nullptr) return valid;
687 valid &= default_value_->CheckValid();
688
689 if (!valid) return false;
690
691 return !ValueString(AidlConstantValueDecorator).empty();
692 }
693
GetCapitalizedName() const694 string AidlVariableDeclaration::GetCapitalizedName() const {
695 AIDL_FATAL_IF(name_.size() <= 0, *this) << "Name can't be empty.";
696 string str = name_;
697 str[0] = static_cast<char>(toupper(str[0]));
698 return str;
699 }
700
ToString() const701 string AidlVariableDeclaration::ToString() const {
702 string ret = type_->ToString() + " " + name_;
703 if (default_value_ != nullptr && default_user_specified_) {
704 ret += " = " + ValueString(AidlConstantValueDecorator);
705 }
706 return ret;
707 }
708
Signature() const709 string AidlVariableDeclaration::Signature() const {
710 return type_->Signature() + " " + name_;
711 }
712
ValueString(const ConstantValueDecorator & decorator) const713 std::string AidlVariableDeclaration::ValueString(const ConstantValueDecorator& decorator) const {
714 if (default_value_ != nullptr) {
715 return default_value_->ValueString(GetType(), decorator);
716 } else {
717 return "";
718 }
719 }
720
TraverseChildren(std::function<void (const AidlNode &)> traverse) const721 void AidlVariableDeclaration::TraverseChildren(
722 std::function<void(const AidlNode&)> traverse) const {
723 traverse(GetType());
724 if (IsDefaultUserSpecified()) {
725 traverse(*GetDefaultValue());
726 }
727 }
728
AidlArgument(const AidlLocation & location,AidlArgument::Direction direction,AidlTypeSpecifier * type,const std::string & name)729 AidlArgument::AidlArgument(const AidlLocation& location, AidlArgument::Direction direction,
730 AidlTypeSpecifier* type, const std::string& name)
731 : AidlVariableDeclaration(location, type, name),
732 direction_(direction),
733 direction_specified_(true) {}
734
AidlArgument(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name)735 AidlArgument::AidlArgument(const AidlLocation& location, AidlTypeSpecifier* type,
736 const std::string& name)
737 : AidlVariableDeclaration(location, type, name),
738 direction_(AidlArgument::IN_DIR),
739 direction_specified_(false) {}
740
to_string(AidlArgument::Direction direction)741 static std::string to_string(AidlArgument::Direction direction) {
742 switch (direction) {
743 case AidlArgument::IN_DIR:
744 return "in";
745 case AidlArgument::OUT_DIR:
746 return "out";
747 case AidlArgument::INOUT_DIR:
748 return "inout";
749 }
750 }
751
GetDirectionSpecifier() const752 string AidlArgument::GetDirectionSpecifier() const {
753 string ret;
754 if (direction_specified_) {
755 ret = to_string(direction_);
756 }
757 return ret;
758 }
759
ToString() const760 string AidlArgument::ToString() const {
761 if (direction_specified_) {
762 return GetDirectionSpecifier() + " " + AidlVariableDeclaration::ToString();
763 } else {
764 return AidlVariableDeclaration::ToString();
765 }
766 }
767
FormatDirections(const std::set<AidlArgument::Direction> & directions)768 static std::string FormatDirections(const std::set<AidlArgument::Direction>& directions) {
769 std::vector<std::string> out;
770 for (const auto& d : directions) {
771 out.push_back(to_string(d));
772 }
773
774 if (out.size() <= 1) { // [] => "" or [A] => "A"
775 return Join(out, "");
776 } else if (out.size() == 2) { // [A,B] => "A or B"
777 return Join(out, " or ");
778 } else { // [A,B,C] => "A, B, or C"
779 out.back() = "or " + out.back();
780 return Join(out, ", ");
781 }
782 }
783
CheckValid(const AidlTypenames & typenames) const784 bool AidlArgument::CheckValid(const AidlTypenames& typenames) const {
785 if (!GetType().CheckValid(typenames)) {
786 return false;
787 }
788
789 const auto& aspect = typenames.GetArgumentAspect(GetType());
790
791 if (aspect.possible_directions.size() == 0) {
792 AIDL_ERROR(this) << aspect.name << " cannot be an argument type";
793 return false;
794 }
795
796 // when direction is not specified, "in" is assumed and should be the only possible direction
797 if (!DirectionWasSpecified() && aspect.possible_directions != std::set{AidlArgument::IN_DIR}) {
798 AIDL_ERROR(this) << "The direction of '" << GetName() << "' is not specified. " << aspect.name
799 << " can be an " << FormatDirections(aspect.possible_directions)
800 << " parameter.";
801 return false;
802 }
803
804 if (aspect.possible_directions.count(GetDirection()) == 0) {
805 AIDL_ERROR(this) << "'" << GetName() << "' can't be an " << GetDirectionSpecifier()
806 << " parameter because " << aspect.name << " can only be an "
807 << FormatDirections(aspect.possible_directions) << " parameter.";
808 return false;
809 }
810
811 return true;
812 }
813
IsHidden() const814 bool AidlCommentable::IsHidden() const {
815 return android::aidl::HasHideInComments(GetComments());
816 }
817
IsDeprecated() const818 bool AidlCommentable::IsDeprecated() const {
819 return android::aidl::FindDeprecated(GetComments()).has_value();
820 }
821
AidlMember(const AidlLocation & location,const Comments & comments)822 AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
823 : AidlCommentable(location, comments) {}
824
AidlConstantDeclaration(const AidlLocation & location,AidlTypeSpecifier * type,const std::string & name,AidlConstantValue * value)825 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
826 AidlTypeSpecifier* type, const std::string& name,
827 AidlConstantValue* value)
828 : AidlMember(location, type->GetComments()), type_(type), name_(name), value_(value) {}
829
CheckValid(const AidlTypenames & typenames) const830 bool AidlConstantDeclaration::CheckValid(const AidlTypenames& typenames) const {
831 bool valid = true;
832 valid &= type_->CheckValid(typenames);
833 valid &= value_->CheckValid();
834 if (!valid) return false;
835
836 const static set<string> kSupportedConstTypes = {"String", "byte", "int", "long"};
837 if (kSupportedConstTypes.find(type_->Signature()) == kSupportedConstTypes.end()) {
838 AIDL_ERROR(this) << "Constant of type " << type_->Signature() << " is not supported.";
839 return false;
840 }
841
842 return true;
843 }
844
ToString() const845 string AidlConstantDeclaration::ToString() const {
846 return "const " + type_->ToString() + " " + name_ + " = " +
847 ValueString(AidlConstantValueDecorator);
848 }
849
Signature() const850 string AidlConstantDeclaration::Signature() const {
851 return type_->Signature() + " " + name_;
852 }
853
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const Comments & comments)854 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
855 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
856 const Comments& comments)
857 : AidlMethod(location, oneway, type, name, args, comments, 0, true) {
858 has_id_ = false;
859 }
860
AidlMethod(const AidlLocation & location,bool oneway,AidlTypeSpecifier * type,const std::string & name,std::vector<std::unique_ptr<AidlArgument>> * args,const Comments & comments,int id,bool is_user_defined)861 AidlMethod::AidlMethod(const AidlLocation& location, bool oneway, AidlTypeSpecifier* type,
862 const std::string& name, std::vector<std::unique_ptr<AidlArgument>>* args,
863 const Comments& comments, int id, bool is_user_defined)
864 : AidlMember(location, comments),
865 oneway_(oneway),
866 type_(type),
867 name_(name),
868 arguments_(std::move(*args)),
869 id_(id),
870 is_user_defined_(is_user_defined) {
871 has_id_ = true;
872 delete args;
873 for (const unique_ptr<AidlArgument>& a : arguments_) {
874 if (a->IsIn()) { in_arguments_.push_back(a.get()); }
875 if (a->IsOut()) { out_arguments_.push_back(a.get()); }
876 }
877 }
878
Signature() const879 string AidlMethod::Signature() const {
880 vector<string> arg_signatures;
881 for (const auto& arg : GetArguments()) {
882 arg_signatures.emplace_back(arg->GetType().Signature());
883 }
884 return GetName() + "(" + Join(arg_signatures, ", ") + ")";
885 }
886
ToString() const887 string AidlMethod::ToString() const {
888 vector<string> arg_strings;
889 for (const auto& arg : GetArguments()) {
890 arg_strings.emplace_back(arg->ToString());
891 }
892 string ret = (IsOneway() ? "oneway " : "") + GetType().ToString() + " " + GetName() + "(" +
893 Join(arg_strings, ", ") + ")";
894 if (HasId()) {
895 ret += " = " + std::to_string(GetId());
896 }
897 return ret;
898 }
899
AidlDefinedType(const AidlLocation & location,const std::string & name,const Comments & comments,const std::string & package,std::vector<std::unique_ptr<AidlMember>> * members)900 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
901 const Comments& comments, const std::string& package,
902 std::vector<std::unique_ptr<AidlMember>>* members)
903 : AidlAnnotatable(location, comments),
904 name_(name),
905 package_(package),
906 split_package_(package.empty() ? std::vector<std::string>()
907 : android::base::Split(package, ".")) {
908 if (members) {
909 for (auto& m : *members) {
910 if (auto constant = m->AsConstantDeclaration(); constant) {
911 constants_.emplace_back(constant);
912 } else if (auto variable = m->AsVariableDeclaration(); variable) {
913 variables_.emplace_back(variable);
914 } else if (auto method = m->AsMethod(); method) {
915 methods_.emplace_back(method);
916 } else {
917 AIDL_FATAL(*m);
918 }
919 members_.push_back(m.release());
920 }
921 delete members;
922 }
923 }
924
CheckValid(const AidlTypenames & typenames) const925 bool AidlDefinedType::CheckValid(const AidlTypenames& typenames) const {
926 if (!AidlAnnotatable::CheckValid(typenames)) {
927 return false;
928 }
929 if (!CheckValidWithMembers(typenames)) {
930 return false;
931 }
932 return true;
933 }
934
GetCanonicalName() const935 std::string AidlDefinedType::GetCanonicalName() const {
936 if (package_.empty()) {
937 return GetName();
938 }
939 return GetPackage() + "." + GetName();
940 }
941
CheckValidWithMembers(const AidlTypenames & typenames) const942 bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
943 bool success = true;
944
945 for (const auto& v : GetFields()) {
946 const bool field_valid = v->CheckValid(typenames);
947 success = success && field_valid;
948 }
949
950 // field names should be unique
951 std::set<std::string> fieldnames;
952 for (const auto& v : GetFields()) {
953 bool duplicated = !fieldnames.emplace(v->GetName()).second;
954 if (duplicated) {
955 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName() << "'";
956 success = false;
957 }
958 }
959
960 // immutable parcelables should have immutable fields.
961 if (IsJavaOnlyImmutable()) {
962 for (const auto& v : GetFields()) {
963 if (!typenames.CanBeJavaOnlyImmutable(v->GetType())) {
964 AIDL_ERROR(v) << "The @JavaOnlyImmutable '" << GetName() << "' has a "
965 << "non-immutable field named '" << v->GetName() << "'.";
966 success = false;
967 }
968 }
969 }
970
971 set<string> constant_names;
972 for (const auto& constant : GetConstantDeclarations()) {
973 if (constant_names.count(constant->GetName()) > 0) {
974 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
975 success = false;
976 }
977 constant_names.insert(constant->GetName());
978 success = success && constant->CheckValid(typenames);
979 }
980
981 return success;
982 }
983
CheckValidForGetterNames() const984 bool AidlDefinedType::CheckValidForGetterNames() const {
985 bool success = true;
986 std::set<std::string> getters;
987 for (const auto& v : GetFields()) {
988 bool duplicated = !getters.emplace(v->GetCapitalizedName()).second;
989 if (duplicated) {
990 AIDL_ERROR(v) << "'" << GetName() << "' has duplicate field name '" << v->GetName()
991 << "' after capitalizing the first letter";
992 success = false;
993 }
994 }
995 return success;
996 }
997
AidlParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,const std::string & cpp_header,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)998 AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
999 const std::string& package, const Comments& comments,
1000 const std::string& cpp_header, std::vector<std::string>* type_params,
1001 std::vector<std::unique_ptr<AidlMember>>* members)
1002 : AidlDefinedType(location, name, comments, package, members),
1003 AidlParameterizable<std::string>(type_params),
1004 cpp_header_(cpp_header) {
1005 // Strip off quotation marks if we actually have a cpp header.
1006 if (cpp_header_.length() >= 2) {
1007 cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
1008 }
1009 }
1010 template <typename T>
AidlParameterizable(const AidlParameterizable & other)1011 AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
1012 // Copying is not supported if it has type parameters.
1013 // It doesn't make a problem because only ArrayBase() makes a copy,
1014 // and it can be called only if a type is not generic.
1015 AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
1016 }
1017
1018 template <typename T>
CheckValid() const1019 bool AidlParameterizable<T>::CheckValid() const {
1020 return true;
1021 };
1022
1023 template <>
CheckValid() const1024 bool AidlParameterizable<std::string>::CheckValid() const {
1025 if (!IsGeneric()) {
1026 return true;
1027 }
1028 std::unordered_set<std::string> set(GetTypeParameters().begin(), GetTypeParameters().end());
1029 if (set.size() != GetTypeParameters().size()) {
1030 AIDL_ERROR(this->AsAidlNode()) << "Every type parameter should be unique.";
1031 return false;
1032 }
1033 return true;
1034 }
1035
CheckValid(const AidlTypenames & typenames) const1036 bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
1037 if (!AidlDefinedType::CheckValid(typenames)) {
1038 return false;
1039 }
1040 if (!AidlParameterizable<std::string>::CheckValid()) {
1041 return false;
1042 }
1043
1044 return true;
1045 }
1046
AidlStructuredParcelable(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)1047 AidlStructuredParcelable::AidlStructuredParcelable(
1048 const AidlLocation& location, const std::string& name, const std::string& package,
1049 const Comments& comments, std::vector<std::string>* type_params,
1050 std::vector<std::unique_ptr<AidlMember>>* members)
1051 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
1052
CheckValid(const AidlTypenames & typenames) const1053 bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
1054 if (!AidlParcelable::CheckValid(typenames)) {
1055 return false;
1056 }
1057
1058 bool success = true;
1059
1060 if (IsFixedSize()) {
1061 for (const auto& v : GetFields()) {
1062 if (!typenames.CanBeFixedSize(v->GetType())) {
1063 AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
1064 << "non-fixed size field named " << v->GetName() << ".";
1065 success = false;
1066 }
1067 }
1068 }
1069
1070 if (IsJavaOnlyImmutable()) {
1071 // Immutable parcelables provide getters
1072 if (!CheckValidForGetterNames()) {
1073 success = false;
1074 }
1075 }
1076
1077 return success;
1078 }
1079
1080 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const1081 bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1082 Options::Language lang) const {
1083 if (IsGeneric()) {
1084 const auto& types = GetTypeParameters();
1085 for (const auto& arg : types) {
1086 if (!arg->LanguageSpecificCheckValid(typenames, lang)) {
1087 return false;
1088 }
1089 }
1090 }
1091
1092 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1093 GetName() == "IBinder") {
1094 AIDL_ERROR(this) << "The " << to_string(lang) << " backend does not support array of IBinder";
1095 return false;
1096 }
1097 if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
1098 // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
1099 AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
1100 return false;
1101 }
1102 if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
1103 IsNullable()) {
1104 if (GetName() == "ParcelFileDescriptor") {
1105 AIDL_ERROR(this) << "The " << to_string(lang)
1106 << " backend does not support nullable array of ParcelFileDescriptor";
1107 return false;
1108 }
1109
1110 const auto defined_type = typenames.TryGetDefinedType(GetName());
1111 if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
1112 AIDL_ERROR(this) << "The " << to_string(lang)
1113 << " backend does not support nullable array of parcelable";
1114 return false;
1115 }
1116 }
1117 if (this->GetName() == "FileDescriptor" &&
1118 (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
1119 AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
1120 return false;
1121 }
1122 if (this->IsGeneric()) {
1123 if (this->GetName() == "List") {
1124 if (lang == Options::Language::NDK) {
1125 const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
1126 const string& contained_type_name = contained_type.GetName();
1127 if (typenames.GetInterface(contained_type)) {
1128 AIDL_ERROR(this) << "List<" << contained_type_name
1129 << "> is not supported. List in NDK doesn't support interface.";
1130 return false;
1131 }
1132 if (contained_type_name == "IBinder") {
1133 AIDL_ERROR(this) << "List<" << contained_type_name
1134 << "> is not supported. List in NDK doesn't support IBinder.";
1135 return false;
1136 }
1137 }
1138 }
1139 }
1140
1141 if (this->IsArray()) {
1142 if (this->GetName() == "List" || this->GetName() == "Map" ||
1143 this->GetName() == "CharSequence") {
1144 AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
1145 return false;
1146 }
1147 }
1148
1149 if (lang != Options::Language::JAVA) {
1150 if (this->GetName() == "List" && !this->IsGeneric()) {
1151 AIDL_ERROR(this) << "Currently, only the Java backend supports non-generic List.";
1152 return false;
1153 }
1154 if (this->GetName() == "Map" || this->GetName() == "CharSequence") {
1155 AIDL_ERROR(this) << "Currently, only Java backend supports " << this->GetName() << ".";
1156 return false;
1157 }
1158 }
1159
1160 return true;
1161 }
1162
1163 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames &,Options::Language lang) const1164 bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
1165 Options::Language lang) const {
1166 if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
1167 const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
1168 if (unstructured_parcelable != nullptr) {
1169 if (unstructured_parcelable->GetCppHeader().empty()) {
1170 AIDL_ERROR(unstructured_parcelable)
1171 << "Unstructured parcelable must have C++ header defined.";
1172 return false;
1173 }
1174 }
1175 }
1176 return true;
1177 }
1178
1179 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const1180 bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1181 Options::Language lang) const {
1182 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1183 return false;
1184 }
1185 for (const auto& v : this->GetFields()) {
1186 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1187 return false;
1188 }
1189 }
1190 return true;
1191 }
1192
AidlEnumerator(const AidlLocation & location,const std::string & name,AidlConstantValue * value,const Comments & comments)1193 AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
1194 AidlConstantValue* value, const Comments& comments)
1195 : AidlCommentable(location, comments),
1196 name_(name),
1197 value_(value),
1198 value_user_specified_(value != nullptr) {}
1199
CheckValid(const AidlTypeSpecifier & enum_backing_type) const1200 bool AidlEnumerator::CheckValid(const AidlTypeSpecifier& enum_backing_type) const {
1201 if (GetValue() == nullptr) {
1202 return false;
1203 }
1204 if (!GetValue()->CheckValid()) {
1205 return false;
1206 }
1207 if (GetValue()->ValueString(enum_backing_type, AidlConstantValueDecorator).empty()) {
1208 AIDL_ERROR(this) << "Enumerator type differs from enum backing type.";
1209 return false;
1210 }
1211 return true;
1212 }
1213
ValueString(const AidlTypeSpecifier & backing_type,const ConstantValueDecorator & decorator) const1214 string AidlEnumerator::ValueString(const AidlTypeSpecifier& backing_type,
1215 const ConstantValueDecorator& decorator) const {
1216 return GetValue()->ValueString(backing_type, decorator);
1217 }
1218
AidlEnumDeclaration(const AidlLocation & location,const std::string & name,std::vector<std::unique_ptr<AidlEnumerator>> * enumerators,const std::string & package,const Comments & comments)1219 AidlEnumDeclaration::AidlEnumDeclaration(const AidlLocation& location, const std::string& name,
1220 std::vector<std::unique_ptr<AidlEnumerator>>* enumerators,
1221 const std::string& package, const Comments& comments)
1222 : AidlDefinedType(location, name, comments, package, nullptr),
1223 enumerators_(std::move(*enumerators)) {
1224 // Fill missing enumerator values with <prev + 1>
1225 // This can't be done in Autofill() because type/ref resolution depends on this.
1226 // For example, with enum E { A, B = A }, B's value 'A' is a reference which can't be
1227 // resolved if A has no value set.
1228 const AidlEnumerator* previous = nullptr;
1229 for (const auto& enumerator : enumerators_) {
1230 if (enumerator->GetValue() == nullptr) {
1231 auto loc = enumerator->GetLocation();
1232 if (previous == nullptr) {
1233 enumerator->SetValue(
1234 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "0")));
1235 } else {
1236 auto prev_value = std::make_unique<AidlConstantReference>(loc, previous->GetName());
1237 enumerator->SetValue(std::make_unique<AidlBinaryConstExpression>(
1238 loc, std::move(prev_value), "+",
1239 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(loc, "1"))));
1240 }
1241 }
1242 previous = enumerator.get();
1243 }
1244 }
1245
Autofill(const AidlTypenames & typenames)1246 bool AidlEnumDeclaration::Autofill(const AidlTypenames& typenames) {
1247 if (auto annot = BackingType(); annot != nullptr) {
1248 // Autofill() is called before the grand CheckValid(). But AidlAnnotation::ParamValue()
1249 // calls AidlConstantValue::evaluate() which requires CheckValid() to be called before. So we
1250 // need to call CheckValid().
1251 if (!annot->CheckValid()) {
1252 return false;
1253 }
1254 auto type = annot->ParamValue<std::string>("type").value();
1255 backing_type_ =
1256 std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, Comments{});
1257 } else {
1258 // Default to byte type for enums.
1259 backing_type_ =
1260 std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, Comments{});
1261 }
1262 // Autofill() is called after type resolution, we resolve the backing type manually.
1263 if (!backing_type_->Resolve(typenames)) {
1264 AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
1265 }
1266 return true;
1267 }
1268
CheckValid(const AidlTypenames & typenames) const1269 bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
1270 if (!AidlDefinedType::CheckValid(typenames)) {
1271 return false;
1272 }
1273 if (!GetMembers().empty()) {
1274 AIDL_ERROR(this) << "Enum doesn't support fields/constants/methods.";
1275 return false;
1276 }
1277 if (backing_type_ == nullptr) {
1278 AIDL_ERROR(this) << "Enum declaration missing backing type.";
1279 return false;
1280 }
1281 bool success = true;
1282 for (const auto& enumerator : enumerators_) {
1283 success = success && enumerator->CheckValid(GetBackingType());
1284 }
1285
1286 return success;
1287 }
1288
AidlUnionDecl(const AidlLocation & location,const std::string & name,const std::string & package,const Comments & comments,std::vector<std::string> * type_params,std::vector<std::unique_ptr<AidlMember>> * members)1289 AidlUnionDecl::AidlUnionDecl(const AidlLocation& location, const std::string& name,
1290 const std::string& package, const Comments& comments,
1291 std::vector<std::string>* type_params,
1292 std::vector<std::unique_ptr<AidlMember>>* members)
1293 : AidlParcelable(location, name, package, comments, "" /*cpp_header*/, type_params, members) {}
1294
CheckValid(const AidlTypenames & typenames) const1295 bool AidlUnionDecl::CheckValid(const AidlTypenames& typenames) const {
1296 // visit parents
1297 if (!AidlParcelable::CheckValid(typenames)) {
1298 return false;
1299 }
1300
1301 // unions provide getters always
1302 if (!CheckValidForGetterNames()) {
1303 return false;
1304 }
1305
1306 // now, visit self!
1307 bool success = true;
1308
1309 // TODO(b/170807936) do we need to allow ParcelableHolder in union?
1310 for (const auto& v : GetFields()) {
1311 if (v->GetType().GetName() == "ParcelableHolder") {
1312 AIDL_ERROR(*v) << "A union can't have a member of ParcelableHolder '" << v->GetName() << "'";
1313 success = false;
1314 }
1315 }
1316
1317 if (GetFields().empty()) {
1318 AIDL_ERROR(*this) << "The union '" << this->GetName() << "' has no fields.";
1319 return false;
1320 }
1321
1322 // first member should have useful default value (implicit or explicit)
1323 const auto& first = GetFields()[0];
1324 if (!first->HasUsefulDefaultValue()) {
1325 // Most types can be initialized without a default value. For example,
1326 // interface types are inherently nullable. But, enum types should have
1327 // an explicit default value.
1328 if (!first->GetType().IsArray() && typenames.GetEnumDeclaration(first->GetType())) {
1329 AIDL_ERROR(first)
1330 << "The union's first member should have a useful default value. Enum types can be "
1331 "initialized with a reference. (e.g. ... = MyEnum.FOO;)";
1332 return false;
1333 }
1334 // In Java, array types are initialized as null without a default value. To be sure that default
1335 // initialized unions are accepted by other backends we require arrays also have a default
1336 // value.
1337 if (first->GetType().IsArray()) {
1338 AIDL_ERROR(first)
1339 << "The union's first member should have a useful default value. Arrays can be "
1340 "initialized with values(e.g. ... = { values... };) or marked as @nullable.";
1341 return false;
1342 }
1343 }
1344
1345 return success;
1346 }
1347
1348 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const1349 bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1350 Options::Language lang) const {
1351 if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
1352 return false;
1353 }
1354 for (const auto& v : this->GetFields()) {
1355 if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1356 return false;
1357 }
1358 }
1359 return true;
1360 }
1361
1362 // TODO: we should treat every backend all the same in future.
LanguageSpecificCheckValid(const AidlTypenames & typenames,Options::Language lang) const1363 bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
1364 Options::Language lang) const {
1365 for (const auto& m : this->GetMethods()) {
1366 if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1367 return false;
1368 }
1369 for (const auto& arg : m->GetArguments()) {
1370 if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
1371 return false;
1372 }
1373 }
1374 }
1375 return true;
1376 }
1377
AidlInterface(const AidlLocation & location,const std::string & name,const Comments & comments,bool oneway,const std::string & package,std::vector<std::unique_ptr<AidlMember>> * members)1378 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
1379 const Comments& comments, bool oneway, const std::string& package,
1380 std::vector<std::unique_ptr<AidlMember>>* members)
1381 : AidlDefinedType(location, name, comments, package, members) {
1382 for (auto& m : GetMethods()) {
1383 m.get()->ApplyInterfaceOneway(oneway);
1384 }
1385 }
1386
CheckValid(const AidlTypenames & typenames) const1387 bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
1388 if (!AidlDefinedType::CheckValid(typenames)) {
1389 return false;
1390 }
1391 // Has to be a pointer due to deleting copy constructor. No idea why.
1392 map<string, const AidlMethod*> method_names;
1393 for (const auto& m : GetMethods()) {
1394 if (!m->GetType().CheckValid(typenames)) {
1395 return false;
1396 }
1397
1398 // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
1399 if (m->GetType().GetName() == "ParcelableHolder") {
1400 AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
1401 return false;
1402 }
1403 if (m->IsOneway() && m->GetType().GetName() != "void") {
1404 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
1405 return false;
1406 }
1407
1408 set<string> argument_names;
1409 for (const auto& arg : m->GetArguments()) {
1410 auto it = argument_names.find(arg->GetName());
1411 if (it != argument_names.end()) {
1412 AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
1413 << arg->GetName() << "'";
1414 return false;
1415 }
1416 argument_names.insert(arg->GetName());
1417
1418 if (!arg->CheckValid(typenames)) {
1419 return false;
1420 }
1421
1422 if (m->IsOneway() && arg->IsOut()) {
1423 AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
1424 return false;
1425 }
1426
1427 // check that the name doesn't match a keyword
1428 if (IsJavaKeyword(arg->GetName().c_str())) {
1429 AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
1430 return false;
1431 }
1432
1433 // Reserve a namespace for internal use
1434 if (android::base::StartsWith(arg->GetName(), "_aidl")) {
1435 AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
1436 return false;
1437 }
1438 }
1439
1440 auto it = method_names.find(m->GetName());
1441 // prevent duplicate methods
1442 if (it == method_names.end()) {
1443 method_names[m->GetName()] = m.get();
1444 } else {
1445 AIDL_ERROR(m) << "attempt to redefine method " << m->GetName() << ":";
1446 AIDL_ERROR(it->second) << "previously defined here.";
1447 return false;
1448 }
1449
1450 static set<string> reserved_methods{"asBinder()", "getInterfaceHash()", "getInterfaceVersion()",
1451 "getTransactionName(int)"};
1452
1453 if (reserved_methods.find(m->Signature()) != reserved_methods.end()) {
1454 AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
1455 return false;
1456 }
1457 }
1458
1459 bool success = true;
1460 set<string> constant_names;
1461 for (const auto& constant : GetConstantDeclarations()) {
1462 if (constant_names.count(constant->GetName()) > 0) {
1463 AIDL_ERROR(constant) << "Found duplicate constant name '" << constant->GetName() << "'";
1464 success = false;
1465 }
1466 constant_names.insert(constant->GetName());
1467 success = success && constant->CheckValid(typenames);
1468 }
1469 return success;
1470 }
1471
GetDescriptor() const1472 std::string AidlInterface::GetDescriptor() const {
1473 std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
1474 if (annotatedDescriptor != "") {
1475 return annotatedDescriptor;
1476 }
1477 return GetCanonicalName();
1478 }
1479
AidlImport(const AidlLocation & location,const std::string & needed_class,const Comments & comments)1480 AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class,
1481 const Comments& comments)
1482 : AidlNode(location, comments), needed_class_(needed_class) {}
1483
1484 // Resolves unresolved type name to fully qualified typename to import
1485 // case #1: SimpleName --> import p.SimpleName
1486 // case #2: Outer.Inner --> import p.Outer
1487 // case #3: p.SimpleName --> (as is)
ResolveName(const std::string & unresolved_name) const1488 std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
1489 std::string canonical_name;
1490 const auto first_dot = unresolved_name.find_first_of('.');
1491 const std::string class_name =
1492 (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
1493 for (const auto& import : Imports()) {
1494 const auto& fq_name = import->GetNeededClass();
1495 const auto last_dot = fq_name.find_last_of('.');
1496 const std::string imported_type_name =
1497 (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
1498 if (imported_type_name == class_name) {
1499 if (canonical_name != "" && canonical_name != fq_name) {
1500 AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
1501 return {};
1502 }
1503 canonical_name = fq_name;
1504 }
1505 }
1506 // if not found, use unresolved_name as it is
1507 if (canonical_name == "") {
1508 return unresolved_name;
1509 }
1510 return canonical_name;
1511 }
1512