/*
 * Copyright (C) 2019 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 "simpleperf.h"

#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#include <android/log.h>
#include <mutex>
#include <sstream>

namespace simpleperf {

constexpr int AID_USER_OFFSET = 100000;

enum RecordCmd {
  CMD_PAUSE_RECORDING = 1,
  CMD_RESUME_RECORDING,
};

class RecordOptionsImpl {
 public:
  std::string output_filename;
  std::string event = "cpu-cycles";
  size_t freq = 4000;
  double duration_in_second = 0.0;
  std::vector<pid_t> threads;
  bool dwarf_callgraph = false;
  bool fp_callgraph = false;
  bool trace_offcpu = false;
};

RecordOptions::RecordOptions() : impl_(new RecordOptionsImpl) {}

RecordOptions::~RecordOptions() {
  delete impl_;
}

RecordOptions& RecordOptions::SetOutputFilename(const std::string& filename) {
  impl_->output_filename = filename;
  return *this;
}

RecordOptions& RecordOptions::SetEvent(const std::string& event) {
  impl_->event = event;
  return *this;
}

RecordOptions& RecordOptions::SetSampleFrequency(size_t freq) {
  impl_->freq = freq;
  return *this;
}

RecordOptions& RecordOptions::SetDuration(double duration_in_second) {
  impl_->duration_in_second = duration_in_second;
  return *this;
}

RecordOptions& RecordOptions::SetSampleThreads(const std::vector<pid_t>& threads) {
  impl_->threads = threads;
  return *this;
}

RecordOptions& RecordOptions::RecordDwarfCallGraph() {
  impl_->dwarf_callgraph = true;
  impl_->fp_callgraph = false;
  return *this;
}

RecordOptions& RecordOptions::RecordFramePointerCallGraph() {
  impl_->fp_callgraph = true;
  impl_->dwarf_callgraph = false;
  return *this;
}

RecordOptions& RecordOptions::TraceOffCpu() {
  impl_->trace_offcpu = true;
  return *this;
}

static std::string GetDefaultOutputFilename() {
  time_t t = time(nullptr);
  struct tm tm;
  if (localtime_r(&t, &tm) != &tm) {
    return "perf.data";
  }
  char* buf = nullptr;
  asprintf(&buf, "perf-%02d-%02d-%02d-%02d-%02d.data", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
           tm.tm_min, tm.tm_sec);
  std::string result = buf;
  free(buf);
  return result;
}

std::vector<std::string> RecordOptions::ToRecordArgs() const {
  std::vector<std::string> args;
  std::string output_filename = impl_->output_filename;
  if (output_filename.empty()) {
    output_filename = GetDefaultOutputFilename();
  }
  args.insert(args.end(), {"-o", output_filename});
  args.insert(args.end(), {"-e", impl_->event});
  args.insert(args.end(), {"-f", std::to_string(impl_->freq)});
  if (impl_->duration_in_second != 0.0) {
    args.insert(args.end(), {"--duration", std::to_string(impl_->duration_in_second)});
  }
  if (impl_->threads.empty()) {
    args.insert(args.end(), {"-p", std::to_string(getpid())});
  } else {
    std::ostringstream os;
    os << *(impl_->threads.begin());
    for (auto it = std::next(impl_->threads.begin()); it != impl_->threads.end(); ++it) {
      os << "," << *it;
    }
    args.insert(args.end(), {"-t", os.str()});
  }
  if (impl_->dwarf_callgraph) {
    args.push_back("-g");
  } else if (impl_->fp_callgraph) {
    args.insert(args.end(), {"--call-graph", "fp"});
  }
  if (impl_->trace_offcpu) {
    args.push_back("--trace-offcpu");
  }
  return args;
}

static void Abort(const char* fmt, ...) {
  va_list vl;
  va_start(vl, fmt);
  __android_log_vprint(ANDROID_LOG_FATAL, "simpleperf", fmt, vl);
  va_end(vl);
  abort();
}

class ProfileSessionImpl {
 public:
  ProfileSessionImpl(const std::string& app_data_dir)
      : app_data_dir_(app_data_dir), simpleperf_data_dir_(app_data_dir + "/simpleperf_data") {}
  ~ProfileSessionImpl();
  void StartRecording(const std::vector<std::string>& args);
  void PauseRecording();
  void ResumeRecording();
  void StopRecording();

 private:
  std::string FindSimpleperf();
  std::string FindSimpleperfInTempDir();
  void CheckIfPerfEnabled();
  std::string GetProperty(const std::string& name);
  void CreateSimpleperfDataDir();
  void CreateSimpleperfProcess(const std::string& simpleperf_path,
                               const std::vector<std::string>& record_args);
  void SendCmd(const std::string& cmd);
  std::string ReadReply();

  enum State {
    NOT_YET_STARTED,
    STARTED,
    PAUSED,
    STOPPED,
  };

  const std::string app_data_dir_;
  const std::string simpleperf_data_dir_;
  std::mutex lock_;  // Protect all members below.
  State state_ = NOT_YET_STARTED;
  pid_t simpleperf_pid_ = -1;
  int control_fd_ = -1;
  int reply_fd_ = -1;
  bool trace_offcpu_ = false;
};

ProfileSessionImpl::~ProfileSessionImpl() {
  if (control_fd_ != -1) {
    close(control_fd_);
  }
  if (reply_fd_ != -1) {
    close(reply_fd_);
  }
}

void ProfileSessionImpl::StartRecording(const std::vector<std::string>& args) {
  std::lock_guard<std::mutex> guard(lock_);
  if (state_ != NOT_YET_STARTED) {
    Abort("startRecording: session in wrong state %d", state_);
  }
  for (const auto& arg : args) {
    if (arg == "--trace-offcpu") {
      trace_offcpu_ = true;
    }
  }
  std::string simpleperf_path = FindSimpleperf();
  CheckIfPerfEnabled();
  CreateSimpleperfDataDir();
  CreateSimpleperfProcess(simpleperf_path, args);
  state_ = STARTED;
}

void ProfileSessionImpl::PauseRecording() {
  std::lock_guard<std::mutex> guard(lock_);
  if (state_ != STARTED) {
    Abort("pauseRecording: session in wrong state %d", state_);
  }
  if (trace_offcpu_) {
    Abort("--trace-offcpu doesn't work well with pause/resume recording");
  }
  SendCmd("pause");
  state_ = PAUSED;
}

void ProfileSessionImpl::ResumeRecording() {
  std::lock_guard<std::mutex> guard(lock_);
  if (state_ != PAUSED) {
    Abort("resumeRecording: session in wrong state %d", state_);
  }
  SendCmd("resume");
  state_ = STARTED;
}

void ProfileSessionImpl::StopRecording() {
  std::lock_guard<std::mutex> guard(lock_);
  if (state_ != STARTED && state_ != PAUSED) {
    Abort("stopRecording: session in wrong state %d", state_);
  }
  // Send SIGINT to simpleperf to stop recording.
  if (kill(simpleperf_pid_, SIGINT) == -1) {
    Abort("failed to stop simpleperf: %s", strerror(errno));
  }
  int status;
  pid_t result = TEMP_FAILURE_RETRY(waitpid(simpleperf_pid_, &status, 0));
  if (result == -1) {
    Abort("failed to call waitpid: %s", strerror(errno));
  }
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    Abort("simpleperf exited with error, status = 0x%x", status);
  }
  state_ = STOPPED;
}

void ProfileSessionImpl::SendCmd(const std::string& cmd) {
  std::string data = cmd + "\n";
  if (TEMP_FAILURE_RETRY(write(control_fd_, &data[0], data.size())) !=
      static_cast<ssize_t>(data.size())) {
    Abort("failed to send cmd to simpleperf: %s", strerror(errno));
  }
  if (ReadReply() != "ok") {
    Abort("failed to run cmd in simpleperf: %s", cmd.c_str());
  }
}

static bool IsExecutableFile(const std::string& path) {
  struct stat st;
  if (stat(path.c_str(), &st) == 0) {
    if (S_ISREG(st.st_mode) && (st.st_mode & S_IXUSR)) {
      return true;
    }
  }
  return false;
}

static std::string ReadFile(FILE* fp) {
  std::string s;
  if (fp == nullptr) {
    return s;
  }
  char buf[200];
  while (true) {
    ssize_t n = fread(buf, 1, sizeof(buf), fp);
    if (n <= 0) {
      break;
    }
    s.insert(s.end(), buf, buf + n);
  }
  fclose(fp);
  return s;
}

static bool RunCmd(std::vector<const char*> args, std::string* stdout) {
  int stdout_fd[2];
  if (pipe(stdout_fd) != 0) {
    return false;
  }
  args.push_back(nullptr);
  // Fork handlers (like gsl_library_close) may hang in a multi-thread environment.
  // So we use vfork instead of fork to avoid calling them.
  int pid = vfork();
  if (pid == -1) {
    return false;
  }
  if (pid == 0) {
    // child process
    close(stdout_fd[0]);
    dup2(stdout_fd[1], 1);
    close(stdout_fd[1]);
    execvp(const_cast<char*>(args[0]), const_cast<char**>(args.data()));
    _exit(1);
  }
  // parent process
  close(stdout_fd[1]);
  int status;
  pid_t result = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
  if (result == -1) {
    Abort("failed to call waitpid: %s", strerror(errno));
  }
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    return false;
  }
  if (stdout == nullptr) {
    close(stdout_fd[0]);
  } else {
    *stdout = ReadFile(fdopen(stdout_fd[0], "r"));
  }
  return true;
}

std::string ProfileSessionImpl::FindSimpleperf() {
  // 1. Try /data/local/tmp/simpleperf first. Probably it's newer than /system/bin/simpleperf.
  std::string simpleperf_path = FindSimpleperfInTempDir();
  if (!simpleperf_path.empty()) {
    return simpleperf_path;
  }
  // 2. Try /system/bin/simpleperf, which is available on Android >= Q.
  simpleperf_path = "/system/bin/simpleperf";
  if (IsExecutableFile(simpleperf_path)) {
    return simpleperf_path;
  }
  Abort("can't find simpleperf on device. Please run api_profiler.py.");
  return "";
}

std::string ProfileSessionImpl::FindSimpleperfInTempDir() {
  const std::string path = "/data/local/tmp/simpleperf";
  if (!IsExecutableFile(path)) {
    return "";
  }
  // Copy it to app_dir to execute it.
  const std::string to_path = app_data_dir_ + "/simpleperf";
  if (!RunCmd({"/system/bin/cp", path.c_str(), to_path.c_str()}, nullptr)) {
    return "";
  }
  // For apps with target sdk >= 29, executing app data file isn't allowed.
  // For android R, app context isn't allowed to use perf_event_open.
  // So test executing downloaded simpleperf.
  std::string s;
  if (!RunCmd({to_path.c_str(), "list", "sw"}, &s)) {
    return "";
  }
  if (s.find("cpu-clock") == std::string::npos) {
    return "";
  }
  return to_path;
}

void ProfileSessionImpl::CheckIfPerfEnabled() {
  if (GetProperty("persist.simpleperf.profile_app_uid") == std::to_string(getuid())) {
    std::string time_str = GetProperty("persist.simpleperf.profile_app_expiration_time");
    if (!time_str.empty()) {
      errno = 0;
      uint64_t expiration_time = strtoull(time_str.data(), nullptr, 10);
      if (errno == 0 && expiration_time > time(nullptr)) {
        return;
      }
    }
  }
  if (GetProperty("security.perf_harden") == "1") {
    Abort("Recording app isn't enabled on the device. Please run api_profiler.py.");
  }
}

std::string ProfileSessionImpl::GetProperty(const std::string& name) {
  std::string s;
  if (!RunCmd({"/system/bin/getprop", name.c_str()}, &s)) {
    return "";
  }
  return s;
}

void ProfileSessionImpl::CreateSimpleperfDataDir() {
  struct stat st;
  if (stat(simpleperf_data_dir_.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
    return;
  }
  if (mkdir(simpleperf_data_dir_.c_str(), 0700) == -1) {
    Abort("failed to create simpleperf data dir %s: %s", simpleperf_data_dir_.c_str(),
          strerror(errno));
  }
}

void ProfileSessionImpl::CreateSimpleperfProcess(const std::string& simpleperf_path,
                                                 const std::vector<std::string>& record_args) {
  // 1. Create control/reply pips.
  int control_fd[2];
  int reply_fd[2];
  if (pipe(control_fd) != 0 || pipe(reply_fd) != 0) {
    Abort("failed to call pipe: %s", strerror(errno));
  }

  // 2. Prepare simpleperf arguments.
  std::vector<std::string> args;
  args.emplace_back(simpleperf_path);
  args.emplace_back("record");
  args.emplace_back("--log-to-android-buffer");
  args.insert(args.end(), {"--log", "debug"});
  args.emplace_back("--stdio-controls-profiling");
  args.emplace_back("--in-app");
  args.insert(args.end(), {"--tracepoint-events", "/data/local/tmp/tracepoint_events"});
  args.insert(args.end(), record_args.begin(), record_args.end());
  char* argv[args.size() + 1];
  for (size_t i = 0; i < args.size(); ++i) {
    argv[i] = &args[i][0];
  }
  argv[args.size()] = nullptr;

  // 3. Start simpleperf process.
  // Fork handlers (like gsl_library_close) may hang in a multi-thread environment.
  // So we use vfork instead of fork to avoid calling them.
  int pid = vfork();
  if (pid == -1) {
    Abort("failed to fork: %s", strerror(errno));
  }
  if (pid == 0) {
    // child process
    close(control_fd[1]);
    dup2(control_fd[0], 0);  // simpleperf read control cmd from fd 0.
    close(control_fd[0]);
    close(reply_fd[0]);
    dup2(reply_fd[1], 1);  // simpleperf writes reply to fd 1.
    close(reply_fd[0]);
    chdir(simpleperf_data_dir_.c_str());
    execvp(argv[0], argv);
    Abort("failed to call exec: %s", strerror(errno));
  }
  // parent process
  close(control_fd[0]);
  control_fd_ = control_fd[1];
  close(reply_fd[1]);
  reply_fd_ = reply_fd[0];
  simpleperf_pid_ = pid;

  // 4. Wait until simpleperf starts recording.
  std::string start_flag = ReadReply();
  if (start_flag != "started") {
    Abort("failed to receive simpleperf start flag");
  }
}

std::string ProfileSessionImpl::ReadReply() {
  std::string s;
  while (true) {
    char c;
    ssize_t result = TEMP_FAILURE_RETRY(read(reply_fd_, &c, 1));
    if (result <= 0 || c == '\n') {
      break;
    }
    s.push_back(c);
  }
  return s;
}

ProfileSession::ProfileSession() {
  FILE* fp = fopen("/proc/self/cmdline", "r");
  if (fp == nullptr) {
    Abort("failed to open /proc/self/cmdline: %s", strerror(errno));
  }
  std::string s = ReadFile(fp);
  for (int i = 0; i < s.size(); i++) {
    if (s[i] == '\0') {
      s = s.substr(0, i);
      break;
    }
  }
  std::string app_data_dir = "/data/data/" + s;
  int uid = getuid();
  if (uid >= AID_USER_OFFSET) {
    int user_id = uid / AID_USER_OFFSET;
    app_data_dir = "/data/user/" + std::to_string(user_id) + "/" + s;
  }
  impl_ = new ProfileSessionImpl(app_data_dir);
}

ProfileSession::ProfileSession(const std::string& app_data_dir)
    : impl_(new ProfileSessionImpl(app_data_dir)) {}

ProfileSession::~ProfileSession() {
  delete impl_;
}

void ProfileSession::StartRecording(const RecordOptions& options) {
  StartRecording(options.ToRecordArgs());
}

void ProfileSession::StartRecording(const std::vector<std::string>& record_args) {
  impl_->StartRecording(record_args);
}

void ProfileSession::PauseRecording() {
  impl_->PauseRecording();
}

void ProfileSession::ResumeRecording() {
  impl_->ResumeRecording();
}

void ProfileSession::StopRecording() {
  impl_->StopRecording();
}

}  // namespace simpleperf
