/*
 * 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 "ast_java.h"
#include "generate_java.h"
#include "logging.h"
#include "options.h"

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

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

#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;

  explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
  std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
    auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
                                        StringPrintf("%s%d", base_.c_str(), index_));
    vars_.push_back(v);
    index_++;
    return v;
  }

  std::shared_ptr<Variable> Get(int index) { return vars_[index]; }

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

// =================================================
class StubClass : public Class {
 public:
  StubClass(const AidlInterface* interfaceType, const Options& options);
  ~StubClass() override = default;

  // non-copyable, non-movable
  StubClass(const StubClass&) = delete;
  StubClass(StubClass&&) = delete;
  StubClass& operator=(const StubClass&) = delete;
  StubClass& operator=(StubClass&&) = delete;

  std::shared_ptr<Variable> transact_code;
  std::shared_ptr<Variable> transact_data;
  std::shared_ptr<Variable> transact_reply;
  std::shared_ptr<Variable> transact_flags;
  std::shared_ptr<SwitchStatement> transact_switch_meta;
  std::shared_ptr<SwitchStatement> transact_switch_user;
  std::shared_ptr<StatementBlock> transact_statements;
  std::shared_ptr<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();

  std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);

 private:
  void make_as_interface(const AidlInterface* interfaceType);

  std::shared_ptr<Variable> transact_descriptor;
  const Options& options_;
};

StubClass::StubClass(const AidlInterface* interfaceType, 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 = interfaceType->GetCanonicalName() + ".Stub";
  this->extends = "android.os.Binder";
  this->interfaces.push_back(interfaceType->GetCanonicalName());

  // ctor
  auto ctor = std::make_shared<Method>();
  ctor->modifiers = PUBLIC;
  ctor->comment =
      "/** Construct the stub at attach it to the "
      "interface. */";
  ctor->name = "Stub";
  ctor->statements = std::make_shared<StatementBlock>();
  if (interfaceType->IsVintfStability()) {
    auto stability = std::make_shared<LiteralStatement>("this.markVintfStability();\n");
    ctor->statements->Add(stability);
  }
  auto attach = std::make_shared<MethodCall>(
      THIS_VALUE, "attachInterface",
      std::vector<std::shared_ptr<Expression>>{THIS_VALUE,
                                               std::make_shared<LiteralExpression>("DESCRIPTOR")});
  ctor->statements->Add(attach);
  this->elements.push_back(ctor);

  // asInterface
  make_as_interface(interfaceType);

  // asBinder
  auto asBinder = std::make_shared<Method>();
  asBinder->modifiers = PUBLIC | OVERRIDE;
  asBinder->returnType = "android.os.IBinder";
  asBinder->name = "asBinder";
  asBinder->statements = std::make_shared<StatementBlock>();
  asBinder->statements->Add(std::make_shared<ReturnStatement>(THIS_VALUE));
  this->elements.push_back(asBinder);

  if (options_.GenTransactionNames()) {
    // getDefaultTransactionName
    auto getDefaultTransactionName = std::make_shared<Method>();
    getDefaultTransactionName->comment = "/** @hide */";
    getDefaultTransactionName->modifiers = PUBLIC | STATIC;
    getDefaultTransactionName->returnType = "java.lang.String";
    getDefaultTransactionName->name = "getDefaultTransactionName";
    auto code = std::make_shared<Variable>("int", "transactionCode");
    getDefaultTransactionName->parameters.push_back(code);
    getDefaultTransactionName->statements = std::make_shared<StatementBlock>();
    this->code_to_method_name_switch = std::make_shared<SwitchStatement>(code);
    getDefaultTransactionName->statements->Add(this->code_to_method_name_switch);
    this->elements.push_back(getDefaultTransactionName);

    // getTransactionName
    auto getTransactionName = std::make_shared<Method>();
    getTransactionName->comment = "/** @hide */";
    getTransactionName->modifiers = PUBLIC;
    getTransactionName->returnType = "java.lang.String";
    getTransactionName->name = "getTransactionName";
    auto code2 = std::make_shared<Variable>("int", "transactionCode");
    getTransactionName->parameters.push_back(code2);
    getTransactionName->statements = std::make_shared<StatementBlock>();
    getTransactionName->statements->Add(std::make_shared<ReturnStatement>(
        std::make_shared<MethodCall>(THIS_VALUE, "getDefaultTransactionName",
                                     std::vector<std::shared_ptr<Expression>>{code2})));
    this->elements.push_back(getTransactionName);
  }

  // onTransact
  this->transact_code = std::make_shared<Variable>("int", "code");
  this->transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
  this->transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
  this->transact_flags = std::make_shared<Variable>("int", "flags");
  auto onTransact = std::make_shared<Method>();
  onTransact->modifiers = PUBLIC | OVERRIDE;
  onTransact->returnType = "boolean";
  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 = std::make_shared<StatementBlock>();
  transact_statements = onTransact->statements;
  onTransact->exceptions.push_back("android.os.RemoteException");
  this->elements.push_back(onTransact);
  this->transact_switch_meta = std::make_shared<SwitchStatement>(this->transact_code);
  this->transact_switch_user = std::make_shared<SwitchStatement>(this->transact_code);
}

void StubClass::finish() {
  auto default_case = std::make_shared<Case>();

  auto superCall = std::make_shared<MethodCall>(
      SUPER_VALUE, "onTransact",
      std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
                                               this->transact_reply, this->transact_flags});
  default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
  transact_switch_user->cases.push_back(default_case);

  // Meta transactions are looked up prior to user-defined transactions.
  transact_statements->Add(this->transact_switch_meta);
  transact_statements->Add(this->transact_switch_user);

  // 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.
    auto code_switch_default_case = std::make_shared<Case>();
    code_switch_default_case->statements->Add(std::make_shared<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.
std::shared_ptr<Expression> StubClass::get_transact_descriptor(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 std::make_shared<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 std::make_shared<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 = std::make_shared<Variable>("java.lang.String", "descriptor");
    transact_statements->Add(std::make_shared<VariableDeclaration>(
        transact_descriptor, std::make_shared<LiteralExpression>("DESCRIPTOR")));
  }
  return transact_descriptor;
}

void StubClass::make_as_interface(const AidlInterface* interfaceType) {
  auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");

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

  auto ifstatement = std::make_shared<IfStatement>();
  ifstatement->expression = std::make_shared<Comparison>(obj, "==", NULL_VALUE);
  ifstatement->statements = std::make_shared<StatementBlock>();
  ifstatement->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
  m->statements->Add(ifstatement);

  // IInterface iin = obj.queryLocalInterface(DESCRIPTOR)
  auto queryLocalInterface = std::make_shared<MethodCall>(obj, "queryLocalInterface");
  queryLocalInterface->arguments.push_back(std::make_shared<LiteralExpression>("DESCRIPTOR"));
  auto iin = std::make_shared<Variable>("android.os.IInterface", "iin");
  auto iinVd = std::make_shared<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;
  auto iinNotNull = std::make_shared<Comparison>(iin, "!=", NULL_VALUE);
  auto instOfCheck = std::make_shared<Comparison>(
      iin, " instanceof ", std::make_shared<LiteralExpression>(interfaceType->GetCanonicalName()));
  auto instOfStatement = std::make_shared<IfStatement>();
  instOfStatement->expression = std::make_shared<Comparison>(iinNotNull, "&&", instOfCheck);
  instOfStatement->statements = std::make_shared<StatementBlock>();
  instOfStatement->statements->Add(std::make_shared<ReturnStatement>(
      std::make_shared<Cast>(interfaceType->GetCanonicalName(), iin)));
  m->statements->Add(instOfStatement);

  auto ne = std::make_shared<NewExpression>(interfaceType->GetCanonicalName() + ".Stub.Proxy");
  ne->arguments.push_back(obj);
  m->statements->Add(std::make_shared<ReturnStatement>(ne));

  this->elements.push_back(m);
}

// =================================================
class ProxyClass : public Class {
 public:
  ProxyClass(const AidlInterface* interfaceType, const Options& options);
  ~ProxyClass() override;

  std::shared_ptr<Variable> mRemote;
};

ProxyClass::ProxyClass(const AidlInterface* interfaceType, const Options& options) : Class() {
  this->modifiers = PRIVATE | STATIC;
  this->what = Class::CLASS;
  this->type = interfaceType->GetCanonicalName() + ".Stub.Proxy";
  this->interfaces.push_back(interfaceType->GetCanonicalName());

  // IBinder mRemote
  mRemote = std::make_shared<Variable>("android.os.IBinder", "mRemote");
  this->elements.push_back(std::make_shared<Field>(PRIVATE, mRemote));

  // Proxy()
  auto remote = std::make_shared<Variable>("android.os.IBinder", "remote");
  auto ctor = std::make_shared<Method>();
  ctor->name = "Proxy";
  ctor->statements = std::make_shared<StatementBlock>();
  ctor->parameters.push_back(remote);
  ctor->statements->Add(std::make_shared<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(std::make_shared<LiteralClassElement>(code.str()));
  }
  if (!options.Hash().empty()) {
    std::ostringstream code;
    code << "private String mCachedHash = \"-1\";\n";
    this->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
  }

  // IBinder asBinder()
  auto asBinder = std::make_shared<Method>();
  asBinder->modifiers = PUBLIC | OVERRIDE;
  asBinder->returnType = "android.os.IBinder";
  asBinder->name = "asBinder";
  asBinder->statements = std::make_shared<StatementBlock>();
  asBinder->statements->Add(std::make_shared<ReturnStatement>(mRemote));
  this->elements.push_back(asBinder);
}

ProxyClass::~ProxyClass() {}

// =================================================
static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
                               std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
                               std::shared_ptr<Variable> parcel) {
  auto len = std::make_shared<Variable>("int", v->name + "_length");
  addTo->Add(
      std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
  auto lencheck = std::make_shared<IfStatement>();
  lencheck->expression =
      std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
  lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
  lencheck->elseif = std::make_shared<IfStatement>();
  lencheck->elseif->statements->Add(std::make_shared<Assignment>(
      v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
  addTo->Add(lencheck);
}

static void 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) {
  string code;
  CodeWriterPtr writer = CodeWriter::ForString(&code);
  CodeGeneratorContext context{
      .writer = *(writer.get()),
      .typenames = typenames,
      .type = type,
      .parcel = parcel->name,
      .var = v->name,
      .is_return_value = is_return_value,
  };
  WriteToParcelFor(context);
  writer->Close();
  addTo->Add(std::make_shared<LiteralStatement>(code));
}

void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type) {
  for (const auto& constant : type.GetConstantDeclarations()) {
    const AidlTypeSpecifier& type = constant->GetType();
    out << GenerateComments(*constant);
    out << GenerateAnnotations(*constant);
    out << "public static final " << type.Signature() << " " << constant->GetName() << " = "
        << constant->ValueString(ConstantValueDecorator) << ";\n";
  }
}

static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
                                                         const AidlTypenames& typenames) {
  auto decl = std::make_shared<Method>();
  decl->comment = GenerateComments(method);
  decl->modifiers = PUBLIC;
  decl->returnType = JavaSignatureOf(method.GetType(), typenames);
  decl->name = method.GetName();
  decl->annotations = JavaAnnotationsFor(method);

  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
    var->annotations = JavaAnnotationsFor(arg->GetType());
    decl->parameters.push_back(var);
  }

  decl->exceptions.push_back("android.os.RemoteException");

  return decl;
}

static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
                               std::shared_ptr<Variable> transact_data,
                               std::shared_ptr<Variable> transact_reply,
                               const AidlTypenames& typenames,
                               std::shared_ptr<StatementBlock> statement_block,
                               std::shared_ptr<StubClass> stubClass, const Options& options) {
  // try and finally
  auto tryStatement = std::make_shared<TryStatement>();
  auto finallyStatement = std::make_shared<FinallyStatement>();
  auto& statements = statement_block;

  if (options.GenTraces()) {
    statements->Add(tryStatement);
    statements->Add(finallyStatement);
    statements = tryStatement->statements;
    tryStatement->statements->Add(std::make_shared<MethodCall>(
        std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
        std::vector<std::shared_ptr<Expression>>{
            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
            std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
                                                      "::" + method.GetName() + "::server")}));
    finallyStatement->statements->Add(std::make_shared<MethodCall>(
        std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
        std::vector<std::shared_ptr<Expression>>{
            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
  }

  auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());

  // interface token validation is the very first thing we do
  statements->Add(std::make_shared<MethodCall>(
      transact_data, "enforceInterface",
      std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&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()) {
      std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);

      statements->Add(std::make_shared<VariableDeclaration>(v));

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

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

  // the real call
  if (method.GetType().GetName() == "void") {
    statements->Add(realCall);

    if (!oneway) {
      // report that there were no exceptions
      auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
      statements->Add(ex);
    }
  } else {
    auto _result =
        std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
      statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));

    if (!oneway) {
      // report that there were no exceptions
      auto ex = std::make_shared<MethodCall>(transact_reply, "writeNoException");
      statements->Add(ex);
    }

    // marshall the return value
    generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
                             typenames);
  }

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

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

  // return true
  statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
}

static void 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) {
  auto c = std::make_shared<Case>(transactCodeName);

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

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

static void 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) {
  std::string outline_name = "onTransact$" + method.GetName() + "$";
  // Generate an "outlined" method with the actual code.
  {
    auto transact_data = std::make_shared<Variable>("android.os.Parcel", "data");
    auto transact_reply = std::make_shared<Variable>("android.os.Parcel", "reply");
    auto onTransact_case = std::make_shared<Method>();
    onTransact_case->modifiers = PRIVATE;
    onTransact_case->returnType = "boolean";
    onTransact_case->name = outline_name;
    onTransact_case->parameters.push_back(transact_data);
    onTransact_case->parameters.push_back(transact_reply);
    onTransact_case->statements = std::make_shared<StatementBlock>();
    onTransact_case->exceptions.push_back("android.os.RemoteException");
    stubClass->elements.push_back(onTransact_case);

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

  // Generate the case dispatch.
  {
    auto c = std::make_shared<Case>(transactCodeName);

    auto helper_call =
        std::make_shared<MethodCall>(THIS_VALUE, outline_name,
                                     std::vector<std::shared_ptr<Expression>>{
                                         stubClass->transact_data, stubClass->transact_reply});
    c->statements->Add(std::make_shared<ReturnStatement>(helper_call));

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

static std::shared_ptr<Method> 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) {
  auto proxy = std::make_shared<Method>();
  proxy->comment = GenerateComments(method);
  proxy->modifiers = PUBLIC | OVERRIDE;
  proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
  proxy->name = method.GetName();
  proxy->statements = std::make_shared<StatementBlock>();
  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    proxy->parameters.push_back(
        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
  }
  proxy->exceptions.push_back("android.os.RemoteException");

  // the parcels
  auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
  proxy->statements->Add(std::make_shared<VariableDeclaration>(
      _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));

  if (iface.IsSensitiveData()) {
    proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();"));
  }

  std::shared_ptr<Variable> _reply = nullptr;
  if (!oneway) {
    _reply = std::make_shared<Variable>("android.os.Parcel", "_reply");
    proxy->statements->Add(std::make_shared<VariableDeclaration>(
        _reply, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
  }

  // the return value
  std::shared_ptr<Variable> _result = nullptr;
  if (method.GetType().GetName() != "void") {
    _result = std::make_shared<Variable>(*proxy->returnType, "_result");
    proxy->statements->Add(std::make_shared<VariableDeclaration>(_result));
  }

  // try and finally
  auto tryStatement = std::make_shared<TryStatement>();
  proxy->statements->Add(tryStatement);
  auto finallyStatement = std::make_shared<FinallyStatement>();
  proxy->statements->Add(finallyStatement);

  if (options.GenTraces()) {
    tryStatement->statements->Add(std::make_shared<MethodCall>(
        std::make_shared<LiteralExpression>("android.os.Trace"), "traceBegin",
        std::vector<std::shared_ptr<Expression>>{
            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL"),
            std::make_shared<StringLiteralExpression>("AIDL::java::" + iface.GetName() +
                                                      "::" + method.GetName() + "::client")}));
  }

  // the interface identifier token: the DESCRIPTOR constant, marshalled as a
  // string
  tryStatement->statements->Add(std::make_shared<MethodCall>(
      _data, "writeInterfaceToken",
      std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("DESCRIPTOR")}));

  // the parameters
  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
    auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
    AidlArgument::Direction dir = arg->GetDirection();
    if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
      auto checklen = std::make_shared<IfStatement>();
      checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
      checklen->statements->Add(std::make_shared<MethodCall>(
          _data, "writeInt",
          std::vector<std::shared_ptr<Expression>>{std::make_shared<LiteralExpression>("-1")}));
      checklen->elseif = std::make_shared<IfStatement>();
      checklen->elseif->statements->Add(std::make_shared<MethodCall>(
          _data, "writeInt",
          std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
      tryStatement->statements->Add(checklen);
    } else if (dir & AidlArgument::IN_DIR) {
      generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
                               typenames);
    }
  }

  std::vector<std::string> flags;
  if (oneway) flags.push_back("android.os.IBinder.FLAG_ONEWAY");
  if (iface.IsSensitiveData()) flags.push_back("android.os.IBinder.FLAG_CLEAR_BUF");

  // the transact call
  auto call = std::make_shared<MethodCall>(
      proxyClass->mRemote, "transact",
      std::vector<std::shared_ptr<Expression>>{
          std::make_shared<LiteralExpression>("Stub." + transactCodeName), _data,
          _reply ? _reply : NULL_VALUE,
          std::make_shared<LiteralExpression>(flags.empty() ? "0" : Join(flags, " | "))});
  auto _status = std::make_shared<Variable>("boolean", "_status");
  tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));

  // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
  // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
  // is versioned. We can't throw the exception for unversioned interface because that would be an
  // app breaking change.
  vector<string> arg_names;
  for (const auto& arg : method.GetArguments()) {
    arg_names.emplace_back(arg->GetName());
  }
  bool has_return_type = method.GetType().GetName() != "void";

  auto checkDefaultImpl = std::make_shared<IfStatement>();
  checkDefaultImpl->expression = std::make_shared<LiteralExpression>("getDefaultImpl() != null");
  if (has_return_type) {
    checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
        android::base::StringPrintf("return getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
                                    Join(arg_names, ", ").c_str())));
  } else {
    checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>(
        android::base::StringPrintf("getDefaultImpl().%s(%s);\n", method.GetName().c_str(),
                                    Join(arg_names, ", ").c_str())));
    checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
  }
  if (options.Version() > 0) {
    checkDefaultImpl->elseif = std::make_shared<IfStatement>();
    checkDefaultImpl->elseif->statements->Add(
        std::make_shared<LiteralStatement>(android::base::StringPrintf(
            "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
            method.GetName().c_str())));
  }

  auto checkTransactionError = std::make_shared<IfStatement>();
  checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
  checkTransactionError->statements->Add(checkDefaultImpl);

  tryStatement->statements->Add(checkTransactionError);

  // throw back exceptions.
  if (_reply) {
    auto ex = std::make_shared<MethodCall>(_reply, "readException");
    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 = typenames,
                                   .type = method.GetType(),
                                   .parcel = _reply->name,
                                   .var = _result->name,
                                   .is_classloader_created = &is_classloader_created};
      CreateFromParcelFor(context);
      writer->Close();
      tryStatement->statements->Add(std::make_shared<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 = typenames,
                                     .type = arg->GetType(),
                                     .parcel = _reply->name,
                                     .var = arg->GetName(),
                                     .is_classloader_created = &is_classloader_created};
        ReadFromParcelFor(context);
        writer->Close();
        tryStatement->statements->Add(std::make_shared<LiteralStatement>(code));
      }
    }

    finallyStatement->statements->Add(std::make_shared<MethodCall>(_reply, "recycle"));
  }
  finallyStatement->statements->Add(std::make_shared<MethodCall>(_data, "recycle"));

  if (options.GenTraces()) {
    finallyStatement->statements->Add(std::make_shared<MethodCall>(
        std::make_shared<LiteralExpression>("android.os.Trace"), "traceEnd",
        std::vector<std::shared_ptr<Expression>>{
            std::make_shared<LiteralExpression>("android.os.Trace.TRACE_TAG_AIDL")}));
  }

  if (_result != nullptr) {
    proxy->statements->Add(std::make_shared<ReturnStatement>(_result));
  }

  return proxy;
}

static void 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) {
  const bool oneway = method.IsOneway();

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

  auto transactCode =
      std::make_shared<Field>(STATIC | FINAL, std::make_shared<Variable>("int", transactCodeName));
  transactCode->value =
      StringPrintf("(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
  stubClass->elements.push_back(transactCode);

  // getTransactionName
  if (options.GenTransactionNames()) {
    auto c = std::make_shared<Case>(transactCodeName);
    c->statements->Add(std::make_shared<ReturnStatement>(
        std::make_shared<StringLiteralExpression>(method.GetName())));
    stubClass->code_to_method_name_switch->cases.push_back(c);
  }

  // == the declaration in the interface ===================================
  std::shared_ptr<ClassElement> decl;
  if (method.IsUserDefined()) {
    decl = generate_interface_method(method, typenames);
  } else {
    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
      std::ostringstream code;
      code << "public int " << kGetInterfaceVersion << "() "
           << "throws android.os.RemoteException;\n";
      decl = std::make_shared<LiteralClassElement>(code.str());
    }
    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
      std::ostringstream code;
      code << "public String " << kGetInterfaceHash << "() "
           << "throws android.os.RemoteException;\n";
      decl = std::make_shared<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, typenames,
                                 options);
    } else {
      generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
    }
  } else {
    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
      auto c = std::make_shared<Case>(transactCodeName);
      std::ostringstream code;
      code << "data.enforceInterface(descriptor);\n"
           << "reply.writeNoException();\n"
           << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
           << "return true;\n";
      c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
      stubClass->transact_switch_meta->cases.push_back(c);
    }
    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
      auto c = std::make_shared<Case>(transactCodeName);
      std::ostringstream code;
      code << "data.enforceInterface(descriptor);\n"
           << "reply.writeNoException();\n"
           << "reply.writeString(" << kGetInterfaceHash << "());\n"
           << "return true;\n";
      c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
      stubClass->transact_switch_meta->cases.push_back(c);
    }
  }

  // == the proxy method ===================================================
  std::shared_ptr<ClassElement> proxy = nullptr;
  if (method.IsUserDefined()) {
    proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
                                  options);

  } 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"
           << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
           << "data, reply, 0);\n"
           << "      if (!_status) {\n"
           << "        if (getDefaultImpl() != null) {\n"
           << "          return getDefaultImpl().getInterfaceVersion();\n"
           << "        }\n"
           << "      }\n"
           << "      reply.readException();\n"
           << "      mCachedVersion = reply.readInt();\n"
           << "    } finally {\n"
           << "      reply.recycle();\n"
           << "      data.recycle();\n"
           << "    }\n"
           << "  }\n"
           << "  return mCachedVersion;\n"
           << "}\n";
      proxy = std::make_shared<LiteralClassElement>(code.str());
    }
    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
      std::ostringstream code;
      code << "@Override\n"
           << "public synchronized String " << kGetInterfaceHash << "()"
           << " throws "
           << "android.os.RemoteException {\n"
           << "  if (\"-1\".equals(mCachedHash)) {\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"
           << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
           << "data, reply, 0);\n"
           << "      if (!_status) {\n"
           << "        if (getDefaultImpl() != null) {\n"
           << "          return getDefaultImpl().getInterfaceHash();\n"
           << "        }\n"
           << "      }\n"
           << "      reply.readException();\n"
           << "      mCachedHash = reply.readString();\n"
           << "    } finally {\n"
           << "      reply.recycle();\n"
           << "      data.recycle();\n"
           << "    }\n"
           << "  }\n"
           << "  return mCachedHash;\n"
           << "}\n";
      proxy = std::make_shared<LiteralClassElement>(code.str());
    }
  }
  if (proxy != nullptr) {
    proxyClass->elements.push_back(proxy);
  }
}

static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
                                           Class* interface, std::shared_ptr<StubClass> stub,
                                           std::shared_ptr<ProxyClass> proxy) {
  // the interface descriptor transaction handler
  auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
  c->statements->Add(std::make_shared<MethodCall>(
      stub->transact_reply, "writeString",
      std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
  c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
  stub->transact_switch_meta->cases.push_back(c);

  // and the proxy-side method returning the descriptor directly
  auto getDesc = std::make_shared<Method>();
  getDesc->modifiers = PUBLIC;
  getDesc->returnType = "java.lang.String";
  getDesc->name = "getInterfaceDescriptor";
  getDesc->statements = std::make_shared<StatementBlock>();
  getDesc->statements->Add(
      std::make_shared<ReturnStatement>(std::make_shared<LiteralExpression>("DESCRIPTOR")));
  proxy->elements.push_back(getDesc);

  // add the DESCRIPTOR field to the interface class
  Class* classToAddDescriptor = interface;
  static std::set<std::string> greylist = {
#include "hiddenapi-greylist"
  };
  if (greylist.find(iface->GetCanonicalName()) != greylist.end()) {
    // For app compatibility, we keep DESCRIPTOR to the stub class for
    // the interfaces that are in the greylist.
    classToAddDescriptor = stub.get();
  }
  auto descriptor = std::make_shared<Field>(
      STATIC | FINAL | PUBLIC, std::make_shared<Variable>("java.lang.String", "DESCRIPTOR"));
  std::string name = iface->GetDescriptor();
  if (options.IsStructured()) {
    // mangle the interface name at build time and demangle it at runtime, to avoid
    // being renamed by jarjar. See b/153843174
    std::replace(name.begin(), name.end(), '.', '$');
    descriptor->value = "\"" + name + "\".replace('$', '.')";
  } else {
    descriptor->value = "\"" + name + "\"";
  }
  classToAddDescriptor->elements.push_back(descriptor);
}

// 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,
                                    const std::shared_ptr<StubClass> stub, size_t outline_threshold,
                                    size_t non_outline_count) {
  AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
  // 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 auto& 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 shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
                                                             const AidlTypenames& typenames) {
  auto default_method = std::make_shared<Method>();
  default_method->comment = GenerateComments(method);
  default_method->modifiers = PUBLIC | OVERRIDE;
  default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
  default_method->name = method.GetName();
  default_method->statements = std::make_shared<StatementBlock>();
  for (const auto& arg : method.GetArguments()) {
    default_method->parameters.push_back(
        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
  }
  default_method->exceptions.push_back("android.os.RemoteException");

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

static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
                                                     const AidlTypenames& typenames,
                                                     const Options& options) {
  auto default_class = std::make_shared<Class>();
  default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
  default_class->modifiers = PUBLIC | STATIC;
  default_class->what = Class::CLASS;
  default_class->type = iface.GetCanonicalName() + ".Default";
  default_class->interfaces.emplace_back(iface.GetCanonicalName());

  for (const auto& m : iface.GetMethods()) {
    if (m->IsUserDefined()) {
      default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
    } else {
      // These are called only when the remote side does not implement these
      // methods, which is normally impossible, because these methods are
      // automatically declared in the interface class and not implementing
      // them on the remote side causes a compilation error. But if the remote
      // side somehow managed to not implement it, that's an error and we
      // report the case by returning an invalid value here.
      if (m->GetName() == kGetInterfaceVersion && options.Version() > 0) {
        std::ostringstream code;
        code << "@Override\n"
             << "public int " << kGetInterfaceVersion << "() {\n"
             << "  return 0;\n"
             << "}\n";
        default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
      }
      if (m->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
        std::ostringstream code;
        code << "@Override\n"
             << "public String " << kGetInterfaceHash << "() {\n"
             << "  return \"\";\n"
             << "}\n";
        default_class->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
      }
    }
  }

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

  return default_class;
}

std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
                                                       const AidlTypenames& typenames,
                                                       const Options& options) {
  // the interface class
  auto interface = std::make_unique<Class>();
  interface->comment = GenerateComments(*iface);
  interface->modifiers = PUBLIC;
  interface->what = Class::INTERFACE;
  interface->type = iface->GetCanonicalName();
  interface->interfaces.push_back("android.os.IInterface");
  interface->annotations = JavaAnnotationsFor(*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(std::make_shared<LiteralClassElement>(code.str()));
  }
  if (!options.Hash().empty()) {
    std::ostringstream code;
    code << "public static final String HASH = \"" << options.Hash() << "\";\n";
    interface->elements.emplace_back(std::make_shared<LiteralClassElement>(code.str()));
  }

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

  // the stub inner class
  auto stub = std::make_shared<StubClass>(iface, options);
  interface->elements.push_back(stub);

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

  // the proxy inner class
  auto proxy = std::make_shared<ProxyClass>(iface, options);
  stub->elements.push_back(proxy);

  // stub and proxy support for getInterfaceDescriptor()
  generate_interface_descriptors(options, iface, interface.get(), stub, proxy);

  // all the declared constants of the interface
  string constants;
  generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
  interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));

  // all the declared methods of the interface

  for (const auto& item : iface->GetMethods()) {
    generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
                     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 = iface->GetCanonicalName();
  stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
      StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
                   "  // Only one user of this interface can use this function\n"
                   "  // at a time. This is a heuristic to detect if two different\n"
                   "  // users in the same process use this function.\n"
                   "  if (Stub.Proxy.sDefaultImpl != null) {\n"
                   "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
                   "  }\n"
                   "  if (impl != null) {\n"
                   "    Stub.Proxy.sDefaultImpl = impl;\n"
                   "    return true;\n"
                   "  }\n"
                   "  return false;\n"
                   "}\n",
                   i_name.c_str())));
  stub->elements.emplace_back(
      std::make_shared<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(std::make_shared<LiteralClassElement>(
      StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));

  stub->finish();

  return interface;
}

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