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