• 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