// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Commands used are documented here:
// https://github.com/mozilla/libadb.js/blob/master/android-tools/adb-bin/SERVICES.TXT

#include "chrome/test/chromedriver/chrome/adb_impl.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/string_escape.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/time/time.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/net/adb_client_socket.h"
#include "net/base/net_errors.h"

namespace {

// This class is bound in the callback to AdbQuery and isn't freed until the
// callback is run, even if the function that creates the buffer times out.
class ResponseBuffer : public base::RefCountedThreadSafe<ResponseBuffer> {
 public:
  ResponseBuffer()
      : ready_(base::WaitableEvent::ResetPolicy::MANUAL,
               base::WaitableEvent::InitialState::NOT_SIGNALED) {}

  void OnResponse(int result, const std::string& response) {
    response_ = response;
    result_ = result;
    ready_.Signal();
  }

  Status GetResponse(
      std::string* response, const base::TimeDelta& timeout) {
    base::TimeTicks deadline = base::TimeTicks::Now() + timeout;
    while (!ready_.IsSignaled()) {
      base::TimeDelta delta = deadline - base::TimeTicks::Now();
      if (delta <= base::TimeDelta())
        return Status(kTimeout, base::StringPrintf(
            "Adb command timed out after %d seconds",
            static_cast<int>(timeout.InSeconds())));
      ready_.TimedWait(timeout);
    }
    if (result_ < 0) {
      return Status(kUnknownError,
                    "Failed to run adb command with networking error: " +
                        net::ErrorToString(result_) +
                        ". Is the adb server running? Extra response: <" +
                        response_ + ">.");
    }
    if (result_ > 0) {
      return Status(
          // TODO(crouleau): Use an error code that can differentiate this from
          // the above networking error.
          kUnknownError,
          "The adb command failed. Extra response: <" + response_ + ">.");
    }
    *response = response_;
    return Status(kOk);
  }

 private:
  friend class base::RefCountedThreadSafe<ResponseBuffer>;
  ~ResponseBuffer() {}

  std::string response_;
  int result_;
  base::WaitableEvent ready_;
};

void ExecuteCommandOnIOThread(
    const std::string& command, scoped_refptr<ResponseBuffer> response_buffer,
    int port) {
  CHECK(base::MessageLoopCurrentForIO::IsSet());
  AdbClientSocket::AdbQuery(port, command,
      base::Bind(&ResponseBuffer::OnResponse, response_buffer));
}

void SendFileOnIOThread(const std::string& device_serial,
                        const std::string& filename,
                        const std::string& content,
                        scoped_refptr<ResponseBuffer> response_buffer,
                        int port) {
  CHECK(base::MessageLoopCurrentForIO::IsSet());
  AdbClientSocket::SendFile(
      port, device_serial, filename, content,
      base::Bind(&ResponseBuffer::OnResponse, response_buffer));
}

}  // namespace

AdbImpl::AdbImpl(
    const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
    int port)
    : io_task_runner_(io_task_runner), port_(port) {
  CHECK(io_task_runner_.get());
}

AdbImpl::~AdbImpl() {}

Status AdbImpl::GetDevices(std::vector<std::string>* devices) {
  std::string response;
  Status status = ExecuteCommand("host:devices", &response);
  if (!status.IsOk())
    return status;
  base::StringTokenizer lines(response, "\n");
  while (lines.GetNext()) {
    std::vector<std::string> fields = base::SplitString(
        lines.token_piece(), base::kWhitespaceASCII,
        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    if (fields.size() == 2 && fields[1] == "device") {
      devices->push_back(fields[0]);
    }
  }
  return Status(kOk);
}

Status AdbImpl::ForwardPort(const std::string& device_serial,
                            const std::string& remote_abstract,
                            int* local_port_output) {
  std::string response;
  Status adb_command_status = ExecuteHostCommand(
      device_serial, "forward:tcp:0;localabstract:" + remote_abstract,
      &response);
  // response should be the port number like "39025".
  if (!adb_command_status.IsOk())
    return Status(kUnknownError, "Failed to forward ports to device " +
                                     device_serial + ": " + response + ". " +
                                     adb_command_status.message());
  base::StringToInt(response, local_port_output);
  if (*local_port_output == 0) {
    return Status(
        kUnknownError,
        "Failed to forward ports to device " + device_serial +
            ". No port chosen: " + response +
            ". Perhaps your adb version is out of date. "
            "ChromeDriver 2.39 and newer require adb version 1.0.38 or newer. "
            "Run 'adb version' in your terminal of the host device to find "
            "your version of adb.");
  }

  return Status(kOk);
}

Status AdbImpl::SetCommandLineFile(const std::string& device_serial,
                                   const std::string& command_line_file,
                                   const std::string& exec_name,
                                   const std::string& args) {
  std::string response;
  std::string command(exec_name + " " + args + "\n");
  scoped_refptr<ResponseBuffer> response_buffer = new ResponseBuffer;
  VLOG(1) << "Sending command line file: " << command_line_file;
  io_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&SendFileOnIOThread, device_serial, command_line_file,
                     command, response_buffer, port_));
  Status status =
      response_buffer->GetResponse(&response, base::TimeDelta::FromSeconds(30));
  return status;
}

Status AdbImpl::CheckAppInstalled(
    const std::string& device_serial, const std::string& package) {
  std::string response;
  std::string command = "pm path " + package;
  Status status = ExecuteHostShellCommand(device_serial, command, &response);
  if (!status.IsOk())
    return status;
  if (response.find("package") == std::string::npos)
    return Status(kUnknownError, package + " is not installed on device " +
                  device_serial);
  return Status(kOk);
}

Status AdbImpl::ClearAppData(
    const std::string& device_serial, const std::string& package) {
  std::string response;
  std::string command = "pm clear " + package;
  Status status = ExecuteHostShellCommand(device_serial, command, &response);
  if (!status.IsOk())
    return status;
  if (response.find("Success") == std::string::npos)
    return Status(kUnknownError, "Failed to clear data for " + package +
                  " on device " + device_serial + ": " + response);
  return Status(kOk);
}

Status AdbImpl::SetDebugApp(
    const std::string& device_serial, const std::string& package) {
  std::string response;
  return ExecuteHostShellCommand(
      device_serial, "am set-debug-app --persistent " + package, &response);
}

Status AdbImpl::Launch(
    const std::string& device_serial, const std::string& package,
    const std::string& activity) {
  std::string response;
  Status status = ExecuteHostShellCommand(
      device_serial,
      "am start -W -n " + package + "/" + activity + " -d data:,",
      &response);
  if (!status.IsOk())
    return status;
  if (response.find("Complete") == std::string::npos)
    return Status(kUnknownError,
                  "Failed to start " + package + " on device " + device_serial +
                  ": " + response);
  return Status(kOk);
}

Status AdbImpl::ForceStop(
    const std::string& device_serial, const std::string& package) {
  std::string response;
  return ExecuteHostShellCommand(
      device_serial, "am force-stop " + package, &response);
}

Status AdbImpl::GetPidByName(const std::string& device_serial,
                             const std::string& process_name,
                             int* pid) {
  std::string response;
  // on Android O `ps` returns only user processes, so also try with `-A` flag.
  Status status =
      ExecuteHostShellCommand(device_serial, "ps && ps -A", &response);

  if (!status.IsOk())
    return status;

  for (const base::StringPiece& line : base::SplitString(
           response, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    std::vector<base::StringPiece> tokens = base::SplitStringPiece(
        line, base::kWhitespaceASCII,
        base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    if (tokens.size() != 8 && tokens.size() != 9)
      continue;
    // The ps command on Android M+ does not always output a value for WCHAN,
    // so the process name might appear in the 8th or 9th column. Use the
    // right-most column for process name.
    if (tokens[tokens.size() - 1] == process_name) {
      if (base::StringToInt(tokens[1], pid)) {
        return Status(kOk);
      } else {
        break;
      }
    }
  }

  return Status(kUnknownError,
                "Failed to get PID for the following process: " + process_name);
}

Status AdbImpl::GetSocketByPattern(const std::string& device_serial,
                                   const std::string& grep_pattern,
                                   std::string* socket_name) {
  std::string response;
  std::string grep_command = "grep -a '" + grep_pattern + "' /proc/net/unix";
  Status status =
      ExecuteHostShellCommand(device_serial, grep_command, &response);

  if (!status.IsOk())
    return status;

  for (const base::StringPiece& line : base::SplitString(
           response, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
    std::vector<base::StringPiece> tokens = base::SplitStringPiece(
        line, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
        base::SPLIT_WANT_NONEMPTY);
    if (tokens.size() != 8)
      continue;
    *socket_name = tokens[7].as_string();
    return Status(kOk);
  }

  return Status(kUnknownError,
                "Failed to get sockets matching: " + grep_pattern);
}

Status AdbImpl::ExecuteCommand(
    const std::string& command, std::string* response) {
  scoped_refptr<ResponseBuffer> response_buffer = new ResponseBuffer;
  VLOG(1) << "Sending adb command: " << command;
  io_task_runner_->PostTask(FROM_HERE,
                            base::BindOnce(&ExecuteCommandOnIOThread, command,
                                           response_buffer, port_));
  Status status = response_buffer->GetResponse(
      response, base::TimeDelta::FromSeconds(30));
  if (status.IsOk()) {
    VLOG(1) << "Received adb response: " << *response;
  }
  return status;
}

Status AdbImpl::ExecuteHostCommand(
    const std::string& device_serial,
    const std::string& host_command, std::string* response) {
  return ExecuteCommand(
      "host-serial:" + device_serial + ":" + host_command, response);
}

Status AdbImpl::ExecuteHostShellCommand(
    const std::string& device_serial,
    const std::string& shell_command,
    std::string* response) {
  return ExecuteCommand(
      "host:transport:" + device_serial + "|shell:" + shell_command,
      response);
}
