• 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 "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/macros.h>
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   DISALLOW_COPY_AND_ASSIGN(VariableFactory);
68 };
69 
70 // =================================================
71 class StubClass : public Class {
72  public:
73   StubClass(const AidlInterface* interfaceType, const Options& options);
74   ~StubClass() override = default;
75 
76   std::shared_ptr<Variable> transact_code;
77   std::shared_ptr<Variable> transact_data;
78   std::shared_ptr<Variable> transact_reply;
79   std::shared_ptr<Variable> transact_flags;
80   std::shared_ptr<SwitchStatement> transact_switch;
81   std::shared_ptr<StatementBlock> transact_statements;
82   std::shared_ptr<SwitchStatement> code_to_method_name_switch;
83 
84   // Where onTransact cases should be generated as separate methods.
85   bool transact_outline;
86   // Specific methods that should be outlined when transact_outline is true.
87   std::unordered_set<const AidlMethod*> outline_methods;
88   // Number of all methods.
89   size_t all_method_count;
90 
91   // Finish generation. This will add a default case to the switch.
92   void finish();
93 
94   std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
95 
96  private:
97   void make_as_interface(const AidlInterface* interfaceType);
98 
99   std::shared_ptr<Variable> transact_descriptor;
100   const Options& options_;
101 
102   DISALLOW_COPY_AND_ASSIGN(StubClass);
103 };
104 
StubClass(const AidlInterface * interfaceType,const Options & options)105 StubClass::StubClass(const AidlInterface* interfaceType, const Options& options)
106     : Class(), options_(options) {
107   transact_descriptor = nullptr;
108   transact_outline = false;
109   all_method_count = 0;  // Will be set when outlining may be enabled.
110 
111   this->comment = "/** Local-side IPC implementation stub class. */";
112   this->modifiers = PUBLIC | ABSTRACT | STATIC;
113   this->what = Class::CLASS;
114   this->type = interfaceType->GetCanonicalName() + ".Stub";
115   this->extends = "android.os.Binder";
116   this->interfaces.push_back(interfaceType->GetCanonicalName());
117 
118   // descriptor
119   auto descriptor = std::make_shared<Field>(
120       STATIC | FINAL | PRIVATE, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
121   if (options.IsStructured()) {
122     // mangle the interface name at build time and demangle it at runtime, to avoid
123     // being renamed by jarjar. See b/153843174
124     std::string name = interfaceType->GetCanonicalName();
125     std::replace(name.begin(), name.end(), '.', '$');
126     descriptor->value = "\"" + name + "\".replace('$', '.')";
127   } else {
128     descriptor->value = "\"" + interfaceType->GetCanonicalName() + "\"";
129   }
130   this->elements.push_back(descriptor);
131 
132   // ctor
133   auto ctor = std::make_shared<Method>();
134   ctor->modifiers = PUBLIC;
135   ctor->comment =
136       "/** Construct the stub at attach it to the "
137       "interface. */";
138   ctor->name = "Stub";
139   ctor->statements = std::make_shared<StatementBlock>();
140   if (interfaceType->IsVintfStability()) {
141     auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
142     ctor->statements->Add(stability);
143   }
144   auto attach = std::make_shared<MethodCall>(
145       THIS_VALUE, "attachInterface",
146       std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
147                                                std::make_shared<LiteralExpression>("DESCRIPTOR")});
148   ctor->statements->Add(attach);
149   this->elements.push_back(ctor);
150 
151   // asInterface
152   make_as_interface(interfaceType);
153 
154   // asBinder
155   auto asBinder = std::make_shared<Method>();
156   asBinder->modifiers = PUBLIC | OVERRIDE;
157   asBinder->returnType = "android.os.IBinder";
158   asBinder->name = "asBinder";
159   asBinder->statements = std::make_shared<StatementBlock>();
160   asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
161   this->elements.push_back(asBinder);
162 
163   if (options_.GenTransactionNames()) {
164     // getDefaultTransactionName
165     auto getDefaultTransactionName = std::make_shared<Method>();
166     getDefaultTransactionName->comment = "/** @hide */";
167     getDefaultTransactionName->modifiers = PUBLIC | STATIC;
168     getDefaultTransactionName->returnType = "java.lang.String";
169     getDefaultTransactionName->name = "getDefaultTransactionName";
170     auto code = std::make_shared<Variable>("int", "transactionCode");
171     getDefaultTransactionName->parameters.push_back(code);
172     getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
173     this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
174     getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
175     this->elements.push_back(getDefaultTransactionName);
176 
177     // getTransactionName
178     auto getTransactionName = std::make_shared<Method>();
179     getTransactionName->comment = "/** @hide */";
180     getTransactionName->modifiers = PUBLIC;
181     getTransactionName->returnType = "java.lang.String";
182     getTransactionName->name = "getTransactionName";
183     auto code2 = std::make_shared<Variable>("int", "transactionCode");
184     getTransactionName->parameters.push_back(code2);
185     getTransactionName->statements = std::make_shared<StatementBlock>();
186     getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
187         std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
188                                      std::vector<std::shared_ptr<Expression>>{code2})));
189     this->elements.push_back(getTransactionName);
190   }
191 
192   // onTransact
193   this->transact_code = std::make_shared<Variable>("int", "code");
194   this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
195   this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
196   this->transact_flags = std::make_shared<Variable>("int", "flags");
197   auto onTransact = std::make_shared<Method>();
198   onTransact->modifiers = PUBLIC | OVERRIDE;
199   onTransact->returnType = "boolean";
200   onTransact->name = "onTransact";
201   onTransact->parameters.push_back(this->transact_code);
202   onTransact->parameters.push_back(this->transact_data);
203   onTransact->parameters.push_back(this->transact_reply);
204   onTransact->parameters.push_back(this->transact_flags);
205   onTransact->statements = std::make_shared<StatementBlock>();
206   transact_statements = onTransact->statements;
207   onTransact->exceptions.push_back("android.os.RemoteException");
208   this->elements.push_back(onTransact);
209   this->transact_switch = std::make_shared<SwitchStatement>(this->transact_code);
210 }
211 
finish()212 void StubClass::finish() {
213   auto default_case = std::make_shared<Case>();
214 
215   auto superCall = std::make_shared<MethodCall>(
216       SUPER_VALUE, "onTransact",
217       std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
218                                                this->transact_reply, this->transact_flags});
219   default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
220   transact_switch->cases.push_back(default_case);
221 
222   transact_statements->Add(this->transact_switch);
223 
224   // getTransactionName
225   if (options_.GenTransactionNames()) {
226     // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
227     // Common transaction codes will not be resolved to a string by getTransactionName. The method
228     // will return NULL in this case.
229     auto code_switch_default_case = std::make_shared<Case>();
230     code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
231     this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
232   }
233 }
234 
235 // The the expression for the interface's descriptor to be used when
236 // generating code for the given method. Null is acceptable for method
237 // and stands for synthetic cases.
get_transact_descriptor(const AidlMethod * method)238 std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
239   if (transact_outline) {
240     if (method != nullptr) {
241       // When outlining, each outlined method needs its own literal.
242       if (outline_methods.count(method) != 0) {
243         return std::make_shared<LiteralExpression>("DESCRIPTOR");
244       }
245     } else {
246       // Synthetic case. A small number is assumed. Use its own descriptor
247       // if there are only synthetic cases.
248       if (outline_methods.size() == all_method_count) {
249         return std::make_shared<LiteralExpression>("DESCRIPTOR");
250       }
251     }
252   }
253 
254   // When not outlining, store the descriptor literal into a local variable, in
255   // an effort to save const-string instructions in each switch case.
256   if (transact_descriptor == nullptr) {
257     transact_descriptor = std::make_shared<Variable>("java.lang.String", "descriptor");
258     transact_statements->Add(std::make_shared<VariableDeclaration>(
259         transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
260   }
261   return transact_descriptor;
262 }
263 
make_as_interface(const AidlInterface * interfaceType)264 void StubClass::make_as_interface(const AidlInterface* interfaceType) {
265   auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
266 
267   auto m = std::make_shared<Method>();
268   m->comment = "/**\n * Cast an IBinder object into an ";
269   m->comment += interfaceType->GetCanonicalName();
270   m->comment += " interface,\n";
271   m->comment += " * generating a proxy if needed.\n */";
272   m->modifiers = PUBLIC | STATIC;
273   m->returnType = interfaceType->GetCanonicalName();
274   m->name = "asInterface";
275   m->parameters.push_back(obj);
276   m->statements = std::make_shared<StatementBlock>();
277 
278   auto ifstatement = std::make_shared<IfStatement>();
279   ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
280   ifstatement->statements = std::make_shared<StatementBlock>();
281   ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
282   m->statements->Add(ifstatement);
283 
284   // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
285   auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
286   queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
287   auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
288   auto iinVd = std::make_shared<VariableDeclaration>(iin, queryLocalInterface);
289   m->statements->Add(iinVd);
290 
291   // Ensure the instance type of the local object is as expected.
292   // One scenario where this is needed is if another package (with a
293   // different class loader) runs in the same process as the service.
294 
295   // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
296   // iin;
297   auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
298   auto instOfCheck = std::make_shared<Comparison>(
299       iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
300   auto instOfStatement = std::make_shared<IfStatement>();
301   instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
302   instOfStatement->statements = std::make_shared<StatementBlock>();
303   instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
304       std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
305   m->statements->Add(instOfStatement);
306 
307   auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
308   ne->arguments.push_back(obj);
309   m->statements->Add(std::make_shared<ReturnStatement>(ne));
310 
311   this->elements.push_back(m);
312 }
313 
314 // =================================================
315 class ProxyClass : public Class {
316  public:
317   ProxyClass(const AidlInterface* interfaceType, const Options& options);
318   ~ProxyClass() override;
319 
320   std::shared_ptr<Variable> mRemote;
321 };
322 
ProxyClass(const AidlInterface * interfaceType,const Options & options)323 ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
324   this->modifiers = PRIVATE | STATIC;
325   this->what = Class::CLASS;
326   this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
327   this->interfaces.push_back(interfaceType->GetCanonicalName());
328 
329   // IBinder mRemote
330   mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
331   this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));
332 
333   // Proxy()
334   auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
335   auto ctor = std::make_shared<Method>();
336   ctor->name = "Proxy";
337   ctor->statements = std::make_shared<StatementBlock>();
338   ctor->parameters.push_back(remote);
339   ctor->statements->Add(std::make_shared<Assignment>(mRemote, remote));
340   this->elements.push_back(ctor);
341 
342   if (options.Version() > 0) {
343     std::ostringstream code;
344     code << "private int mCachedVersion = -1;\n";
345     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
346   }
347   if (!options.Hash().empty()) {
348     std::ostringstream code;
349     code << "private String mCachedHash = \"-1\";\n";
350     this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
351   }
352 
353   // IBinder asBinder()
354   auto asBinder = std::make_shared<Method>();
355   asBinder->modifiers = PUBLIC | OVERRIDE;
356   asBinder->returnType = "android.os.IBinder";
357   asBinder->name = "asBinder";
358   asBinder->statements = std::make_shared<StatementBlock>();
359   asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
360   this->elements.push_back(asBinder);
361 }
362 
~ProxyClass()363 ProxyClass::~ProxyClass() {}
364 
365 // =================================================
generate_new_array(const AidlTypeSpecifier & type,const AidlTypenames & typenames,std::shared_ptr<StatementBlock> addTo,std::shared_ptr<Variable> v,std::shared_ptr<Variable> parcel)366 static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
367                                std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
368                                std::shared_ptr<Variable> parcel) {
369   auto len = std::make_shared<Variable>("int", v->name + "_length");
370   addTo->Add(
371       std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
372   auto lencheck = std::make_shared<IfStatement>();
373   lencheck->expression =
374       std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
375   lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
376   lencheck->elseif = std::make_shared<IfStatement>();
377   lencheck->elseif->statements->Add(std::make_shared<Assignment>(
378       v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
379   addTo->Add(lencheck);
380 }
381 
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)382 static void generate_write_to_parcel(const AidlTypeSpecifier& type,
383                                      std::shared_ptr<StatementBlock> addTo,
384                                      std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
385                                      bool is_return_value, const AidlTypenames& typenames) {
386   string code;
387   CodeWriterPtr writer = CodeWriter::ForString(&code);
388   CodeGeneratorContext context{
389       .writer = *(writer.get()),
390       .typenames = typenames,
391       .type = type,
392       .parcel = parcel->name,
393       .var = v->name,
394       .is_return_value = is_return_value,
395   };
396   WriteToParcelFor(context);
397   writer->Close();
398   addTo->Add(std::make_shared<LiteralStatement>(code));
399 }
400 
generate_int_constant(Class * interface,const std::string & name,const std::string & value)401 static void generate_int_constant(Class* interface, const std::string& name,
402                                   const std::string& value) {
403   auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
404   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
405 }
406 
generate_string_constant(Class * interface,const std::string & name,const std::string & value)407 static void generate_string_constant(Class* interface, const std::string& name,
408                                      const std::string& value) {
409   auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
410   interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
411 }
412 
generate_interface_method(const AidlMethod & method,const AidlTypenames & typenames)413 static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
414                                                          const AidlTypenames& typenames) {
415   auto decl = std::make_shared<Method>();
416   decl->comment = method.GetComments();
417   decl->modifiers = PUBLIC;
418   decl->returnType = JavaSignatureOf(method.GetType(), typenames);
419   decl->name = method.GetName();
420   decl->annotations = generate_java_annotations(method.GetType());
421 
422   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
423     decl->parameters.push_back(
424         std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
425   }
426 
427   decl->exceptions.push_back("android.os.RemoteException");
428 
429   return decl;
430 }
431 
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> statements,std::shared_ptr<StubClass> stubClass,const Options & options)432 static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
433                                std::shared_ptr<Variable> transact_data,
434                                std::shared_ptr<Variable> transact_reply,
435                                const AidlTypenames& typenames,
436                                std::shared_ptr<StatementBlock> statements,
437                                std::shared_ptr<StubClass> stubClass, const Options& options) {
438   std::shared_ptr<TryStatement> tryStatement;
439   std::shared_ptr<FinallyStatement> finallyStatement;
440   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
441 
442   // interface token validation is the very first thing we do
443   statements->Add(std::make_shared<MethodCall>(
444       transact_data, "enforceInterface",
445       std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
446 
447   // args
448   VariableFactory stubArgs("_arg");
449   {
450     // keep this across different args in order to create the classloader
451     // at most once.
452     bool is_classloader_created = false;
453     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
454       std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
455 
456       statements->Add(std::make_shared<VariableDeclaration>(v));
457 
458       if (arg->GetDirection() & AidlArgument::IN_DIR) {
459         string code;
460         CodeWriterPtr writer = CodeWriter::ForString(&code);
461         CodeGeneratorContext context{.writer = *(writer.get()),
462                                      .typenames = typenames,
463                                      .type = arg->GetType(),
464                                      .parcel = transact_data->name,
465                                      .var = v->name,
466                                      .is_classloader_created = &is_classloader_created};
467         CreateFromParcelFor(context);
468         writer->Close();
469         statements->Add(std::make_shared<LiteralStatement>(code));
470       } else {
471         if (!arg->GetType().IsArray()) {
472           statements->Add(std::make_shared<Assignment>(
473               v, std::make_shared<NewExpression>(
474                      InstantiableJavaSignatureOf(arg->GetType(), typenames))));
475         } else {
476           generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
477         }
478       }
479 
480       realCall->arguments.push_back(v);
481     }
482   }
483 
484   if (options.GenTraces()) {
485     // try and finally, but only when generating trace code
486     tryStatement = std::make_shared<TryStatement>();
487     finallyStatement = std::make_shared<FinallyStatement>();
488 
489     tryStatement->statements->Add(std::make_shared<MethodCall>(
490         std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
491         std::vector<std::shared_ptr<Expression>>{
492             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
493             std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
494                                                       "::server")}));
495 
496     finallyStatement->statements->Add(std::make_shared<MethodCall>(
497         std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
498         std::vector<std::shared_ptr<Expression>>{
499             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
500   }
501 
502   // the real call
503   if (method.GetType().GetName() == "void") {
504     if (options.GenTraces()) {
505       statements->Add(tryStatement);
506       tryStatement->statements->Add(realCall);
507       statements->Add(finallyStatement);
508     } else {
509       statements->Add(realCall);
510     }
511 
512     if (!oneway) {
513       // report that there were no exceptions
514       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
515       statements->Add(ex);
516     }
517   } else {
518     auto _result =
519         std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
520     if (options.GenTraces()) {
521       statements->Add(std::make_shared<VariableDeclaration>(_result));
522       statements->Add(tryStatement);
523       tryStatement->statements->Add(std::make_shared<Assignment>(_result, realCall));
524       statements->Add(finallyStatement);
525     } else {
526       statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
527     }
528 
529     if (!oneway) {
530       // report that there were no exceptions
531       auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
532       statements->Add(ex);
533     }
534 
535     // marshall the return value
536     generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
537                              typenames);
538   }
539 
540   // out parameters
541   int i = 0;
542   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
543     std::shared_ptr<Variable> v = stubArgs.Get(i++);
544 
545     if (arg->GetDirection() & AidlArgument::OUT_DIR) {
546       generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
547     }
548   }
549 
550   // return true
551   statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
552 }
553 
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)554 static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
555                                const std::string& transactCodeName, bool oneway,
556                                std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
557                                const Options& options) {
558   auto c = std::make_shared<Case>(transactCodeName);
559 
560   generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
561                      typenames, c->statements, stubClass, options);
562 
563   stubClass->transact_switch->cases.push_back(c);
564 }
565 
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)566 static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
567                                        const std::string& transactCodeName, bool oneway,
568                                        std::shared_ptr<StubClass> stubClass,
569                                        const AidlTypenames& typenames, const Options& options) {
570   std::string outline_name = "onTransact$" + method.GetName() + "$";
571   // Generate an "outlined" method with the actual code.
572   {
573     auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
574     auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
575     auto onTransact_case = std::make_shared<Method>();
576     onTransact_case->modifiers = PRIVATE;
577     onTransact_case->returnType = "boolean";
578     onTransact_case->name = outline_name;
579     onTransact_case->parameters.push_back(transact_data);
580     onTransact_case->parameters.push_back(transact_reply);
581     onTransact_case->statements = std::make_shared<StatementBlock>();
582     onTransact_case->exceptions.push_back("android.os.RemoteException");
583     stubClass->elements.push_back(onTransact_case);
584 
585     generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
586                        onTransact_case->statements, stubClass, options);
587   }
588 
589   // Generate the case dispatch.
590   {
591     auto c = std::make_shared<Case>(transactCodeName);
592 
593     auto helper_call =
594         std::make_shared<MethodCall>(THIS_VALUE, outline_name,
595                                      std::vector<std::shared_ptr<Expression>>{
596                                          stubClass->transact_data, stubClass->transact_reply});
597     c->statements->Add(std::make_shared<ReturnStatement>(helper_call));
598 
599     stubClass->transact_switch->cases.push_back(c);
600   }
601 }
602 
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)603 static std::shared_ptr<Method> generate_proxy_method(
604     const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
605     bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
606     const Options& options) {
607   auto proxy = std::make_shared<Method>();
608   proxy->comment = method.GetComments();
609   proxy->modifiers = PUBLIC | OVERRIDE;
610   proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
611   proxy->name = method.GetName();
612   proxy->statements = std::make_shared<StatementBlock>();
613   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
614     proxy->parameters.push_back(
615         std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
616   }
617   proxy->exceptions.push_back("android.os.RemoteException");
618 
619   // the parcels
620   auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
621   proxy->statements->Add(std::make_shared<VariableDeclaration>(
622       _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
623   std::shared_ptr<Variable> _reply = nullptr;
624   if (!oneway) {
625     _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
626     proxy->statements->Add(std::make_shared<VariableDeclaration>(
627         _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
628   }
629 
630   // the return value
631   std::shared_ptr<Variable> _result = nullptr;
632   if (method.GetType().GetName() != "void") {
633     _result = std::make_shared<Variable>(*proxy->returnType, "_result");
634     proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
635   }
636 
637   // try and finally
638   auto tryStatement = std::make_shared<TryStatement>();
639   proxy->statements->Add(tryStatement);
640   auto finallyStatement = std::make_shared<FinallyStatement>();
641   proxy->statements->Add(finallyStatement);
642 
643   if (options.GenTraces()) {
644     tryStatement->statements->Add(std::make_shared<MethodCall>(
645         std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
646         std::vector<std::shared_ptr<Expression>>{
647             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
648             std::make_shared<StringLiteralExpression>(iface.GetName() + "::" + method.GetName() +
649                                                       "::client")}));
650   }
651 
652   // the interface identifier token: the DESCRIPTOR constant, marshalled as a
653   // string
654   tryStatement->statements->Add(std::make_shared<MethodCall>(
655       _data, "writeInterfaceToken",
656       std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));
657 
658   // the parameters
659   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
660     auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
661     AidlArgument::Direction dir = arg->GetDirection();
662     if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
663       auto checklen = std::make_shared<IfStatement>();
664       checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
665       checklen->statements->Add(std::make_shared<MethodCall>(
666           _data, "writeInt",
667           std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
668       checklen->elseif = std::make_shared<IfStatement>();
669       checklen->elseif->statements->Add(std::make_shared<MethodCall>(
670           _data, "writeInt",
671           std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
672       tryStatement->statements->Add(checklen);
673     } else if (dir & AidlArgument::IN_DIR) {
674       generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
675                                typenames);
676     }
677   }
678 
679   // the transact call
680   auto call = std::make_shared<MethodCall>(
681       proxyClass->mRemote, "transact",
682       std::vector<std::shared_ptr<Expression>>{
683           std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
684           _reply ? _reply : NULL_VALUE,
685           std::make_shared<LiteralExpression>(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")});
686   auto _status = std::make_shared<Variable>("boolean", "_status");
687   tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
688 
689   // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
690   // back to the local method in the default impl, if set before.
691   vector<string> arg_names;
692   for (const auto& arg : method.GetArguments()) {
693     arg_names.emplace_back(arg->GetName());
694   }
695   bool has_return_type = method.GetType().GetName() != "void";
696   tryStatement->statements->Add(std::make_shared<LiteralStatement>(
697       android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
698                                                     "  return getDefaultImpl().%s(%s);\n"
699                                                     "}\n"
700                                                   : "if (!_status && getDefaultImpl() != null) {\n"
701                                                     "  getDefaultImpl().%s(%s);\n"
702                                                     "  return;\n"
703                                                     "}\n",
704                                   method.GetName().c_str(), Join(arg_names, ", ").c_str())));
705 
706   // throw back exceptions.
707   if (_reply) {
708     auto ex = std::make_shared<MethodCall>(_reply, "readException");
709     tryStatement->statements->Add(ex);
710   }
711 
712   // returning and cleanup
713   if (_reply != nullptr) {
714     // keep this across return value and arguments in order to create the
715     // classloader at most once.
716     bool is_classloader_created = false;
717     if (_result != nullptr) {
718       string code;
719       CodeWriterPtr writer = CodeWriter::ForString(&code);
720       CodeGeneratorContext context{.writer = *(writer.get()),
721                                    .typenames = typenames,
722                                    .type = method.GetType(),
723                                    .parcel = _reply->name,
724                                    .var = _result->name,
725                                    .is_classloader_created = &is_classloader_created};
726       CreateFromParcelFor(context);
727       writer->Close();
728       tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
729     }
730 
731     // the out/inout parameters
732     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
733       if (arg->GetDirection() & AidlArgument::OUT_DIR) {
734         string code;
735         CodeWriterPtr writer = CodeWriter::ForString(&code);
736         CodeGeneratorContext context{.writer = *(writer.get()),
737                                      .typenames = typenames,
738                                      .type = arg->GetType(),
739                                      .parcel = _reply->name,
740                                      .var = arg->GetName(),
741                                      .is_classloader_created = &is_classloader_created};
742         ReadFromParcelFor(context);
743         writer->Close();
744         tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
745       }
746     }
747 
748     finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
749   }
750   finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));
751 
752   if (options.GenTraces()) {
753     finallyStatement->statements->Add(std::make_shared<MethodCall>(
754         std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
755         std::vector<std::shared_ptr<Expression>>{
756             std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
757   }
758 
759   if (_result != nullptr) {
760     proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
761   }
762 
763   return proxy;
764 }
765 
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)766 static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
767                              std::shared_ptr<StubClass> stubClass,
768                              std::shared_ptr<ProxyClass> proxyClass, int index,
769                              const AidlTypenames& typenames, const Options& options) {
770   const bool oneway = method.IsOneway();
771 
772   // == the TRANSACT_ constant =============================================
773   string transactCodeName = "TRANSACTION_";
774   transactCodeName += method.GetName();
775 
776   auto transactCode =
777       std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
778   transactCode->value =
779       StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
780   stubClass->elements.push_back(transactCode);
781 
782   // getTransactionName
783   if (options.GenTransactionNames()) {
784     auto c = std::make_shared<Case>(transactCodeName);
785     c->statements->Add(std::make_shared<ReturnStatement>(
786         std::make_shared<StringLiteralExpression>(method.GetName())));
787     stubClass->code_to_method_name_switch->cases.push_back(c);
788   }
789 
790   // == the declaration in the interface ===================================
791   std::shared_ptr<ClassElement> decl;
792   if (method.IsUserDefined()) {
793     decl = generate_interface_method(method, typenames);
794   } else {
795     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
796       std::ostringstream code;
797       code << "public int " << kGetInterfaceVersion << "() "
798            << "throws android.os.RemoteException;\n";
799       decl = std::make_shared<LiteralClassElement>(code.str());
800     }
801     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
802       std::ostringstream code;
803       code << "public String " << kGetInterfaceHash << "() "
804            << "throws android.os.RemoteException;\n";
805       decl = std::make_shared<LiteralClassElement>(code.str());
806     }
807   }
808   interface->elements.push_back(decl);
809 
810   // == the stub method ====================================================
811   if (method.IsUserDefined()) {
812     bool outline_stub =
813         stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
814     if (outline_stub) {
815       generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
816                                  options);
817     } else {
818       generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
819     }
820   } else {
821     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
822       auto c = std::make_shared<Case>(transactCodeName);
823       std::ostringstream code;
824       code << "data.enforceInterface(descriptor);\n"
825            << "reply.writeNoException();\n"
826            << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
827            << "return true;\n";
828       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
829       stubClass->transact_switch->cases.push_back(c);
830     }
831     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
832       auto c = std::make_shared<Case>(transactCodeName);
833       std::ostringstream code;
834       code << "data.enforceInterface(descriptor);\n"
835            << "reply.writeNoException();\n"
836            << "reply.writeString(" << kGetInterfaceHash << "());\n"
837            << "return true;\n";
838       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
839       stubClass->transact_switch->cases.push_back(c);
840     }
841   }
842 
843   // == the proxy method ===================================================
844   std::shared_ptr<ClassElement> proxy = nullptr;
845   if (method.IsUserDefined()) {
846     proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
847                                   options);
848 
849   } else {
850     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
851       std::ostringstream code;
852       code << "@Override\n"
853            << "public int " << kGetInterfaceVersion << "()"
854            << " throws "
855            << "android.os.RemoteException {\n"
856            << "  if (mCachedVersion == -1) {\n"
857            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
858            << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
859            << "    try {\n"
860            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
861            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
862            << "data, reply, 0);\n"
863            << "      if (!_status) {\n"
864            << "        if (getDefaultImpl() != null) {\n"
865            << "          return getDefaultImpl().getInterfaceVersion();\n"
866            << "        }\n"
867            << "      }\n"
868            << "      reply.readException();\n"
869            << "      mCachedVersion = reply.readInt();\n"
870            << "    } finally {\n"
871            << "      reply.recycle();\n"
872            << "      data.recycle();\n"
873            << "    }\n"
874            << "  }\n"
875            << "  return mCachedVersion;\n"
876            << "}\n";
877       proxy = std::make_shared<LiteralClassElement>(code.str());
878     }
879     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
880       std::ostringstream code;
881       code << "@Override\n"
882            << "public synchronized String " << kGetInterfaceHash << "()"
883            << " throws "
884            << "android.os.RemoteException {\n"
885            << "  if (\"-1\".equals(mCachedHash)) {\n"
886            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
887            << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
888            << "    try {\n"
889            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
890            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
891            << "data, reply, 0);\n"
892            << "      if (!_status) {\n"
893            << "        if (getDefaultImpl() != null) {\n"
894            << "          return getDefaultImpl().getInterfaceHash();\n"
895            << "        }\n"
896            << "      }\n"
897            << "      reply.readException();\n"
898            << "      mCachedHash = reply.readString();\n"
899            << "    } finally {\n"
900            << "      reply.recycle();\n"
901            << "      data.recycle();\n"
902            << "    }\n"
903            << "  }\n"
904            << "  return mCachedHash;\n"
905            << "}\n";
906       proxy = std::make_shared<LiteralClassElement>(code.str());
907     }
908   }
909   if (proxy != nullptr) {
910     proxyClass->elements.push_back(proxy);
911   }
912 }
913 
generate_interface_descriptors(std::shared_ptr<StubClass> stub,std::shared_ptr<ProxyClass> proxy)914 static void generate_interface_descriptors(std::shared_ptr<StubClass> stub,
915                                            std::shared_ptr<ProxyClass> proxy) {
916   // the interface descriptor transaction handler
917   auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
918   c->statements->Add(std::make_shared<MethodCall>(
919       stub->transact_reply, "writeString",
920       std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
921   c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
922   stub->transact_switch->cases.push_back(c);
923 
924   // and the proxy-side method returning the descriptor directly
925   auto getDesc = std::make_shared<Method>();
926   getDesc->modifiers = PUBLIC;
927   getDesc->returnType = "java.lang.String";
928   getDesc->name = "getInterfaceDescriptor";
929   getDesc->statements = std::make_shared<StatementBlock>();
930   getDesc->statements->Add(
931       std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
932   proxy->elements.push_back(getDesc);
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(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