1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/power_profiler/power_profiler_service.h"
6
7#include "base/bind.h"
8#include "base/message_loop/message_loop.h"
9#include "base/threading/sequenced_worker_pool.h"
10#include "content/public/browser/browser_thread.h"
11
12namespace content {
13
14PowerProfilerService::PowerProfilerService()
15    : status_(UNINITIALIZED),
16      data_provider_(PowerDataProvider::Create()) {
17  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
18
19  // No provider supported for current platform.
20  if (!data_provider_.get())
21    return;
22  sample_period_ = data_provider_->GetSamplingRate();
23  status_ = INITIALIZED;
24  task_runner_ = BrowserThread::GetBlockingPool()->GetSequencedTaskRunner(
25      BrowserThread::GetBlockingPool()->GetSequenceToken());
26}
27
28PowerProfilerService::PowerProfilerService(
29    scoped_ptr<PowerDataProvider> provider,
30    scoped_refptr<base::TaskRunner> task_runner,
31    const base::TimeDelta& sample_period)
32    : task_runner_(task_runner),
33      status_(UNINITIALIZED),
34      sample_period_(sample_period),
35      data_provider_(provider.Pass()) {
36  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
37
38  if (data_provider_.get())
39      status_ = INITIALIZED;
40}
41
42PowerProfilerService::~PowerProfilerService() {
43}
44
45bool PowerProfilerService::IsAvailable() const {
46  return status_ !=  UNINITIALIZED;
47}
48
49std::string PowerProfilerService::GetAccuracyLevel() const {
50  DCHECK(IsAvailable());
51  switch (data_provider_->GetAccuracyLevel()) {
52    case PowerDataProvider::High:
53      return "High";
54    case PowerDataProvider::Moderate:
55      return "Moderate";
56    case PowerDataProvider::Low:
57      return "Low";
58  }
59  return "";
60}
61
62PowerProfilerService* PowerProfilerService::GetInstance() {
63  return Singleton<PowerProfilerService>::get();
64}
65
66void PowerProfilerService::AddObserver(PowerProfilerObserver* observer) {
67  if (status_ == UNINITIALIZED)
68    return;
69
70  observers_.AddObserver(observer);
71  if (status_ != PROFILING)
72    Start();
73}
74
75void PowerProfilerService::RemoveObserver(PowerProfilerObserver* observer) {
76  observers_.RemoveObserver(observer);
77
78  if (status_ == PROFILING && !observers_.might_have_observers())
79    Stop();
80}
81
82void PowerProfilerService::Start() {
83  DCHECK(status_ == INITIALIZED);
84  status_ = PROFILING;
85
86  // Send out power events immediately.
87  QueryData();
88
89  query_power_timer_.Start(FROM_HERE,
90      sample_period_, this, &PowerProfilerService::QueryData);
91}
92
93void PowerProfilerService::Stop() {
94  DCHECK(status_ == PROFILING);
95
96  query_power_timer_.Stop();
97  status_ = INITIALIZED;
98}
99
100void PowerProfilerService::QueryData() {
101  task_runner_->PostTask(
102      FROM_HERE, base::Bind(&PowerProfilerService::QueryDataOnTaskRunner,
103                            base::Unretained(this)));
104}
105
106void PowerProfilerService::Notify(const PowerEventVector& events) {
107  FOR_EACH_OBSERVER(PowerProfilerObserver, observers_, OnPowerEvent(events));
108}
109
110void PowerProfilerService::QueryDataOnTaskRunner() {
111  DCHECK(task_runner_->RunsTasksOnCurrentThread());
112  DCHECK(status_ == PROFILING);
113
114  // Get data and notify.
115  PowerEventVector events = data_provider_->GetData();
116  if (events.size() != 0) {
117    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
118        &PowerProfilerService::Notify, base::Unretained(this), events));
119  }
120}
121
122}  // namespace content
123