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

#include <brillo/message_loops/base_message_loop.h>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <unistd.h>

#ifndef __ANDROID_HOST__
// Used for MISC_MAJOR. Only required for the target and not always available
// for the host.
#include <linux/major.h>
#endif

#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/run_loop.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/message_loop/message_pump_type.h>
#include <base/threading/thread_task_runner_handle.h>

#include <brillo/location_logging.h>
#include <brillo/strings/string_utils.h>

namespace {

const char kMiscMinorPath[] = "/proc/misc";
const char kBinderDriverName[] = "binder";

}  // namespace

namespace brillo {

const int BaseMessageLoop::kInvalidMinor = -1;
const int BaseMessageLoop::kUninitializedMinor = -2;

BaseMessageLoop::BaseMessageLoop() {
  CHECK(!base::ThreadTaskRunnerHandle::IsSet())
      << "You can't create a base::SingleThreadTaskExecutor when another "
         "base::SingleThreadTaskExecutor is already created for this thread.";
  owned_task_executor_.reset(
      new base::SingleThreadTaskExecutor(base::MessagePumpType::IO));
  task_runner_ = owned_task_executor_->task_runner();
  watcher_ = std::make_unique<base::FileDescriptorWatcher>(task_runner_);
}

BaseMessageLoop::BaseMessageLoop(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    : task_runner_(task_runner),
      watcher_(std::make_unique<base::FileDescriptorWatcher>(task_runner)) {}

BaseMessageLoop::~BaseMessageLoop() {
  // Note all pending canceled delayed tasks when destroying the message loop.
  size_t lazily_deleted_tasks = 0;
  for (const auto& delayed_task : delayed_tasks_) {
    if (delayed_task.second.closure.is_null()) {
      lazily_deleted_tasks++;
    } else {
      DVLOG_LOC(delayed_task.second.location, 1)
          << "Removing delayed task_id " << delayed_task.first
          << " leaked on BaseMessageLoop, scheduled from this location.";
    }
  }
  if (lazily_deleted_tasks) {
    LOG(INFO) << "Leaking " << lazily_deleted_tasks << " canceled tasks.";
  }
}

MessageLoop::TaskId BaseMessageLoop::PostDelayedTask(
    const base::Location& from_here,
    base::OnceClosure task,
    base::TimeDelta delay) {
  TaskId task_id = NextTaskId();
  bool base_scheduled = task_runner_->PostDelayedTask(
      from_here,
      base::BindOnce(&BaseMessageLoop::OnRanPostedTask,
                     weak_ptr_factory_.GetWeakPtr(), task_id),
      delay);
  DVLOG_LOC(from_here, 1) << "Scheduling delayed task_id " << task_id
                          << " to run in " << delay << ".";
  if (!base_scheduled)
    return MessageLoop::kTaskIdNull;

  delayed_tasks_.emplace(task_id,
                         DelayedTask{from_here, task_id, std::move(task)});
  return task_id;
}

bool BaseMessageLoop::CancelTask(TaskId task_id) {
  if (task_id == kTaskIdNull)
    return false;
  auto delayed_task_it = delayed_tasks_.find(task_id);
  if (delayed_task_it == delayed_tasks_.end())
    return false;

  // A DelayedTask was found for this task_id at this point.

  // Check if the callback was already canceled but we have the entry in
  // delayed_tasks_ since it didn't fire yet in the message loop.
  if (delayed_task_it->second.closure.is_null())
    return false;

  DVLOG_LOC(delayed_task_it->second.location, 1)
      << "Removing task_id " << task_id << " scheduled from this location.";
  // We reset to closure to a null OnceClosure to release all the resources
  // used by this closure at this point, but we don't remove the task_id from
  // delayed_tasks_ since we can't tell base::SingleThreadTaskExecutor to not
  // run it.
  delayed_task_it->second.closure.Reset();

  return true;
}

bool BaseMessageLoop::RunOnce(bool may_block) {
  run_once_ = true;
  // Uses the base::SingleThreadTaskExecutor implicitly.
  base::RunLoop run_loop;
  base_run_loop_ = &run_loop;
  if (!may_block)
    run_loop.RunUntilIdle();
  else
    run_loop.Run();
  base_run_loop_ = nullptr;
  // If the flag was reset to false, it means a closure was run.
  if (!run_once_)
    return true;

  run_once_ = false;
  return false;
}

void BaseMessageLoop::Run() {
  // Uses the base::SingleThreadTaskExecutor implicitly.
  base::RunLoop run_loop;
  base_run_loop_ = &run_loop;
  run_loop.Run();
  base_run_loop_ = nullptr;
}

void BaseMessageLoop::BreakLoop() {
  if (base_run_loop_ == nullptr) {
    DVLOG(1) << "Message loop not running, ignoring BreakLoop().";
    return;  // Message loop not running, nothing to do.
  }
  base_run_loop_->Quit();
}

base::RepeatingClosure BaseMessageLoop::QuitClosure() const {
  if (base_run_loop_ == nullptr)
    return base::DoNothing();
  return base_run_loop_->QuitClosure();
}

MessageLoop::TaskId BaseMessageLoop::NextTaskId() {
  TaskId res;
  do {
    res = ++last_id_;
    // We would run out of memory before we run out of task ids.
  } while (!res || delayed_tasks_.find(res) != delayed_tasks_.end());
  return res;
}

void BaseMessageLoop::OnRanPostedTask(MessageLoop::TaskId task_id) {
  auto task_it = delayed_tasks_.find(task_id);
  DCHECK(task_it != delayed_tasks_.end());
  if (!task_it->second.closure.is_null()) {
    DVLOG_LOC(task_it->second.location, 1)
        << "Running delayed task_id " << task_id
        << " scheduled from this location.";
    // Mark the task as canceled while we are running it so CancelTask returns
    // false.
    std::move(task_it->second.closure).Run();

    // If the |run_once_| flag is set, it is because we are instructed to run
    // only once callback.
    if (run_once_) {
      run_once_ = false;
      BreakLoop();
    }
  }
  delayed_tasks_.erase(task_it);
}

int BaseMessageLoop::ParseBinderMinor(const std::string& file_contents) {
  int result = kInvalidMinor;
  // Split along '\n', then along the ' '. Note that base::SplitString trims all
  // white spaces at the beginning and end after splitting.
  std::vector<std::string> lines = base::SplitString(
      file_contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  for (const std::string& line : lines) {
    if (line.empty())
      continue;
    std::string number;
    std::string name;
    if (!string_utils::SplitAtFirst(line, " ", &number, &name, false))
      continue;

    if (name == kBinderDriverName && base::StringToInt(number, &result))
      break;
  }
  return result;
}

unsigned int BaseMessageLoop::GetBinderMinor() {
  if (binder_minor_ != kUninitializedMinor)
    return binder_minor_;

  std::string proc_misc;
  if (!base::ReadFileToString(base::FilePath(kMiscMinorPath), &proc_misc))
    return binder_minor_;
  binder_minor_ = ParseBinderMinor(proc_misc);
  return binder_minor_;
}

}  // namespace brillo
