/*
 * 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::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->JavaType(), 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);
  ~StubClass() override = 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->JavaType();
  this->extends = types->BinderNativeType()->JavaType();
  this->interfaces.push_back(interfaceType->JavaType());

  // descriptor
  Field* descriptor = new Field(STATIC | FINAL | PRIVATE,
                                new Variable(types->StringType()->JavaType(), "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()->JavaType();
  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()->JavaType();
    getDefaultTransactionName->name = "getDefaultTransactionName";
    Variable* code = new Variable(types->IntType()->JavaType(), "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()->JavaType();
    getTransactionName->name = "getTransactionName";
    Variable* code2 = new Variable(types->IntType()->JavaType(), "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()->JavaType(), "code");
  this->transact_data = new Variable(types->ParcelType()->JavaType(), "data");
  this->transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
  this->transact_flags = new Variable(types->IntType()->JavaType(), "flags");
  Method* onTransact = new Method;
  onTransact->modifiers = PUBLIC | OVERRIDE;
  onTransact->returnType = types->BoolType()->JavaType();
  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()->JavaType());
  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()->JavaType(), "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()->JavaType(), "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->JavaType();
  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(types);
  Variable* iin = new Variable(iinType.JavaType(), "iin");
  VariableDeclaration* iinVd = new VariableDeclaration(iin, queryLocalInterface);
  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->JavaType(), iin)));
  m->statements->Add(instOfStatement);

  NewExpression* ne = new NewExpression(interfaceType->GetProxy()->InstantiableName());
  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);
  ~ProxyClass() override;

  Variable* mRemote;
};

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->JavaType();
  this->interfaces.push_back(interfaceType->JavaType());

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

  // Proxy()
  Variable* remote = new Variable(types->IBinderType()->JavaType(), "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()->JavaType();
  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()->JavaType(), 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->JavaType(), 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) {
  auto code = StringPrintf("public static final int %s = %s;\n", name.c_str(), value.c_str());
  interface->elements.push_back(new LiteralClassElement(code));
}

static void generate_string_constant(Class* interface, const std::string& name,
                                     const std::string& value) {
  auto code = StringPrintf("public static final String %s = %s;\n", name.c_str(), value.c_str());
  interface->elements.push_back(new LiteralClassElement(code));
}

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>()->JavaType();
  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>()->JavaType(),
                                            arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
  }

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

  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(t->InstantiableName())));
        } else {
          generate_new_array(t, 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>()->JavaType(),
                                     "_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()->JavaType(), "data");
    Variable* transact_reply = new Variable(types->ParcelType()->JavaType(), "reply");
    Method* onTransact_case = new Method;
    onTransact_case->modifiers = PRIVATE;
    onTransact_case->returnType = types->BoolType()->JavaType();
    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()->JavaType());
    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>()->JavaType();
  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>()->JavaType(),
                                             arg->GetName(), arg->GetType().IsArray() ? 1 : 0));
  }
  proxy->exceptions.push_back(types->RemoteExceptionType()->JavaType());

  // the parcels
  Variable* _data = new Variable(types->ParcelType()->JavaType(), "_data");
  proxy->statements->Add(
      new VariableDeclaration(_data, new MethodCall(types->ParcelType()->JavaType(), "obtain")));
  Variable* _reply = nullptr;
  if (!oneway) {
    _reply = new Variable(types->ParcelType()->JavaType(), "_reply");
    proxy->statements->Add(
        new VariableDeclaration(_reply, new MethodCall(types->ParcelType()->JavaType(), "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->JavaType(), 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()->JavaType(), "_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 = method.IsOneway();

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

  Field* transactCode =
      new Field(STATIC | FINAL, new Variable(types->IntType()->JavaType(), 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 << "data.enforceInterface(descriptor);\n"
           << "reply.writeNoException();\n"
           << "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"
           << "      data.writeInterfaceToken(DESCRIPTOR);\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()->JavaType();
  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>()->JavaType();
  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>()->JavaType(), arg->GetName(),
                     arg->GetType().IsArray() ? 1 : 0));
  }
  default_method->exceptions.push_back(method.GetType()
                                           .GetLanguageType<Type>()
                                           ->GetTypeNamespace()
                                           ->RemoteExceptionType()
                                           ->JavaType());

  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()->JavaType();
  default_class->interfaces.emplace_back(iface.GetLanguageType<InterfaceType>()->JavaType());

  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->JavaType();
  interface->interfaces.push_back(types->IInterfaceType()->JavaType());
  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
