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 and 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           // if impossibly large array requested, return false
613           (*writer) << "if (" << var_length << " > 1000000) {\n";
614           (*writer) << "  throw new android.os.BadParcelableException(\"Array too large: \" + "
615                     << var_length << ");\n";
616           (*writer) << "} else if (" << var_length << " < 0) {\n";
617           (*writer) << "  " << v->name << " = null;\n";
618           (*writer) << "} else {\n";
619           (*writer) << "  " << v->name << " = new " << java_type << "[" << var_length << "];\n";
620           (*writer) << "}\n";
621         } else if (arg->GetType().IsFixedSizeArray()) {
622           // fixed-size array can be created with a known size
623           string dimensions;
624           for (auto dim : arg->GetType().GetFixedSizeArrayDimensions()) {
625             dimensions += "[" + std::to_string(dim) + "]";
626           }
627           (*writer) << v->name << " = new " << java_type << dimensions << ";\n";
628         } else {
629           // otherwise, create a new instance with a default constructor
630           (*writer) << v->name << " = new " << java_type << "();\n";
631         }
632       }
633       writer->Close();
634       statements->Add(std::make_shared<LiteralStatement>(code));
635 
636       realCall->arguments.push_back(v);
637     }
638   }
639 
640   // EOF check
641   if (!method.GetArguments().empty() && options.GetMinSdkVersion() > 32u) {
642     statements->Add(std::make_shared<MethodCall>(transact_data, "enforceNoDataAvail"));
643   }
644 
645   // the real call
646   if (method.GetType().GetName() == "void") {
647     statements->Add(realCall);
648 
649     if (!oneway) {
650       // report that there were no exceptions
651       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
652       statements->Add(ex);
653     }
654   } else {
655     auto _result = std::make_shared<Variable>(JavaSignatureOf(method.GetType()), "_result");
656     statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
657 
658     if (!oneway) {
659       // report that there were no exceptions
660       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
661       statements->Add(ex);
662     }
663 
664     // marshall the return value
665     GenerateWriteToParcel(statements, typenames, method.GetType(), transact_reply->name,
666                           _result->name, options.GetMinSdkVersion(), /*is_return_value=*/true);
667   }
668 
669   // out parameters
670   int i = 0;
671   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
672     std::shared_ptr<Variable> v = stubArgs.Get(i++);
673     if (arg->GetDirection() & AidlArgument::OUT_DIR) {
674       GenerateWriteToParcel(statements, typenames, arg->GetType(), transact_reply->name, v->name,
675                             options.GetMinSdkVersion(), /*is_return_value=*/true);
676     }
677   }
678 }
679 
GenerateStubCase(const AidlMethod & method,const std::string & transactCodeName,bool oneway,const std::shared_ptr<StubClass> & stubClass,const AidlTypenames & typenames,const Options & options)680 static void GenerateStubCase(const AidlMethod& method, const std::string& transactCodeName,
681                              bool oneway, const std::shared_ptr<StubClass>& stubClass,
682                              const AidlTypenames& typenames, const Options& options) {
683   auto c = std::make_shared<Case>(transactCodeName);
684 
685   GenerateStubCode(method, oneway, stubClass->transact_data, stubClass->transact_reply, typenames,
686                    c->statements, options);
687   c->statements->Add(std::make_shared<BreakStatement>());
688 
689   stubClass->transact_switch_user->cases.push_back(c);
690 }
691 
GenerateStubCaseOutline(const AidlMethod & method,const std::string & transactCodeName,bool oneway,const std::shared_ptr<StubClass> & stubClass,const AidlTypenames & typenames,const Options & options)692 static void GenerateStubCaseOutline(const AidlMethod& method, const std::string& transactCodeName,
693                                     bool oneway, const std::shared_ptr<StubClass>& stubClass,
694                                     const AidlTypenames& typenames, const Options& options) {
695   std::string outline_name = "onTransact$" + method.GetName() + "$";
696   // Generate an "outlined" method with the actual code.
697   {
698     auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
699     auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
700     auto onTransact_case = std::make_shared<Method>();
701     onTransact_case->modifiers = PRIVATE;
702     onTransact_case->returnType = "boolean";
703     onTransact_case->name = outline_name;
704     onTransact_case->parameters.push_back(transact_data);
705     onTransact_case->parameters.push_back(transact_reply);
706     onTransact_case->statements = std::make_shared<StatementBlock>();
707     onTransact_case->exceptions.push_back("android.os.RemoteException");
708     stubClass->elements.push_back(onTransact_case);
709 
710     GenerateStubCode(method, oneway, transact_data, transact_reply, typenames,
711                      onTransact_case->statements, options);
712     onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
713   }
714 
715   // Generate the case dispatch.
716   {
717     auto c = std::make_shared<Case>(transactCodeName);
718 
719     auto helper_call =
720         std::make_shared<MethodCall>(THIS_VALUE, outline_name,
721                                      std::vector<std::shared_ptr<Expression>>{
722                                          stubClass->transact_data, stubClass->transact_reply});
723     c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
724 
725     stubClass->transact_switch_user->cases.push_back(c);
726   }
727 }
728 
729 template <typename Formatter>
ArgList(const AidlMethod & method,Formatter formatter)730 static std::string ArgList(const AidlMethod& method, Formatter formatter) {
731   vector<string> args;
732   for (const auto& arg : method.GetArguments()) {
733     args.push_back(std::invoke(formatter, *arg));
734   }
735   return Join(args, ", ");
736 }
737 
FormatArgForDecl(const AidlArgument & arg)738 static std::string FormatArgForDecl(const AidlArgument& arg) {
739   return JavaSignatureOf(arg.GetType()) + " " + arg.GetName();
740 }
741 
GenerateProxyMethod(CodeWriter & out,const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,const AidlTypenames & typenames,const Options & options)742 static void GenerateProxyMethod(CodeWriter& out, const AidlInterface& iface,
743                                 const AidlMethod& method, const std::string& transactCodeName,
744                                 bool oneway, const AidlTypenames& typenames,
745                                 const Options& options) {
746   bool is_void = method.GetType().GetName() == "void";
747 
748   out << GenerateComments(method);
749   out << "@Override public " << JavaSignatureOf(method.GetType()) << " " << method.GetName() << "("
750       << ArgList(method, FormatArgForDecl) << ") throws android.os.RemoteException\n{\n";
751   out.Indent();
752 
753   if (method.IsNew() && ShouldForceDowngradeFor(CommunicationSide::WRITE)) {
754     out << "if (true) {\n";
755     out << "  throw new android.os.RemoteException(\"Method " + method.GetName() +
756                " is unimplemented.\");\n";
757     out << "}\n";
758   }
759 
760   // the parcels
761   if (options.GenRpc()) {
762     out << "android.os.Parcel _data = android.os.Parcel.obtain(asBinder());\n";
763   } else {
764     out << "android.os.Parcel _data = android.os.Parcel.obtain();\n";
765   }
766 
767   if (iface.IsSensitiveData()) {
768     out << "_data.markSensitive();\n";
769   }
770 
771   if (!oneway) {
772     out << "android.os.Parcel _reply = android.os.Parcel.obtain();\n";
773   }
774 
775   // the return value
776   if (!is_void) {
777     out << JavaSignatureOf(method.GetType()) << " _result;\n";
778   }
779 
780   out << "try {\n";
781   out.Indent();
782 
783   // the interface identifier token: the DESCRIPTOR constant, marshalled as a
784   // string
785   out << "_data.writeInterfaceToken(DESCRIPTOR);\n";
786 
787   // the parameters
788   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
789     AidlArgument::Direction dir = arg->GetDirection();
790     if (dir == AidlArgument::OUT_DIR && arg->GetType().IsDynamicArray()) {
791       // In Java we pass a pre-allocated array for an 'out' argument. For transaction,
792       // we pass the size of the array so that the remote can allocate the array with the same size.
793       out << "_data.writeInt(" << arg->GetName() << ".length);\n";
794     } else if (dir & AidlArgument::IN_DIR) {
795       GenerateWriteToParcel(out, typenames, arg->GetType(), "_data", arg->GetName(),
796                             options.GetMinSdkVersion(), /*is_return_value=*/false);
797     }
798   }
799 
800   std::vector<std::string> flags;
801   if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
802   if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");
803 
804   // the transact call
805   out << "boolean _status = mRemote.transact(Stub." << transactCodeName << ", _data, "
806       << (oneway ? "null" : "_reply") << ", " << (flags.empty() ? "0" : Join(flags, " | "))
807       << ");\n";
808 
809   // TODO(b/151102494): annotation is applied on the return type
810   if (method.GetType().IsPropagateAllowBlocking() && !oneway) {
811     if (options.GetMinSdkVersion() < JAVA_PROPAGATE_VERSION) {
812       out << "if (android.os.Build.VERSION.SDK_INT >= " + std::to_string(JAVA_PROPAGATE_VERSION) +
813                  ") { _reply.setPropagateAllowBlocking(); }\n";
814     } else {
815       out << "_reply.setPropagateAllowBlocking();\n";
816     }
817   }
818 
819   // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
820   // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
821   // is versioned. We can't throw the exception for unversioned interface because that would be an
822   // app breaking change.
823   if (iface.IsJavaDefault() || options.Version() > 0) {
824     out << "if (!_status) {\n";
825     out.Indent();
826 
827     if (iface.IsJavaDefault()) {
828       out << "if (getDefaultImpl() != null) {\n";
829       out.Indent();
830       if (is_void) {
831         out << "getDefaultImpl()." << method.GetName() << "("
832             << ArgList(method, &AidlArgument::GetName) << ");\n";
833         out << "return;\n";
834       } else {
835         out << "return getDefaultImpl()." << method.GetName() << "("
836             << ArgList(method, &AidlArgument::GetName) << ");\n";
837       }
838       out.Dedent();
839       out << "}\n";
840     }
841 
842     // TODO(b/274144762): we shouldn't have different behavior for versioned interfaces
843     // also this set to false for all exceptions, not just unimplemented methods.
844     if (options.Version() > 0) {
845       out << "throw new android.os.RemoteException(\"Method " << method.GetName()
846           << " is unimplemented.\");\n";
847     }
848 
849     out.Dedent();
850     out << "}\n";
851   }
852 
853   if (!oneway) {
854     // keep this across return value and arguments in order to create the
855     // classloader at most once.
856     bool is_classloader_created = false;
857 
858     // throw back exceptions.
859     out << "_reply.readException();\n";
860 
861     if (!is_void) {
862       CreateFromParcelFor(CodeGeneratorContext{.writer = out,
863                                                .typenames = typenames,
864                                                .type = method.GetType(),
865                                                .parcel = "_reply",
866                                                .var = "_result",
867                                                .min_sdk_version = options.GetMinSdkVersion(),
868                                                .is_classloader_created = &is_classloader_created});
869     }
870 
871     // the out/inout parameters
872     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
873       if (arg->GetDirection() & AidlArgument::OUT_DIR) {
874         ReadFromParcelFor(CodeGeneratorContext{.writer = out,
875                                                .typenames = typenames,
876                                                .type = arg->GetType(),
877                                                .parcel = "_reply",
878                                                .var = arg->GetName(),
879                                                .min_sdk_version = options.GetMinSdkVersion(),
880                                                .is_classloader_created = &is_classloader_created});
881       }
882     }
883   }
884 
885   out.Dedent();
886   out << "}\nfinally {\n";
887   out.Indent();
888 
889   // returning and cleanup
890   if (!oneway) {
891     out << "_reply.recycle();\n";
892   }
893   out << "_data.recycle();\n";
894 
895   out.Dedent();
896   out << "}\n";  // finally
897 
898   if (!is_void) {
899     out << "return _result;\n";
900   }
901 
902   out.Dedent();
903   out << "}\n";  // method body
904 }
905 
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)906 static void GenerateMethods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
907                             std::shared_ptr<StubClass> stubClass,
908                             std::shared_ptr<ProxyClass> proxyClass, int index,
909                             const AidlTypenames& typenames, const Options& options) {
910   const bool oneway = method.IsOneway();
911 
912   // == the TRANSACT_ constant =============================================
913   string transactCodeName = "TRANSACTION_";
914   transactCodeName += method.GetName();
915 
916   auto transactCode =
917       std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
918   transactCode->value =
919       StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
920   stubClass->elements.push_back(transactCode);
921 
922   // getTransactionName
923   if (options.GenTransactionNames() || options.GenTraces()) {
924     auto c = std::make_shared<Case>(transactCodeName);
925     c->statements->Add(std::make_shared<ReturnStatement>(
926         std::make_shared<StringLiteralExpression>(method.GetName())));
927     stubClass->code_to_method_name_switch->cases.push_back(c);
928   }
929 
930   // == the declaration in the interface ===================================
931   std::shared_ptr<ClassElement> decl;
932   if (method.IsUserDefined()) {
933     decl = GenerateInterfaceMethod(iface, method);
934   } else {
935     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
936       std::ostringstream code;
937       code << "public int " << kGetInterfaceVersion << "() "
938            << "throws android.os.RemoteException;\n";
939       decl = std::make_shared<LiteralClassElement>(code.str());
940     }
941     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
942       std::ostringstream code;
943       code << "public String " << kGetInterfaceHash << "() "
944            << "throws android.os.RemoteException;\n";
945       decl = std::make_shared<LiteralClassElement>(code.str());
946     }
947   }
948   interface->elements.push_back(decl);
949 
950   // == the stub method ====================================================
951   if (method.IsUserDefined()) {
952     bool outline_stub =
953         stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
954     if (outline_stub) {
955       GenerateStubCaseOutline(method, transactCodeName, oneway, stubClass, typenames, options);
956     } else {
957       GenerateStubCase(method, transactCodeName, oneway, stubClass, typenames, options);
958     }
959     if (iface.EnforceExpression() || method.GetType().EnforceExpression()) {
960       GeneratePermissionMethod(iface, method, stubClass);
961     }
962   } else {
963     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
964       auto ifStatement = std::make_shared<IfStatement>();
965       ifStatement->expression = std::make_shared<LiteralExpression>("code == " + transactCodeName);
966       std::ostringstream code;
967       code << "reply.writeNoException();\n"
968            << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
969            << "return true;\n";
970       ifStatement->statements->Add(std::make_shared<LiteralStatement>(code.str()));
971       stubClass->transact_if_statements_meta.push_back(ifStatement);
972     }
973     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
974       auto ifStatement = std::make_shared<IfStatement>();
975       ifStatement->expression = std::make_shared<LiteralExpression>("code == " + transactCodeName);
976       std::ostringstream code;
977       code << "reply.writeNoException();\n"
978            << "reply.writeString(" << kGetInterfaceHash << "());\n"
979            << "return true;\n";
980       ifStatement->statements->Add(std::make_shared<LiteralStatement>(code.str()));
981       stubClass->transact_if_statements_meta.push_back(ifStatement);
982     }
983   }
984 
985   // == the proxy method ===================================================
986   string proxy_code;
987   CodeWriterPtr writer = CodeWriter::ForString(&proxy_code);
988   CodeWriter& code = *writer;
989   if (method.IsUserDefined()) {
990     GenerateProxyMethod(code, iface, method, transactCodeName, oneway, typenames, options);
991   } else {
992     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
993       code << "@Override\n"
994            << "public int " << kGetInterfaceVersion << "()"
995            << " throws "
996            << "android.os.RemoteException {\n"
997            << "  if (mCachedVersion == -1) {\n";
998       if (options.GenRpc()) {
999         code << "    android.os.Parcel data = android.os.Parcel.obtain(asBinder());\n";
1000       } else {
1001         code << "    android.os.Parcel data = android.os.Parcel.obtain();\n";
1002       }
1003       code << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
1004            << "    try {\n"
1005            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
1006            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
1007            << "data, reply, 0);\n";
1008       if (iface.IsJavaDefault()) {
1009         code << "      if (!_status) {\n"
1010              << "        if (getDefaultImpl() != null) {\n"
1011              << "          return getDefaultImpl().getInterfaceVersion();\n"
1012              << "        }\n"
1013              << "      }\n";
1014       }
1015       code << "      reply.readException();\n"
1016            << "      mCachedVersion = reply.readInt();\n"
1017            << "    } finally {\n"
1018            << "      reply.recycle();\n"
1019            << "      data.recycle();\n"
1020            << "    }\n"
1021            << "  }\n"
1022            << "  return mCachedVersion;\n"
1023            << "}\n";
1024     }
1025     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1026       code << "@Override\n"
1027            << "public synchronized String " << kGetInterfaceHash << "()"
1028            << " throws "
1029            << "android.os.RemoteException {\n"
1030            << "  if (\"-1\".equals(mCachedHash)) {\n";
1031       if (options.GenRpc()) {
1032         code << "    android.os.Parcel data = android.os.Parcel.obtain(asBinder());\n";
1033       } else {
1034         code << "    android.os.Parcel data = android.os.Parcel.obtain();\n";
1035       }
1036       code << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
1037            << "    try {\n"
1038            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
1039            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
1040            << "data, reply, 0);\n";
1041       if (iface.IsJavaDefault()) {
1042         code << "      if (!_status) {\n"
1043              << "        if (getDefaultImpl() != null) {\n"
1044              << "          return getDefaultImpl().getInterfaceHash();\n"
1045              << "        }\n"
1046              << "      }\n";
1047       }
1048       code << "      reply.readException();\n"
1049            << "      mCachedHash = reply.readString();\n"
1050            << "    } finally {\n"
1051            << "      reply.recycle();\n"
1052            << "      data.recycle();\n"
1053            << "    }\n"
1054            << "  }\n"
1055            << "  return mCachedHash;\n"
1056            << "}\n";
1057     }
1058   }
1059   code.Close();
1060   if (!proxy_code.empty()) {
1061     proxyClass->elements.push_back(std::make_shared<LiteralClassElement>(proxy_code));
1062   }
1063 }
1064 
GenerateInterfaceDescriptors(const Options & options,const AidlInterface * iface,Class * interface,std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)1065 static void GenerateInterfaceDescriptors(const Options& options, const AidlInterface* iface,
1066                                          Class* interface, std::shared_ptr<StubClass> stub,
1067                                          std::shared_ptr<ProxyClass> proxy) {
1068   // the interface descriptor transaction handler
1069   auto ifStatement = std::make_shared<IfStatement>();
1070   ifStatement->expression = std::make_shared<LiteralExpression>("code == INTERFACE_TRANSACTION");
1071   ifStatement->statements->Add(std::make_shared<MethodCall>(
1072       stub->transact_reply, "writeString",
1073       std::vector<std::shared_ptr<Expression>>{stub->GetTransactDescriptor(nullptr)}));
1074   ifStatement->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
1075   stub->transact_if_statements_meta.push_back(ifStatement);
1076 
1077   // and the proxy-side method returning the descriptor directly
1078   auto getDesc = std::make_shared<Method>();
1079   getDesc->modifiers = PUBLIC;
1080   getDesc->returnType = "java.lang.String";
1081   getDesc->name = "getInterfaceDescriptor";
1082   getDesc->statements = std::make_shared<StatementBlock>();
1083   getDesc->statements->Add(
1084       std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
1085   proxy->elements.push_back(getDesc);
1086 
1087   // add the DESCRIPTOR field to the interface class
1088   Class* classToAddDescriptor = interface;
1089   static std::set<std::string> greylist = {
1090 #include "hiddenapi-greylist"
1091   };
1092   if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
1093     // For app compatibility, we keep DESCRIPTOR to the stub class for
1094     // the interfaces that are in the greylist.
1095     classToAddDescriptor = stub.get();
1096   }
1097   auto descriptor = std::make_shared<Field>(
1098       STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
1099   descriptor->comment = "/** @hide */";
1100   std::string name = iface->GetDescriptor();
1101 
1102   // TODO(b/242862858): avoid differentiating behahavior. This is currently blocked
1103   // to fix because of a metalava lint which disallows running code to generate
1104   // static fields.
1105   if (options.IsStructured()) {
1106     // mangle the interface name at build time and demangle it at runtime, to avoid
1107     // being renamed by jarjar. See b/153843174
1108     std::replace(name.begin(), name.end(), '.', '$');
1109     descriptor->value = "\"" + name + "\".replace('$', '.')";
1110   } else {
1111     descriptor->value = "\"" + name + "\"";
1112   }
1113   classToAddDescriptor->elements.push_back(descriptor);
1114 }
1115 
1116 // Check whether (some) methods in this interface should be "outlined," that
1117 // is, have specific onTransact methods for certain cases. Set up StubClass
1118 // metadata accordingly.
1119 //
1120 // Outlining will be enabled if the interface has more than outline_threshold
1121 // methods. In that case, the methods are sorted by number of arguments
1122 // (so that more "complex" methods come later), and the first non_outline_count
1123 // number of methods not outlined (are kept in the onTransact() method).
1124 //
1125 // 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)1126 static void ComputeOutlineMethods(const AidlInterface* iface, const std::shared_ptr<StubClass> stub,
1127                                   size_t outline_threshold, size_t non_outline_count) {
1128   AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
1129   // We'll outline (create sub methods) if there are more than min_methods
1130   // cases.
1131   stub->transact_outline = iface->GetMethods().size() > outline_threshold;
1132   if (stub->transact_outline) {
1133     stub->all_method_count = iface->GetMethods().size();
1134     std::vector<const AidlMethod*> methods;
1135     methods.reserve(iface->GetMethods().size());
1136     for (const auto& ptr : iface->GetMethods()) {
1137       methods.push_back(ptr.get());
1138     }
1139 
1140     std::stable_sort(
1141         methods.begin(),
1142         methods.end(),
1143         [](const AidlMethod* m1, const AidlMethod* m2) {
1144           return m1->GetArguments().size() < m2->GetArguments().size();
1145         });
1146 
1147     stub->outline_methods.insert(methods.begin() + non_outline_count,
1148                                  methods.end());
1149   }
1150 }
1151 
GenerateDefaultImplMethod(const AidlMethod & method)1152 static shared_ptr<ClassElement> GenerateDefaultImplMethod(const AidlMethod& method) {
1153   auto default_method = std::make_shared<Method>();
1154   default_method->comment = GenerateComments(method);
1155   default_method->modifiers = PUBLIC | OVERRIDE;
1156   default_method->returnType = JavaSignatureOf(method.GetType());
1157   default_method->name = method.GetName();
1158   default_method->statements = std::make_shared<StatementBlock>();
1159   for (const auto& arg : method.GetArguments()) {
1160     default_method->parameters.push_back(
1161         std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
1162   }
1163   default_method->exceptions.push_back("android.os.RemoteException");
1164 
1165   if (method.GetType().GetName() != "void") {
1166     const string& defaultValue = DefaultJavaValueOf(method.GetType());
1167     default_method->statements->Add(
1168         std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
1169   }
1170   return default_method;
1171 }
1172 
GenerateDefaultImplClass(const AidlInterface & iface,const Options & options)1173 static shared_ptr<Class> GenerateDefaultImplClass(const AidlInterface& iface,
1174                                                   const Options& options) {
1175   auto default_class = std::make_shared<Class>();
1176   default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
1177   default_class->modifiers = PUBLIC | STATIC;
1178   default_class->what = Class::CLASS;
1179   default_class->type = iface.GetCanonicalName() + ".Default";
1180   default_class->interfaces.emplace_back(iface.GetCanonicalName());
1181 
1182   for (const auto& m : iface.GetMethods()) {
1183     if (m->IsUserDefined()) {
1184       default_class->elements.emplace_back(GenerateDefaultImplMethod(*m));
1185     } else {
1186       // These are called only when the remote side does not implement these
1187       // methods, which is normally impossible, because these methods are
1188       // automatically declared in the interface class and not implementing
1189       // them on the remote side causes a compilation error. But if the remote
1190       // side somehow managed to not implement it, that's an error and we
1191       // report the case by returning an invalid value here.
1192       if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1193         std::ostringstream code;
1194         code << "@Override\n"
1195              << "public int " << kGetInterfaceVersion << "() {\n"
1196              << "  return 0;\n"
1197              << "}\n";
1198         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1199       }
1200       if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1201         std::ostringstream code;
1202         code << "@Override\n"
1203              << "public String " << kGetInterfaceHash << "() {\n"
1204              << "  return \"\";\n"
1205              << "}\n";
1206         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1207       }
1208     }
1209   }
1210 
1211   default_class->elements.emplace_back(
1212       std::make_shared<LiteralClassElement>("@Override\n"
1213                                             "public android.os.IBinder asBinder() {\n"
1214                                             "  return null;\n"
1215                                             "}\n"));
1216 
1217   return default_class;
1218 }
1219 
GenerateDelegatorMethod(const AidlMethod & method)1220 static shared_ptr<ClassElement> GenerateDelegatorMethod(const AidlMethod& method) {
1221   auto delegator_method = std::make_shared<Method>();
1222   delegator_method->comment = GenerateComments(method);
1223   delegator_method->modifiers = PUBLIC | OVERRIDE;
1224   delegator_method->returnType = JavaSignatureOf(method.GetType());
1225   delegator_method->name = method.GetName();
1226   delegator_method->statements = std::make_shared<StatementBlock>();
1227   std::vector<std::string> argNames;
1228   for (const auto& arg : method.GetArguments()) {
1229     delegator_method->parameters.push_back(
1230         std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
1231     argNames.push_back(arg->GetName());
1232   }
1233   delegator_method->exceptions.push_back("android.os.RemoteException");
1234 
1235   std::string return_str;
1236   if (method.GetType().GetName() != "void") {
1237     return_str = "return ";
1238   }
1239   delegator_method->statements->Add(
1240       std::make_shared<LiteralStatement>(return_str + "mImpl." + method.GetName() + "(" +
1241                                          android::base::Join(argNames, ",") + ");\n"));
1242   return delegator_method;
1243 }
1244 
GenerateDelegatorClass(const AidlInterface & iface,const Options & options)1245 static shared_ptr<Class> GenerateDelegatorClass(const AidlInterface& iface,
1246                                                 const Options& options) {
1247   auto delegator_class = std::make_shared<Class>();
1248   delegator_class->comment = "/** Delegator implementation for " + iface.GetName() + ". */";
1249   delegator_class->modifiers = PUBLIC | STATIC;
1250   delegator_class->what = Class::CLASS;
1251   delegator_class->type = iface.GetCanonicalName() + ".Delegator";
1252   delegator_class->extends = iface.GetCanonicalName() + ".Stub";
1253 
1254   // constructor
1255   delegator_class->elements.emplace_back(
1256       std::make_shared<LiteralClassElement>("public Delegator(" + iface.GetCanonicalName() +
1257                                             " impl) {\n"
1258                                             "  this.mImpl = impl;\n"
1259                                             "}\n"));
1260   // meta methods
1261   if (!options.Hash().empty()) {
1262     delegator_class->elements.emplace_back(
1263         std::make_shared<LiteralClassElement>("@Override\n"
1264                                               "public String " +
1265                                               kGetInterfaceHash +
1266                                               "() throws android.os.RemoteException {\n"
1267                                               "  return mImpl." +
1268                                               kGetInterfaceHash +
1269                                               "();\n"
1270                                               "}\n"));
1271   }
1272   if (options.Version() > 0) {
1273     delegator_class->elements.emplace_back(
1274         std::make_shared<LiteralClassElement>("@Override\n"
1275                                               "public int " +
1276                                               kGetInterfaceVersion +
1277                                               "() throws android.os.RemoteException {\n"
1278                                               "  int implVer = mImpl." +
1279                                               kGetInterfaceVersion +
1280                                               "();\n"
1281                                               "  return VERSION < implVer ? VERSION : implVer;\n"
1282                                               "}\n"));
1283   }
1284 
1285   // user defined methods
1286   for (const auto& m : iface.GetMethods()) {
1287     if (m->IsUserDefined()) {
1288       delegator_class->elements.emplace_back(GenerateDelegatorMethod(*m));
1289     }
1290   }
1291 
1292   delegator_class->elements.emplace_back(
1293       std::make_shared<LiteralClassElement>(iface.GetCanonicalName() + " mImpl;\n"));
1294 
1295   return delegator_class;
1296 }
1297 
GenerateMaxTransactionId(int max_transaction_id)1298 static shared_ptr<ClassElement> GenerateMaxTransactionId(int max_transaction_id) {
1299   auto getMaxTransactionId = std::make_shared<Method>();
1300   getMaxTransactionId->comment = "/** @hide */";
1301   getMaxTransactionId->modifiers = PUBLIC;
1302   getMaxTransactionId->returnType = "int";
1303   getMaxTransactionId->name = "getMaxTransactionId";
1304   getMaxTransactionId->statements = std::make_shared<StatementBlock>();
1305   getMaxTransactionId->statements->Add(std::make_shared<ReturnStatement>(
1306       std::make_shared<LiteralExpression>(std::to_string(max_transaction_id))));
1307   return getMaxTransactionId;
1308 }
1309 
GenerateInterfaceClass(const AidlInterface * iface,const AidlTypenames & typenames,const Options & options)1310 std::unique_ptr<Class> GenerateInterfaceClass(const AidlInterface* iface,
1311                                               const AidlTypenames& typenames,
1312                                               const Options& options) {
1313   // the interface class
1314   auto interface = std::make_unique<Class>();
1315   interface->comment = GenerateComments(*iface);
1316   interface->modifiers = PUBLIC;
1317   interface->what = Class::INTERFACE;
1318   interface->type = iface->GetCanonicalName();
1319   interface->interfaces.push_back("android.os.IInterface");
1320   interface->annotations = JavaAnnotationsFor(*iface);
1321 
1322   if (options.Version()) {
1323     std::ostringstream code;
1324     code << "/**\n"
1325          << " * The version of this interface that the caller is built against.\n"
1326          << " * This might be different from what {@link #getInterfaceVersion()\n"
1327          << " * getInterfaceVersion} returns as that is the version of the interface\n"
1328          << " * that the remote object is implementing.\n"
1329          << " */\n"
1330          << "public static final int VERSION = ";
1331     if (options.IsLatestUnfrozenVersion()) {
1332       code << "true ? " << options.PreviousVersion() << " : " << options.Version() << ";\n";
1333     } else {
1334       code << options.Version() << ";\n";
1335     }
1336 
1337     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1338   }
1339   if (!options.Hash().empty() || options.IsLatestUnfrozenVersion()) {
1340     std::ostringstream code;
1341     if (options.IsLatestUnfrozenVersion()) {
1342       code << "public static final String HASH = \"" << options.PreviousHash() << "\";\n";
1343     } else {
1344       code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1345     }
1346 
1347     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1348   }
1349 
1350   // the default impl class
1351   auto default_impl = GenerateDefaultImplClass(*iface, options);
1352   interface->elements.emplace_back(default_impl);
1353 
1354   // the delegator class
1355   if (iface->IsJavaDelegator()) {
1356     auto delegator = GenerateDelegatorClass(*iface, options);
1357     interface->elements.emplace_back(delegator);
1358   }
1359 
1360   // the stub inner class
1361   auto stub = std::make_shared<StubClass>(iface, options);
1362   interface->elements.push_back(stub);
1363 
1364   ComputeOutlineMethods(iface, stub, options.onTransact_outline_threshold_,
1365                         options.onTransact_non_outline_count_);
1366 
1367   // the proxy inner class
1368   auto proxy = std::make_shared<ProxyClass>(iface, options);
1369   stub->elements.push_back(proxy);
1370 
1371   // stub and proxy support for getInterfaceDescriptor()
1372   GenerateInterfaceDescriptors(options, iface, interface.get(), stub, proxy);
1373 
1374   // all the declared constants of the interface
1375   string constants;
1376   GenerateConstantDeclarations(*CodeWriter::ForString(&constants), *iface);
1377   interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
1378 
1379   // all the declared methods of the interface
1380   int max_transaction_id = 0;
1381   for (const auto& item : iface->GetMethods()) {
1382     GenerateMethods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames, options);
1383     max_transaction_id = std::max(max_transaction_id, item->GetId());
1384   }
1385 
1386   // getMaxTransactionId
1387   if (options.GenTransactionNames() || options.GenTraces()) {
1388     stub->elements.push_back(GenerateMaxTransactionId(max_transaction_id));
1389   }
1390 
1391   // all the nested types
1392   string code;
1393   auto writer = CodeWriter::ForString(&code);
1394   for (const auto& nested : iface->GetNestedTypes()) {
1395     GenerateClass(*writer, *nested, typenames, options);
1396   }
1397   GenerateParcelHelpers(*writer, *iface, typenames, options);
1398   writer->Close();
1399   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
1400 
1401   if (iface->IsJavaDefault()) {
1402     // additional static methods for the default impl set/get to the
1403     // stub class. Can't add them to the interface as the generated java files
1404     // may be compiled with Java < 1.7 where static interface method isn't
1405     // supported.
1406     // TODO(b/111417145) make this conditional depending on the Java language
1407     // version requested
1408     const string i_name = iface->GetCanonicalName();
1409     stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
1410         StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1411                      "  // Only one user of this interface can use this function\n"
1412                      "  // at a time. This is a heuristic to detect if two different\n"
1413                      "  // users in the same process use this function.\n"
1414                      "  if (Stub.Proxy.sDefaultImpl != null) {\n"
1415                      "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1416                      "  }\n"
1417                      "  if (impl != null) {\n"
1418                      "    Stub.Proxy.sDefaultImpl = impl;\n"
1419                      "    return true;\n"
1420                      "  }\n"
1421                      "  return false;\n"
1422                      "}\n",
1423                      i_name.c_str())));
1424     stub->elements.emplace_back(
1425         std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1426                                                            "  return Stub.Proxy.sDefaultImpl;\n"
1427                                                            "}\n",
1428                                                            i_name.c_str())));
1429 
1430     // the static field is defined in the proxy class, not in the interface class
1431     // because all fields in an interface class are by default final.
1432     proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
1433         StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
1434   }
1435 
1436   stub->Finish();
1437 
1438   return interface;
1439 }
1440 
1441 }  // namespace java
1442 }  // namespace aidl
1443 }  // namespace android
1444