Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: content/browser/power_usage_monitor_impl.cc

Issue 560553005: Battery impact UMA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix review comments Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_usage_monitor_impl.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/histogram.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/time/time.h"
14 #include "content/common/battery_status_messages.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/browser/notification_source.h"
18 #include "content/public/browser/notification_types.h"
19 #include "content/public/browser/power_usage_monitor.h"
20 #include "content/public/browser/render_process_host.h"
21
22 namespace content {
23
24 void StartPowerUsageMonitor() {
25 PowerUsageMonitor::GetInstance()->Initialize();
26 }
27
28 PowerUsageMonitor::HistogramRecorder::HistogramRecorder() :
29 weak_ptr_factory_(this) {
30 }
31
32 PowerUsageMonitor::HistogramRecorder::~HistogramRecorder() {
33 }
34
35 void PowerUsageMonitor::HistogramRecorder::CancelPendingHistgramReports() {
36 weak_ptr_factory_.InvalidateWeakPtrs();
37 }
38
39 void PowerUsageMonitor::HistogramRecorder::ReportBatteryLevelHistogram(
40 base::TimeDelta discharge_time) {
41 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
42 const std::string histogram_name =
43 base::StringPrintf("Power.BatteryDischarge_%d",
44 discharge_time.InMinutes());
45 base::HistogramBase* histogram = base::Histogram::FactoryGet(
46 histogram_name,
47 0,
48 100,
49 102,
50 base::Histogram::kUmaTargetedHistogramFlag);
51 double discharge_amount =
52 PowerUsageMonitor::GetInstance()->DischargeAmount();
53 histogram->Add(discharge_amount * 100);
54
55 PowerUsageMonitor::GetInstance()->BatteryLevelReported();
56 }
57
58
59 PowerUsageMonitor::PowerUsageMonitor() :
Daniel Erat 2014/09/30 23:55:24 fix style here (please read the chromium and googl
60 histogram_recorder_(new HistogramRecorder()),
61 was_on_battery_power_(false),
62 initial_battery_level_(0),
63 current_battery_level_(0) {
64
65 // PowerUsageMonitor gets battery level information.
66 callback_ = base::Bind(&PowerUsageMonitor::OnBatteryStatusUpdate,
67 base::Unretained(this));
68
69 // Power Monitor used to get suspend/resume notifications.
70 base::PowerMonitor::Get()->AddObserver(this);
71
72 registrar_.Add(this,
73 NOTIFICATION_RENDERER_PROCESS_CREATED,
74 NotificationService::AllBrowserContextsAndSources());
75
76 registrar_.Add(this,
77 NOTIFICATION_RENDERER_PROCESS_TERMINATED,
78 NotificationService::AllBrowserContextsAndSources());
79 registrar_.Add(this,
80 NOTIFICATION_RENDERER_PROCESS_CLOSED,
81 NotificationService::AllBrowserContextsAndSources());
82 }
83
84 PowerUsageMonitor::~PowerUsageMonitor() {
85 base::PowerMonitor::Get()->RemoveObserver(this);
86 }
87
88 PowerUsageMonitor* PowerUsageMonitor::GetInstance() {
89 return Singleton<PowerUsageMonitor,
90 LeakySingletonTraits<PowerUsageMonitor> >::get();
91 }
92
93 void PowerUsageMonitor::Initialize() {
94 const base::TimeDelta delay = base::TimeDelta::FromSeconds(1);
95
96 BrowserThread::PostDelayedTask(BrowserThread::IO,
97 FROM_HERE, base::Bind(&PowerUsageMonitor::StartOnIOThread,
98 base::Unretained(this)), delay);
99 }
100
101 void PowerUsageMonitor::StartOnIOThread() {
102 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
103 subscription_ =
104 BatteryStatusService::GetInstance()->AddCallback(callback_);
105 }
106
107 void PowerUsageMonitor::DischargeStarted(double battery_level) {
108 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
109
110 // Cancel any in-progress ReportBatteryLevelHistogram() calls.
111 histogram_recorder_->CancelPendingHistgramReports();
112
113 // Rate-limit power recording to once every 24 hours.
114 if (!first_histogram_report_timestamp_.is_null()) {
115 base::TimeDelta time_since_last_report =
116 base::Time::Now() - first_histogram_report_timestamp_;
117 if (time_since_last_report.InHours() < 24)
118 return;
119
120 // More than 24 hours have passed, reset timestamp.
121 first_histogram_report_timestamp_ = base::Time();
122 }
123
124 was_on_battery_power_ = true;
125 initial_battery_level_ = battery_level;
126 current_battery_level_ = battery_level;
127 start_discharge_time_ = base::Time::Now();
128
129 const int kBatteryReportingIntervalMinutes[] = {5, 15, 30};
130
131 for (size_t i = 0; i < arraysize(kBatteryReportingIntervalMinutes); ++i) {
132 base::TimeDelta delay =
133 base::TimeDelta::FromMinutes(kBatteryReportingIntervalMinutes[i]);
134 BrowserThread::PostDelayedTask(BrowserThread::IO,
Daniel Erat 2014/09/30 23:55:24 can you move this into HistogramRecorder so it doe
135 FROM_HERE, base::Bind(
136 &PowerUsageMonitor::HistogramRecorder::ReportBatteryLevelHistogram,
137 histogram_recorder_->GetWeakPtr(), delay), delay);
138 }
139 }
140
141 void PowerUsageMonitor::WallPowerConnected(double battery_level) {
142 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
143 // Cancel any in-progress ReportBatteryLevelHistogram() calls.
144 histogram_recorder_->CancelPendingHistgramReports();
145
146 if (!start_discharge_time_.is_null()) {
147 base::TimeDelta discharge_time = base::Time::Now() - start_discharge_time_;
148 double discharge_percent = initial_battery_level_ - battery_level;
149 double discharge_rate = discharge_percent / discharge_time.InMinutes();
150
151 if (discharge_time.InMinutes() > 30)
Daniel Erat 2014/09/30 23:55:24 need curly brackets here
152 UMA_HISTOGRAM_PERCENTAGE("Power.BatteryDischargeRateWhenUnplugged",
153 discharge_rate * 100.0);
154 }
155
156 was_on_battery_power_ = false;
157 initial_battery_level_ = 0;
158 current_battery_level_ = 0;
159 start_discharge_time_ = base::Time();
160 }
161
162 void PowerUsageMonitor::OnBatteryStatusUpdate(
163 const blink::WebBatteryStatus& status) {
164 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
165
166 bool now_on_battery_power = (status.charging == 0);
167 double battery_level = status.level;
168
169 if (now_on_battery_power == was_on_battery_power_) {
170 if (now_on_battery_power)
171 current_battery_level_ = battery_level;
172 return;
173 } else if (now_on_battery_power) { // Wall power disconnected.
174 DischargeStarted(battery_level);
175 } else { // Wall power connected.
176 WallPowerConnected(battery_level);
177 }
178 }
179
180 void PowerUsageMonitor::BatteryLevelReported() {
181 if (first_histogram_report_timestamp_.is_null()) {
182 // Record timestamp of first histogram report.
183 first_histogram_report_timestamp_ = base::Time::Now();
184 }
185 }
186
187 void PowerUsageMonitor::SetHistogramRecorderForTest(
188 scoped_ptr<HistogramRecorder> recorder) {
189 histogram_recorder_ = recorder.Pass();
190 }
191
192 void PowerUsageMonitor::OnSuspend() {
193 BrowserThread::PostTask(BrowserThread::IO,
194 FROM_HERE,
195 base::Bind(
Daniel Erat 2014/09/30 23:55:24 fix weird indenting -- i recommend clang-format
196 &PowerUsageMonitor::CancelPendingHistogramRecordingOnIOThread,
197 base::Unretained(this)));
198 }
199
200 void PowerUsageMonitor::Observe(int type,
201 const NotificationSource& source,
202 const NotificationDetails& details) {
203 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
204
205 RenderProcessHost* rph =
206 Source<RenderProcessHost>(source).ptr();
207
208 size_t previous_num_live_renderers = live_renderers_.size();
209
210 if(type == NOTIFICATION_RENDERER_PROCESS_CREATED) {
Daniel Erat 2014/09/30 23:55:24 nit: add a space between 'if' and '(' here and eve
211 live_renderers_.insert(rph->GetID());
212 } else if(type == NOTIFICATION_RENDERER_PROCESS_TERMINATED ||
213 type == NOTIFICATION_RENDERER_PROCESS_CLOSED) {
214 live_renderers_.erase(rph->GetID());
215 }
216
217 if (live_renderers_.size() == 0 && previous_num_live_renderers != 0) {
218 // All render processes have died.
219 BrowserThread::PostTask(BrowserThread::IO,
220 FROM_HERE,
Daniel Erat 2014/09/30 23:55:24 fix indenting
221 base::Bind(
222 &PowerUsageMonitor::CancelPendingHistogramRecordingOnIOThread,
223 base::Unretained(this)));
224 }
225 }
226
227 void PowerUsageMonitor::CancelPendingHistogramRecordingOnIOThread() {
228 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229
230 // Cancel any in-progress histogram reports and reporting of discharge UMA.
231 histogram_recorder_->CancelPendingHistgramReports();
232 start_discharge_time_ = base::Time();
233 }
234
235 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698