| // 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 "thermald/temperature_sensor_monitor.h" |
| |
| #include <string> |
| |
| #include "base/callback.h" |
| #include "base/check.h" |
| #include "base/logging.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.h" |
| |
| using std::string; |
| |
| namespace thermald { |
| |
| static const int kNoTemperature = -273150; |
| |
| TemperatureSensorMonitor::TemperatureSensorMonitor( |
| TemperatureSensorInterface *sensor, base::TimeDelta sample_period) |
| : sensor_(sensor), |
| sample_period_(sample_period), |
| weak_ptr_factory_(this), |
| timer_(new base::RepeatingTimer()) { |
| DCHECK(sensor); |
| |
| DVLOG(3) << "[" << sensor_->name() << "] Constructor"; |
| subscribers_.set_removal_callback( |
| base::Bind(&TemperatureSensorMonitor::OnSubscriberRemoved, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| TemperatureSensorMonitor::~TemperatureSensorMonitor() { |
| DVLOG(3) << "[" << sensor_->name() << "] Destructor"; |
| |
| // Sampling only needs to be stopped when there is at least one subscriber. |
| // Otherwise either the sampling never started or it has been stopped |
| // earlier when the last active subscriber canceled its subscription. |
| if (!subscribers_.empty()) { |
| StopSampling(); |
| } |
| } |
| |
| string TemperatureSensorMonitor::name() const { |
| return sensor_->name(); |
| } |
| |
| void TemperatureSensorMonitor::ReadAndReportTemperature() { |
| if (!sensor_->IsOperational()) { |
| if (sensor_was_operational_) { |
| LOG(WARNING) << "[" << sensor_->name() << "] Sensor is not operational"; |
| sensor_was_operational_ = false; |
| } |
| |
| return; |
| } else if (!sensor_was_operational_) { |
| LOG(INFO) << "[" << sensor_->name() << "] Sensor became operational"; |
| sensor_was_operational_ = true; |
| } |
| |
| int temperature; |
| if (!sensor_->ReadTemperature(&temperature)) { |
| LOG(WARNING) << "[" << sensor_->name() << "] Failed to read temperature"; |
| return; |
| } |
| |
| if (temperature != prev_temperature_) { |
| DVLOG(1) << "[" << sensor_->name() << "] Temperature changed: " |
| << temperature; |
| subscribers_.Notify(temperature); |
| prev_temperature_ = temperature; |
| } |
| } |
| |
| void TemperatureSensorMonitor::ReportInitialTemperature( |
| const TemperatureMonitorCallback &cb, int temperature) { |
| // Don't report the initial temperature if an updated reading has already |
| // been reported from the regular polling. |
| if (temperature == prev_temperature_) { |
| cb.Run(temperature); |
| } |
| } |
| |
| #if BASE_VER < 860220 |
| std::unique_ptr<TemperatureMonitorInterface::Subscription> |
| #else |
| base::CallbackListSubscription |
| #endif |
| TemperatureSensorMonitor::Subscribe(const TemperatureMonitorCallback &cb) { |
| if (subscribers_.empty()) { |
| StartSampling(); |
| } else { |
| if (prev_temperature_ != kNoTemperature) { |
| // Schedule task to report initial temperature. |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::Bind(&TemperatureSensorMonitor::ReportInitialTemperature, |
| weak_ptr_factory_.GetWeakPtr(), cb, prev_temperature_)); |
| } |
| } |
| |
| return subscribers_.Add(cb); |
| } |
| |
| void TemperatureSensorMonitor::OnSubscriberRemoved() { |
| if (subscribers_.empty()) { |
| StopSampling(); |
| } |
| } |
| |
| void TemperatureSensorMonitor::StartSampling() { |
| DVLOG(1) << "[" << sensor_->name() << "] Start sampling"; |
| |
| prev_temperature_ = kNoTemperature; |
| sensor_was_operational_ = true; |
| |
| // Take first temperature reading immediately. |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::Bind(&TemperatureSensorMonitor::ReadAndReportTemperature, |
| weak_ptr_factory_.GetWeakPtr())); |
| |
| timer_->Start(FROM_HERE, sample_period_, |
| base::Bind(&TemperatureSensorMonitor::ReadAndReportTemperature, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void TemperatureSensorMonitor::StopSampling() { |
| DVLOG(1) << "[" << sensor_->name() << "] Stop sampling"; |
| |
| timer_->Stop(); |
| } |
| |
| } // namespace thermald |