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