/*
 * Copyright (C) 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "aidl.h"
#include "aidl_to_java.h"
#include "generate_java.h"
#include "options.h"
#include "type_java.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <algorithm>
#include <unordered_set>
#include <utility>
#include <vector>

#include <android-base/macros.h>
#include <android-base/stringprintf.h>

using android::base::Join;
using android::base::StringPrintf;

using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;

namespace android {
namespace aidl {
namespace java {

// =================================================
class VariableFactory {
 public:
  using Variable = ::android::aidl::java::Variable;
  using Type = ::android::aidl::java::Type;

  explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
  Variable* Get(const Type* type) {
    Variable* v = new Variable(type, StringPrintf("%s%d", base_.c_str(), index_));
    vars_.push_back(v);
    index_++;
    return v;
  }

  Variable* Get(int index) { return vars_[index]; }

 private:
  std::vector<Variable*> vars_;
  std::string base_;
  int index_;

  DISALLOW_COPY_AND_ASSIGN(VariableFactory);
};

// =================================================
class StubClass : public Class {
 public:
  StubClass(const Type* type, const InterfaceType* interfaceType, JavaTypeNamespace* types,
            const Options& options);
  virtual ~StubClass() = default;

  Variable* transact_code;
  Variable* transact_data;
  Variable* transact_reply;
  Variable* transact_flags;
  SwitchStatement* transact_switch;
  StatementBlock* transact_statements;
  SwitchStatement* code_to_method_name_switch;

  // Where onTransact cases should be generated as separate methods.
  bool transact_outline;
  // Specific methods that should be outlined when transact_outline is true.
  std::unordered_set<const AidlMethod*> outline_methods;
  // Number of all methods.
  size_t all_method_count;

  // Finish generation. This will add a default case to the switch.
  void finish();

  Expression* get_transact_descriptor(const JavaTypeNamespace* types,
                                      const AidlMethod* method);

 private:
  void make_as_interface(const InterfaceType* interfaceType,
                         JavaTypeNamespace* types);

  Variable* transact_descriptor;
  const Options& options_;

  DISALLOW_COPY_AND_ASSIGN(StubClass);
};

StubClass::StubClass(const Type* type, const InterfaceType* interfaceType, JavaTypeNamespace* types,
                     const Options& options)
    : Class(), options_(options) {
  transact_descriptor = nullptr;
  transact_outline = false;
  all_method_count = 0;  // Will be set when outlining may be enabled.

  this->comment = "/** Local-side IPC implementation stub class. */";
  this->modifiers = PUBLIC | ABSTRACT | STATIC;
  this->what = Class::CLASS;
  this->type = type;
  this->extends = types->BinderNativeType();
  this->interfaces.push_back(interfaceType);

  // descriptor
  Field* descriptor =
      new Field(STATIC | FINAL | PRIVATE,
                new Variable(types->StringType(), "DESCRIPTOR"));
  descriptor->value = "\"" + interfaceType->JavaType() + "\"";
  this->elements.push_back(descriptor);

  // ctor
  Method* ctor = new Method;
  ctor->modifiers = PUBLIC;
  ctor->comment =
      "/** Construct the stub at attach it to the "
      "interface. */";
  ctor->name = "Stub";
  ctor->statements = new StatementBlock;
  MethodCall* attach =
      new MethodCall(THIS_VALUE, "attachInterface", 2, THIS_VALUE,
                     new LiteralExpression("DESCRIPTOR"));
  ctor->statements->Add(attach);
  this->elements.push_back(ctor);

  // asInterface
  make_as_interface(interfaceType, types);

  // asBinder
  Method* asBinder = new Method;
  asBinder->modifiers = PUBLIC | OVERRIDE;
  asBinder->returnType = types->IBinderType();
  asBinder->name = "asBinder";
  asBinder->statements = new StatementBlock;
  asBinder->statements->Add(new ReturnStatement(THIS_VALUE));
  this->elements.push_back(asBinder);

  if (options_.GenTransactionNames()) {
    // getDefaultTransactionName
    Method* getDefaultTransactionName = new Method;
    getDefaultTransactionName->modifiers = PUBLIC | STATIC;
    getDefaultTransactionName->returnType = types->StringType();
    getDefaultTransactionName->name = "getDefaultTransactionName";
    Variable* code = new Variable(types->IntType(), "transactionCode");
    getDefaultTransactionName->parameters.push_back(code);
    getDefaultTransactionName->statements = new StatementBlock;
    this->code_to_method_name_switch = new SwitchStatement(code);
    getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
    this->elements.push_back(getDefaultTransactionName);

    // getTransactionName
    Method* getTransactionName = new Method;
    getTransactionName->modifiers = PUBLIC;
    getTransactionName->returnType = types->StringType();
    getTransactionName->name = "getTransactionName";
    Variable* code2 = new Variable(types->IntType(), "transactionCode");
    getTransactionName->parameters.push_back(code2);
    getTransactionName->statements = new StatementBlock;
    getTransactionName->statements->Add(
        new ReturnStatement(new MethodCall(THIS_VALUE, "getDefaultTransactionName", 1, code2)));
    this->elements.push_back(getTransactionName);
  }

  // onTransact
  this->transact_code = new Variable(types->IntType(), "code");
  this->transact_data = new Variable(types->ParcelType(), "data");
  this->transact_reply = new Variable(types->ParcelType(), "reply");
  this->transact_flags = new Variable(types->IntType(), "flags");
  Method* onTransact = new Method;
  onTransact->modifiers = PUBLIC | OVERRIDE;
  onTransact->returnType = types->BoolType();
  onTransact->name = "onTransact";
  onTransact->parameters.push_back(this->transact_code);
  onTransact->parameters.push_back(this->transact_data);
  onTransact->parameters.push_back(this->transact_reply);
  onTransact->parameters.push_back(this->transact_flags);
  onTransact->statements = new StatementBlock;
  transact_statements = onTransact->statements;
  onTransact->exceptions.push_back(types->RemoteExceptionType());
  this->elements.push_back(onTransact);
  this->transact_switch = new SwitchStatement(this->transact_code);
}

void StubClass::finish() {
  Case* default_case = new Case;

  MethodCall* superCall = new MethodCall(
        SUPER_VALUE, "onTransact", 4, this->transact_code, this->transact_data,
        this->transact_reply, this->transact_flags);
  default_case->statements->Add(new ReturnStatement(superCall));
  transact_switch->cases.push_back(default_case);

  transact_statements->Add(this->transact_switch);

  // getTransactionName
  if (options_.GenTransactionNames()) {
    // Some transaction codes are common, e.g. INTERFACE_TRANSACTION or DUMP_TRANSACTION.
    // Common transaction codes will not be resolved to a string by getTransactionName. The method
    // will return NULL in this case.
    Case* code_switch_default_case = new Case;
    code_switch_default_case->statements->Add(new ReturnStatement(NULL_VALUE));
    this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
  }
}

// The the expression for the interface's descriptor to be used when
// generating code for the given method. Null is acceptable for method
// and stands for synthetic cases.
Expression* StubClass::get_transact_descriptor(const JavaTypeNamespace* types,
                                               const AidlMethod* method) {
  if (transact_outline) {
    if (method != nullptr) {
      // When outlining, each outlined method needs its own literal.
      if (outline_methods.count(method) != 0) {
        return new LiteralExpression("DESCRIPTOR");
      }
    } else {
      // Synthetic case. A small number is assumed. Use its own descriptor
      // if there are only synthetic cases.
      if (outline_methods.size() == all_method_count) {
        return new LiteralExpression("DESCRIPTOR");
      }
    }
  }

  // When not outlining, store the descriptor literal into a local variable, in
  // an effort to save const-string instructions in each switch case.
  if (transact_descriptor == nullptr) {
    transact_descriptor = new Variable(types->StringType(), "descriptor");
    transact_statements->Add(
        new VariableDeclaration(transact_descriptor,
                                new LiteralExpression("DESCRIPTOR")));
  }
  return transact_descriptor;
}

void StubClass::make_as_interface(const InterfaceType* interfaceType,
                                  JavaTypeNamespace* types) {
  Variable* obj = new Variable(types->IBinderType(), "obj");

  Method* m = new Method;
  m->comment = "/**\n * Cast an IBinder object into an ";
  m->comment += interfaceType->JavaType();
  m->comment += " interface,\n";
  m->comment += " * generating a proxy if needed.\n */";
  m->modifiers = PUBLIC | STATIC;
  m->returnType = interfaceType;
  m->name = "asInterface";
  m->parameters.push_back(obj);
  m->statements = new StatementBlock;

  IfStatement* ifstatement = new IfStatement();
  ifstatement->expression = new Comparison(obj, "==", NULL_VALUE);
  ifstatement->statements = new StatementBlock;
  ifstatement->statements->Add(new ReturnStatement(NULL_VALUE));
  m->statements->Add(ifstatement);

  // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
  MethodCall* queryLocalInterface = new MethodCall(obj, "queryLocalInterface");
  queryLocalInterface->arguments.push_back(new LiteralExpression("DESCRIPTOR"));
  IInterfaceType* iinType = new IInterfaceType(types);
  Variable* iin = new Variable(iinType, "iin");
  VariableDeclaration* iinVd =
      new VariableDeclaration(iin, queryLocalInterface, nullptr);
  m->statements->Add(iinVd);

  // Ensure the instance type of the local object is as expected.
  // One scenario where this is needed is if another package (with a
  // different class loader) runs in the same process as the service.

  // if (iin != null && iin instanceof <interfaceType>) return (<interfaceType>)
  // iin;
  Comparison* iinNotNull = new Comparison(iin, "!=", NULL_VALUE);
  Comparison* instOfCheck =
      new Comparison(iin, " instanceof ",
                     new LiteralExpression(interfaceType->JavaType()));
  IfStatement* instOfStatement = new IfStatement();
  instOfStatement->expression = new Comparison(iinNotNull, "&&", instOfCheck);
  instOfStatement->statements = new StatementBlock;
  instOfStatement->statements->Add(
      new ReturnStatement(new Cast(interfaceType, iin)));
  m->statements->Add(instOfStatement);

  NewExpression* ne = new NewExpression(interfaceType->GetProxy());
  ne->arguments.push_back(obj);
  m->statements->Add(new ReturnStatement(ne));

  this->elements.push_back(m);
}

// =================================================
class ProxyClass : public Class {
 public:
  ProxyClass(const JavaTypeNamespace* types, const Type* type, const InterfaceType* interfaceType,
             const Options& options);
  virtual ~ProxyClass();

  Variable* mRemote;
  bool mOneWay;
};

ProxyClass::ProxyClass(const JavaTypeNamespace* types, const Type* type,
                       const InterfaceType* interfaceType, const Options& options)
    : Class() {
  this->modifiers = PRIVATE | STATIC;
  this->what = Class::CLASS;
  this->type = type;
  this->interfaces.push_back(interfaceType);

  mOneWay = interfaceType->OneWay();

  // IBinder mRemote
  mRemote = new Variable(types->IBinderType(), "mRemote");
  this->elements.push_back(new Field(PRIVATE, mRemote));

  // Proxy()
  Variable* remote = new Variable(types->IBinderType(), "remote");
  Method* ctor = new Method;
  ctor->name = "Proxy";
  ctor->statements = new StatementBlock;
  ctor->parameters.push_back(remote);
  ctor->statements->Add(new Assignment(mRemote, remote));
  this->elements.push_back(ctor);

  if (options.Version() > 0) {
    std::ostringstream code;
    code << "private int mCachedVersion = -1;\n";
    this->elements.emplace_back(new LiteralClassElement(code.str()));
  }

  // IBinder asBinder()
  Method* asBinder = new Method;
  asBinder->modifiers = PUBLIC | OVERRIDE;
  asBinder->returnType = types->IBinderType();
  asBinder->name = "asBinder";
  asBinder->statements = new StatementBlock;
  asBinder->statements->Add(new ReturnStatement(mRemote));
  this->elements.push_back(asBinder);
}

ProxyClass::~ProxyClass() {}

// =================================================
static void generate_new_array(const Type* t, StatementBlock* addTo,
                               Variable* v, Variable* parcel,
                               JavaTypeNamespace* types) {
  Variable* len = new Variable(types->IntType(), v->name + "_length");
  addTo->Add(new VariableDeclaration(len, new MethodCall(parcel, "readInt")));
  IfStatement* lencheck = new IfStatement();
  lencheck->expression = new Comparison(len, "<", new LiteralExpression("0"));
  lencheck->statements->Add(new Assignment(v, NULL_VALUE));
  lencheck->elseif = new IfStatement();
  lencheck->elseif->statements->Add(
      new Assignment(v, new NewArrayExpression(t, len)));
  addTo->Add(lencheck);
}

static void generate_write_to_parcel(const AidlTypeSpecifier& type, StatementBlock* addTo,
                                     Variable* v, Variable* parcel, bool is_return_value,
                                     const AidlTypenames& typenames) {
  string code;
  CodeWriterPtr writer = CodeWriter::ForString(&code);
  CodeGeneratorContext context{
      .writer = *(writer.get()),
      .typenames = typenames,
      .type = type,
      .var = v->name,
      .parcel = parcel->name,
      .is_return_value = is_return_value,
  };
  WriteToParcelFor(context);
  writer->Close();
  addTo->Add(new LiteralStatement(code));
}

static void generate_int_constant(Class* interface, const std::string& name,
                                  const std::string& value) {
  IntConstant* decl = new IntConstant(name, value);
  interface->elements.push_back(decl);
}

static void generate_string_constant(Class* interface, const std::string& name,
                                     const std::string& value) {
  StringConstant* decl = new StringConstant(name, value);
  interface->elements.push_back(decl);
}

static std::unique_ptr<Method> generate_interface_method(
    const AidlMethod& method, JavaTypeNamespace* types) {
  std::unique_ptr<Method> decl(new Method);
  decl->comment = method.GetComments();
  decl->modifiers = PUBLIC;
  decl->returnType = method.GetType().GetLanguageType<Type>();
  decl->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
  decl->name = method.GetName();
  decl->annotations = generate_java_annotations(method.GetType());

  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    decl->parameters.push_back(
        new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(),
                     arg->GetType().IsArray() ? 1 : 0));
  }

  decl->exceptions.push_back(types->RemoteExceptionType());

  return decl;
}

static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
                               Variable* transact_data, Variable* transact_reply,
                               JavaTypeNamespace* types, StatementBlock* statements,
                               StubClass* stubClass, const Options& options) {
  TryStatement* tryStatement = nullptr;
  FinallyStatement* finallyStatement = nullptr;
  MethodCall* realCall = new MethodCall(THIS_VALUE, method.GetName());

  // interface token validation is the very first thing we do
  statements->Add(new MethodCall(transact_data,
                                 "enforceInterface", 1,
                                 stubClass->get_transact_descriptor(types,
                                                                    &method)));

  // args
  VariableFactory stubArgs("_arg");
  {
    // keep this across different args in order to create the classloader
    // at most once.
    bool is_classloader_created = false;
    for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
      const Type* t = arg->GetType().GetLanguageType<Type>();
      Variable* v = stubArgs.Get(t);
      v->dimension = arg->GetType().IsArray() ? 1 : 0;

      statements->Add(new VariableDeclaration(v));

      if (arg->GetDirection() & AidlArgument::IN_DIR) {
        string code;
        CodeWriterPtr writer = CodeWriter::ForString(&code);
        CodeGeneratorContext context{.writer = *(writer.get()),
                                     .typenames = types->typenames_,
                                     .type = arg->GetType(),
                                     .var = v->name,
                                     .parcel = transact_data->name,
                                     .is_classloader_created = &is_classloader_created};
        CreateFromParcelFor(context);
        writer->Close();
        statements->Add(new LiteralStatement(code));
      } else {
        if (!arg->GetType().IsArray()) {
          statements->Add(new Assignment(v, new NewExpression(v->type)));
        } else {
          generate_new_array(v->type,
                             statements,
                             v,
                             transact_data,
                             types);
        }
      }

      realCall->arguments.push_back(v);
    }
  }

  if (options.GenTraces()) {
    // try and finally, but only when generating trace code
    tryStatement = new TryStatement();
    finallyStatement = new FinallyStatement();

    tryStatement->statements->Add(new MethodCall(
        new LiteralExpression("android.os.Trace"), "traceBegin", 2,
        new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
        new StringLiteralExpression(iface.GetName() + "::"
            + method.GetName() + "::server")));

    finallyStatement->statements->Add(new MethodCall(
        new LiteralExpression("android.os.Trace"), "traceEnd", 1,
        new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
  }

  // the real call
  if (method.GetType().GetName() == "void") {
    if (options.GenTraces()) {
      statements->Add(tryStatement);
      tryStatement->statements->Add(realCall);
      statements->Add(finallyStatement);
    } else {
      statements->Add(realCall);
    }

    if (!oneway) {
      // report that there were no exceptions
      MethodCall* ex =
          new MethodCall(transact_reply, "writeNoException", 0);
      statements->Add(ex);
    }
  } else {
    Variable* _result =
        new Variable(method.GetType().GetLanguageType<Type>(),
                     "_result",
                     method.GetType().IsArray() ? 1 : 0);
    if (options.GenTraces()) {
      statements->Add(new VariableDeclaration(_result));
      statements->Add(tryStatement);
      tryStatement->statements->Add(new Assignment(_result, realCall));
      statements->Add(finallyStatement);
    } else {
      statements->Add(new VariableDeclaration(_result, realCall));
    }

    if (!oneway) {
      // report that there were no exceptions
      MethodCall* ex =
          new MethodCall(transact_reply, "writeNoException", 0);
      statements->Add(ex);
    }

    // marshall the return value
    generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
                             types->typenames_);
  }

  // out parameters
  int i = 0;
  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    Variable* v = stubArgs.Get(i++);

    if (arg->GetDirection() & AidlArgument::OUT_DIR) {
      generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true,
                               types->typenames_);
    }
  }

  // return true
  statements->Add(new ReturnStatement(TRUE_VALUE));
}

static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
                               const std::string& transactCodeName, bool oneway,
                               StubClass* stubClass, JavaTypeNamespace* types,
                               const Options& options) {
  Case* c = new Case(transactCodeName);

  generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
                     types, c->statements, stubClass, options);

  stubClass->transact_switch->cases.push_back(c);
}

static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
                                       const std::string& transactCodeName, bool oneway,
                                       StubClass* stubClass, JavaTypeNamespace* types,
                                       const Options& options) {
  std::string outline_name = "onTransact$" + method.GetName() + "$";
  // Generate an "outlined" method with the actual code.
  {
    Variable* transact_data = new Variable(types->ParcelType(), "data");
    Variable* transact_reply = new Variable(types->ParcelType(), "reply");
    Method* onTransact_case = new Method;
    onTransact_case->modifiers = PRIVATE;
    onTransact_case->returnType = types->BoolType();
    onTransact_case->name = outline_name;
    onTransact_case->parameters.push_back(transact_data);
    onTransact_case->parameters.push_back(transact_reply);
    onTransact_case->statements = new StatementBlock;
    onTransact_case->exceptions.push_back(types->RemoteExceptionType());
    stubClass->elements.push_back(onTransact_case);

    generate_stub_code(iface, method, oneway, transact_data, transact_reply, types,
                       onTransact_case->statements, stubClass, options);
  }

  // Generate the case dispatch.
  {
    Case* c = new Case(transactCodeName);

    MethodCall* helper_call = new MethodCall(THIS_VALUE,
                                             outline_name,
                                             2,
                                             stubClass->transact_data,
                                             stubClass->transact_reply);
    c->statements->Add(new ReturnStatement(helper_call));

    stubClass->transact_switch->cases.push_back(c);
  }
}

static std::unique_ptr<Method> generate_proxy_method(
    const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
    bool oneway, ProxyClass* proxyClass, JavaTypeNamespace* types, const Options& options) {
  std::unique_ptr<Method> proxy(new Method);
  proxy->comment = method.GetComments();
  proxy->modifiers = PUBLIC | OVERRIDE;
  proxy->returnType = method.GetType().GetLanguageType<Type>();
  proxy->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
  proxy->name = method.GetName();
  proxy->statements = new StatementBlock;
  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    proxy->parameters.push_back(
        new Variable(arg->GetType().GetLanguageType<Type>(), arg->GetName(),
                     arg->GetType().IsArray() ? 1 : 0));
  }
  proxy->exceptions.push_back(types->RemoteExceptionType());

  // the parcels
  Variable* _data = new Variable(types->ParcelType(), "_data");
  proxy->statements->Add(new VariableDeclaration(
      _data, new MethodCall(types->ParcelType(), "obtain")));
  Variable* _reply = nullptr;
  if (!oneway) {
    _reply = new Variable(types->ParcelType(), "_reply");
    proxy->statements->Add(new VariableDeclaration(
        _reply, new MethodCall(types->ParcelType(), "obtain")));
  }

  // the return value
  Variable* _result = nullptr;
  if (method.GetType().GetName() != "void") {
    _result = new Variable(proxy->returnType, "_result",
                           method.GetType().IsArray() ? 1 : 0);
    proxy->statements->Add(new VariableDeclaration(_result));
  }

  // try and finally
  TryStatement* tryStatement = new TryStatement();
  proxy->statements->Add(tryStatement);
  FinallyStatement* finallyStatement = new FinallyStatement();
  proxy->statements->Add(finallyStatement);

  if (options.GenTraces()) {
    tryStatement->statements->Add(new MethodCall(
          new LiteralExpression("android.os.Trace"), "traceBegin", 2,
          new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL"),
          new StringLiteralExpression(iface.GetName() + "::" +
                                      method.GetName() + "::client")));
  }

  // the interface identifier token: the DESCRIPTOR constant, marshalled as a
  // string
  tryStatement->statements->Add(new MethodCall(
      _data, "writeInterfaceToken", 1, new LiteralExpression("DESCRIPTOR")));

  // the parameters
  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    const Type* t = arg->GetType().GetLanguageType<Type>();
    Variable* v =
        new Variable(t, arg->GetName(), arg->GetType().IsArray() ? 1 : 0);
    AidlArgument::Direction dir = arg->GetDirection();
    if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
      IfStatement* checklen = new IfStatement();
      checklen->expression = new Comparison(v, "==", NULL_VALUE);
      checklen->statements->Add(
          new MethodCall(_data, "writeInt", 1, new LiteralExpression("-1")));
      checklen->elseif = new IfStatement();
      checklen->elseif->statements->Add(
          new MethodCall(_data, "writeInt", 1, new FieldVariable(v, "length")));
      tryStatement->statements->Add(checklen);
    } else if (dir & AidlArgument::IN_DIR) {
      generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
                               types->typenames_);
    } else {
      delete v;
    }
  }

  // the transact call
  unique_ptr<MethodCall> call(new MethodCall(
      proxyClass->mRemote, "transact", 4, new LiteralExpression("Stub." + transactCodeName), _data,
      _reply ? _reply : NULL_VALUE,
      new LiteralExpression(oneway ? "android.os.IBinder.FLAG_ONEWAY" : "0")));
  unique_ptr<Variable> _status(new Variable(types->BoolType(), "_status"));
  tryStatement->statements->Add(new VariableDeclaration(_status.release(), call.release()));

  // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall
  // back to the local method in the default impl, if set before.
  vector<string> arg_names;
  for (const auto& arg : method.GetArguments()) {
    arg_names.emplace_back(arg->GetName());
  }
  bool has_return_type = method.GetType().GetName() != "void";
  tryStatement->statements->Add(new LiteralStatement(
      android::base::StringPrintf(has_return_type ? "if (!_status && getDefaultImpl() != null) {\n"
                                                    "  return getDefaultImpl().%s(%s);\n"
                                                    "}\n"
                                                  : "if (!_status && getDefaultImpl() != null) {\n"
                                                    "  getDefaultImpl().%s(%s);\n"
                                                    "  return;\n"
                                                    "}\n",
                                  method.GetName().c_str(), Join(arg_names, ", ").c_str())));

  // throw back exceptions.
  if (_reply) {
    MethodCall* ex = new MethodCall(_reply, "readException", 0);
    tryStatement->statements->Add(ex);
  }

  // returning and cleanup
  if (_reply != nullptr) {
    // keep this across return value and arguments in order to create the
    // classloader at most once.
    bool is_classloader_created = false;
    if (_result != nullptr) {
      string code;
      CodeWriterPtr writer = CodeWriter::ForString(&code);
      CodeGeneratorContext context{.writer = *(writer.get()),
                                   .typenames = types->typenames_,
                                   .type = method.GetType(),
                                   .var = _result->name,
                                   .parcel = _reply->name,
                                   .is_classloader_created = &is_classloader_created};
      CreateFromParcelFor(context);
      writer->Close();
      tryStatement->statements->Add(new LiteralStatement(code));
    }

    // the out/inout parameters
    for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
      if (arg->GetDirection() & AidlArgument::OUT_DIR) {
        string code;
        CodeWriterPtr writer = CodeWriter::ForString(&code);
        CodeGeneratorContext context{.writer = *(writer.get()),
                                     .typenames = types->typenames_,
                                     .type = arg->GetType(),
                                     .var = arg->GetName(),
                                     .parcel = _reply->name,
                                     .is_classloader_created = &is_classloader_created};
        ReadFromParcelFor(context);
        writer->Close();
        tryStatement->statements->Add(new LiteralStatement(code));
      }
    }

    finallyStatement->statements->Add(new MethodCall(_reply, "recycle"));
  }
  finallyStatement->statements->Add(new MethodCall(_data, "recycle"));

  if (options.GenTraces()) {
    finallyStatement->statements->Add(new MethodCall(
        new LiteralExpression("android.os.Trace"), "traceEnd", 1,
        new LiteralExpression("android.os.Trace.TRACE_TAG_AIDL")));
  }

  if (_result != nullptr) {
    proxy->statements->Add(new ReturnStatement(_result));
  }

  return proxy;
}

static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
                             StubClass* stubClass, ProxyClass* proxyClass, int index,
                             JavaTypeNamespace* types, const Options& options) {
  const bool oneway = proxyClass->mOneWay || method.IsOneway();

  // == the TRANSACT_ constant =============================================
  string transactCodeName = "TRANSACTION_";
  transactCodeName += method.GetName();

  Field* transactCode = new Field(
      STATIC | FINAL, new Variable(types->IntType(), transactCodeName));
  transactCode->value =
      StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
  stubClass->elements.push_back(transactCode);

  // getTransactionName
  if (options.GenTransactionNames()) {
    Case* c = new Case(transactCodeName);
    c->statements->Add(new ReturnStatement(new StringLiteralExpression(method.GetName())));
    stubClass->code_to_method_name_switch->cases.push_back(c);
  }

  // == the declaration in the interface ===================================
  ClassElement* decl;
  if (method.IsUserDefined()) {
    decl = generate_interface_method(method, types).release();
  } else {
    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
      std::ostringstream code;
      code << "public int " << kGetInterfaceVersion << "() "
           << "throws android.os.RemoteException;\n";
      decl = new LiteralClassElement(code.str());
    }
  }
  interface->elements.push_back(decl);

  // == the stub method ====================================================
  if (method.IsUserDefined()) {
    bool outline_stub =
        stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
    if (outline_stub) {
      generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, types,
                                 options);
    } else {
      generate_stub_case(iface, method, transactCodeName, oneway, stubClass, types, options);
    }
  } else {
    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
      Case* c = new Case(transactCodeName);
      std::ostringstream code;
      code << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
           << "return true;\n";
      c->statements->Add(new LiteralStatement(code.str()));
      stubClass->transact_switch->cases.push_back(c);
    }
  }

  // == the proxy method ===================================================
  ClassElement* proxy = nullptr;
  if (method.IsUserDefined()) {
    proxy =
        generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, types, options)
            .release();

  } else {
    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
      std::ostringstream code;
      code << "@Override\n"
           << "public int " << kGetInterfaceVersion << "()"
           << " throws "
           << "android.os.RemoteException {\n"
           << "  if (mCachedVersion == -1) {\n"
           << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
           << "    try {\n"
           << "      mRemote.transact(Stub." << transactCodeName << ", "
           << "data, reply, 0);\n"
           << "      mCachedVersion = reply.readInt();\n"
           << "    } finally {\n"
           << "      reply.recycle();\n"
           << "      data.recycle();\n"
           << "    }\n"
           << "  }\n"
           << "  return mCachedVersion;\n"
           << "}\n";
      proxy = new LiteralClassElement(code.str());
    }
  }
  if (proxy != nullptr) {
    proxyClass->elements.push_back(proxy);
  }
}

static void generate_interface_descriptors(StubClass* stub, ProxyClass* proxy,
                                           const JavaTypeNamespace* types) {
  // the interface descriptor transaction handler
  Case* c = new Case("INTERFACE_TRANSACTION");
  c->statements->Add(new MethodCall(stub->transact_reply, "writeString", 1,
                                    stub->get_transact_descriptor(types,
                                                                  nullptr)));
  c->statements->Add(new ReturnStatement(TRUE_VALUE));
  stub->transact_switch->cases.push_back(c);

  // and the proxy-side method returning the descriptor directly
  Method* getDesc = new Method;
  getDesc->modifiers = PUBLIC;
  getDesc->returnType = types->StringType();
  getDesc->returnTypeDimension = 0;
  getDesc->name = "getInterfaceDescriptor";
  getDesc->statements = new StatementBlock;
  getDesc->statements->Add(
      new ReturnStatement(new LiteralExpression("DESCRIPTOR")));
  proxy->elements.push_back(getDesc);
}

// Check whether (some) methods in this interface should be "outlined," that
// is, have specific onTransact methods for certain cases. Set up StubClass
// metadata accordingly.
//
// Outlining will be enabled if the interface has more than outline_threshold
// methods. In that case, the methods are sorted by number of arguments
// (so that more "complex" methods come later), and the first non_outline_count
// number of methods not outlined (are kept in the onTransact() method).
//
// Requirements: non_outline_count <= outline_threshold.
static void compute_outline_methods(const AidlInterface* iface,
                                    StubClass* stub,
                                    size_t outline_threshold,
                                    size_t non_outline_count) {
  CHECK_LE(non_outline_count, outline_threshold);
  // We'll outline (create sub methods) if there are more than min_methods
  // cases.
  stub->transact_outline = iface->GetMethods().size() > outline_threshold;
  if (stub->transact_outline) {
    stub->all_method_count = iface->GetMethods().size();
    std::vector<const AidlMethod*> methods;
    methods.reserve(iface->GetMethods().size());
    for (const std::unique_ptr<AidlMethod>& ptr : iface->GetMethods()) {
      methods.push_back(ptr.get());
    }

    std::stable_sort(
        methods.begin(),
        methods.end(),
        [](const AidlMethod* m1, const AidlMethod* m2) {
          return m1->GetArguments().size() < m2->GetArguments().size();
        });

    stub->outline_methods.insert(methods.begin() + non_outline_count,
                                 methods.end());
  }
}

static unique_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method) {
  unique_ptr<Method> default_method(new Method);
  default_method->comment = method.GetComments();
  default_method->modifiers = PUBLIC | OVERRIDE;
  default_method->returnType = method.GetType().GetLanguageType<Type>();
  default_method->returnTypeDimension = method.GetType().IsArray() ? 1 : 0;
  default_method->name = method.GetName();
  default_method->statements = new StatementBlock;
  for (const auto& arg : method.GetArguments()) {
    default_method->parameters.push_back(new Variable(
        arg->GetType().GetLanguageType<Type>(), arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
  }
  default_method->exceptions.push_back(
      method.GetType().GetLanguageType<Type>()->GetTypeNamespace()->RemoteExceptionType());

  if (method.GetType().GetName() != "void") {
    const string& defaultValue = DefaultJavaValueOf(method.GetType());
    default_method->statements->Add(
        new LiteralStatement(StringPrintf("return %s;\n", defaultValue.c_str())));
  }
  return default_method;
}

static unique_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
                                                     const Options& options) {
  unique_ptr<Class> default_class(new Class);
  default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
  default_class->modifiers = PUBLIC | STATIC;
  default_class->what = Class::CLASS;
  default_class->type = iface.GetLanguageType<InterfaceType>()->GetDefaultImpl();
  default_class->interfaces.emplace_back(iface.GetLanguageType<InterfaceType>());

  for (const auto& m : iface.GetMethods()) {
    if (m->IsUserDefined()) {
      default_class->elements.emplace_back(generate_default_impl_method(*(m.get())).release());
    } else {
      if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
        // This is called only when the remote side is not implementing this
        // method, which is impossible in normal case, because this method is
        // automatically declared in the interface class and not implementing
        // it in the remote side is causing compilation error. But if the remote
        // side somehow managed to not implement it, that's an error and we
        // report the case by returning -1 here.
        std::ostringstream code;
        code << "@Override\n"
             << "public int " << kGetInterfaceVersion << "() {\n"
             << "  return -1;\n"
             << "}\n";
        default_class->elements.emplace_back(new LiteralClassElement(code.str()));
      }
    }
  }

  default_class->elements.emplace_back(
      new LiteralClassElement("@Override\n"
                              "public android.os.IBinder asBinder() {\n"
                              "  return null;\n"
                              "}\n"));

  return default_class;
}

Class* generate_binder_interface_class(const AidlInterface* iface, JavaTypeNamespace* types,
                                       const Options& options) {
  const InterfaceType* interfaceType = iface->GetLanguageType<InterfaceType>();

  // the interface class
  Class* interface = new Class;
  interface->comment = iface->GetComments();
  interface->modifiers = PUBLIC;
  interface->what = Class::INTERFACE;
  interface->type = interfaceType;
  interface->interfaces.push_back(types->IInterfaceType());
  interface->annotations = generate_java_annotations(*iface);

  if (options.Version()) {
    std::ostringstream code;
    code << "/**\n"
         << " * The version of this interface that the caller is built against.\n"
         << " * This might be different from what {@link #getInterfaceVersion()\n"
         << " * getInterfaceVersion} returns as that is the version of the interface\n"
         << " * that the remote object is implementing.\n"
         << " */\n"
         << "public static final int VERSION = " << options.Version() << ";\n";
    interface->elements.emplace_back(new LiteralClassElement(code.str()));
  }

  // the default impl class
  Class* default_impl = generate_default_impl_class(*iface, options).release();
  interface->elements.emplace_back(default_impl);

  // the stub inner class
  StubClass* stub =
      new StubClass(interfaceType->GetStub(), interfaceType, types, options);
  interface->elements.push_back(stub);

  compute_outline_methods(iface,
                          stub,
                          options.onTransact_outline_threshold_,
                          options.onTransact_non_outline_count_);

  // the proxy inner class
  ProxyClass* proxy = new ProxyClass(types, interfaceType->GetProxy(), interfaceType, options);
  stub->elements.push_back(proxy);

  // stub and proxy support for getInterfaceDescriptor()
  generate_interface_descriptors(stub, proxy, types);

  // all the declared constants of the interface
  for (const auto& constant : iface->GetConstantDeclarations()) {
    const AidlConstantValue& value = constant->GetValue();

    switch (value.GetType()) {
      case AidlConstantValue::Type::STRING: {
        generate_string_constant(interface, constant->GetName(),
                                 constant->ValueString(ConstantValueDecorator));
        break;
      }
      case AidlConstantValue::Type::INTEGRAL:
      case AidlConstantValue::Type::HEXIDECIMAL: {
        generate_int_constant(interface, constant->GetName(),
                              constant->ValueString(ConstantValueDecorator));
        break;
      }
      default: {
        LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
      }
    }
  }

  // all the declared methods of the interface

  for (const auto& item : iface->GetMethods()) {
    generate_methods(*iface,
                     *item,
                     interface,
                     stub,
                     proxy,
                     item->GetId(),
                     types,
                     options);
  }

  // additional static methods for the default impl set/get to the
  // stub class. Can't add them to the interface as the generated java files
  // may be compiled with Java < 1.7 where static interface method isn't
  // supported.
  // TODO(b/111417145) make this conditional depending on the Java language
  // version requested
  const string i_name = interfaceType->JavaType();
  stub->elements.emplace_back(new LiteralClassElement(
      StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
                   "  if (Stub.Proxy.sDefaultImpl == null && impl != null) {\n"
                   "    Stub.Proxy.sDefaultImpl = impl;\n"
                   "    return true;\n"
                   "  }\n"
                   "  return false;\n"
                   "}\n",
                   i_name.c_str())));
  stub->elements.emplace_back(
      new LiteralClassElement(StringPrintf("public static %s getDefaultImpl() {\n"
                                           "  return Stub.Proxy.sDefaultImpl;\n"
                                           "}\n",
                                           i_name.c_str())));

  // the static field is defined in the proxy class, not in the interface class
  // because all fields in an interface class are by default final.
  proxy->elements.emplace_back(new LiteralClassElement(
      StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));

  stub->finish();

  return interface;
}

}  // namespace java
}  // namespace android
}  // namespace aidl
