• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016, 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.h"
18 #include "aidl_language.h"
19 #include "aidl_to_common.h"
20 #include "aidl_to_java.h"
21 #include "aidl_typenames.h"
22 #include "ast_java.h"
23 #include "code_writer.h"
24 #include "generate_java.h"
25 #include "logging.h"
26 #include "options.h"
27 #include "parser.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include <algorithm>
34 #include <unordered_set>
35 #include <utility>
36 #include <vector>
37 
38 #include <android-base/stringprintf.h>
39 
40 using android::base::Join;
41 using android::base::StringPrintf;
42 
43 using std::string;
44 using std::unique_ptr;
45 using std::vector;
46 
47 namespace android {
48 namespace aidl {
49 namespace java {
50 
51 // =================================================
52 class VariableFactory {
53  public:
54   using Variable = ::android::aidl::java::Variable;
55 
VariableFactory(const std::string & base)56   explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Get(const AidlTypeSpecifier & type)57   std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type) {
58     auto v = std::make_shared<Variable>(JavaSignatureOf(type),
59                                         StringPrintf("%s%d", base_.c_str(), index_));
60     vars_.push_back(v);
61     index_++;
62     return v;
63   }
64 
Get(int index)65   std::shared_ptr<Variable> Get(int index) { return vars_[index]; }
66 
67  private:
68   std::vector<std::shared_ptr<Variable>> vars_;
69   std::string base_;
70   int index_;
71 };
72 
73 // =================================================
74 class StubClass : public Class {
75  public:
76   StubClass(const AidlInterface* interfaceType, const Options& options);
77   ~StubClass() override = default;
78 
79   // non-copyable, non-movable
80   StubClass(const StubClass&) = delete;
81   StubClass(StubClass&&) = delete;
82   StubClass& operator=(const StubClass&) = delete;
83   StubClass& operator=(StubClass&&) = delete;
84 
85   std::shared_ptr<Variable> transact_code;
86   std::shared_ptr<Variable> transact_data;
87   std::shared_ptr<Variable> transact_reply;
88   std::shared_ptr<Variable> transact_flags;
89   std::vector<std::shared_ptr<IfStatement>> transact_if_statements_meta;
90   std::shared_ptr<SwitchStatement> transact_switch_user;
91   std::shared_ptr<StatementBlock> transact_statements;
92   std::shared_ptr<SwitchStatement> code_to_method_name_switch;
93 
94   // Where onTransact cases should be generated as separate methods.
95   bool transact_outline;
96   // Specific methods that should be outlined when transact_outline is true.
97   std::unordered_set<const AidlMethod*> outline_methods;
98   // Number of all methods.
99   size_t all_method_count;
100 
101   // Finish generation. This will add a default case to the switch.
102   void Finish();
103 
104   std::shared_ptr<Expression> GetTransactDescriptor(const AidlMethod* method);
105 
106  private:
107   void MakeConstructors(const AidlInterface* interfaceType);
108   void MakeAsInterface(const AidlInterface* interfaceType);
109 
110   std::shared_ptr<Variable> transact_descriptor;
111   const Options& options_;
112 };
113 
StubClass(const AidlInterface * interfaceType,const Options & options)114 StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
115     : Class(), options_(options) {
116   transact_descriptor = nullptr;
117   transact_outline = false;
118   all_method_count = 0;  // Will be set when outlining may be enabled.
119 
120   this->comment = "/** Local-side IPC implementation stub class. */";
121   this->modifiers = PUBLIC | ABSTRACT | STATIC;
122   this->what = Class::CLASS;
123   this->type = interfaceType->GetCanonicalName() + ".Stub";
124   this->extends = "android.os.Binder";
125   this->interfaces.push_back(interfaceType->GetCanonicalName());
126 
127   MakeConstructors(interfaceType);
128   MakeAsInterface(interfaceType);
129 
130   // asBinder
131   auto asBinder = std::make_shared<Method>();
132   asBinder->modifiers = PUBLIC | OVERRIDE;
133   asBinder->returnType = "android.os.IBinder";
134   asBinder->name = "asBinder";
135   asBinder->statements = std::make_shared<StatementBlock>();
136   asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
137   this->elements.push_back(asBinder);
138 
139   if (options_.GenTransactionNames() || options_.GenTraces()) {
140     // getDefaultTransactionName
141     auto getDefaultTransactionName = std::make_shared<Method>();
142     getDefaultTransactionName->comment = "/** @hide */";
143     getDefaultTransactionName->modifiers = PUBLIC | STATIC;
144     getDefaultTransactionName->returnType = "java.lang.String";
145     getDefaultTransactionName->name = "getDefaultTransactionName";
146     auto code = std::make_shared<Variable>("int", "transactionCode");
147     getDefaultTransactionName->parameters.push_back(code);
148     getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
149     this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
150     getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
151     this->elements.push_back(getDefaultTransactionName);
152 
153     // getTransactionName
154     auto getTransactionName = std::make_shared<Method>();
155     getTransactionName->comment = "/** @hide */";
156     getTransactionName->modifiers = PUBLIC;
157     getTransactionName->returnType = "java.lang.String";
158     getTransactionName->name = "getTransactionName";
159     auto code2 = std::make_shared<Variable>("int", "transactionCode");
160     getTransactionName->parameters.push_back(code2);
161     getTransactionName->statements = std::make_shared<StatementBlock>();
162     getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
163         std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
164                                      std::vector<std::shared_ptr<Expression>>{code2})));
165     this->elements.push_back(getTransactionName);
166   }
167 
168   // onTransact
169   this->transact_code = std::make_shared<Variable>("int", "code");
170   this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
171   this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
172   this->transact_flags = std::make_shared<Variable>("int", "flags");
173   auto onTransact = std::make_shared<Method>();
174   onTransact->modifiers = PUBLIC | OVERRIDE;
175   onTransact->returnType = "boolean";
176   onTransact->name = "onTransact";
177   onTransact->parameters.push_back(this->transact_code);
178   onTransact->parameters.push_back(this->transact_data);
179   onTransact->parameters.push_back(this->transact_reply);
180   onTransact->parameters.push_back(this->transact_flags);
181   onTransact->statements = std::make_shared<StatementBlock>();
182   transact_statements = onTransact->statements;
183   onTransact->exceptions.push_back("android.os.RemoteException");
184   this->elements.push_back(onTransact);
185   this->transact_switch_user = std::make_shared<SwitchStatement>(this->transact_code);
186 }
187 
Finish()188 void StubClass::Finish() {
189   auto default_case = std::make_shared<Case>();
190 
191   auto superCall = std::make_shared<MethodCall>(
192       SUPER_VALUE, "onTransact",
193       std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
194                                                this->transact_reply, this->transact_flags});
195   default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
196 
197   auto case_count = transact_switch_user->cases.size();
198   transact_switch_user->cases.push_back(default_case);
199 
200   // Interface token validation is done for user-defined transactions.
201   if (case_count > 0) {
202     auto ifStatement = std::make_shared<IfStatement>();
203     ifStatement->expression = std::make_shared<LiteralExpression>(
204         "code >= android.os.IBinder.FIRST_CALL_TRANSACTION && "
205         "code <= android.os.IBinder.LAST_CALL_TRANSACTION");
206     ifStatement->statements = std::make_shared<StatementBlock>();
207     ifStatement->statements->Add(std::make_shared<MethodCall>(
208         this->transact_data, "enforceInterface",
209         std::vector<std::shared_ptr<Expression>>{this->GetTransactDescriptor(nullptr)}));
210     transact_statements->Add(ifStatement);
211   }
212 
213   // Build the if/else chain for the meta methods. There at most 3 different
214   // statements so if/else is more efficient than a switch statement.
215   // Meta transactions are looked up prior to user-defined transactions.
216   AIDL_FATAL_IF(this->transact_if_statements_meta.size() == 0, AIDL_LOCATION_HERE)
217       << "Expecting to have meta methods and found none.";
218   AIDL_FATAL_IF(this->transact_if_statements_meta.size() > 3, AIDL_LOCATION_HERE)
219       << "Expecting to have at most 3 meta methods and found "
220       << this->transact_if_statements_meta.size();
221   auto ifStatement = this->transact_if_statements_meta[0];
222   std::shared_ptr<IfStatement> currentIfStatement = ifStatement;
223   for (size_t i = 1; i < transact_if_statements_meta.size(); i++) {
224     currentIfStatement->elseif = this->transact_if_statements_meta[i];
225     currentIfStatement = currentIfStatement->elseif;
226   }
227 
228   transact_statements->Add(ifStatement);
229   transact_statements->Add(this->transact_switch_user);
230 
231   // getTransactionName
232   if (options_.GenTransactionNames() || options_.GenTraces()) {
233     // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
234     // Common transaction codes will not be resolved to a string by getTransactionName. The method
235     // will return NULL in this case.
236     auto code_switch_default_case = std::make_shared<Case>();
237     code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
238     this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
239   }
240 
241   // There will be at least one statement for the default, but if we emit a
242   // return true after that default, it will be unreachable.
243   if (case_count > 0) {
244     transact_statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
245   }
246 }
247 
248 // The the expression for the interface's descriptor to be used when
249 // generating code for the given method. Null is acceptable for method
250 // and stands for synthetic cases.
GetTransactDescriptor(const AidlMethod * method)251 std::shared_ptr<Expression> StubClass::GetTransactDescriptor(const AidlMethod* method) {
252   if (transact_outline) {
253     if (method != nullptr) {
254       // When outlining, each outlined method needs its own literal.
255       if (outline_methods.count(method) != 0) {
256         return std::make_shared<LiteralExpression>("DESCRIPTOR");
257       }
258     } else {
259       // Synthetic case. A small number is assumed. Use its own descriptor
260       // if there are only synthetic cases.
261       if (outline_methods.size() == all_method_count) {
262         return std::make_shared<LiteralExpression>("DESCRIPTOR");
263       }
264     }
265   }
266 
267   // When not outlining, store the descriptor literal into a local variable, in
268   // an effort to save const-string instructions in each switch case.
269   if (transact_descriptor == nullptr) {
270     transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
271     transact_statements->Add(std::make_shared<VariableDeclaration>(
272         transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
273   }
274   return transact_descriptor;
275 }
276 
MakeConstructors(const AidlInterface * interfaceType)277 void StubClass::MakeConstructors(const AidlInterface* interfaceType) {
278   string ctors_code;
279   CodeWriterPtr writer = CodeWriter::ForString(&ctors_code);
280   CodeWriter& code = *writer;
281 
282   if (interfaceType->UsesPermissions()) {
283     code << "private final android.os.PermissionEnforcer mEnforcer;\n";
284     code << "/** Construct the stub using the Enforcer provided. */\n";
285     code << "public Stub(android.os.PermissionEnforcer enforcer)\n";
286   } else {
287     code << "/** Construct the stub at attach it to the interface. */\n";
288     code << "@SuppressWarnings(\"this-escape\")\n";
289     code << "public Stub()\n";
290   }
291   code << "{\n";
292   code.Indent();
293   if (interfaceType->IsVintfStability()) {
294     code << "this.markVintfStability();\n";
295   }
296   code << "this.attachInterface(this, DESCRIPTOR);\n";
297   if (interfaceType->UsesPermissions()) {
298     code << "if (enforcer == null) {\n";
299     code.Indent();
300     code << "throw new IllegalArgumentException(\"enforcer cannot be null\");\n";
301     code.Dedent();
302     code << "}\n";
303     code << "mEnforcer = enforcer;\n";
304   }
305   code.Dedent();
306   code << "}\n";
307 
308   // Setup a default constructor for permissions interfaces.
309   if (interfaceType->UsesPermissions()) {
310     code << "@Deprecated\n";
311     code << "/** Default constructor. */\n";
312     code << "public Stub() {\n";
313     code.Indent();
314     code << "this(android.os.PermissionEnforcer.fromContext(\n";
315     code << "   android.app.ActivityThread.currentActivityThread().getSystemContext()));\n";
316     code.Dedent();
317     code << "}\n";
318   }
319 
320   code.Close();
321   this->elements.push_back(std::make_shared<LiteralClassElement>(ctors_code));
322 }
323 
MakeAsInterface(const AidlInterface * interfaceType)324 void StubClass::MakeAsInterface(const AidlInterface* interfaceType) {
325   auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
326 
327   auto m = std::make_shared<Method>();
328   m->comment = "/**\n * Cast an IBinder object into an ";
329   m->comment += interfaceType->GetCanonicalName();
330   m->comment += " interface,\n";
331   m->comment += " * generating a proxy if needed.\n */";
332   m->modifiers = PUBLIC | STATIC;
333   m->returnType = interfaceType->GetCanonicalName();
334   m->name = "asInterface";
335   m->parameters.push_back(obj);
336   m->statements = std::make_shared<StatementBlock>();
337 
338   auto ifstatement = std::make_shared<IfStatement>();
339   ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
340   ifstatement->statements = std::make_shared<StatementBlock>();
341   ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
342   m->statements->Add(ifstatement);
343 
344   // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
345   auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
346   queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
347   auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
348   auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
349   m->statements->Add(iinVd);
350 
351   // Ensure the instance type of the local object is as expected.
352   // One scenario where this is needed is if another package (with a
353   // different class loader) runs in the same process as the service.
354 
355   // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
356   // iin;
357   auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
358   auto instOfCheck = std::make_shared<Comparison>(
359       iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
360   auto instOfStatement = std::make_shared<IfStatement>();
361   instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
362   instOfStatement->statements = std::make_shared<StatementBlock>();
363   instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
364       std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
365   m->statements->Add(instOfStatement);
366 
367   auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
368   ne->arguments.push_back(obj);
369   m->statements->Add(std::make_shared<ReturnStatement>(ne));
370 
371   this->elements.push_back(m);
372 }
373 
374 // =================================================
375 class ProxyClass : public Class {
376  public:
377   ProxyClass(const AidlInterface* interfaceType, const Options& options);
378   ~ProxyClass() override;
379 
380   std::shared_ptr<Variable> mRemote;
381 };
382 
ProxyClass(const AidlInterface * interfaceType,const Options & options)383 ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
384   this->modifiers = PRIVATE | STATIC;
385   this->what = Class::CLASS;
386   this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
387   this->interfaces.push_back(interfaceType->GetCanonicalName());
388 
389   // IBinder mRemote
390   mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
391   this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
392 
393   // Proxy()
394   auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
395   auto ctor = std::make_shared<Method>();
396   ctor->name = "Proxy";
397   ctor->statements = std::make_shared<StatementBlock>();
398   ctor->parameters.push_back(remote);
399   ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
400   this->elements.push_back(ctor);
401 
402   if (options.Version() > 0) {
403     std::ostringstream code;
404     code << "private int mCachedVersion = -1;\n";
405     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
406   }
407   if (!options.Hash().empty()) {
408     std::ostringstream code;
409     code << "private String mCachedHash = \"-1\";\n";
410     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
411   }
412 
413   // IBinder asBinder()
414   auto asBinder = std::make_shared<Method>();
415   asBinder->modifiers = PUBLIC | OVERRIDE;
416   asBinder->returnType = "android.os.IBinder";
417   asBinder->name = "asBinder";
418   asBinder->statements = std::make_shared<StatementBlock>();
419   asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
420   this->elements.push_back(asBinder);
421 }
422 
~ProxyClass()423 ProxyClass::~ProxyClass() {}
424 
425 // =================================================
426 
GenerateWriteToParcel(CodeWriter & out,const AidlTypenames & typenames,const AidlTypeSpecifier & type,const std::string & parcel,const std::string & var,uint32_t min_sdk_version,bool is_return_value)427 static void GenerateWriteToParcel(CodeWriter& out, const AidlTypenames& typenames,
428                                   const AidlTypeSpecifier& type, const std::string& parcel,
429                                   const std::string& var, uint32_t min_sdk_version,
430                                   bool is_return_value) {
431   WriteToParcelFor(CodeGeneratorContext{
432       .writer = out,
433       .typenames = typenames,
434       .type = type,
435       .parcel = parcel,
436       .var = var,
437       .min_sdk_version = min_sdk_version,
438       .write_to_parcel_flag =
439           is_return_value ? "android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE" : "0",
440   });
441 }
442 
GenerateWriteToParcel(std::shared_ptr<StatementBlock> addTo,const AidlTypenames & typenames,const AidlTypeSpecifier & type,const std::string & parcel,const std::string & var,uint32_t min_sdk_version,bool is_return_value)443 static void GenerateWriteToParcel(std::shared_ptr<StatementBlock> addTo,
444                                   const AidlTypenames& typenames, const AidlTypeSpecifier& type,
445                                   const std::string& parcel, const std::string& var,
446                                   uint32_t min_sdk_version, bool is_return_value) {
447   string code;
448   GenerateWriteToParcel(*CodeWriter::ForString(&code), typenames, type, parcel, var,
449                         min_sdk_version, is_return_value);
450   addTo->Add(std::make_shared<LiteralStatement>(code));
451 }
452 
GenerateConstantDeclarations(CodeWriter & out,const AidlDefinedType & type)453 void GenerateConstantDeclarations(CodeWriter& out, const AidlDefinedType& type) {
454   for (const auto& constant : type.GetConstantDeclarations()) {
455     const AidlTypeSpecifier& type = constant->GetType();
456     out << GenerateComments(*constant);
457     out << GenerateAnnotations(*constant);
458     out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
459         << constant->ValueString(ConstantValueDecorator) << ";\n";
460   }
461 }
462 
GenerateInterfaceMethod(const AidlInterface & iface,const AidlMethod & method)463 static std::shared_ptr<Method> GenerateInterfaceMethod(const AidlInterface& iface,
464                                                        const AidlMethod& method) {
465   auto decl = std::make_shared<Method>();
466   decl->comment = GenerateComments(method);
467   decl->modifiers = PUBLIC;
468   decl->returnType = JavaSignatureOf(method.GetType());
469   decl->name = method.GetName();
470   decl->annotations = JavaAnnotationsFor(method);
471   // If the interface has some permission annotation, add it to the method.
472   if (auto iface_annotation = JavaPermissionAnnotation(iface); iface_annotation) {
473     decl->annotations.push_back(*iface_annotation);
474   }
475 
476   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
477     auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
478     var->annotations = JavaAnnotationsFor(arg->GetType());
479     decl->parameters.push_back(var);
480   }
481 
482   decl->exceptions.push_back("android.os.RemoteException");
483 
484   return decl;
485 }
486 
487 // Visitor for the permission declared in the @EnforcePermission annotation.
488 class PermissionVisitor {
489  public:
PermissionVisitor(CodeWriter * code,const AidlMethod & method)490   PermissionVisitor(CodeWriter* code, const AidlMethod& method) : code_(code), method_(method) {}
491 
~PermissionVisitor()492   ~PermissionVisitor() {
493     code_->Dedent();
494     *code_ << "}\n";
495   }
496 
Credentials() const497   string Credentials() const { return "getCallingPid(), getCallingUid()"; }
498 
Prologue()499   void Prologue() {
500     *code_ << "/** Helper method to enforce permissions for " << method_.GetName() << " */\n";
501     *code_ << "protected void " << method_.GetName() << "_enforcePermission() "
502            << "throws SecurityException {\n";
503     code_->Indent();
504   }
505 
AddStaticArrayPermissions(const std::vector<std::string> & permissions)506   void AddStaticArrayPermissions(const std::vector<std::string>& permissions) {
507     *code_ << "static final String[] PERMISSIONS_" << method_.GetName() << " = {"
508            << Join(permissions, ", ") << "};\n";
509   }
510 
operator ()(const perm::AllOf & quantifier)511   void operator()(const perm::AllOf& quantifier) {
512     std::vector<std::string> permissions;
513     permissions.reserve(quantifier.operands.size());
514     for (auto const& permission : quantifier.operands) {
515       permissions.push_back(android::aidl::perm::JavaFullName(permission));
516     }
517     AddStaticArrayPermissions(permissions);
518     Prologue();
519     *code_ << "mEnforcer.enforcePermissionAllOf(PERMISSIONS_" << method_.GetName() << ", "
520            << Credentials() << ");\n";
521   }
522 
operator ()(const perm::AnyOf & quantifier)523   void operator()(const perm::AnyOf& quantifier) {
524     std::vector<std::string> permissions;
525     permissions.reserve(quantifier.operands.size());
526     for (auto const& permission : quantifier.operands) {
527       permissions.push_back(android::aidl::perm::JavaFullName(permission));
528     }
529     AddStaticArrayPermissions(permissions);
530     Prologue();
531     *code_ << "mEnforcer.enforcePermissionAnyOf(PERMISSIONS_" << method_.GetName() << ", "
532            << Credentials() << ");\n";
533   }
534 
operator ()(const std::string & permission)535   void operator()(const std::string& permission) {
536     auto permissionName = android::aidl::perm::JavaFullName(permission);
537     Prologue();
538     *code_ << "mEnforcer.enforcePermission(" << permissionName << ", " << Credentials() << ");\n";
539   }
540 
541  private:
542   CodeWriter* code_;
543   const AidlMethod& method_;
544 };
545 
GeneratePermissionMethod(const AidlInterface & iface,const AidlMethod & method,const std::shared_ptr<Class> & addTo)546 static void GeneratePermissionMethod(const AidlInterface& iface, const AidlMethod& method,
547                                      const std::shared_ptr<Class>& addTo) {
548   string code;
549   CodeWriterPtr writer = CodeWriter::ForString(&code);
550 
551   if (auto ifacePermExpr = iface.EnforceExpression(); ifacePermExpr) {
552     std::visit(PermissionVisitor(writer.get(), method), *ifacePermExpr.get());
553   } else if (auto methodPermExpr = method.GetType().EnforceExpression(); methodPermExpr) {
554     std::visit(PermissionVisitor(writer.get(), method), *methodPermExpr.get());
555   }
556   writer->Close();
557   addTo->elements.push_back(std::make_shared<LiteralClassElement>(code));
558 }
559 
GenerateStubCode(const AidlMethod & method,bool oneway,std::shared_ptr<Variable> transact_data,std::shared_ptr<Variable> transact_reply,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> statement_block,const Options & options)560 static void GenerateStubCode(const AidlMethod& method, bool oneway,
561                              std::shared_ptr<Variable> transact_data,
562                              std::shared_ptr<Variable> transact_reply,
563                              const AidlTypenames& typenames,
564                              std::shared_ptr<StatementBlock> statement_block,
565                              const Options& options) {
566   // try and finally
567   auto& statements = statement_block;
568 
569   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
570 
571   // args
572   VariableFactory stubArgs("_arg");
573   {
574     // keep this across different args in order to create the classloader
575     // at most once.
576     bool is_classloader_created = false;
577 
578     if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::READ)) {
579       auto if_statement = std::make_shared<IfStatement>();
580       if_statement->expression = std::make_shared<LiteralExpression>("true");
581       if_statement->statements = std::make_shared<StatementBlock>();
582       if_statement->statements->Add(
583           std::make_shared<LiteralExpression>("throw new android.os.RemoteException(\"Method " +
584                                               method.GetName() + " is unimplemented.\")"));
585       statements->Add(if_statement);
586     }
587     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
588       std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType());
589 
590       statements->Add(std::make_shared<VariableDeclaration>(v));
591 
592       string code;
593       CodeWriterPtr writer = CodeWriter::ForString(&code);
594       if (arg->GetDirection() & AidlArgument::IN_DIR) {
595         // "in/inout" parameter should be created from parcel.
596         CodeGeneratorContext context{.writer = *(writer.get()),
597                                      .typenames = typenames,
598                                      .type = arg->GetType(),
599                                      .parcel = transact_data->name,
600                                      .var = v->name,
601                                      .min_sdk_version = options.GetMinSdkVersion(),
602                                      .is_classloader_created = &is_classloader_created};
603         CreateFromParcelFor(context);
604       } else {
605         // "out" parameter should be instantiated before calling the real impl.
606         string java_type = InstantiableJavaSignatureOf(arg->GetType());
607 
608         if (arg->GetType().IsDynamicArray()) {
609           // dynamic array should be created with a passed length.
610           string var_length = v->name + "_length";
611           (*writer) << "int " << var_length << " = data.readInt();\n";
612           (*writer) << "if (" << var_length << " < 0) {\n";
613           (*writer) << "  " << v->name << " = null;\n";
614           (*writer) << "} else {\n";
615           (*writer) << "  " << v->name << " = new " << java_type << "[" << var_length << "];\n";
616           (*writer) << "}\n";
617         } else if (arg->GetType().IsFixedSizeArray()) {
618           // fixed-size array can be created with a known size
619           string dimensions;
620           for (auto dim : arg->GetType().GetFixedSizeArrayDimensions()) {
621             dimensions += "[" + std::to_string(dim) + "]";
622           }
623           (*writer) << v->name << " = new " << java_type << dimensions << ";\n";
624         } else {
625           // otherwise, create a new instance with a default constructor
626           (*writer) << v->name << " = new " << java_type << "();\n";
627         }
628       }
629       writer->Close();
630       statements->Add(std::make_shared<LiteralStatement>(code));
631 
632       realCall->arguments.push_back(v);
633     }
634   }
635 
636   // EOF check
637   if (!method.GetArguments().empty() && options.GetMinSdkVersion() > 32u) {
638     statements->Add(std::make_shared<MethodCall>(transact_data, "enforceNoDataAvail"));
639   }
640 
641   // the real call
642   if (method.GetType().GetName() == "void") {
643     statements->Add(realCall);
644 
645     if (!oneway) {
646       // report that there were no exceptions
647       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
648       statements->Add(ex);
649     }
650   } else {
651     auto _result = std::make_shared<Variable>(JavaSignatureOf(method.GetType()), "_result");
652     statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
653 
654     if (!oneway) {
655       // report that there were no exceptions
656       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
657       statements->Add(ex);
658     }
659 
660     // marshall the return value
661     GenerateWriteToParcel(statements, typenames, method.GetType(), transact_reply->name,
662                           _result->name, options.GetMinSdkVersion(), /*is_return_value=*/true);
663   }
664 
665   // out parameters
666   int i = 0;
667   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
668     std::shared_ptr<Variable> v = stubArgs.Get(i++);
669     if (arg->GetDirection() & AidlArgument::OUT_DIR) {
670       GenerateWriteToParcel(statements, typenames, arg->GetType(), transact_reply->name, v->name,
671                             options.GetMinSdkVersion(), /*is_return_value=*/true);
672     }
673   }
674 }
675 
GenerateStubCase(const AidlMethod & method,const std::string & transactCodeName,bool oneway,const std::shared_ptr<StubClass> & stubClass,const AidlTypenames & typenames,const Options & options)676 static void GenerateStubCase(const AidlMethod& method, const std::string& transactCodeName,
677                              bool oneway, const std::shared_ptr<StubClass>& stubClass,
678                              const AidlTypenames& typenames, const Options& options) {
679   auto c = std::make_shared<Case>(transactCodeName);
680 
681   GenerateStubCode(method, oneway, stubClass->transact_data, stubClass->transact_reply, typenames,
682                    c->statements, options);
683   c->statements->Add(std::make_shared<BreakStatement>());
684 
685   stubClass->transact_switch_user->cases.push_back(c);
686 }
687 
GenerateStubCaseOutline(const AidlMethod & method,const std::string & transactCodeName,bool oneway,const std::shared_ptr<StubClass> & stubClass,const AidlTypenames & typenames,const Options & options)688 static void GenerateStubCaseOutline(const AidlMethod& method, const std::string& transactCodeName,
689                                     bool oneway, const std::shared_ptr<StubClass>& stubClass,
690                                     const AidlTypenames& typenames, const Options& options) {
691   std::string outline_name = "onTransact$" + method.GetName() + "$";
692   // Generate an "outlined" method with the actual code.
693   {
694     auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
695     auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
696     auto onTransact_case = std::make_shared<Method>();
697     onTransact_case->modifiers = PRIVATE;
698     onTransact_case->returnType = "boolean";
699     onTransact_case->name = outline_name;
700     onTransact_case->parameters.push_back(transact_data);
701     onTransact_case->parameters.push_back(transact_reply);
702     onTransact_case->statements = std::make_shared<StatementBlock>();
703     onTransact_case->exceptions.push_back("android.os.RemoteException");
704     stubClass->elements.push_back(onTransact_case);
705 
706     GenerateStubCode(method, oneway, transact_data, transact_reply, typenames,
707                      onTransact_case->statements, options);
708     onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
709   }
710 
711   // Generate the case dispatch.
712   {
713     auto c = std::make_shared<Case>(transactCodeName);
714 
715     auto helper_call =
716         std::make_shared<MethodCall>(THIS_VALUE, outline_name,
717                                      std::vector<std::shared_ptr<Expression>>{
718                                          stubClass->transact_data, stubClass->transact_reply});
719     c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
720 
721     stubClass->transact_switch_user->cases.push_back(c);
722   }
723 }
724 
725 template <typename Formatter>
ArgList(const AidlMethod & method,Formatter formatter)726 static std::string ArgList(const AidlMethod& method, Formatter formatter) {
727   vector<string> args;
728   for (const auto& arg : method.GetArguments()) {
729     args.push_back(std::invoke(formatter, *arg));
730   }
731   return Join(args, ", ");
732 }
733 
FormatArgForDecl(const AidlArgument & arg)734 static std::string FormatArgForDecl(const AidlArgument& arg) {
735   return JavaSignatureOf(arg.GetType()) + " " + arg.GetName();
736 }
737 
GenerateProxyMethod(CodeWriter & out,const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,const AidlTypenames & typenames,const Options & options)738 static void GenerateProxyMethod(CodeWriter& out, const AidlInterface& iface,
739                                 const AidlMethod& method, const std::string& transactCodeName,
740                                 bool oneway, const AidlTypenames& typenames,
741                                 const Options& options) {
742   bool is_void = method.GetType().GetName() == "void";
743 
744   out << GenerateComments(method);
745   out << "@Override public " << JavaSignatureOf(method.GetType()) << " " << method.GetName() << "("
746       << ArgList(method, FormatArgForDecl) << ") throws android.os.RemoteException\n{\n";
747   out.Indent();
748 
749   if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
750     out << "if (true) {\n";
751     out << "  throw new android.os.RemoteException(\"Method " + method.GetName() +
752                " is unimplemented.\");\n";
753     out << "}\n";
754   }
755 
756   // the parcels
757   if (options.GenRpc()) {
758     out << "android.os.Parcel _data = android.os.Parcel.obtain(asBinder());\n";
759   } else {
760     out << "android.os.Parcel _data = android.os.Parcel.obtain();\n";
761   }
762 
763   if (iface.IsSensitiveData()) {
764     out << "_data.markSensitive();\n";
765   }
766 
767   if (!oneway) {
768     out << "android.os.Parcel _reply = android.os.Parcel.obtain();\n";
769   }
770 
771   // the return value
772   if (!is_void) {
773     out << JavaSignatureOf(method.GetType()) << " _result;\n";
774   }
775 
776   out << "try {\n";
777   out.Indent();
778 
779   // the interface identifier token: the DESCRIPTOR constant, marshalled as a
780   // string
781   out << "_data.writeInterfaceToken(DESCRIPTOR);\n";
782 
783   // the parameters
784   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
785     AidlArgument::Direction dir = arg->GetDirection();
786     if (dir == AidlArgument::OUT_DIR && arg->GetType().IsDynamicArray()) {
787       // In Java we pass a pre-allocated array for an 'out' argument. For transaction,
788       // we pass the size of the array so that the remote can allocate the array with the same size.
789       out << "_data.writeInt(" << arg->GetName() << ".length);\n";
790     } else if (dir & AidlArgument::IN_DIR) {
791       GenerateWriteToParcel(out, typenames, arg->GetType(), "_data", arg->GetName(),
792                             options.GetMinSdkVersion(), /*is_return_value=*/false);
793     }
794   }
795 
796   std::vector<std::string> flags;
797   if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
798   if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
799 
800   // the transact call
801   out << "boolean _status = mRemote.transact(Stub." << transactCodeName << ", _data, "
802       << (oneway ? "null" : "_reply") << ", " << (flags.empty() ? "0" : Join(flags, " | "))
803       << ");\n";
804 
805   // TODO(b/151102494): annotation is applied on the return type
806   if (method.GetType().IsPropagateAllowBlocking() && !oneway) {
807     if (options.GetMinSdkVersion() < JAVA_PROPAGATE_VERSION) {
808       out << "if (android.os.Build.VERSION.SDK_INT >= " + std::to_string(JAVA_PROPAGATE_VERSION) +
809                  ") { _reply.setPropagateAllowBlocking(); }\n";
810     } else {
811       out << "_reply.setPropagateAllowBlocking();\n";
812     }
813   }
814 
815   // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
816   // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
817   // is versioned. We can't throw the exception for unversioned interface because that would be an
818   // app breaking change.
819   if (iface.IsJavaDefault() || options.Version() > 0) {
820     out << "if (!_status) {\n";
821     out.Indent();
822 
823     if (iface.IsJavaDefault()) {
824       out << "if (getDefaultImpl() != null) {\n";
825       out.Indent();
826       if (is_void) {
827         out << "getDefaultImpl()." << method.GetName() << "("
828             << ArgList(method, &AidlArgument::GetName) << ");\n";
829         out << "return;\n";
830       } else {
831         out << "return getDefaultImpl()." << method.GetName() << "("
832             << ArgList(method, &AidlArgument::GetName) << ");\n";
833       }
834       out.Dedent();
835       out << "}\n";
836     }
837 
838     // TODO(b/274144762): we shouldn't have different behavior for versioned interfaces
839     // also this set to false for all exceptions, not just unimplemented methods.
840     if (options.Version() > 0) {
841       out << "throw new android.os.RemoteException(\"Method " << method.GetName()
842           << " is unimplemented.\");\n";
843     }
844 
845     out.Dedent();
846     out << "}\n";
847   }
848 
849   if (!oneway) {
850     // keep this across return value and arguments in order to create the
851     // classloader at most once.
852     bool is_classloader_created = false;
853 
854     // throw back exceptions.
855     out << "_reply.readException();\n";
856 
857     if (!is_void) {
858       CreateFromParcelFor(CodeGeneratorContext{.writer = out,
859                                                .typenames = typenames,
860                                                .type = method.GetType(),
861                                                .parcel = "_reply",
862                                                .var = "_result",
863                                                .min_sdk_version = options.GetMinSdkVersion(),
864                                                .is_classloader_created = &is_classloader_created});
865     }
866 
867     // the out/inout parameters
868     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
869       if (arg->GetDirection() & AidlArgument::OUT_DIR) {
870         ReadFromParcelFor(CodeGeneratorContext{.writer = out,
871                                                .typenames = typenames,
872                                                .type = arg->GetType(),
873                                                .parcel = "_reply",
874                                                .var = arg->GetName(),
875                                                .min_sdk_version = options.GetMinSdkVersion(),
876                                                .is_classloader_created = &is_classloader_created});
877       }
878     }
879   }
880 
881   out.Dedent();
882   out << "}\nfinally {\n";
883   out.Indent();
884 
885   // returning and cleanup
886   if (!oneway) {
887     out << "_reply.recycle();\n";
888   }
889   out << "_data.recycle();\n";
890 
891   out.Dedent();
892   out << "}\n";  // finally
893 
894   if (!is_void) {
895     out << "return _result;\n";
896   }
897 
898   out.Dedent();
899   out << "}\n";  // method body
900 }
901 
GenerateMethods(const AidlInterface & iface,const AidlMethod & method,Class * interface,std::shared_ptr<StubClass> stubClass,std::shared_ptr<ProxyClass> proxyClass,int index,const AidlTypenames & typenames,const Options & options)902 static void GenerateMethods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
903                             std::shared_ptr<StubClass> stubClass,
904                             std::shared_ptr<ProxyClass> proxyClass, int index,
905                             const AidlTypenames& typenames, const Options& options) {
906   const bool oneway = method.IsOneway();
907 
908   // == the TRANSACT_ constant =============================================
909   string transactCodeName = "TRANSACTION_";
910   transactCodeName += method.GetName();
911 
912   auto transactCode =
913       std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
914   transactCode->value =
915       StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
916   stubClass->elements.push_back(transactCode);
917 
918   // getTransactionName
919   if (options.GenTransactionNames() || options.GenTraces()) {
920     auto c = std::make_shared<Case>(transactCodeName);
921     c->statements->Add(std::make_shared<ReturnStatement>(
922         std::make_shared<StringLiteralExpression>(method.GetName())));
923     stubClass->code_to_method_name_switch->cases.push_back(c);
924   }
925 
926   // == the declaration in the interface ===================================
927   std::shared_ptr<ClassElement> decl;
928   if (method.IsUserDefined()) {
929     decl = GenerateInterfaceMethod(iface, method);
930   } else {
931     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
932       std::ostringstream code;
933       code << "public int " << kGetInterfaceVersion << "() "
934            << "throws android.os.RemoteException;\n";
935       decl = std::make_shared<LiteralClassElement>(code.str());
936     }
937     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
938       std::ostringstream code;
939       code << "public String " << kGetInterfaceHash << "() "
940            << "throws android.os.RemoteException;\n";
941       decl = std::make_shared<LiteralClassElement>(code.str());
942     }
943   }
944   interface->elements.push_back(decl);
945 
946   // == the stub method ====================================================
947   if (method.IsUserDefined()) {
948     bool outline_stub =
949         stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
950     if (outline_stub) {
951       GenerateStubCaseOutline(method, transactCodeName, oneway, stubClass, typenames, options);
952     } else {
953       GenerateStubCase(method, transactCodeName, oneway, stubClass, typenames, options);
954     }
955     if (iface.EnforceExpression() || method.GetType().EnforceExpression()) {
956       GeneratePermissionMethod(iface, method, stubClass);
957     }
958   } else {
959     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
960       auto ifStatement = std::make_shared<IfStatement>();
961       ifStatement->expression = std::make_shared<LiteralExpression>("code == " + transactCodeName);
962       std::ostringstream code;
963       code << "reply.writeNoException();\n"
964            << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
965            << "return true;\n";
966       ifStatement->statements->Add(std::make_shared<LiteralStatement>(code.str()));
967       stubClass->transact_if_statements_meta.push_back(ifStatement);
968     }
969     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
970       auto ifStatement = std::make_shared<IfStatement>();
971       ifStatement->expression = std::make_shared<LiteralExpression>("code == " + transactCodeName);
972       std::ostringstream code;
973       code << "reply.writeNoException();\n"
974            << "reply.writeString(" << kGetInterfaceHash << "());\n"
975            << "return true;\n";
976       ifStatement->statements->Add(std::make_shared<LiteralStatement>(code.str()));
977       stubClass->transact_if_statements_meta.push_back(ifStatement);
978     }
979   }
980 
981   // == the proxy method ===================================================
982   string proxy_code;
983   CodeWriterPtr writer = CodeWriter::ForString(&proxy_code);
984   CodeWriter& code = *writer;
985   if (method.IsUserDefined()) {
986     GenerateProxyMethod(code, iface, method, transactCodeName, oneway, typenames, options);
987   } else {
988     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
989       code << "@Override\n"
990            << "public int " << kGetInterfaceVersion << "()"
991            << " throws "
992            << "android.os.RemoteException {\n"
993            << "  if (mCachedVersion == -1) {\n";
994       if (options.GenRpc()) {
995         code << "    android.os.Parcel data = android.os.Parcel.obtain(asBinder());\n";
996       } else {
997         code << "    android.os.Parcel data = android.os.Parcel.obtain();\n";
998       }
999       code << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
1000            << "    try {\n"
1001            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
1002            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
1003            << "data, reply, 0);\n";
1004       if (iface.IsJavaDefault()) {
1005         code << "      if (!_status) {\n"
1006              << "        if (getDefaultImpl() != null) {\n"
1007              << "          return getDefaultImpl().getInterfaceVersion();\n"
1008              << "        }\n"
1009              << "      }\n";
1010       }
1011       code << "      reply.readException();\n"
1012            << "      mCachedVersion = reply.readInt();\n"
1013            << "    } finally {\n"
1014            << "      reply.recycle();\n"
1015            << "      data.recycle();\n"
1016            << "    }\n"
1017            << "  }\n"
1018            << "  return mCachedVersion;\n"
1019            << "}\n";
1020     }
1021     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1022       code << "@Override\n"
1023            << "public synchronized String " << kGetInterfaceHash << "()"
1024            << " throws "
1025            << "android.os.RemoteException {\n"
1026            << "  if (\"-1\".equals(mCachedHash)) {\n";
1027       if (options.GenRpc()) {
1028         code << "    android.os.Parcel data = android.os.Parcel.obtain(asBinder());\n";
1029       } else {
1030         code << "    android.os.Parcel data = android.os.Parcel.obtain();\n";
1031       }
1032       code << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
1033            << "    try {\n"
1034            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
1035            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
1036            << "data, reply, 0);\n";
1037       if (iface.IsJavaDefault()) {
1038         code << "      if (!_status) {\n"
1039              << "        if (getDefaultImpl() != null) {\n"
1040              << "          return getDefaultImpl().getInterfaceHash();\n"
1041              << "        }\n"
1042              << "      }\n";
1043       }
1044       code << "      reply.readException();\n"
1045            << "      mCachedHash = reply.readString();\n"
1046            << "    } finally {\n"
1047            << "      reply.recycle();\n"
1048            << "      data.recycle();\n"
1049            << "    }\n"
1050            << "  }\n"
1051            << "  return mCachedHash;\n"
1052            << "}\n";
1053     }
1054   }
1055   code.Close();
1056   if (!proxy_code.empty()) {
1057     proxyClass->elements.push_back(std::make_shared<LiteralClassElement>(proxy_code));
1058   }
1059 }
1060 
GenerateInterfaceDescriptors(const Options & options,const AidlInterface * iface,Class * interface,std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)1061 static void GenerateInterfaceDescriptors(const Options& options, const AidlInterface* iface,
1062                                          Class* interface, std::shared_ptr<StubClass> stub,
1063                                          std::shared_ptr<ProxyClass> proxy) {
1064   // the interface descriptor transaction handler
1065   auto ifStatement = std::make_shared<IfStatement>();
1066   ifStatement->expression = std::make_shared<LiteralExpression>("code == INTERFACE_TRANSACTION");
1067   ifStatement->statements->Add(std::make_shared<MethodCall>(
1068       stub->transact_reply, "writeString",
1069       std::vector<std::shared_ptr<Expression>>{stub->GetTransactDescriptor(nullptr)}));
1070   ifStatement->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
1071   stub->transact_if_statements_meta.push_back(ifStatement);
1072 
1073   // and the proxy-side method returning the descriptor directly
1074   auto getDesc = std::make_shared<Method>();
1075   getDesc->modifiers = PUBLIC;
1076   getDesc->returnType = "java.lang.String";
1077   getDesc->name = "getInterfaceDescriptor";
1078   getDesc->statements = std::make_shared<StatementBlock>();
1079   getDesc->statements->Add(
1080       std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
1081   proxy->elements.push_back(getDesc);
1082 
1083   // add the DESCRIPTOR field to the interface class
1084   Class* classToAddDescriptor = interface;
1085   static std::set<std::string> greylist = {
1086 #include "hiddenapi-greylist"
1087   };
1088   if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
1089     // For app compatibility, we keep DESCRIPTOR to the stub class for
1090     // the interfaces that are in the greylist.
1091     classToAddDescriptor = stub.get();
1092   }
1093   auto descriptor = std::make_shared<Field>(
1094       STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
1095   descriptor->comment = "/** @hide */";
1096   std::string name = iface->GetDescriptor();
1097 
1098   // TODO(b/242862858): avoid differentiating behahavior. This is currently blocked
1099   // to fix because of a metalava lint which disallows running code to generate
1100   // static fields.
1101   if (options.IsStructured()) {
1102     // mangle the interface name at build time and demangle it at runtime, to avoid
1103     // being renamed by jarjar. See b/153843174
1104     std::replace(name.begin(), name.end(), '.', '$');
1105     descriptor->value = "\"" + name + "\".replace('$', '.')";
1106   } else {
1107     descriptor->value = "\"" + name + "\"";
1108   }
1109   classToAddDescriptor->elements.push_back(descriptor);
1110 }
1111 
1112 // Check whether (some) methods in this interface should be "outlined," that
1113 // is, have specific onTransact methods for certain cases. Set up StubClass
1114 // metadata accordingly.
1115 //
1116 // Outlining will be enabled if the interface has more than outline_threshold
1117 // methods. In that case, the methods are sorted by number of arguments
1118 // (so that more "complex" methods come later), and the first non_outline_count
1119 // number of methods not outlined (are kept in the onTransact() method).
1120 //
1121 // Requirements: non_outline_count <= outline_threshold.
ComputeOutlineMethods(const AidlInterface * iface,const std::shared_ptr<StubClass> stub,size_t outline_threshold,size_t non_outline_count)1122 static void ComputeOutlineMethods(const AidlInterface* iface, const std::shared_ptr<StubClass> stub,
1123                                   size_t outline_threshold, size_t non_outline_count) {
1124   AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
1125   // We'll outline (create sub methods) if there are more than min_methods
1126   // cases.
1127   stub->transact_outline = iface->GetMethods().size() > outline_threshold;
1128   if (stub->transact_outline) {
1129     stub->all_method_count = iface->GetMethods().size();
1130     std::vector<const AidlMethod*> methods;
1131     methods.reserve(iface->GetMethods().size());
1132     for (const auto& ptr : iface->GetMethods()) {
1133       methods.push_back(ptr.get());
1134     }
1135 
1136     std::stable_sort(
1137         methods.begin(),
1138         methods.end(),
1139         [](const AidlMethod* m1, const AidlMethod* m2) {
1140           return m1->GetArguments().size() < m2->GetArguments().size();
1141         });
1142 
1143     stub->outline_methods.insert(methods.begin() + non_outline_count,
1144                                  methods.end());
1145   }
1146 }
1147 
GenerateDefaultImplMethod(const AidlMethod & method)1148 static shared_ptr<ClassElement> GenerateDefaultImplMethod(const AidlMethod& method) {
1149   auto default_method = std::make_shared<Method>();
1150   default_method->comment = GenerateComments(method);
1151   default_method->modifiers = PUBLIC | OVERRIDE;
1152   default_method->returnType = JavaSignatureOf(method.GetType());
1153   default_method->name = method.GetName();
1154   default_method->statements = std::make_shared<StatementBlock>();
1155   for (const auto& arg : method.GetArguments()) {
1156     default_method->parameters.push_back(
1157         std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
1158   }
1159   default_method->exceptions.push_back("android.os.RemoteException");
1160 
1161   if (method.GetType().GetName() != "void") {
1162     const string& defaultValue = DefaultJavaValueOf(method.GetType());
1163     default_method->statements->Add(
1164         std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
1165   }
1166   return default_method;
1167 }
1168 
GenerateDefaultImplClass(const AidlInterface & iface,const Options & options)1169 static shared_ptr<Class> GenerateDefaultImplClass(const AidlInterface& iface,
1170                                                   const Options& options) {
1171   auto default_class = std::make_shared<Class>();
1172   default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1173   default_class->modifiers = PUBLIC | STATIC;
1174   default_class->what = Class::CLASS;
1175   default_class->type = iface.GetCanonicalName() + ".Default";
1176   default_class->interfaces.emplace_back(iface.GetCanonicalName());
1177 
1178   for (const auto& m : iface.GetMethods()) {
1179     if (m->IsUserDefined()) {
1180       default_class->elements.emplace_back(GenerateDefaultImplMethod(*m));
1181     } else {
1182       // These are called only when the remote side does not implement these
1183       // methods, which is normally impossible, because these methods are
1184       // automatically declared in the interface class and not implementing
1185       // them on the remote side causes a compilation error. But if the remote
1186       // side somehow managed to not implement it, that's an error and we
1187       // report the case by returning an invalid value here.
1188       if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1189         std::ostringstream code;
1190         code << "@Override\n"
1191              << "public int " << kGetInterfaceVersion << "() {\n"
1192              << "  return 0;\n"
1193              << "}\n";
1194         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1195       }
1196       if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1197         std::ostringstream code;
1198         code << "@Override\n"
1199              << "public String " << kGetInterfaceHash << "() {\n"
1200              << "  return \"\";\n"
1201              << "}\n";
1202         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1203       }
1204     }
1205   }
1206 
1207   default_class->elements.emplace_back(
1208       std::make_shared<LiteralClassElement>("@Override\n"
1209                                             "public android.os.IBinder asBinder() {\n"
1210                                             "  return null;\n"
1211                                             "}\n"));
1212 
1213   return default_class;
1214 }
1215 
GenerateDelegatorMethod(const AidlMethod & method)1216 static shared_ptr<ClassElement> GenerateDelegatorMethod(const AidlMethod& method) {
1217   auto delegator_method = std::make_shared<Method>();
1218   delegator_method->comment = GenerateComments(method);
1219   delegator_method->modifiers = PUBLIC | OVERRIDE;
1220   delegator_method->returnType = JavaSignatureOf(method.GetType());
1221   delegator_method->name = method.GetName();
1222   delegator_method->statements = std::make_shared<StatementBlock>();
1223   std::vector<std::string> argNames;
1224   for (const auto& arg : method.GetArguments()) {
1225     delegator_method->parameters.push_back(
1226         std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
1227     argNames.push_back(arg->GetName());
1228   }
1229   delegator_method->exceptions.push_back("android.os.RemoteException");
1230 
1231   std::string return_str;
1232   if (method.GetType().GetName() != "void") {
1233     return_str = "return ";
1234   }
1235   delegator_method->statements->Add(
1236       std::make_shared<LiteralStatement>(return_str + "mImpl." + method.GetName() + "(" +
1237                                          android::base::Join(argNames, ",") + ");\n"));
1238   return delegator_method;
1239 }
1240 
GenerateDelegatorClass(const AidlInterface & iface,const Options & options)1241 static shared_ptr<Class> GenerateDelegatorClass(const AidlInterface& iface,
1242                                                 const Options& options) {
1243   auto delegator_class = std::make_shared<Class>();
1244   delegator_class->comment = "/** Delegator implementation for " + iface.GetName() + ". */";
1245   delegator_class->modifiers = PUBLIC | STATIC;
1246   delegator_class->what = Class::CLASS;
1247   delegator_class->type = iface.GetCanonicalName() + ".Delegator";
1248   delegator_class->extends = iface.GetCanonicalName() + ".Stub";
1249 
1250   // constructor
1251   delegator_class->elements.emplace_back(
1252       std::make_shared<LiteralClassElement>("public Delegator(" + iface.GetCanonicalName() +
1253                                             " impl) {\n"
1254                                             "  this.mImpl = impl;\n"
1255                                             "}\n"));
1256   // meta methods
1257   if (!options.Hash().empty()) {
1258     delegator_class->elements.emplace_back(
1259         std::make_shared<LiteralClassElement>("@Override\n"
1260                                               "public String " +
1261                                               kGetInterfaceHash +
1262                                               "() throws android.os.RemoteException {\n"
1263                                               "  return mImpl." +
1264                                               kGetInterfaceHash +
1265                                               "();\n"
1266                                               "}\n"));
1267   }
1268   if (options.Version() > 0) {
1269     delegator_class->elements.emplace_back(
1270         std::make_shared<LiteralClassElement>("@Override\n"
1271                                               "public int " +
1272                                               kGetInterfaceVersion +
1273                                               "() throws android.os.RemoteException {\n"
1274                                               "  int implVer = mImpl." +
1275                                               kGetInterfaceVersion +
1276                                               "();\n"
1277                                               "  return VERSION < implVer ? VERSION : implVer;\n"
1278                                               "}\n"));
1279   }
1280 
1281   // user defined methods
1282   for (const auto& m : iface.GetMethods()) {
1283     if (m->IsUserDefined()) {
1284       delegator_class->elements.emplace_back(GenerateDelegatorMethod(*m));
1285     }
1286   }
1287 
1288   delegator_class->elements.emplace_back(
1289       std::make_shared<LiteralClassElement>(iface.GetCanonicalName() + " mImpl;\n"));
1290 
1291   return delegator_class;
1292 }
1293 
GenerateMaxTransactionId(int max_transaction_id)1294 static shared_ptr<ClassElement> GenerateMaxTransactionId(int max_transaction_id) {
1295   auto getMaxTransactionId = std::make_shared<Method>();
1296   getMaxTransactionId->comment = "/** @hide */";
1297   getMaxTransactionId->modifiers = PUBLIC;
1298   getMaxTransactionId->returnType = "int";
1299   getMaxTransactionId->name = "getMaxTransactionId";
1300   getMaxTransactionId->statements = std::make_shared<StatementBlock>();
1301   getMaxTransactionId->statements->Add(std::make_shared<ReturnStatement>(
1302       std::make_shared<LiteralExpression>(std::to_string(max_transaction_id))));
1303   return getMaxTransactionId;
1304 }
1305 
GenerateInterfaceClass(const AidlInterface * iface,const AidlTypenames & typenames,const Options & options)1306 std::unique_ptr<Class> GenerateInterfaceClass(const AidlInterface* iface,
1307                                               const AidlTypenames& typenames,
1308                                               const Options& options) {
1309   // the interface class
1310   auto interface = std::make_unique<Class>();
1311   interface->comment = GenerateComments(*iface);
1312   interface->modifiers = PUBLIC;
1313   interface->what = Class::INTERFACE;
1314   interface->type = iface->GetCanonicalName();
1315   interface->interfaces.push_back("android.os.IInterface");
1316   interface->annotations = JavaAnnotationsFor(*iface);
1317 
1318   if (options.Version()) {
1319     std::ostringstream code;
1320     code << "/**\n"
1321          << " * The version of this interface that the caller is built against.\n"
1322          << " * This might be different from what {@link #getInterfaceVersion()\n"
1323          << " * getInterfaceVersion} returns as that is the version of the interface\n"
1324          << " * that the remote object is implementing.\n"
1325          << " */\n"
1326          << "public static final int VERSION = ";
1327     if (options.IsLatestUnfrozenVersion()) {
1328       code << "true ? " << options.PreviousVersion() << " : " << options.Version() << ";\n";
1329     } else {
1330       code << options.Version() << ";\n";
1331     }
1332 
1333     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1334   }
1335   if (!options.Hash().empty() || options.IsLatestUnfrozenVersion()) {
1336     std::ostringstream code;
1337     if (options.IsLatestUnfrozenVersion()) {
1338       code << "public static final String HASH = \"" << options.PreviousHash() << "\";\n";
1339     } else {
1340       code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1341     }
1342 
1343     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1344   }
1345 
1346   // the default impl class
1347   auto default_impl = GenerateDefaultImplClass(*iface, options);
1348   interface->elements.emplace_back(default_impl);
1349 
1350   // the delegator class
1351   if (iface->IsJavaDelegator()) {
1352     auto delegator = GenerateDelegatorClass(*iface, options);
1353     interface->elements.emplace_back(delegator);
1354   }
1355 
1356   // the stub inner class
1357   auto stub = std::make_shared<StubClass>(iface, options);
1358   interface->elements.push_back(stub);
1359 
1360   ComputeOutlineMethods(iface, stub, options.onTransact_outline_threshold_,
1361                         options.onTransact_non_outline_count_);
1362 
1363   // the proxy inner class
1364   auto proxy = std::make_shared<ProxyClass>(iface, options);
1365   stub->elements.push_back(proxy);
1366 
1367   // stub and proxy support for getInterfaceDescriptor()
1368   GenerateInterfaceDescriptors(options, iface, interface.get(), stub, proxy);
1369 
1370   // all the declared constants of the interface
1371   string constants;
1372   GenerateConstantDeclarations(*CodeWriter::ForString(&constants), *iface);
1373   interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
1374 
1375   // all the declared methods of the interface
1376   int max_transaction_id = 0;
1377   for (const auto& item : iface->GetMethods()) {
1378     GenerateMethods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames, options);
1379     max_transaction_id = std::max(max_transaction_id, item->GetId());
1380   }
1381 
1382   // getMaxTransactionId
1383   if (options.GenTransactionNames() || options.GenTraces()) {
1384     stub->elements.push_back(GenerateMaxTransactionId(max_transaction_id));
1385   }
1386 
1387   // all the nested types
1388   string code;
1389   auto writer = CodeWriter::ForString(&code);
1390   for (const auto& nested : iface->GetNestedTypes()) {
1391     GenerateClass(*writer, *nested, typenames, options);
1392   }
1393   GenerateParcelHelpers(*writer, *iface, typenames, options);
1394   writer->Close();
1395   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
1396 
1397   if (iface->IsJavaDefault()) {
1398     // additional static methods for the default impl set/get to the
1399     // stub class. Can't add them to the interface as the generated java files
1400     // may be compiled with Java < 1.7 where static interface method isn't
1401     // supported.
1402     // TODO(b/111417145) make this conditional depending on the Java language
1403     // version requested
1404     const string i_name = iface->GetCanonicalName();
1405     stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
1406         StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1407                      "  // Only one user of this interface can use this function\n"
1408                      "  // at a time. This is a heuristic to detect if two different\n"
1409                      "  // users in the same process use this function.\n"
1410                      "  if (Stub.Proxy.sDefaultImpl != null) {\n"
1411                      "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1412                      "  }\n"
1413                      "  if (impl != null) {\n"
1414                      "    Stub.Proxy.sDefaultImpl = impl;\n"
1415                      "    return true;\n"
1416                      "  }\n"
1417                      "  return false;\n"
1418                      "}\n",
1419                      i_name.c_str())));
1420     stub->elements.emplace_back(
1421         std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1422                                                            "  return Stub.Proxy.sDefaultImpl;\n"
1423                                                            "}\n",
1424                                                            i_name.c_str())));
1425 
1426     // the static field is defined in the proxy class, not in the interface class
1427     // because all fields in an interface class are by default final.
1428     proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
1429         StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
1430   }
1431 
1432   stub->Finish();
1433 
1434   return interface;
1435 }
1436 
1437 }  // namespace java
1438 }  // namespace aidl
1439 }  // namespace android
1440