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_to_java.h"
19 #include "generate_java.h"
20 #include "logging.h"
21 #include "options.h"
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <algorithm>
28 #include <unordered_set>
29 #include <utility>
30 #include <vector>
31 
32 #include <android-base/stringprintf.h>
33 
34 using android::base::Join;
35 using android::base::StringPrintf;
36 
37 using std::string;
38 using std::unique_ptr;
39 using std::vector;
40 
41 namespace android {
42 namespace aidl {
43 namespace java {
44 
45 // =================================================
46 class VariableFactory {
47  public:
48   using Variable = ::android::aidl::java::Variable;
49 
VariableFactory(const std::string & base)50   explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
Get(const AidlTypeSpecifier & type,const AidlTypenames & typenames)51   std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
52     auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
53                                         StringPrintf("%s%d", base_.c_str(), index_));
54     vars_.push_back(v);
55     index_++;
56     return v;
57   }
58 
Get(int index)59   std::shared_ptr<Variable> Get(int index) { return vars_[index]; }
60 
61  private:
62   std::vector<std::shared_ptr<Variable>> vars_;
63   std::string base_;
64   int index_;
65 };
66 
67 // =================================================
68 class StubClass : public Class {
69  public:
70   StubClass(const AidlInterface* interfaceType, const Options& options);
71   ~StubClass() override = default;
72 
73   // non-copyable, non-movable
74   StubClass(const StubClass&) = delete;
75   StubClass(StubClass&&) = delete;
76   StubClass& operator=(const StubClass&) = delete;
77   StubClass& operator=(StubClass&&) = delete;
78 
79   std::shared_ptr<Variable> transact_code;
80   std::shared_ptr<Variable> transact_data;
81   std::shared_ptr<Variable> transact_reply;
82   std::shared_ptr<Variable> transact_flags;
83   std::shared_ptr<SwitchStatement> transact_switch;
84   std::shared_ptr<StatementBlock> transact_statements;
85   std::shared_ptr<SwitchStatement> code_to_method_name_switch;
86 
87   // Where onTransact cases should be generated as separate methods.
88   bool transact_outline;
89   // Specific methods that should be outlined when transact_outline is true.
90   std::unordered_set<const AidlMethod*> outline_methods;
91   // Number of all methods.
92   size_t all_method_count;
93 
94   // Finish generation. This will add a default case to the switch.
95   void finish();
96 
97   std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
98 
99  private:
100   void make_as_interface(const AidlInterface* interfaceType);
101 
102   std::shared_ptr<Variable> transact_descriptor;
103   const Options& options_;
104 };
105 
StubClass(const AidlInterface * interfaceType,const Options & options)106 StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
107     : Class(), options_(options) {
108   transact_descriptor = nullptr;
109   transact_outline = false;
110   all_method_count = 0;  // Will be set when outlining may be enabled.
111 
112   this->comment = "/** Local-side IPC implementation stub class. */";
113   this->modifiers = PUBLIC | ABSTRACT | STATIC;
114   this->what = Class::CLASS;
115   this->type = interfaceType->GetCanonicalName() + ".Stub";
116   this->extends = "android.os.Binder";
117   this->interfaces.push_back(interfaceType->GetCanonicalName());
118 
119   // ctor
120   auto ctor = std::make_shared<Method>();
121   ctor->modifiers = PUBLIC;
122   ctor->comment =
123       "/** Construct the stub at attach it to the "
124       "interface. */";
125   ctor->name = "Stub";
126   ctor->statements = std::make_shared<StatementBlock>();
127   if (interfaceType->IsVintfStability()) {
128     auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
129     ctor->statements->Add(stability);
130   }
131   auto attach = std::make_shared<MethodCall>(
132       THIS_VALUE, "attachInterface",
133       std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
134                                                std::make_shared<LiteralExpression>("DESCRIPTOR")});
135   ctor->statements->Add(attach);
136   this->elements.push_back(ctor);
137 
138   // asInterface
139   make_as_interface(interfaceType);
140 
141   // asBinder
142   auto asBinder = std::make_shared<Method>();
143   asBinder->modifiers = PUBLIC | OVERRIDE;
144   asBinder->returnType = "android.os.IBinder";
145   asBinder->name = "asBinder";
146   asBinder->statements = std::make_shared<StatementBlock>();
147   asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
148   this->elements.push_back(asBinder);
149 
150   if (options_.GenTransactionNames()) {
151     // getDefaultTransactionName
152     auto getDefaultTransactionName = std::make_shared<Method>();
153     getDefaultTransactionName->comment = "/** @hide */";
154     getDefaultTransactionName->modifiers = PUBLIC | STATIC;
155     getDefaultTransactionName->returnType = "java.lang.String";
156     getDefaultTransactionName->name = "getDefaultTransactionName";
157     auto code = std::make_shared<Variable>("int", "transactionCode");
158     getDefaultTransactionName->parameters.push_back(code);
159     getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
160     this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
161     getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
162     this->elements.push_back(getDefaultTransactionName);
163 
164     // getTransactionName
165     auto getTransactionName = std::make_shared<Method>();
166     getTransactionName->comment = "/** @hide */";
167     getTransactionName->modifiers = PUBLIC;
168     getTransactionName->returnType = "java.lang.String";
169     getTransactionName->name = "getTransactionName";
170     auto code2 = std::make_shared<Variable>("int", "transactionCode");
171     getTransactionName->parameters.push_back(code2);
172     getTransactionName->statements = std::make_shared<StatementBlock>();
173     getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
174         std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
175                                      std::vector<std::shared_ptr<Expression>>{code2})));
176     this->elements.push_back(getTransactionName);
177   }
178 
179   // onTransact
180   this->transact_code = std::make_shared<Variable>("int", "code");
181   this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
182   this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
183   this->transact_flags = std::make_shared<Variable>("int", "flags");
184   auto onTransact = std::make_shared<Method>();
185   onTransact->modifiers = PUBLIC | OVERRIDE;
186   onTransact->returnType = "boolean";
187   onTransact->name = "onTransact";
188   onTransact->parameters.push_back(this->transact_code);
189   onTransact->parameters.push_back(this->transact_data);
190   onTransact->parameters.push_back(this->transact_reply);
191   onTransact->parameters.push_back(this->transact_flags);
192   onTransact->statements = std::make_shared<StatementBlock>();
193   transact_statements = onTransact->statements;
194   onTransact->exceptions.push_back("android.os.RemoteException");
195   this->elements.push_back(onTransact);
196   this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code);
197 }
198 
finish()199 void StubClass::finish() {
200   auto default_case = std::make_shared<Case>();
201 
202   auto superCall = std::make_shared<MethodCall>(
203       SUPER_VALUE, "onTransact",
204       std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
205                                                this->transact_reply, this->transact_flags});
206   default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
207   transact_switch->cases.push_back(default_case);
208 
209   transact_statements->Add(this->transact_switch);
210 
211   // getTransactionName
212   if (options_.GenTransactionNames()) {
213     // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
214     // Common transaction codes will not be resolved to a string by getTransactionName. The method
215     // will return NULL in this case.
216     auto code_switch_default_case = std::make_shared<Case>();
217     code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
218     this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
219   }
220 }
221 
222 // The the expression for the interface's descriptor to be used when
223 // generating code for the given method. Null is acceptable for method
224 // and stands for synthetic cases.
get_transact_descriptor(const AidlMethod * method)225 std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
226   if (transact_outline) {
227     if (method != nullptr) {
228       // When outlining, each outlined method needs its own literal.
229       if (outline_methods.count(method) != 0) {
230         return std::make_shared<LiteralExpression>("DESCRIPTOR");
231       }
232     } else {
233       // Synthetic case. A small number is assumed. Use its own descriptor
234       // if there are only synthetic cases.
235       if (outline_methods.size() == all_method_count) {
236         return std::make_shared<LiteralExpression>("DESCRIPTOR");
237       }
238     }
239   }
240 
241   // When not outlining, store the descriptor literal into a local variable, in
242   // an effort to save const-string instructions in each switch case.
243   if (transact_descriptor == nullptr) {
244     transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
245     transact_statements->Add(std::make_shared<VariableDeclaration>(
246         transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
247   }
248   return transact_descriptor;
249 }
250 
make_as_interface(const AidlInterface * interfaceType)251 void StubClass::make_as_interface(const AidlInterface* interfaceType) {
252   auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
253 
254   auto m = std::make_shared<Method>();
255   m->comment = "/**\n * Cast an IBinder object into an ";
256   m->comment += interfaceType->GetCanonicalName();
257   m->comment += " interface,\n";
258   m->comment += " * generating a proxy if needed.\n */";
259   m->modifiers = PUBLIC | STATIC;
260   m->returnType = interfaceType->GetCanonicalName();
261   m->name = "asInterface";
262   m->parameters.push_back(obj);
263   m->statements = std::make_shared<StatementBlock>();
264 
265   auto ifstatement = std::make_shared<IfStatement>();
266   ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
267   ifstatement->statements = std::make_shared<StatementBlock>();
268   ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
269   m->statements->Add(ifstatement);
270 
271   // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
272   auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
273   queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
274   auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
275   auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
276   m->statements->Add(iinVd);
277 
278   // Ensure the instance type of the local object is as expected.
279   // One scenario where this is needed is if another package (with a
280   // different class loader) runs in the same process as the service.
281 
282   // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
283   // iin;
284   auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
285   auto instOfCheck = std::make_shared<Comparison>(
286       iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
287   auto instOfStatement = std::make_shared<IfStatement>();
288   instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
289   instOfStatement->statements = std::make_shared<StatementBlock>();
290   instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
291       std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
292   m->statements->Add(instOfStatement);
293 
294   auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
295   ne->arguments.push_back(obj);
296   m->statements->Add(std::make_shared<ReturnStatement>(ne));
297 
298   this->elements.push_back(m);
299 }
300 
301 // =================================================
302 class ProxyClass : public Class {
303  public:
304   ProxyClass(const AidlInterface* interfaceType, const Options& options);
305   ~ProxyClass() override;
306 
307   std::shared_ptr<Variable> mRemote;
308 };
309 
ProxyClass(const AidlInterface * interfaceType,const Options & options)310 ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
311   this->modifiers = PRIVATE | STATIC;
312   this->what = Class::CLASS;
313   this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
314   this->interfaces.push_back(interfaceType->GetCanonicalName());
315 
316   // IBinder mRemote
317   mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
318   this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
319 
320   // Proxy()
321   auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
322   auto ctor = std::make_shared<Method>();
323   ctor->name = "Proxy";
324   ctor->statements = std::make_shared<StatementBlock>();
325   ctor->parameters.push_back(remote);
326   ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
327   this->elements.push_back(ctor);
328 
329   if (options.Version() > 0) {
330     std::ostringstream code;
331     code << "private int mCachedVersion = -1;\n";
332     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
333   }
334   if (!options.Hash().empty()) {
335     std::ostringstream code;
336     code << "private String mCachedHash = \"-1\";\n";
337     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
338   }
339 
340   // IBinder asBinder()
341   auto asBinder = std::make_shared<Method>();
342   asBinder->modifiers = PUBLIC | OVERRIDE;
343   asBinder->returnType = "android.os.IBinder";
344   asBinder->name = "asBinder";
345   asBinder->statements = std::make_shared<StatementBlock>();
346   asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
347   this->elements.push_back(asBinder);
348 }
349 
~ProxyClass()350 ProxyClass::~ProxyClass() {}
351 
352 // =================================================
generate_new_array(const AidlTypeSpecifier & type,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel)353 static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
354                                std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
355                                std::shared_ptr<Variable> parcel) {
356   auto len = std::make_shared<Variable>("int", v->name + "_length");
357   addTo->Add(
358       std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
359   auto lencheck = std::make_shared<IfStatement>();
360   lencheck->expression =
361       std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
362   lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
363   lencheck->elseif = std::make_shared<IfStatement>();
364   lencheck->elseif->statements->Add(std::make_shared<Assignment>(
365       v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
366   addTo->Add(lencheck);
367 }
368 
generate_write_to_parcel(const AidlTypeSpecifier & type,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel,bool is_return_value,const AidlTypenames & typenames)369 static void generate_write_to_parcel(const AidlTypeSpecifier& type,
370                                      std::shared_ptr<StatementBlock> addTo,
371                                      std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
372                                      bool is_return_value, const AidlTypenames& typenames) {
373   string code;
374   CodeWriterPtr writer = CodeWriter::ForString(&code);
375   CodeGeneratorContext context{
376       .writer = *(writer.get()),
377       .typenames = typenames,
378       .type = type,
379       .parcel = parcel->name,
380       .var = v->name,
381       .is_return_value = is_return_value,
382   };
383   WriteToParcelFor(context);
384   writer->Close();
385   addTo->Add(std::make_shared<LiteralStatement>(code));
386 }
387 
generate_int_constant(Class * interface,const std::string & name,const std::string & value)388 static void generate_int_constant(Class* interface, const std::string& name,
389                                   const std::string& value) {
390   auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
391   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
392 }
393 
generate_string_constant(Class * interface,const std::string & name,const std::string & value)394 static void generate_string_constant(Class* interface, const std::string& name,
395                                      const std::string& value) {
396   auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
397   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
398 }
399 
generate_interface_method(const AidlMethod & method,const AidlTypenames & typenames)400 static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
401                                                          const AidlTypenames& typenames) {
402   auto decl = std::make_shared<Method>();
403   decl->comment = method.GetComments();
404   decl->modifiers = PUBLIC;
405   decl->returnType = JavaSignatureOf(method.GetType(), typenames);
406   decl->name = method.GetName();
407   decl->annotations = generate_java_annotations(method.GetType());
408 
409   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
410     auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
411     var->annotations = generate_java_annotations(arg->GetType());
412     decl->parameters.push_back(var);
413   }
414 
415   decl->exceptions.push_back("android.os.RemoteException");
416 
417   return decl;
418 }
419 
generate_stub_code(const AidlInterface & iface,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,std::shared_ptr<StubClass> stubClass,const Options & options)420 static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
421                                std::shared_ptr<Variable> transact_data,
422                                std::shared_ptr<Variable> transact_reply,
423                                const AidlTypenames& typenames,
424                                std::shared_ptr<StatementBlock> statement_block,
425                                std::shared_ptr<StubClass> stubClass, const Options& options) {
426   // try and finally
427   auto tryStatement = std::make_shared<TryStatement>();
428   auto finallyStatement = std::make_shared<FinallyStatement>();
429   auto& statements = statement_block;
430 
431   if (options.GenTraces()) {
432     statements->Add(tryStatement);
433     statements->Add(finallyStatement);
434     statements = tryStatement->statements;
435     tryStatement->statements->Add(std::make_shared<MethodCall>(
436         std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
437         std::vector<std::shared_ptr<Expression>>{
438             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
439             std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
440                                                       "::" + method.GetName() + "::server")}));
441     finallyStatement->statements->Add(std::make_shared<MethodCall>(
442         std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
443         std::vector<std::shared_ptr<Expression>>{
444             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
445   }
446 
447   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
448 
449   // interface token validation is the very first thing we do
450   statements->Add(std::make_shared<MethodCall>(
451       transact_data, "enforceInterface",
452       std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
453 
454   // args
455   VariableFactory stubArgs("_arg");
456   {
457     // keep this across different args in order to create the classloader
458     // at most once.
459     bool is_classloader_created = false;
460     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
461       std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
462 
463       statements->Add(std::make_shared<VariableDeclaration>(v));
464 
465       if (arg->GetDirection() & AidlArgument::IN_DIR) {
466         string code;
467         CodeWriterPtr writer = CodeWriter::ForString(&code);
468         CodeGeneratorContext context{.writer = *(writer.get()),
469                                      .typenames = typenames,
470                                      .type = arg->GetType(),
471                                      .parcel = transact_data->name,
472                                      .var = v->name,
473                                      .is_classloader_created = &is_classloader_created};
474         CreateFromParcelFor(context);
475         writer->Close();
476         statements->Add(std::make_shared<LiteralStatement>(code));
477       } else {
478         if (!arg->GetType().IsArray()) {
479           statements->Add(std::make_shared<Assignment>(
480               v, std::make_shared<NewExpression>(
481                      InstantiableJavaSignatureOf(arg->GetType(), typenames))));
482         } else {
483           generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
484         }
485       }
486 
487       realCall->arguments.push_back(v);
488     }
489   }
490 
491   // the real call
492   if (method.GetType().GetName() == "void") {
493     statements->Add(realCall);
494 
495     if (!oneway) {
496       // report that there were no exceptions
497       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
498       statements->Add(ex);
499     }
500   } else {
501     auto _result =
502         std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
503       statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
504 
505     if (!oneway) {
506       // report that there were no exceptions
507       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
508       statements->Add(ex);
509     }
510 
511     // marshall the return value
512     generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
513                              typenames);
514   }
515 
516   // out parameters
517   int i = 0;
518   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
519     std::shared_ptr<Variable> v = stubArgs.Get(i++);
520 
521     if (arg->GetDirection() & AidlArgument::OUT_DIR) {
522       generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
523     }
524   }
525 
526   // return true
527   statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
528 }
529 
generate_stub_case(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)530 static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
531                                const std::string& transactCodeName, bool oneway,
532                                std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
533                                const Options& options) {
534   auto c = std::make_shared<Case>(transactCodeName);
535 
536   generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
537                      typenames, c->statements, stubClass, options);
538 
539   stubClass->transact_switch->cases.push_back(c);
540 }
541 
generate_stub_case_outline(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<StubClass> stubClass,const AidlTypenames & typenames,const Options & options)542 static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
543                                        const std::string& transactCodeName, bool oneway,
544                                        std::shared_ptr<StubClass> stubClass,
545                                        const AidlTypenames& typenames, const Options& options) {
546   std::string outline_name = "onTransact$" + method.GetName() + "$";
547   // Generate an "outlined" method with the actual code.
548   {
549     auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
550     auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
551     auto onTransact_case = std::make_shared<Method>();
552     onTransact_case->modifiers = PRIVATE;
553     onTransact_case->returnType = "boolean";
554     onTransact_case->name = outline_name;
555     onTransact_case->parameters.push_back(transact_data);
556     onTransact_case->parameters.push_back(transact_reply);
557     onTransact_case->statements = std::make_shared<StatementBlock>();
558     onTransact_case->exceptions.push_back("android.os.RemoteException");
559     stubClass->elements.push_back(onTransact_case);
560 
561     generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
562                        onTransact_case->statements, stubClass, options);
563   }
564 
565   // Generate the case dispatch.
566   {
567     auto c = std::make_shared<Case>(transactCodeName);
568 
569     auto helper_call =
570         std::make_shared<MethodCall>(THIS_VALUE, outline_name,
571                                      std::vector<std::shared_ptr<Expression>>{
572                                          stubClass->transact_data, stubClass->transact_reply});
573     c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
574 
575     stubClass->transact_switch->cases.push_back(c);
576   }
577 }
578 
generate_proxy_method(const AidlInterface & iface,const AidlMethod & method,const std::string & transactCodeName,bool oneway,std::shared_ptr<ProxyClass> proxyClass,const AidlTypenames & typenames,const Options & options)579 static std::shared_ptr<Method> generate_proxy_method(
580     const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
581     bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
582     const Options& options) {
583   auto proxy = std::make_shared<Method>();
584   proxy->comment = method.GetComments();
585   proxy->modifiers = PUBLIC | OVERRIDE;
586   proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
587   proxy->name = method.GetName();
588   proxy->statements = std::make_shared<StatementBlock>();
589   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
590     proxy->parameters.push_back(
591         std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
592   }
593   proxy->exceptions.push_back("android.os.RemoteException");
594 
595   // the parcels
596   auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
597   proxy->statements->Add(std::make_shared<VariableDeclaration>(
598       _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
599   std::shared_ptr<Variable> _reply = nullptr;
600   if (!oneway) {
601     _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
602     proxy->statements->Add(std::make_shared<VariableDeclaration>(
603         _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
604   }
605 
606   // the return value
607   std::shared_ptr<Variable> _result = nullptr;
608   if (method.GetType().GetName() != "void") {
609     _result = std::make_shared<Variable>(*proxy->returnType, "_result");
610     proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
611   }
612 
613   // try and finally
614   auto tryStatement = std::make_shared<TryStatement>();
615   proxy->statements->Add(tryStatement);
616   auto finallyStatement = std::make_shared<FinallyStatement>();
617   proxy->statements->Add(finallyStatement);
618 
619   if (options.GenTraces()) {
620     tryStatement->statements->Add(std::make_shared<MethodCall>(
621         std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
622         std::vector<std::shared_ptr<Expression>>{
623             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
624             std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
625                                                       "::" + method.GetName() + "::client")}));
626   }
627 
628   // the interface identifier token: the DESCRIPTOR constant, marshalled as a
629   // string
630   tryStatement->statements->Add(std::make_shared<MethodCall>(
631       _data, "writeInterfaceToken",
632       std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
633 
634   // the parameters
635   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
636     auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
637     AidlArgument::Direction dir = arg->GetDirection();
638     if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
639       auto checklen = std::make_shared<IfStatement>();
640       checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
641       checklen->statements->Add(std::make_shared<MethodCall>(
642           _data, "writeInt",
643           std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
644       checklen->elseif = std::make_shared<IfStatement>();
645       checklen->elseif->statements->Add(std::make_shared<MethodCall>(
646           _data, "writeInt",
647           std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
648       tryStatement->statements->Add(checklen);
649     } else if (dir & AidlArgument::IN_DIR) {
650       generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
651                                typenames);
652     }
653   }
654 
655   // the transact call
656   auto call = std::make_shared<MethodCall>(
657       proxyClass->mRemote, "transact",
658       std::vector<std::shared_ptr<Expression>>{
659           std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
660           _reply ? _reply : NULL_VALUE,
661           std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")});
662   auto _status = std::make_shared<Variable>("boolean", "_status");
663   tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
664 
665   // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
666   // back to the local method in the default impl, if set before.
667   vector<string> arg_names;
668   for (const auto& arg : method.GetArguments()) {
669     arg_names.emplace_back(arg->GetName());
670   }
671   bool has_return_type = method.GetType().GetName() != "void";
672   tryStatement->statements->Add(std::make_shared<LiteralStatement>(
673       android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
674                                                     "  return getDefaultImpl().%s(%s);\n"
675                                                     "}\n"
676                                                   : "if (!_status && getDefaultImpl() != null) {\n"
677                                                     "  getDefaultImpl().%s(%s);\n"
678                                                     "  return;\n"
679                                                     "}\n",
680                                   method.GetName().c_str(), Join(arg_names, ", ").c_str())));
681 
682   // throw back exceptions.
683   if (_reply) {
684     auto ex = std::make_shared<MethodCall>(_reply, "readException");
685     tryStatement->statements->Add(ex);
686   }
687 
688   // returning and cleanup
689   if (_reply != nullptr) {
690     // keep this across return value and arguments in order to create the
691     // classloader at most once.
692     bool is_classloader_created = false;
693     if (_result != nullptr) {
694       string code;
695       CodeWriterPtr writer = CodeWriter::ForString(&code);
696       CodeGeneratorContext context{.writer = *(writer.get()),
697                                    .typenames = typenames,
698                                    .type = method.GetType(),
699                                    .parcel = _reply->name,
700                                    .var = _result->name,
701                                    .is_classloader_created = &is_classloader_created};
702       CreateFromParcelFor(context);
703       writer->Close();
704       tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
705     }
706 
707     // the out/inout parameters
708     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
709       if (arg->GetDirection() & AidlArgument::OUT_DIR) {
710         string code;
711         CodeWriterPtr writer = CodeWriter::ForString(&code);
712         CodeGeneratorContext context{.writer = *(writer.get()),
713                                      .typenames = typenames,
714                                      .type = arg->GetType(),
715                                      .parcel = _reply->name,
716                                      .var = arg->GetName(),
717                                      .is_classloader_created = &is_classloader_created};
718         ReadFromParcelFor(context);
719         writer->Close();
720         tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
721       }
722     }
723 
724     finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
725   }
726   finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
727 
728   if (options.GenTraces()) {
729     finallyStatement->statements->Add(std::make_shared<MethodCall>(
730         std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
731         std::vector<std::shared_ptr<Expression>>{
732             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
733   }
734 
735   if (_result != nullptr) {
736     proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
737   }
738 
739   return proxy;
740 }
741 
generate_methods(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)742 static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
743                              std::shared_ptr<StubClass> stubClass,
744                              std::shared_ptr<ProxyClass> proxyClass, int index,
745                              const AidlTypenames& typenames, const Options& options) {
746   const bool oneway = method.IsOneway();
747 
748   // == the TRANSACT_ constant =============================================
749   string transactCodeName = "TRANSACTION_";
750   transactCodeName += method.GetName();
751 
752   auto transactCode =
753       std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
754   transactCode->value =
755       StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
756   stubClass->elements.push_back(transactCode);
757 
758   // getTransactionName
759   if (options.GenTransactionNames()) {
760     auto c = std::make_shared<Case>(transactCodeName);
761     c->statements->Add(std::make_shared<ReturnStatement>(
762         std::make_shared<StringLiteralExpression>(method.GetName())));
763     stubClass->code_to_method_name_switch->cases.push_back(c);
764   }
765 
766   // == the declaration in the interface ===================================
767   std::shared_ptr<ClassElement> decl;
768   if (method.IsUserDefined()) {
769     decl = generate_interface_method(method, typenames);
770   } else {
771     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
772       std::ostringstream code;
773       code << "public int " << kGetInterfaceVersion << "() "
774            << "throws android.os.RemoteException;\n";
775       decl = std::make_shared<LiteralClassElement>(code.str());
776     }
777     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
778       std::ostringstream code;
779       code << "public String " << kGetInterfaceHash << "() "
780            << "throws android.os.RemoteException;\n";
781       decl = std::make_shared<LiteralClassElement>(code.str());
782     }
783   }
784   interface->elements.push_back(decl);
785 
786   // == the stub method ====================================================
787   if (method.IsUserDefined()) {
788     bool outline_stub =
789         stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
790     if (outline_stub) {
791       generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
792                                  options);
793     } else {
794       generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
795     }
796   } else {
797     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
798       auto c = std::make_shared<Case>(transactCodeName);
799       std::ostringstream code;
800       code << "data.enforceInterface(descriptor);\n"
801            << "reply.writeNoException();\n"
802            << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
803            << "return true;\n";
804       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
805       stubClass->transact_switch->cases.push_back(c);
806     }
807     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
808       auto c = std::make_shared<Case>(transactCodeName);
809       std::ostringstream code;
810       code << "data.enforceInterface(descriptor);\n"
811            << "reply.writeNoException();\n"
812            << "reply.writeString(" << kGetInterfaceHash << "());\n"
813            << "return true;\n";
814       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
815       stubClass->transact_switch->cases.push_back(c);
816     }
817   }
818 
819   // == the proxy method ===================================================
820   std::shared_ptr<ClassElement> proxy = nullptr;
821   if (method.IsUserDefined()) {
822     proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
823                                   options);
824 
825   } else {
826     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
827       std::ostringstream code;
828       code << "@Override\n"
829            << "public int " << kGetInterfaceVersion << "()"
830            << " throws "
831            << "android.os.RemoteException {\n"
832            << "  if (mCachedVersion == -1) {\n"
833            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
834            << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
835            << "    try {\n"
836            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
837            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
838            << "data, reply, 0);\n"
839            << "      if (!_status) {\n"
840            << "        if (getDefaultImpl() != null) {\n"
841            << "          return getDefaultImpl().getInterfaceVersion();\n"
842            << "        }\n"
843            << "      }\n"
844            << "      reply.readException();\n"
845            << "      mCachedVersion = reply.readInt();\n"
846            << "    } finally {\n"
847            << "      reply.recycle();\n"
848            << "      data.recycle();\n"
849            << "    }\n"
850            << "  }\n"
851            << "  return mCachedVersion;\n"
852            << "}\n";
853       proxy = std::make_shared<LiteralClassElement>(code.str());
854     }
855     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
856       std::ostringstream code;
857       code << "@Override\n"
858            << "public synchronized String " << kGetInterfaceHash << "()"
859            << " throws "
860            << "android.os.RemoteException {\n"
861            << "  if (\"-1\".equals(mCachedHash)) {\n"
862            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
863            << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
864            << "    try {\n"
865            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
866            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
867            << "data, reply, 0);\n"
868            << "      if (!_status) {\n"
869            << "        if (getDefaultImpl() != null) {\n"
870            << "          return getDefaultImpl().getInterfaceHash();\n"
871            << "        }\n"
872            << "      }\n"
873            << "      reply.readException();\n"
874            << "      mCachedHash = reply.readString();\n"
875            << "    } finally {\n"
876            << "      reply.recycle();\n"
877            << "      data.recycle();\n"
878            << "    }\n"
879            << "  }\n"
880            << "  return mCachedHash;\n"
881            << "}\n";
882       proxy = std::make_shared<LiteralClassElement>(code.str());
883     }
884   }
885   if (proxy != nullptr) {
886     proxyClass->elements.push_back(proxy);
887   }
888 }
889 
generate_interface_descriptors(const Options & options,const AidlInterface * iface,Class * interface,std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)890 static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
891                                            Class* interface, std::shared_ptr<StubClass> stub,
892                                            std::shared_ptr<ProxyClass> proxy) {
893   // the interface descriptor transaction handler
894   auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
895   c->statements->Add(std::make_shared<MethodCall>(
896       stub->transact_reply, "writeString",
897       std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
898   c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
899   stub->transact_switch->cases.push_back(c);
900 
901   // and the proxy-side method returning the descriptor directly
902   auto getDesc = std::make_shared<Method>();
903   getDesc->modifiers = PUBLIC;
904   getDesc->returnType = "java.lang.String";
905   getDesc->name = "getInterfaceDescriptor";
906   getDesc->statements = std::make_shared<StatementBlock>();
907   getDesc->statements->Add(
908       std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
909   proxy->elements.push_back(getDesc);
910 
911   // add the DESCRIPTOR field to the interface class
912   Class* classToAddDescriptor = interface;
913   static std::set<std::string> greylist = {
914 #include "hiddenapi-greylist"
915   };
916   if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
917     // For app compatibility, we keep DESCRIPTOR to the stub class for
918     // the interfaces that are in the greylist.
919     classToAddDescriptor = stub.get();
920   }
921   auto descriptor = std::make_shared<Field>(
922       STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
923   if (options.IsStructured()) {
924     // mangle the interface name at build time and demangle it at runtime, to avoid
925     // being renamed by jarjar. See b/153843174
926     std::string name = iface->GetCanonicalName();
927     std::replace(name.begin(), name.end(), '.', '$');
928     descriptor->value = "\"" + name + "\".replace('$', '.')";
929   } else {
930     descriptor->value = "\"" + iface->GetCanonicalName() + "\"";
931   }
932   classToAddDescriptor->elements.push_back(descriptor);
933 }
934 
935 // Check whether (some) methods in this interface should be "outlined," that
936 // is, have specific onTransact methods for certain cases. Set up StubClass
937 // metadata accordingly.
938 //
939 // Outlining will be enabled if the interface has more than outline_threshold
940 // methods. In that case, the methods are sorted by number of arguments
941 // (so that more "complex" methods come later), and the first non_outline_count
942 // number of methods not outlined (are kept in the onTransact() method).
943 //
944 // Requirements: non_outline_count <= outline_threshold.
compute_outline_methods(const AidlInterface * iface,const std::shared_ptr<StubClass> stub,size_t outline_threshold,size_t non_outline_count)945 static void compute_outline_methods(const AidlInterface* iface,
946                                     const std::shared_ptr<StubClass> stub, size_t outline_threshold,
947                                     size_t non_outline_count) {
948   CHECK_LE(non_outline_count, outline_threshold);
949   // We'll outline (create sub methods) if there are more than min_methods
950   // cases.
951   stub->transact_outline = iface->GetMethods().size() > outline_threshold;
952   if (stub->transact_outline) {
953     stub->all_method_count = iface->GetMethods().size();
954     std::vector<const AidlMethod*> methods;
955     methods.reserve(iface->GetMethods().size());
956     for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
957       methods.push_back(ptr.get());
958     }
959 
960     std::stable_sort(
961         methods.begin(),
962         methods.end(),
963         [](const AidlMethod* m1, const AidlMethod* m2) {
964           return m1->GetArguments().size() < m2->GetArguments().size();
965         });
966 
967     stub->outline_methods.insert(methods.begin() + non_outline_count,
968                                  methods.end());
969   }
970 }
971 
generate_default_impl_method(const AidlMethod & method,const AidlTypenames & typenames)972 static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
973                                                              const AidlTypenames& typenames) {
974   auto default_method = std::make_shared<Method>();
975   default_method->comment = method.GetComments();
976   default_method->modifiers = PUBLIC | OVERRIDE;
977   default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
978   default_method->name = method.GetName();
979   default_method->statements = std::make_shared<StatementBlock>();
980   for (const auto& arg : method.GetArguments()) {
981     default_method->parameters.push_back(
982         std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
983   }
984   default_method->exceptions.push_back("android.os.RemoteException");
985 
986   if (method.GetType().GetName() != "void") {
987     const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
988     default_method->statements->Add(
989         std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
990   }
991   return default_method;
992 }
993 
generate_default_impl_class(const AidlInterface & iface,const AidlTypenames & typenames,const Options & options)994 static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
995                                                      const AidlTypenames& typenames,
996                                                      const Options& options) {
997   auto default_class = std::make_shared<Class>();
998   default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
999   default_class->modifiers = PUBLIC | STATIC;
1000   default_class->what = Class::CLASS;
1001   default_class->type = iface.GetCanonicalName() + ".Default";
1002   default_class->interfaces.emplace_back(iface.GetCanonicalName());
1003 
1004   for (const auto& m : iface.GetMethods()) {
1005     if (m->IsUserDefined()) {
1006       default_class->elements.emplace_back(generate_default_impl_method(*m.get(), typenames));
1007     } else {
1008       // These are called only when the remote side does not implement these
1009       // methods, which is normally impossible, because these methods are
1010       // automatically declared in the interface class and not implementing
1011       // them on the remote side causes a compilation error. But if the remote
1012       // side somehow managed to not implement it, that's an error and we
1013       // report the case by returning an invalid value here.
1014       if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
1015         std::ostringstream code;
1016         code << "@Override\n"
1017              << "public int " << kGetInterfaceVersion << "() {\n"
1018              << "  return 0;\n"
1019              << "}\n";
1020         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1021       }
1022       if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
1023         std::ostringstream code;
1024         code << "@Override\n"
1025              << "public String " << kGetInterfaceHash << "() {\n"
1026              << "  return \"\";\n"
1027              << "}\n";
1028         default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1029       }
1030     }
1031   }
1032 
1033   default_class->elements.emplace_back(
1034       std::make_shared<LiteralClassElement>("@Override\n"
1035                                             "public android.os.IBinder asBinder() {\n"
1036                                             "  return null;\n"
1037                                             "}\n"));
1038 
1039   return default_class;
1040 }
1041 
generate_binder_interface_class(const AidlInterface * iface,const AidlTypenames & typenames,const Options & options)1042 std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
1043                                                        const AidlTypenames& typenames,
1044                                                        const Options& options) {
1045   // the interface class
1046   auto interface = std::make_unique<Class>();
1047   interface->comment = iface->GetComments();
1048   interface->modifiers = PUBLIC;
1049   interface->what = Class::INTERFACE;
1050   interface->type = iface->GetCanonicalName();
1051   interface->interfaces.push_back("android.os.IInterface");
1052   interface->annotations = generate_java_annotations(*iface);
1053 
1054   if (options.Version()) {
1055     std::ostringstream code;
1056     code << "/**\n"
1057          << " * The version of this interface that the caller is built against.\n"
1058          << " * This might be different from what {@link #getInterfaceVersion()\n"
1059          << " * getInterfaceVersion} returns as that is the version of the interface\n"
1060          << " * that the remote object is implementing.\n"
1061          << " */\n"
1062          << "public static final int VERSION = " << options.Version() << ";\n";
1063     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1064   }
1065   if (!options.Hash().empty()) {
1066     std::ostringstream code;
1067     code << "public static final String HASH = \"" << options.Hash() << "\";\n";
1068     interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
1069   }
1070 
1071   // the default impl class
1072   auto default_impl = generate_default_impl_class(*iface, typenames, options);
1073   interface->elements.emplace_back(default_impl);
1074 
1075   // the stub inner class
1076   auto stub = std::make_shared<StubClass>(iface, options);
1077   interface->elements.push_back(stub);
1078 
1079   compute_outline_methods(iface,
1080                           stub,
1081                           options.onTransact_outline_threshold_,
1082                           options.onTransact_non_outline_count_);
1083 
1084   // the proxy inner class
1085   auto proxy = std::make_shared<ProxyClass>(iface, options);
1086   stub->elements.push_back(proxy);
1087 
1088   // stub and proxy support for getInterfaceDescriptor()
1089   generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
1090 
1091   // all the declared constants of the interface
1092   for (const auto& constant : iface->GetConstantDeclarations()) {
1093     const AidlConstantValue& value = constant->GetValue();
1094     auto comment = constant->GetType().GetComments();
1095     if (comment.length() != 0) {
1096       auto code = StringPrintf("%s\n", comment.c_str());
1097       interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
1098     }
1099     switch (value.GetType()) {
1100       case AidlConstantValue::Type::STRING: {
1101         generate_string_constant(interface.get(), constant->GetName(),
1102                                  constant->ValueString(ConstantValueDecorator));
1103         break;
1104       }
1105       case AidlConstantValue::Type::BOOLEAN:  // fall-through
1106       case AidlConstantValue::Type::INT8:     // fall-through
1107       case AidlConstantValue::Type::INT32: {
1108         generate_int_constant(interface.get(), constant->GetName(),
1109                               constant->ValueString(ConstantValueDecorator));
1110         break;
1111       }
1112       default: {
1113         LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
1114       }
1115     }
1116   }
1117 
1118   // all the declared methods of the interface
1119 
1120   for (const auto& item : iface->GetMethods()) {
1121     generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
1122                      options);
1123   }
1124 
1125   // additional static methods for the default impl set/get to the
1126   // stub class. Can't add them to the interface as the generated java files
1127   // may be compiled with Java < 1.7 where static interface method isn't
1128   // supported.
1129   // TODO(b/111417145) make this conditional depending on the Java language
1130   // version requested
1131   const string i_name = iface->GetCanonicalName();
1132   stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
1133       StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
1134                    "  // Only one user of this interface can use this function\n"
1135                    "  // at a time. This is a heuristic to detect if two different\n"
1136                    "  // users in the same process use this function.\n"
1137                    "  if (Stub.Proxy.sDefaultImpl != null) {\n"
1138                    "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
1139                    "  }\n"
1140                    "  if (impl != null) {\n"
1141                    "    Stub.Proxy.sDefaultImpl = impl;\n"
1142                    "    return true;\n"
1143                    "  }\n"
1144                    "  return false;\n"
1145                    "}\n",
1146                    i_name.c_str())));
1147   stub->elements.emplace_back(
1148       std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
1149                                                          "  return Stub.Proxy.sDefaultImpl;\n"
1150                                                          "}\n",
1151                                                          i_name.c_str())));
1152 
1153   // the static field is defined in the proxy class, not in the interface class
1154   // because all fields in an interface class are by default final.
1155   proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
1156       StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
1157 
1158   stub->finish();
1159 
1160   return interface;
1161 }
1162 
1163 }  // namespace java
1164 }  // namespace aidl
1165 }  // namespace android
1166