/*
 * 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 "aidl_typenames.h"
#include "ast_java.h"
#include "generate_java.h"
#include "logging.h"
#include "options.h"
#include "parser.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) {
    auto v = std::make_shared<Variable>(JavaSignatureOf(type),
                                        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> GetTransactDescriptor(const AidlMethod* method);

 private:
  void MakeAsInterface(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
  MakeAsInterface(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));

  auto case_count = transact_switch_user->cases.size();
  transact_switch_user->cases.push_back(default_case);

  // Interface token validation is done for user-defined transactions.
  if (case_count > 0) {
    auto ifStatement = std::make_shared<IfStatement>();
    ifStatement->expression = std::make_shared<LiteralExpression>(
        "code >= android.os.IBinder.FIRST_CALL_TRANSACTION && "
        "code <= android.os.IBinder.LAST_CALL_TRANSACTION");
    ifStatement->statements = std::make_shared<StatementBlock>();
    ifStatement->statements->Add(std::make_shared<MethodCall>(
        this->transact_data, "enforceInterface",
        std::vector<std::shared_ptr<Expression>>{this->GetTransactDescriptor(nullptr)}));
    transact_statements->Add(ifStatement);
  }

  // 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);
  }

  // There will be at least one statement for the default, but if we emit a
  // return true after that default, it will be unreachable.
  if (case_count > 0) {
    transact_statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
  }
}

// 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::GetTransactDescriptor(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::MakeAsInterface(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 GenerateWriteToParcel(std::shared_ptr<StatementBlock> addTo,
                                  const AidlTypenames& typenames, const AidlTypeSpecifier& type,
                                  const std::string& parcel, const std::string& var,
                                  uint32_t min_sdk_version, bool is_return_value) {
  string code;
  CodeWriterPtr writer = CodeWriter::ForString(&code);
  CodeGeneratorContext context{
      .writer = *(writer.get()),
      .typenames = typenames,
      .type = type,
      .parcel = parcel,
      .var = var,
      .min_sdk_version = min_sdk_version,
      .is_return_value = is_return_value,
  };
  WriteToParcelFor(context);
  writer->Close();
  addTo->Add(std::make_shared<LiteralStatement>(code));
}

void GenerateConstantDeclarations(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> GenerateInterfaceMethod(const AidlMethod& method) {
  auto decl = std::make_shared<Method>();
  decl->comment = GenerateComments(method);
  decl->modifiers = PUBLIC;
  decl->returnType = JavaSignatureOf(method.GetType());
  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()), arg->GetName());
    var->annotations = JavaAnnotationsFor(arg->GetType());
    decl->parameters.push_back(var);
  }

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

  return decl;
}

// Visitor for the permission declared in the @EnforcePermission annotation.
struct PermissionVisitor {
  shared_ptr<Expression> operator()(const perm::AllOf& quantifier) {
    std::shared_ptr<Expression> result;
    for (const auto& operand : quantifier.operands) {
      auto expr = (*this)(operand);
      if (result) {
        result = std::make_shared<Comparison>(result, "&&", expr);
      } else {
        result = expr;
      }
    }
    return result;
  }

  shared_ptr<Expression> operator()(const perm::AnyOf& quantifier) {
    std::shared_ptr<Expression> result;
    for (const auto& operand : quantifier.operands) {
      auto expr = (*this)(operand);
      if (result) {
        result = std::make_shared<Comparison>(result, "||", expr);
      } else {
        result = expr;
      }
    }
    return result;
  }

  shared_ptr<Expression> operator()(const std::string& permission) {
    auto attributionSource =
        std::string("new android.content.AttributionSource(getCallingUid(), null, null)");
    for (size_t i = 0; i < method_.GetArguments().size(); i++) {
      const auto& arg = method_.GetArguments()[i];
      if (arg->GetType().GetName() == "android.content.AttributionSource") {
        attributionSource = android::base::StringPrintf("_arg%zu", i);
        break;
      }
    }
    auto checkPermission = std::make_shared<MethodCall>(
        THIS_VALUE, "permissionCheckerWrapper",
        std::vector<std::shared_ptr<Expression>>{
            std::make_shared<LiteralExpression>("android.Manifest.permission." + permission),
            std::make_shared<MethodCall>(THIS_VALUE, "getCallingPid"),
            std::make_shared<LiteralExpression>(attributionSource)});
    return checkPermission;
  }

  const AidlMethod& method_;
};

static void GeneratePermissionWrapper(Class* stubClass) {
  // TODO(b/208707422) avoid generating platform-specific API calls.
  std::string permissionCheckerWrapperCode =
      "private boolean permissionCheckerWrapper(\n"
      "    String permission, int pid, android.content.AttributionSource attributionSource) {\n"
      "  android.content.Context ctx =\n"
      "      android.app.ActivityThread.currentActivityThread().getSystemContext();\n"
      "  return (android.content.PermissionChecker.checkPermissionForDataDelivery(\n"
      "          ctx, permission, pid, attributionSource, \"\" /*message*/) ==\n"
      "      android.content.PermissionChecker.PERMISSION_GRANTED);\n"
      "}\n";
  auto permissionCheckerWrapper =
      std::make_shared<LiteralClassElement>(permissionCheckerWrapperCode);
  stubClass->elements.push_back(permissionCheckerWrapper);
}

static void GeneratePermissionCheck(const AidlMethod& method, const perm::Expression& expr,
                                    std::shared_ptr<StatementBlock> addTo) {
  auto ifstatement = std::make_shared<IfStatement>();
  auto combinedExpr = std::visit(PermissionVisitor{method}, expr);
  ifstatement->expression = std::make_shared<Comparison>(combinedExpr, "!=", TRUE_VALUE);
  ifstatement->statements = std::make_shared<StatementBlock>();
  ifstatement->statements->Add(std::make_shared<LiteralStatement>(
      android::base::StringPrintf("throw new SecurityException(\"Access denied, requires: %s\");\n",
                                  perm::AsJavaAnnotation(expr).c_str())));
  addTo->Add(ifstatement);
}

static void GeneratePermissionChecks(const AidlInterface& iface, const AidlMethod& method,
                                     std::shared_ptr<StatementBlock> addTo) {
  auto ifacePermExpr = iface.EnforceExpression();
  if (ifacePermExpr) {
    GeneratePermissionCheck(method, *ifacePermExpr.get(), addTo);
  }
  auto methodPermExpr = method.GetType().EnforceExpression();
  if (methodPermExpr) {
    GeneratePermissionCheck(method, *methodPermExpr.get(), addTo);
  }
}

static void GenerateStubCode(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,
                             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());

  // 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());

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

      string code;
      CodeWriterPtr writer = CodeWriter::ForString(&code);
      if (arg->GetDirection() & AidlArgument::IN_DIR) {
        // "in/inout" parameter should be created from parcel.
        CodeGeneratorContext context{.writer = *(writer.get()),
                                     .typenames = typenames,
                                     .type = arg->GetType(),
                                     .parcel = transact_data->name,
                                     .var = v->name,
                                     .min_sdk_version = options.GetMinSdkVersion(),
                                     .is_classloader_created = &is_classloader_created};
        CreateFromParcelFor(context);
      } else {
        // "out" parameter should be instantiated before calling the real impl.
        string java_type = InstantiableJavaSignatureOf(arg->GetType());

        if (arg->GetType().IsDynamicArray()) {
          // dynamic array should be created with a passed length.
          string var_length = v->name + "_length";
          (*writer) << "int " << var_length << " = data.readInt();\n";
          (*writer) << "if (" << var_length << " < 0) {\n";
          (*writer) << "  " << v->name << " = null;\n";
          (*writer) << "} else {\n";
          (*writer) << "  " << v->name << " = new " << java_type << "[" << var_length << "];\n";
          (*writer) << "}\n";
        } else if (arg->GetType().IsFixedSizeArray()) {
          // fixed-size array can be created with a known size
          string dimensions;
          for (auto dim : arg->GetType().GetFixedSizeArrayDimensions()) {
            dimensions += "[" + std::to_string(dim) + "]";
          }
          (*writer) << v->name << " = new " << java_type << dimensions << ";\n";
        } else {
          // otherwise, create a new instance with a default constructor
          (*writer) << v->name << " = new " << java_type << "();\n";
        }
      }
      writer->Close();
      statements->Add(std::make_shared<LiteralStatement>(code));

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

  // EOF check
  if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= 32u) {
    statements->Add(std::make_shared<MethodCall>(transact_data, "enforceNoDataAvail"));
  }

  GeneratePermissionChecks(iface, method, statements);

  // 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()), "_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
    GenerateWriteToParcel(statements, typenames, method.GetType(), transact_reply->name,
                          _result->name, options.GetMinSdkVersion(), /*is_return_value=*/true);
  }

  // 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) {
      GenerateWriteToParcel(statements, typenames, arg->GetType(), transact_reply->name, v->name,
                            options.GetMinSdkVersion(), /*is_return_value=*/true);
    }
  }
}

static void GenerateStubCase(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);

  GenerateStubCode(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
                   typenames, c->statements, options);
  c->statements->Add(std::make_shared<BreakStatement>());

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

static void GenerateStubCaseOutline(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);

    GenerateStubCode(iface, method, oneway, transact_data, transact_reply, typenames,
                     onTransact_case->statements, options);
    onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
  }

  // 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> GenerateProxyMethod(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());
  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()), arg->GetName()));
  }
  proxy->exceptions.push_back("android.os.RemoteException");

  // the parcels
  auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
  if (options.GenRpc()) {
    proxy->statements->Add(std::make_shared<LiteralStatement>(
        "android.os.Parcel _data = android.os.Parcel.obtain(asBinder());\n"));
  } else {
    proxy->statements->Add(std::make_shared<LiteralStatement>(
        "android.os.Parcel _data = android.os.Parcel.obtain();\n"));
  }

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

  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()), arg->GetName());
    AidlArgument::Direction dir = arg->GetDirection();
    if (dir == AidlArgument::OUT_DIR && arg->GetType().IsDynamicArray()) {
      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) {
      GenerateWriteToParcel(tryStatement->statements, typenames, arg->GetType(), _data->name,
                            v->name, options.GetMinSdkVersion(), /*is_return_value=*/false);
    }
  }

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

  // TODO(b/151102494): annotation is applied on the return type
  if (method.GetType().IsPropagateAllowBlocking()) {
    tryStatement->statements->Add(
        std::make_shared<LiteralStatement>("_reply.setPropagateAllowBlocking();\n"));
  }

  // 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"));
  }

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

  if (iface.IsJavaDefault()) {
    checkTransactionError->statements->Add(checkDefaultImpl);
  }

  if (options.Version() > 0) {
    checkTransactionError->statements->Add(
        std::make_shared<LiteralStatement>(android::base::StringPrintf(
            "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
            method.GetName().c_str())));
  }

  if (iface.IsJavaDefault() || options.Version() > 0) {
    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,
                                   .min_sdk_version = options.GetMinSdkVersion(),
                                   .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(),
                                     .min_sdk_version = options.GetMinSdkVersion(),
                                     .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 GenerateMethods(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 = GenerateInterfaceMethod(method);
  } 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) {
      GenerateStubCaseOutline(iface, method, transactCodeName, oneway, stubClass, typenames,
                              options);
    } else {
      GenerateStubCase(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 << "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 << "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 = GenerateProxyMethod(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";
      if (options.GenRpc()) {
        code << "    data.markForBinder(asBinder());\n";
      }
      code << "    try {\n"
           << "      data.writeInterfaceToken(DESCRIPTOR);\n"
           << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
           << "data, reply, 0);\n";
      if (iface.IsJavaDefault()) {
        code << "      if (!_status) {\n"
             << "        if (getDefaultImpl() != null) {\n"
             << "          return getDefaultImpl().getInterfaceVersion();\n"
             << "        }\n"
             << "      }\n";
      }
      code << "      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";
      if (options.GenRpc()) {
        code << "    data.markForBinder(asBinder());\n";
      }
      code << "    try {\n"
           << "      data.writeInterfaceToken(DESCRIPTOR);\n"
           << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
           << "data, reply, 0);\n";
      if (iface.IsJavaDefault()) {
        code << "      if (!_status) {\n"
             << "        if (getDefaultImpl() != null) {\n"
             << "          return getDefaultImpl().getInterfaceHash();\n"
             << "        }\n"
             << "      }\n";
      }
      code << "      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 GenerateInterfaceDescriptors(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->GetTransactDescriptor(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 ComputeOutlineMethods(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> GenerateDefaultImplMethod(const AidlMethod& method) {
  auto default_method = std::make_shared<Method>();
  default_method->comment = GenerateComments(method);
  default_method->modifiers = PUBLIC | OVERRIDE;
  default_method->returnType = JavaSignatureOf(method.GetType());
  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()), arg->GetName()));
  }
  default_method->exceptions.push_back("android.os.RemoteException");

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

static shared_ptr<Class> GenerateDefaultImplClass(const AidlInterface& iface,
                                                  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(GenerateDefaultImplMethod(*m));
    } 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;
}

static shared_ptr<ClassElement> GenerateDelegatorMethod(const AidlMethod& method) {
  auto delegator_method = std::make_shared<Method>();
  delegator_method->comment = GenerateComments(method);
  delegator_method->modifiers = PUBLIC | OVERRIDE;
  delegator_method->returnType = JavaSignatureOf(method.GetType());
  delegator_method->name = method.GetName();
  delegator_method->statements = std::make_shared<StatementBlock>();
  std::vector<std::string> argNames;
  for (const auto& arg : method.GetArguments()) {
    delegator_method->parameters.push_back(
        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
    argNames.push_back(arg->GetName());
  }
  delegator_method->exceptions.push_back("android.os.RemoteException");

  std::string return_str;
  if (method.GetType().GetName() != "void") {
    return_str = "return ";
  }
  delegator_method->statements->Add(
      std::make_shared<LiteralStatement>(return_str + "mImpl." + method.GetName() + "(" +
                                         android::base::Join(argNames, ",") + ");\n"));
  return delegator_method;
}

static shared_ptr<Class> GenerateDelegatorClass(const AidlInterface& iface,
                                                const Options& options) {
  auto delegator_class = std::make_shared<Class>();
  delegator_class->comment = "/** Delegator implementation for " + iface.GetName() + ". */";
  delegator_class->modifiers = PUBLIC | STATIC;
  delegator_class->what = Class::CLASS;
  delegator_class->type = iface.GetCanonicalName() + ".Delegator";
  delegator_class->extends = iface.GetCanonicalName() + ".Stub";

  // constructor
  delegator_class->elements.emplace_back(
      std::make_shared<LiteralClassElement>("public Delegator(" + iface.GetCanonicalName() +
                                            " impl) {\n"
                                            "  this.mImpl = impl;\n"
                                            "}\n"));
  // meta methods
  if (!options.Hash().empty()) {
    delegator_class->elements.emplace_back(
        std::make_shared<LiteralClassElement>("@Override\n"
                                              "public String " +
                                              kGetInterfaceHash +
                                              "() throws android.os.RemoteException {\n"
                                              "  return mImpl." +
                                              kGetInterfaceHash +
                                              "();\n"
                                              "}\n"));
  }
  if (options.Version() > 0) {
    delegator_class->elements.emplace_back(
        std::make_shared<LiteralClassElement>("@Override\n"
                                              "public int " +
                                              kGetInterfaceVersion +
                                              "() throws android.os.RemoteException {\n"
                                              "  int implVer = mImpl." +
                                              kGetInterfaceVersion +
                                              "();\n"
                                              "  return VERSION < implVer ? VERSION : implVer;\n"
                                              "}\n"));
  }

  // user defined methods
  for (const auto& m : iface.GetMethods()) {
    if (m->IsUserDefined()) {
      delegator_class->elements.emplace_back(GenerateDelegatorMethod(*m));
    }
  }

  delegator_class->elements.emplace_back(
      std::make_shared<LiteralClassElement>(iface.GetCanonicalName() + " mImpl;\n"));

  return delegator_class;
}

static shared_ptr<ClassElement> GenerateMaxTransactionId(int max_transaction_id) {
  auto getMaxTransactionId = std::make_shared<Method>();
  getMaxTransactionId->comment = "/** @hide */";
  getMaxTransactionId->modifiers = PUBLIC;
  getMaxTransactionId->returnType = "int";
  getMaxTransactionId->name = "getMaxTransactionId";
  getMaxTransactionId->statements = std::make_shared<StatementBlock>();
  getMaxTransactionId->statements->Add(std::make_shared<ReturnStatement>(
      std::make_shared<LiteralExpression>(std::to_string(max_transaction_id))));
  return getMaxTransactionId;
}

std::unique_ptr<Class> GenerateInterfaceClass(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 = GenerateDefaultImplClass(*iface, options);
  interface->elements.emplace_back(default_impl);

  // the delegator class
  if (iface->IsJavaDelegator()) {
    auto delegator = GenerateDelegatorClass(*iface, options);
    interface->elements.emplace_back(delegator);
  }

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

  ComputeOutlineMethods(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()
  GenerateInterfaceDescriptors(options, iface, interface.get(), stub, proxy);

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

  // all the declared methods of the interface
  bool permissionWrapperGenerated = false;
  int max_transaction_id = 0;
  for (const auto& item : iface->GetMethods()) {
    if ((iface->EnforceExpression() || item->GetType().EnforceExpression()) &&
        !permissionWrapperGenerated) {
      GeneratePermissionWrapper(stub.get());
      permissionWrapperGenerated = true;
    }
    GenerateMethods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames, options);
    max_transaction_id = std::max(max_transaction_id, item->GetId());
  }

  // getMaxTransactionId
  if (options.GenTransactionNames()) {
    stub->elements.push_back(GenerateMaxTransactionId(max_transaction_id));
  }

  // all the nested types
  string code;
  auto writer = CodeWriter::ForString(&code);
  for (const auto& nested : iface->GetNestedTypes()) {
    GenerateClass(*writer, *nested, typenames, options);
  }
  GenerateParcelHelpers(*writer, *iface, options);
  writer->Close();
  interface->elements.push_back(std::make_shared<LiteralClassElement>(code));

  if (iface->IsJavaDefault()) {
    // 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
