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