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

#include "base/power_monitor/battery_level_provider.h"

#define INITGUID
#include <windows.h>  // Must be in front of other Windows header files.

#include <devguid.h>
#include <poclass.h>
#include <setupapi.h>
#include <winioctl.h>

#include <algorithm>
#include <array>
#include <vector>

#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/win/scoped_devinfo.h"
#include "base/win/scoped_handle.h"

namespace base {
namespace {

// Returns a handle to the battery interface identified by |interface_data|, or
// nullopt if the request failed. |devices| is a device information set that
// contains battery devices information, obtained with ::SetupDiGetClassDevs().
base::win::ScopedHandle GetBatteryHandle(
    HDEVINFO devices,
    SP_DEVICE_INTERFACE_DATA* interface_data) {
  // Query size required to hold |interface_detail|.
  DWORD required_size = 0;
  ::SetupDiGetDeviceInterfaceDetail(devices, interface_data, nullptr, 0,
                                    &required_size, nullptr);
  DWORD error = ::GetLastError();
  if (error != ERROR_INSUFFICIENT_BUFFER)
    return base::win::ScopedHandle();

  // |interface_detail->DevicePath| is variable size.
  std::vector<uint8_t> raw_buf(required_size);
  auto* interface_detail =
      reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(raw_buf.data());
  interface_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

  BOOL success = ::SetupDiGetDeviceInterfaceDetail(
      devices, interface_data, interface_detail, required_size, nullptr,
      nullptr);
  if (!success)
    return base::win::ScopedHandle();

  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);
  base::win::ScopedHandle battery(
      ::CreateFile(interface_detail->DevicePath, GENERIC_READ | GENERIC_WRITE,
                   FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL, nullptr));
  return battery;
}

// Returns the current tag for `battery` handle, BATTERY_TAG_INVALID if there is
// no battery present in this interface or nullopt on retrieval error.
// See
// https://docs.microsoft.com/en-us/windows/win32/power/ioctl-battery-query-tag
absl::optional<ULONG> GetBatteryTag(HANDLE battery) {
  ULONG battery_tag = 0;
  ULONG wait = 0;
  DWORD bytes_returned = 0;
  BOOL success = ::DeviceIoControl(
      battery, IOCTL_BATTERY_QUERY_TAG, &wait, sizeof(wait), &battery_tag,
      sizeof(battery_tag), &bytes_returned, nullptr);
  if (!success) {
    if (::GetLastError() == ERROR_FILE_NOT_FOUND) {
      // No battery present in this interface.
      //
      // TODO(crbug.com/1191045): Change CHECK to DCHECK in October 2022 after
      // verifying that there are no crash reports.
      CHECK_EQ(battery_tag, static_cast<ULONG>(BATTERY_TAG_INVALID));
      return battery_tag;
    }
    // Retrieval error.
    return absl::nullopt;
  }
  return battery_tag;
}

// Returns BATTERY_INFORMATION structure containing battery information, given
// battery handle and tag, or nullopt if the request failed. Battery handle and
// tag are obtained with GetBatteryHandle() and GetBatteryTag(), respectively.
absl::optional<BATTERY_INFORMATION> GetBatteryInformation(HANDLE battery,
                                                          ULONG battery_tag) {
  BATTERY_QUERY_INFORMATION query_information = {};
  query_information.BatteryTag = battery_tag;
  query_information.InformationLevel = BatteryInformation;
  BATTERY_INFORMATION battery_information = {};
  DWORD bytes_returned;
  BOOL success = ::DeviceIoControl(
      battery, IOCTL_BATTERY_QUERY_INFORMATION, &query_information,
      sizeof(query_information), &battery_information,
      sizeof(battery_information), &bytes_returned, nullptr);
  if (!success)
    return absl::nullopt;
  return battery_information;
}

// Returns the granularity of the battery discharge.
absl::optional<uint32_t> GetBatteryBatteryDischargeGranularity(
    HANDLE battery,
    ULONG battery_tag,
    ULONG current_capacity,
    ULONG designed_capacity) {
  BATTERY_QUERY_INFORMATION query_information = {};
  query_information.BatteryTag = battery_tag;
  query_information.InformationLevel = BatteryGranularityInformation;

  // The battery discharge granularity can change as the level of the battery
  // gets closer to zero. The documentation for `BatteryGranularityInformation`
  // says that a maximum of 4 scales is possible. Each scale contains the
  // granularity (in mWh) and the capacity (in mWh) at which the scale takes
  // effect.
  // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-battery_reporting_scale
  std::array<BATTERY_REPORTING_SCALE, 4> battery_reporting_scales;

  DWORD bytes_returned = 0;
  BOOL success = ::DeviceIoControl(
      battery, IOCTL_BATTERY_QUERY_INFORMATION, &query_information,
      sizeof(query_information), &battery_reporting_scales,
      sizeof(battery_reporting_scales), &bytes_returned, nullptr);
  if (!success)
    return absl::nullopt;

  ptrdiff_t nb_elements = base::checked_cast<ptrdiff_t>(
      bytes_returned / sizeof(BATTERY_REPORTING_SCALE));
  if (!nb_elements)
    return absl::nullopt;

  // The granularities are ordered from the highest capacity to the lowest
  // capacity, or from the most coarse granularity to the most precise
  // granularity, according to the documentation.
  // Just in case, the documentation is not trusted for |max_granularity|. All
  // the values are still compared to find the most coarse granularity.
  DWORD max_granularity =
      std::max_element(std::begin(battery_reporting_scales),
                       std::begin(battery_reporting_scales) + nb_elements,
                       [](const auto& lhs, const auto& rhs) {
                         return lhs.Granularity < rhs.Granularity;
                       })
          ->Granularity;

  // Check if the API can be trusted, which would simplify the implementation of
  // this function.
  UMA_HISTOGRAM_BOOLEAN(
      "Power.BatteryDischargeGranularityIsOrdered",
      max_granularity == battery_reporting_scales[0].Granularity);

  return max_granularity;
}

// Returns BATTERY_STATUS structure containing battery state, given battery
// handle and tag, or nullopt if the request failed. Battery handle and tag are
// obtained with GetBatteryHandle() and GetBatteryTag(), respectively.
absl::optional<BATTERY_STATUS> GetBatteryStatus(HANDLE battery,
                                                ULONG battery_tag) {
  BATTERY_WAIT_STATUS wait_status = {};
  wait_status.BatteryTag = battery_tag;
  BATTERY_STATUS battery_status;
  DWORD bytes_returned;
  BOOL success = ::DeviceIoControl(
      battery, IOCTL_BATTERY_QUERY_STATUS, &wait_status, sizeof(wait_status),
      &battery_status, sizeof(battery_status), &bytes_returned, nullptr);
  if (!success)
    return absl::nullopt;
  return battery_status;
}

}  // namespace

class BatteryLevelProviderWin : public BatteryLevelProvider {
 public:
  BatteryLevelProviderWin() = default;
  ~BatteryLevelProviderWin() override = default;

  void GetBatteryState(
      base::OnceCallback<void(const absl::optional<BatteryState>&)> callback)
      override {
    // This is run on |blocking_task_runner_| since `GetBatteryStateImpl()` has
    // blocking calls and can take several seconds to complete.
    blocking_task_runner_->PostTaskAndReplyWithResult(
        FROM_HERE,
        base::BindOnce(&BatteryLevelProviderWin::GetBatteryStateImpl),
        base::BindOnce(&BatteryLevelProviderWin::OnBatteryStateObtained,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  }

 private:
  static absl::optional<BatteryState> GetBatteryStateImpl();

  void OnBatteryStateObtained(
      base::OnceCallback<void(const absl::optional<BatteryState>&)> callback,
      const absl::optional<BatteryState>& battery_state) {
    std::move(callback).Run(battery_state);
  }

  // TaskRunner used to run blocking `GetBatteryStateImpl()` queries, sequenced
  // to avoid the performance cost of concurrent calls.
  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_{
      base::ThreadPool::CreateSequencedTaskRunner(
          {base::MayBlock(),
           base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})};

  base::WeakPtrFactory<BatteryLevelProviderWin> weak_ptr_factory_{this};
};

std::unique_ptr<BatteryLevelProvider> BatteryLevelProvider::Create() {
  return std::make_unique<BatteryLevelProviderWin>();
}

// static
absl::optional<BatteryLevelProvider::BatteryState>
BatteryLevelProviderWin::GetBatteryStateImpl() {
  // Proactively mark as blocking to fail early, since calls below may also
  // trigger ScopedBlockingCall.
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  // Battery interfaces are enumerated at every sample to detect when a new
  // interface is added, and avoid holding dangling handles when a battery is
  // disconnected.
  base::win::ScopedDevInfo devices(::SetupDiGetClassDevs(
      &GUID_DEVICE_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  if (!devices.is_valid()) {
    return absl::nullopt;
  }

  std::vector<BatteryDetails> battery_details_list;

  // The algorithm to enumerate battery devices is taken from
  // https://docs.microsoft.com/en-us/windows/win32/power/enumerating-battery-devices
  // Limit search to 8 batteries max. A system may have several battery slots
  // and each slot may hold an actual battery.
  for (DWORD device_index = 0; device_index < 8; ++device_index) {
    SP_DEVICE_INTERFACE_DATA interface_data = {};
    interface_data.cbSize = sizeof(interface_data);

    BOOL success =
        ::SetupDiEnumDeviceInterfaces(devices.get(), 0, &GUID_DEVCLASS_BATTERY,
                                      device_index, &interface_data);
    if (!success) {
      // Enumeration ended normally.
      if (::GetLastError() == ERROR_NO_MORE_ITEMS)
        break;
      // Error.
      return absl::nullopt;
    }

    base::win::ScopedHandle battery =
        GetBatteryHandle(devices.get(), &interface_data);
    if (!battery.IsValid())
      return absl::nullopt;

    absl::optional<ULONG> battery_tag = GetBatteryTag(battery.Get());
    if (!battery_tag.has_value()) {
      return absl::nullopt;
    } else if (battery_tag.value() == BATTERY_TAG_INVALID) {
      // No battery present in this interface.
      continue;
    }

    auto battery_information =
        GetBatteryInformation(battery.Get(), *battery_tag);
    if (!battery_information.has_value()) {
      return absl::nullopt;
    }

    auto battery_status = GetBatteryStatus(battery.Get(), *battery_tag);
    if (!battery_status.has_value()) {
      return absl::nullopt;
    }

    absl::optional<uint32_t> battery_discharge_granularity =
        GetBatteryBatteryDischargeGranularity(
            battery.Get(), *battery_tag, battery_status->Capacity,
            battery_information->DesignedCapacity);

    battery_details_list.push_back(BatteryDetails(
        {.is_external_power_connected =
             !!(battery_status->PowerState & BATTERY_POWER_ON_LINE),
         .current_capacity = battery_status->Capacity,
         .full_charged_capacity = battery_information->FullChargedCapacity,
         .charge_unit =
             ((battery_information->Capabilities & BATTERY_CAPACITY_RELATIVE)
                  ? BatteryLevelUnit::kRelative
                  : BatteryLevelUnit::kMWh),
         .battery_discharge_granularity = battery_discharge_granularity}));
  }

  return MakeBatteryState(battery_details_list);
}

}  // namespace base
