// Copyright (c) 2013 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 "power_manager/powerd/system/udev.h"

#include <libudev.h>

#include <utility>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/free_deleter.h>

#include "power_manager/common/power_constants.h"
#include "power_manager/powerd/system/tagged_device.h"
#include "power_manager/powerd/system/udev_subsystem_observer.h"
#include "power_manager/powerd/system/udev_tagged_device_observer.h"

namespace power_manager {
namespace system {

namespace {

const char kChromeOSClassPath[] = "/sys/class/chromeos/";
const char kFingerprintSysfsPath[] = "/sys/class/chromeos/cros_fp";
const char kPowerdRoleCrosFP[] = "cros_fingerprint";
const char kPowerdRoleVar[] = "POWERD_ROLE";
const char kPowerdUdevTag[] = "powerd";
const char kPowerdTagsVar[] = "POWERD_TAGS";
// Udev device type for USB devices.
const char kUSBDevice[] = "usb_device";

bool HasPowerdRole(struct udev_device* device, const std::string& role) {
  const char* role_cstr =
      udev_device_get_property_value(device, kPowerdRoleVar);
  const std::string device_role = role_cstr ? role_cstr : "";
  return role == device_role;
}

UdevEvent::Action StrToAction(const char* action_str) {
  if (!action_str)
    return UdevEvent::Action::UNKNOWN;
  else if (strcmp(action_str, "add") == 0)
    return UdevEvent::Action::ADD;
  else if (strcmp(action_str, "remove") == 0)
    return UdevEvent::Action::REMOVE;
  else if (strcmp(action_str, "change") == 0)
    return UdevEvent::Action::CHANGE;
  else if (strcmp(action_str, "online") == 0)
    return UdevEvent::Action::ONLINE;
  else if (strcmp(action_str, "offline") == 0)
    return UdevEvent::Action::OFFLINE;
  else
    return UdevEvent::Action::UNKNOWN;
}

struct UdevDeviceDeleter {
  void operator()(udev_device* dev) {
    if (dev)
      udev_device_unref(dev);
  }
};

};  // namespace

Udev::Udev() : udev_(nullptr), udev_monitor_(nullptr) {}

Udev::~Udev() {
  if (udev_monitor_)
    udev_monitor_unref(udev_monitor_);
  if (udev_)
    udev_unref(udev_);
}

bool Udev::Init() {
  udev_ = udev_new();
  if (!udev_) {
    PLOG(ERROR) << "udev_new() failed";
    return false;
  }

  udev_monitor_ = udev_monitor_new_from_netlink(udev_, "udev");
  if (!udev_monitor_) {
    PLOG(ERROR) << "udev_monitor_new_from_netlink() failed";
    return false;
  }

  if (udev_monitor_filter_add_match_tag(udev_monitor_, kPowerdUdevTag))
    LOG(ERROR) << "udev_monitor_filter_add_match_tag failed";
  if (udev_monitor_filter_update(udev_monitor_))
    LOG(ERROR) << "udev_monitor_filter_update failed";

  udev_monitor_enable_receiving(udev_monitor_);

  int fd = udev_monitor_get_fd(udev_monitor_);
  controller_ = base::FileDescriptorWatcher::WatchReadable(
      fd, base::BindRepeating(&Udev::OnFileCanReadWithoutBlocking,
                              base::Unretained(this)));
  LOG(INFO) << "Watching FD " << fd << " for udev events";

  EnumerateTaggedDevices();

  return true;
}

void Udev::AddSubsystemObserver(const std::string& subsystem,
                                UdevSubsystemObserver* observer) {
  DCHECK(udev_) << "Object uninitialized";
  DCHECK(observer);
  auto it = subsystem_observers_.find(subsystem);
  if (it == subsystem_observers_.end()) {
    it = subsystem_observers_
             .emplace(
                 subsystem,
                 std::make_unique<base::ObserverList<UdevSubsystemObserver>>())
             .first;
  }
  it->second->AddObserver(observer);
}

void Udev::RemoveSubsystemObserver(const std::string& subsystem,
                                   UdevSubsystemObserver* observer) {
  DCHECK(observer);
  auto it = subsystem_observers_.find(subsystem);
  if (it != subsystem_observers_.end())
    it->second->RemoveObserver(observer);
}

void Udev::AddTaggedDeviceObserver(UdevTaggedDeviceObserver* observer) {
  tagged_device_observers_.AddObserver(observer);
}

void Udev::RemoveTaggedDeviceObserver(UdevTaggedDeviceObserver* observer) {
  tagged_device_observers_.RemoveObserver(observer);
}

std::vector<TaggedDevice> Udev::GetTaggedDevices() {
  std::vector<TaggedDevice> devices;
  devices.reserve(tagged_devices_.size());
  for (const std::pair<std::string, TaggedDevice>& pair : tagged_devices_)
    devices.push_back(pair.second);
  return devices;
}

bool Udev::GetSubsystemDevices(const std::string& subsystem,
                               std::vector<UdevDeviceInfo>* devices_out) {
  DCHECK(udev_);
  DCHECK(devices_out);
  struct udev_enumerate* enumerate = udev_enumerate_new(udev_);
  if (!enumerate) {
    LOG(ERROR) << "udev_enumerate_new failed";
    return false;
  }
  int ret = udev_enumerate_add_match_subsystem(enumerate, subsystem.c_str());
  if (ret != 0) {
    LOG(ERROR) << "udev_enumerate_add_match_subsystem failed. Error: "
               << strerror(-ret);
    udev_enumerate_unref(enumerate);
    return false;
  }
  ret = udev_enumerate_scan_devices(enumerate);
  if (ret != 0) {
    LOG(ERROR) << "udev_enumerate_scan_devices failed. Error: "
               << strerror(-ret);
    udev_enumerate_unref(enumerate);
    return false;
  }

  devices_out->clear();

  for (struct udev_list_entry* list_entry =
           udev_enumerate_get_list_entry(enumerate);
       list_entry != nullptr;
       list_entry = udev_list_entry_get_next(list_entry)) {
    const char* syspath = udev_list_entry_get_name(list_entry);
    struct udev_device* device = udev_device_new_from_syspath(udev_, syspath);
    if (!device) {
      LOG(ERROR) << "Enumeration of device with syspath " << syspath
                 << " failed";
      continue;
    }
    UdevDeviceInfo device_info;
    if (GetDeviceInfo(device, &device_info)) {
      devices_out->push_back(std::move(device_info));
    } else {
      LOG(ERROR) << "Could not retrieve Udev info for the device with syspath "
                 << syspath;
    }
    udev_device_unref(device);
  }

  udev_enumerate_unref(enumerate);
  return true;
}

bool Udev::GetSysattr(const std::string& syspath,
                      const std::string& sysattr,
                      std::string* value) {
  DCHECK(udev_);
  DCHECK(value);
  value->clear();

  struct udev_device* device =
      udev_device_new_from_syspath(udev_, syspath.c_str());
  if (!device) {
    LOG(WARNING) << "Failed to open udev device: " << syspath;
    return false;
  }
  const char* value_cstr =
      udev_device_get_sysattr_value(device, sysattr.c_str());
  if (value_cstr)
    *value = value_cstr;
  udev_device_unref(device);
  return value_cstr != nullptr;
}

bool Udev::SetSysattr(const std::string& syspath,
                      const std::string& sysattr,
                      const std::string& value) {
  DCHECK(udev_);

  struct udev_device* device =
      udev_device_new_from_syspath(udev_, syspath.c_str());
  if (!device) {
    LOG(WARNING) << "Failed to open udev device: " << syspath;
    return false;
  }
  // udev can modify this value, hence we copy it first.
  std::unique_ptr<char, base::FreeDeleter> value_mutable(strdup(value.c_str()));
  int rv = udev_device_set_sysattr_value(device, sysattr.c_str(),
                                         value_mutable.get());
  udev_device_unref(device);
  if (rv != 0) {
    LOG(WARNING) << "Failed to set sysattr '" << sysattr << "' on device "
                 << syspath << ": " << strerror(-rv);
    return false;
  }
  return true;
}

base::FilePath Udev::FindParentWithSysattr(const std::string& syspath,
                                           const std::string& sysattr,
                                           const std::string& stop_at_devtype) {
  DCHECK(udev_);

  struct udev_device* device =
      udev_device_new_from_syspath(udev_, syspath.c_str());
  if (!device) {
    LOG(WARNING) << "Failed to open udev device: " << syspath;
    return base::FilePath();
  }

  struct udev_device* parent = device;
  while (parent) {
    const char* value = udev_device_get_sysattr_value(parent, sysattr.c_str());
    const char* devtype = udev_device_get_devtype(parent);
    if (value)
      break;
    // Go up one level unless the devtype matches stop_at_devtype.
    if (devtype && strcmp(stop_at_devtype.c_str(), devtype) == 0) {
      parent = nullptr;
    } else {
      // Returns a pointer to the parent device. No additional reference to
      // the device is acquired, but the child device owns a reference to the
      // parent device.
      parent = udev_device_get_parent(parent);
    }
  }
  base::FilePath parent_syspath;
  if (parent)
    parent_syspath = base::FilePath(udev_device_get_syspath(parent));
  udev_device_unref(device);
  return parent_syspath;
}

base::FilePath Udev::FindWakeCapableParent(const std::string& syspath) {
  base::FilePath wakeup_device_path;
  struct udev_device* device =
      udev_device_new_from_syspath(udev_, syspath.c_str());
  if (!device)
    return wakeup_device_path;

  // Returns a pointer to the parent device. No additional reference to
  // the |device| is acquired, but the |device| owns a reference to the
  // |parent|.
  struct udev_device* parent = udev_device_get_parent(device);
  // We assign powerd roles to the input device. In case |syspath| points to
  // a event device, look also at the parent device to see if it has
  // |kPowerdRoleCrosFP| role.
  if (HasPowerdRole(device, kPowerdRoleCrosFP) ||
      HasPowerdRole(parent, kPowerdRoleCrosFP)) {
    base::FilePath actual_fp_path;
    if (!base::ReadSymbolicLink(base::FilePath(kFingerprintSysfsPath),
                                &actual_fp_path)) {
      PLOG(ERROR) << "Failed to read symlink " << kFingerprintSysfsPath
                  << " for fingerprint device";
    } else {
      std::string wakeup_path =
          base::FilePath(kChromeOSClassPath).Append(actual_fp_path).value();
      wakeup_device_path =
          FindParentWithSysattr(wakeup_path, kPowerWakeup, kUSBDevice);
    }
  } else {
    wakeup_device_path =
        FindParentWithSysattr(syspath, kPowerWakeup, kUSBDevice);
  }
  udev_device_unref(device);
  return wakeup_device_path;
}

bool Udev::GetDeviceInfo(struct udev_device* dev,
                         UdevDeviceInfo* device_info_out) {
  DCHECK(device_info_out);

  const char* subsystem = udev_device_get_subsystem(dev);
  if (!subsystem)
    return false;

  device_info_out->subsystem = subsystem;

  const char* devtype = udev_device_get_devtype(dev);
  if (devtype)
    device_info_out->devtype = devtype;

  const char* sysname = udev_device_get_sysname(dev);
  if (sysname)
    device_info_out->sysname = sysname;

  const char* syspath = udev_device_get_syspath(dev);
  if (syspath)
    device_info_out->syspath = syspath;

  device_info_out->wakeup_device_path = FindWakeCapableParent(syspath);

  return true;
}

bool Udev::GetDevlinks(const std::string& syspath,
                       std::vector<std::string>* out) {
  DCHECK(udev_);
  DCHECK(out);

  std::unique_ptr<udev_device, UdevDeviceDeleter> device(
      udev_device_new_from_syspath(udev_, syspath.c_str()));
  if (!device) {
    PLOG(WARNING) << "Failed to open udev device: " << syspath;
    return false;
  }

  out->clear();

  // TODO(egranata): maybe write a wrapper around udev_list to support
  // for(entry : list) {...}
  struct udev_list_entry* devlink =
      udev_device_get_devlinks_list_entry(device.get());
  while (devlink) {
    const char* name = udev_list_entry_get_name(devlink);
    if (name)
      out->push_back(name);
    devlink = udev_list_entry_get_next(devlink);
  }

  return true;
}

void Udev::OnFileCanReadWithoutBlocking() {
  struct udev_device* dev = udev_monitor_receive_device(udev_monitor_);
  if (!dev)
    return;

  const char* subsystem = udev_device_get_subsystem(dev);
  const char* sysname = udev_device_get_sysname(dev);
  const char* action_str = udev_device_get_action(dev);
  UdevEvent::Action action = StrToAction(action_str);

  VLOG(1) << "Received event: subsystem=" << subsystem << " sysname=" << sysname
          << " action=" << action_str;

  HandleSubsystemEvent(action, dev);
  HandleTaggedDevice(action, dev);

  udev_device_unref(dev);
}

void Udev::HandleSubsystemEvent(UdevEvent::Action action,
                                struct udev_device* dev) {
  UdevEvent event;
  if (!GetDeviceInfo(dev, &(event.device_info)))
    return;
  event.action = action;
  auto it = subsystem_observers_.find(event.device_info.subsystem);
  if (it != subsystem_observers_.end()) {
    for (UdevSubsystemObserver& observer : *it->second)
      observer.OnUdevEvent(event);
  }
}

void Udev::HandleTaggedDevice(UdevEvent::Action action,
                              struct udev_device* dev) {
  if (!udev_device_has_tag(dev, kPowerdUdevTag))
    return;

  const char* syspath = udev_device_get_syspath(dev);
  const char* tags = udev_device_get_property_value(dev, kPowerdTagsVar);

  switch (action) {
    case UdevEvent::Action::ADD:
    case UdevEvent::Action::CHANGE:
      TaggedDeviceChanged(syspath, FindWakeCapableParent(syspath),
                          tags ? tags : "");
      break;

    case UdevEvent::Action::REMOVE:
      TaggedDeviceRemoved(syspath);
      break;

    default:
      break;
  }
}

void Udev::TaggedDeviceChanged(const std::string& syspath,
                               const base::FilePath& wakeup_device_path,
                               const std::string& tags) {
  if (!tags.empty()) {
    LOG(INFO) << (tagged_devices_.count(syspath) ? "Updating" : "Adding")
              << " device " << syspath << " with tags " << tags;
  }

  // Replace existing device with same syspath.
  tagged_devices_[syspath] = TaggedDevice(syspath, wakeup_device_path, tags);
  const TaggedDevice& device = tagged_devices_[syspath];
  for (UdevTaggedDeviceObserver& observer : tagged_device_observers_)
    observer.OnTaggedDeviceChanged(device);
}

void Udev::TaggedDeviceRemoved(const std::string& syspath) {
  TaggedDevice device = tagged_devices_[syspath];
  if (!device.tags().empty())
    LOG(INFO) << "Removing device " << syspath;
  tagged_devices_.erase(syspath);
  for (UdevTaggedDeviceObserver& observer : tagged_device_observers_)
    observer.OnTaggedDeviceRemoved(device);
}

bool Udev::EnumerateTaggedDevices() {
  DCHECK(udev_);

  struct udev_enumerate* enumerate = udev_enumerate_new(udev_);
  if (!enumerate) {
    LOG(ERROR) << "udev_enumerate_new failed";
    return false;
  }
  if (udev_enumerate_add_match_tag(enumerate, kPowerdUdevTag) != 0) {
    LOG(ERROR) << "udev_enumerate_add_match_tag failed";
    udev_enumerate_unref(enumerate);
    return false;
  }
  if (udev_enumerate_scan_devices(enumerate) != 0) {
    LOG(ERROR) << "udev_enumerate_scan_devices failed";
    udev_enumerate_unref(enumerate);
    return false;
  }

  tagged_devices_.clear();

  struct udev_list_entry* entry = nullptr;
  udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate)) {
    const char* syspath = udev_list_entry_get_name(entry);
    struct udev_device* device = udev_device_new_from_syspath(udev_, syspath);
    if (!device) {
      LOG(ERROR) << "Enumerated device does not exist: " << syspath;
      continue;
    }
    const char* tags_cstr =
        udev_device_get_property_value(device, kPowerdTagsVar);
    const std::string tags = tags_cstr ? tags_cstr : "";
    if (!tags.empty())
      LOG(INFO) << "Adding device " << syspath << " with tags " << tags;
    tagged_devices_[syspath] =
        TaggedDevice(syspath, FindWakeCapableParent(syspath), tags);
    udev_device_unref(device);
  }
  udev_enumerate_unref(enumerate);
  return true;
}

}  // namespace system
}  // namespace power_manager
