chromium/tools/mac/power/power_sampler/user_idle_level_sampler.cc

// 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 "tools/mac/power/power_sampler/user_idle_level_sampler.h"

#include <sys/sysctl.h>
#include <sys/types.h>

#include <optional>

#include "base/logging.h"
#include "base/memory/ptr_util.h"

namespace power_sampler {

namespace {

std::optional<int> GetIntSysCtl(const std::vector<int>& mib_name) {
  int value = 0;
  size_t size = sizeof(value);
  int ret = sysctl(const_cast<int*>(mib_name.data()), mib_name.size(), &value,
                   &size, nullptr, 0);
  if (ret != 0) {
    PLOG(ERROR) << "Error in sysctl";
  } else if (size != sizeof(value)) {
    LOG(ERROR)
        << "sysctl returns an unexpected size for machdep.user_idle_level";
  } else {
    return value;
  }

  return std::nullopt;
}

}  // namespace

UserIdleLevelSampler::~UserIdleLevelSampler() = default;

// static
std::unique_ptr<UserIdleLevelSampler> UserIdleLevelSampler::Create() {
  std::vector<int> mib_name(10);

  size_t size = mib_name.size();
  int ret = sysctlnametomib("machdep.user_idle_level", mib_name.data(), &size);
  if (ret != 0) {
    PLOG(ERROR) << "Error in sysctlnametomib";
    return nullptr;
  }

  DCHECK_NE(0u, size);
  mib_name.resize(size);

  if (!GetIntSysCtl(mib_name).has_value())
    return nullptr;

  return base::WrapUnique(new UserIdleLevelSampler(std::move(mib_name)));
}

std::string UserIdleLevelSampler::GetName() {
  return kSamplerName;
}

Sampler::DatumNameUnits UserIdleLevelSampler::GetDatumNameUnits() {
  DatumNameUnits ret;
  ret.insert(std::make_pair("user_idle_level", "int"));
  return ret;
}

Sampler::Sample UserIdleLevelSampler::GetSample(base::TimeTicks sample_time) {
  DCHECK(!mib_name_.empty());

  Sample sample;
  auto value = GetIntSysCtl(mib_name_);
  if (value.has_value())
    sample.emplace("user_idle_level", value.value());

  return sample;
}

UserIdleLevelSampler::UserIdleLevelSampler(std::vector<int> mib_name)
    : mib_name_(std::move(mib_name)) {
  DCHECK(!mib_name_.empty());
}

}  // namespace power_sampler