/*
 * Copyright (C) 2017 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.
 */

#ifndef ART_ADBCONNECTION_ADBCONNECTION_H_
#define ART_ADBCONNECTION_ADBCONNECTION_H_

#include <jni.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <limits>
#include <memory>
#include <vector>

#include "adbconnection/client.h"
#include "base/array_ref.h"
#include "base/mutex.h"
#include "runtime_callbacks.h"

namespace adbconnection {

static constexpr char kJdwpControlName[] = "\0jdwp-control";
static constexpr char kAdbConnectionThreadName[] = "ADB-JDWP Connection Control Thread";

// The default jdwp agent name.
static constexpr char kDefaultJdwpAgentName[] = "libjdwp.so";

class AdbConnectionState;

struct AdbConnectionDebuggerController : public art::DebuggerControlCallback {
  explicit AdbConnectionDebuggerController(AdbConnectionState* connection)
      : connection_(connection) {}

  // Begin running the debugger.
  void StartDebugger() override;

  // The debugger should begin shutting down since the runtime is ending.
  void StopDebugger() override;

  bool IsDebuggerConfigured() override;

 private:
  AdbConnectionState* connection_;
};

enum class DdmPacketType : uint8_t { kReply = 0x80, kCmd = 0x00, };

struct AdbConnectionDdmCallback : public art::DdmCallback {
  explicit AdbConnectionDdmCallback(AdbConnectionState* connection) : connection_(connection) {}

  void DdmPublishChunk(uint32_t type,
                       const art::ArrayRef<const uint8_t>& data)
      REQUIRES_SHARED(art::Locks::mutator_lock_);

 private:
  AdbConnectionState* connection_;
};

class AdbConnectionState {
 public:
  explicit AdbConnectionState(const std::string& name);
  ~AdbConnectionState();

  // Called on the listening thread to start dealing with new input. thr is used to attach the new
  // thread to the runtime.
  void RunPollLoop(art::Thread* self);

  // Sends ddms data over the socket, if there is one. This data is sent even if we haven't finished
  // hand-shaking yet.
  void PublishDdmData(uint32_t type, const art::ArrayRef<const uint8_t>& data);

  // Stops debugger threads during shutdown.
  void StopDebuggerThreads();

  // If StartDebuggerThreads was called successfully.
  bool DebuggerThreadsStarted() {
    return started_debugger_threads_;
  }

 private:
  uint32_t NextDdmId();

  void StartDebuggerThreads();

  // Tell adbd about the new runtime.
  bool SetupAdbConnection();

  std::string MakeAgentArg();

  void SendAgentFds(bool require_handshake);

  void CloseFds();

  void HandleDataWithoutAgent(art::Thread* self);

  void PerformHandshake();

  void AttachJdwpAgent(art::Thread* self);

  void NotifyDdms(bool active);

  void SendDdmPacket(uint32_t id,
                     DdmPacketType type,
                     uint32_t ddm_type,
                     art::ArrayRef<const uint8_t> data);

  std::string agent_name_;

  AdbConnectionDebuggerController controller_;
  AdbConnectionDdmCallback ddm_callback_;

  // Eventfd used to allow the StopDebuggerThreads function to wake up sleeping threads
  android::base::unique_fd sleep_event_fd_;

  // Context which wraps the socket which we use to talk to adbd.
  std::unique_ptr<AdbConnectionClientContext, void(*)(AdbConnectionClientContext*)> control_ctx_;

  // Socket that we use to talk to the agent (if it's loaded).
  android::base::unique_fd local_agent_control_sock_;

  // The fd of the socket the agent uses to talk to us. We need to keep it around in order to clean
  // it up when the runtime goes away.
  android::base::unique_fd remote_agent_control_sock_;

  // The fd that is forwarded through adb to the client. This is guarded by the
  // adb_write_event_fd_.
  android::base::unique_fd adb_connection_socket_;

  // The fd we send to the agent to let us synchronize access to the shared adb_connection_socket_.
  // This is also used as a general lock for the adb_connection_socket_ on any threads other than
  // the poll thread.
  android::base::unique_fd adb_write_event_fd_;

  std::atomic<bool> shutting_down_;

  // True if we have loaded the agent library.
  std::atomic<bool> agent_loaded_;

  // True if the dt_fd_forward transport is listening for a new communication channel.
  std::atomic<bool> agent_listening_;

  // True if the dt_fd_forward transport has the socket. If so we don't do anything to the agent or
  // the adb connection socket until connection goes away.
  std::atomic<bool> agent_has_socket_;

  std::atomic<bool> sent_agent_fds_;

  std::atomic<bool> performed_handshake_;

  bool notified_ddm_active_;

  std::atomic<uint32_t> next_ddm_id_;

  bool started_debugger_threads_;

  friend struct AdbConnectionDebuggerController;
};

}  // namespace adbconnection

#endif  // ART_ADBCONNECTION_ADBCONNECTION_H_
