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

#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <time.h>
#include <unistd.h>

#include <chrono>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>

using android::base::StringPrintf;
using namespace std::chrono_literals;

static std::thread* g_bootcharting_thread;

static std::mutex g_bootcharting_finished_mutex;
static std::condition_variable g_bootcharting_finished_cv;
static bool g_bootcharting_finished;

static long long get_uptime_jiffies() {
  std::string uptime;
  if (!android::base::ReadFileToString("/proc/uptime", &uptime)) return 0;
  return 100LL * strtod(uptime.c_str(), NULL);
}

static std::unique_ptr<FILE, decltype(&fclose)> fopen_unique(const char* filename,
                                                             const char* mode) {
  std::unique_ptr<FILE, decltype(&fclose)> result(fopen(filename, mode), fclose);
  if (!result) PLOG(ERROR) << "bootchart: failed to open " << filename;
  return result;
}

static void log_header() {
  char date[32];
  time_t now_t = time(NULL);
  struct tm now = *localtime(&now_t);
  strftime(date, sizeof(date), "%F %T", &now);

  utsname uts;
  if (uname(&uts) == -1) return;

  std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "");
  if (fingerprint.empty()) return;

  std::string kernel_cmdline;
  android::base::ReadFileToString("/proc/cmdline", &kernel_cmdline);

  auto fp = fopen_unique("/data/bootchart/header", "we");
  if (!fp) return;
  fprintf(&*fp, "version = Android init 0.8\n");
  fprintf(&*fp, "title = Boot chart for Android (%s)\n", date);
  fprintf(&*fp, "system.uname = %s %s %s %s\n", uts.sysname, uts.release, uts.version, uts.machine);
  fprintf(&*fp, "system.release = %s\n", fingerprint.c_str());
  // TODO: use /proc/cpuinfo "model name" line for x86, "Processor" line for arm.
  fprintf(&*fp, "system.cpu = %s\n", uts.machine);
  fprintf(&*fp, "system.kernel.options = %s\n", kernel_cmdline.c_str());
}

static void log_uptime(FILE* log) {
  fprintf(log, "%lld\n", get_uptime_jiffies());
}

static void log_file(FILE* log, const char* procfile) {
  log_uptime(log);

  std::string content;
  if (android::base::ReadFileToString(procfile, &content)) {
    fprintf(log, "%s\n", content.c_str());
  }
}

static void log_processes(FILE* log) {
  log_uptime(log);

  std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir("/proc"), closedir);
  struct dirent* entry;
  while ((entry = readdir(dir.get())) != NULL) {
    // Only match numeric values.
    int pid = atoi(entry->d_name);
    if (pid == 0) continue;

    // /proc/<pid>/stat only has truncated task names, so get the full
    // name from /proc/<pid>/cmdline.
    std::string cmdline;
    android::base::ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &cmdline);
    const char* full_name = cmdline.c_str(); // So we stop at the first NUL.

    // Read process stat line.
    std::string stat;
    if (android::base::ReadFileToString(StringPrintf("/proc/%d/stat", pid), &stat)) {
      if (!cmdline.empty()) {
        // Substitute the process name with its real name.
        size_t open = stat.find('(');
        size_t close = stat.find_last_of(')');
        if (open != std::string::npos && close != std::string::npos) {
          stat.replace(open + 1, close - open - 1, full_name);
        }
      }
      fputs(stat.c_str(), log);
    }
  }

  fputc('\n', log);
}

static void bootchart_thread_main() {
  LOG(INFO) << "Bootcharting started";

  // Open log files.
  auto stat_log = fopen_unique("/data/bootchart/proc_stat.log", "we");
  if (!stat_log) return;
  auto proc_log = fopen_unique("/data/bootchart/proc_ps.log", "we");
  if (!proc_log) return;
  auto disk_log = fopen_unique("/data/bootchart/proc_diskstats.log", "we");
  if (!disk_log) return;

  log_header();

  while (true) {
    {
      std::unique_lock<std::mutex> lock(g_bootcharting_finished_mutex);
      g_bootcharting_finished_cv.wait_for(lock, 200ms);
      if (g_bootcharting_finished) break;
    }

    log_file(&*stat_log, "/proc/stat");
    log_file(&*disk_log, "/proc/diskstats");
    log_processes(&*proc_log);
  }

  LOG(INFO) << "Bootcharting finished";
}

static int do_bootchart_start() {
  // We don't care about the content, but we do care that /data/bootchart/enabled actually exists.
  std::string start;
  if (!android::base::ReadFileToString("/data/bootchart/enabled", &start)) {
    LOG(VERBOSE) << "Not bootcharting";
    return 0;
  }

  g_bootcharting_thread = new std::thread(bootchart_thread_main);
  return 0;
}

static int do_bootchart_stop() {
  if (!g_bootcharting_thread) return 0;

  // Tell the worker thread it's time to quit.
  {
    std::lock_guard<std::mutex> lock(g_bootcharting_finished_mutex);
    g_bootcharting_finished = true;
    g_bootcharting_finished_cv.notify_one();
  }

  g_bootcharting_thread->join();
  delete g_bootcharting_thread;
  g_bootcharting_thread = nullptr;
  return 0;
}

int do_bootchart(const std::vector<std::string>& args) {
  if (args[1] == "start") return do_bootchart_start();
  return do_bootchart_stop();
}
