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