OLD | NEW |
---|---|
(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 | |
OLD | NEW |