OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/media/audio_stream_monitor.h" | 5 #include "content/browser/media/audio_stream_monitor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 } | 86 } |
87 | 87 |
88 void ExpectTabWasRecentlyAudible(bool was_audible, | 88 void ExpectTabWasRecentlyAudible(bool was_audible, |
89 const base::TimeTicks& last_blurt_time) { | 89 const base::TimeTicks& last_blurt_time) { |
90 EXPECT_EQ(was_audible, monitor_->was_recently_audible_); | 90 EXPECT_EQ(was_audible, monitor_->was_recently_audible_); |
91 EXPECT_EQ(last_blurt_time, monitor_->last_blurt_time_); | 91 EXPECT_EQ(last_blurt_time, monitor_->last_blurt_time_); |
92 EXPECT_EQ(monitor_->was_recently_audible_, | 92 EXPECT_EQ(monitor_->was_recently_audible_, |
93 monitor_->off_timer_.IsRunning()); | 93 monitor_->off_timer_.IsRunning()); |
94 } | 94 } |
95 | 95 |
96 void ExpectWebContentsWillBeNotifiedOnce(bool should_be_audible) { | 96 void ExpectIsCurrentlyAudible() const { |
| 97 EXPECT_TRUE(monitor_->IsCurrentlyAudible()); |
| 98 } |
| 99 |
| 100 void ExpectNotCurrentlyAudible() const { |
| 101 EXPECT_FALSE(monitor_->IsCurrentlyAudible()); |
| 102 } |
| 103 |
| 104 void ExpectRecentlyAudibleChangeNotification(bool new_recently_audible) { |
97 EXPECT_CALL( | 105 EXPECT_CALL( |
98 mock_web_contents_delegate_, | 106 mock_web_contents_delegate_, |
99 NavigationStateChanged(RenderViewHostTestHarness::web_contents(), | 107 NavigationStateChanged(RenderViewHostTestHarness::web_contents(), |
100 INVALIDATE_TYPE_TAB)) | 108 INVALIDATE_TYPE_TAB)) |
101 .WillOnce(InvokeWithoutArgs( | 109 .WillOnce(InvokeWithoutArgs( |
102 this, | 110 this, |
103 should_be_audible | 111 new_recently_audible |
104 ? &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOn | 112 ? &AudioStreamMonitorTest::ExpectWasRecentlyAudible |
105 : &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOff)) | 113 : &AudioStreamMonitorTest::ExpectNotRecentlyAudible)) |
106 .RetiresOnSaturation(); | 114 .RetiresOnSaturation(); |
107 } | 115 } |
108 | 116 |
| 117 void ExpectCurrentlyAudibleChangeNotification(bool new_audible) { |
| 118 EXPECT_CALL( |
| 119 mock_web_contents_delegate_, |
| 120 NavigationStateChanged(RenderViewHostTestHarness::web_contents(), |
| 121 INVALIDATE_TYPE_TAB)) |
| 122 .WillOnce(InvokeWithoutArgs( |
| 123 this, |
| 124 new_audible |
| 125 ? &AudioStreamMonitorTest::ExpectIsCurrentlyAudible |
| 126 : &AudioStreamMonitorTest::ExpectNotCurrentlyAudible)) |
| 127 .RetiresOnSaturation(); |
| 128 } |
| 129 |
109 static base::TimeDelta one_polling_interval() { | 130 static base::TimeDelta one_polling_interval() { |
110 return base::TimeDelta::FromSeconds(1) / | 131 return base::TimeDelta::FromSeconds(1) / |
111 static_cast<int>(AudioStreamMonitor::kPowerMeasurementsPerSecond); | 132 static_cast<int>(AudioStreamMonitor::kPowerMeasurementsPerSecond); |
112 } | 133 } |
113 | 134 |
114 static base::TimeDelta holding_period() { | 135 static base::TimeDelta holding_period() { |
115 return base::TimeDelta::FromMilliseconds( | 136 return base::TimeDelta::FromMilliseconds( |
116 AudioStreamMonitor::kHoldOnMilliseconds); | 137 AudioStreamMonitor::kHoldOnMilliseconds); |
117 } | 138 } |
118 | 139 |
(...skipping 10 matching lines...) Expand all Loading... |
129 } | 150 } |
130 | 151 |
131 protected: | 152 protected: |
132 AudioStreamMonitor* monitor_; | 153 AudioStreamMonitor* monitor_; |
133 | 154 |
134 private: | 155 private: |
135 std::pair<float, bool> ReadPower(int stream_id) { | 156 std::pair<float, bool> ReadPower(int stream_id) { |
136 return std::make_pair(current_power_[stream_id], false); | 157 return std::make_pair(current_power_[stream_id], false); |
137 } | 158 } |
138 | 159 |
139 void ExpectIsNotifyingForToggleOn() { | 160 void ExpectWasRecentlyAudible() const { |
140 EXPECT_TRUE(monitor_->WasRecentlyAudible()); | 161 EXPECT_TRUE(monitor_->WasRecentlyAudible()); |
141 } | 162 } |
142 | 163 |
143 void ExpectIsNotifyingForToggleOff() { | 164 void ExpectNotRecentlyAudible() const { |
144 EXPECT_FALSE(monitor_->WasRecentlyAudible()); | 165 EXPECT_FALSE(monitor_->WasRecentlyAudible()); |
145 } | 166 } |
146 | 167 |
147 MockWebContentsDelegate mock_web_contents_delegate_; | 168 MockWebContentsDelegate mock_web_contents_delegate_; |
148 base::SimpleTestTickClock clock_; | 169 base::SimpleTestTickClock clock_; |
149 std::map<int, float> current_power_; | 170 std::map<int, float> current_power_; |
150 | 171 |
151 DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitorTest); | 172 DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitorTest); |
152 }; | 173 }; |
153 | 174 |
154 // Tests that AudioStreamMonitor is polling while it has a | 175 // Tests that AudioStreamMonitor is polling while it has a |
155 // ReadPowerAndClipCallback, and is not polling at other times. | 176 // ReadPowerAndClipCallback, and is not polling at other times. |
156 TEST_F(AudioStreamMonitorTest, PollsWhenProvidedACallback) { | 177 TEST_F(AudioStreamMonitorTest, PollsWhenProvidedACallback) { |
157 EXPECT_FALSE(monitor_->WasRecentlyAudible()); | 178 EXPECT_FALSE(monitor_->WasRecentlyAudible()); |
| 179 ExpectNotCurrentlyAudible(); |
158 ExpectIsPolling(kRenderProcessId, kStreamId, false); | 180 ExpectIsPolling(kRenderProcessId, kStreamId, false); |
159 | 181 |
160 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); | 182 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); |
161 EXPECT_FALSE(monitor_->WasRecentlyAudible()); | 183 EXPECT_FALSE(monitor_->WasRecentlyAudible()); |
| 184 ExpectNotCurrentlyAudible(); |
162 ExpectIsPolling(kRenderProcessId, kStreamId, true); | 185 ExpectIsPolling(kRenderProcessId, kStreamId, true); |
163 | 186 |
164 StopMonitoring(kRenderProcessId, kStreamId); | 187 StopMonitoring(kRenderProcessId, kStreamId); |
165 EXPECT_FALSE(monitor_->WasRecentlyAudible()); | 188 EXPECT_FALSE(monitor_->WasRecentlyAudible()); |
| 189 ExpectNotCurrentlyAudible(); |
166 ExpectIsPolling(kRenderProcessId, kStreamId, false); | 190 ExpectIsPolling(kRenderProcessId, kStreamId, false); |
167 } | 191 } |
168 | 192 |
169 // Tests that AudioStreamMonitor debounces the power level readings it's taking, | 193 // Tests that AudioStreamMonitor debounces the power level readings it's taking, |
170 // which could be fluctuating rapidly between the audible versus silence | 194 // which could be fluctuating rapidly between the audible versus silence |
171 // threshold. See comments in audio_stream_monitor.h for expected behavior. | 195 // threshold. See comments in audio_stream_monitor.h for expected behavior. |
172 TEST_F(AudioStreamMonitorTest, | 196 TEST_F(AudioStreamMonitorTest, |
173 ImpulsesKeepIndicatorOnUntilHoldingPeriodHasPassed) { | 197 ImpulsesKeepIndicatorOnUntilHoldingPeriodHasPassed) { |
174 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); | 198 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); |
175 | 199 |
176 // Expect WebContents will get one call form AudioStreamMonitor to toggle the | 200 // Expect WebContents will get one call form AudioStreamMonitor to toggle the |
177 // indicator on upon the very first poll. | 201 // indicator on upon the very first poll. |
178 ExpectWebContentsWillBeNotifiedOnce(true); | 202 ExpectRecentlyAudibleChangeNotification(true); |
179 | 203 |
180 // Loop, each time testing a slightly longer period of polled silence. The | 204 // Loop, each time testing a slightly longer period of polled silence. The |
181 // indicator should remain on throughout. | 205 // recently audible state should not change while the currently audible one |
182 int num_silence_polls = 0; | 206 // should. |
| 207 int num_silence_polls = 1; |
183 base::TimeTicks last_blurt_time; | 208 base::TimeTicks last_blurt_time; |
184 do { | 209 do { |
| 210 ExpectCurrentlyAudibleChangeNotification(true); |
| 211 |
185 // Poll an audible signal, and expect tab indicator state is on. | 212 // Poll an audible signal, and expect tab indicator state is on. |
186 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power()); | 213 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power()); |
187 last_blurt_time = GetTestClockTime(); | 214 last_blurt_time = GetTestClockTime(); |
188 SimulatePollTimerFired(); | 215 SimulatePollTimerFired(); |
189 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 216 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
190 AdvanceClock(one_polling_interval()); | 217 AdvanceClock(one_polling_interval()); |
191 | 218 |
| 219 ExpectCurrentlyAudibleChangeNotification(false); |
| 220 |
192 // Poll a silent signal repeatedly, ensuring that the indicator is being | 221 // Poll a silent signal repeatedly, ensuring that the indicator is being |
193 // held on during the holding period. | 222 // held on during the holding period. |
194 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power()); | 223 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power()); |
195 for (int i = 0; i < num_silence_polls; ++i) { | 224 for (int i = 0; i < num_silence_polls; ++i) { |
196 SimulatePollTimerFired(); | 225 SimulatePollTimerFired(); |
197 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 226 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
198 // Note: Redundant off timer firings should not have any effect. | 227 // Note: Redundant off timer firings should not have any effect. |
199 SimulateOffTimerFired(); | 228 SimulateOffTimerFired(); |
200 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 229 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
201 AdvanceClock(one_polling_interval()); | 230 AdvanceClock(one_polling_interval()); |
202 } | 231 } |
203 | 232 |
204 ++num_silence_polls; | 233 ++num_silence_polls; |
205 } while (GetTestClockTime() < last_blurt_time + holding_period()); | 234 } while (GetTestClockTime() < last_blurt_time + holding_period()); |
206 | 235 |
207 // At this point, the clock has just advanced to beyond the holding period, so | 236 // At this point, the clock has just advanced to beyond the holding period, so |
208 // the next firing of the off timer should turn off the tab indicator. Also, | 237 // the next firing of the off timer should turn off the tab indicator. Also, |
209 // make sure it stays off for several cycles thereafter. | 238 // make sure it stays off for several cycles thereafter. |
210 ExpectWebContentsWillBeNotifiedOnce(false); | 239 ExpectRecentlyAudibleChangeNotification(false); |
211 for (int i = 0; i < 10; ++i) { | 240 for (int i = 0; i < 10; ++i) { |
212 SimulateOffTimerFired(); | 241 SimulateOffTimerFired(); |
213 ExpectTabWasRecentlyAudible(false, last_blurt_time); | 242 ExpectTabWasRecentlyAudible(false, last_blurt_time); |
214 AdvanceClock(one_polling_interval()); | 243 AdvanceClock(one_polling_interval()); |
215 } | 244 } |
216 } | 245 } |
217 | 246 |
218 // Tests that the AudioStreamMonitor correctly processes the blurts from two | 247 // Tests that the AudioStreamMonitor correctly processes the blurts from two |
219 // different streams in the same tab. | 248 // different streams in the same tab. |
220 TEST_F(AudioStreamMonitorTest, HandlesMultipleStreamsBlurting) { | 249 TEST_F(AudioStreamMonitorTest, HandlesMultipleStreamsBlurting) { |
221 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); | 250 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); |
222 StartMonitoring( | 251 StartMonitoring( |
223 kRenderProcessId, kAnotherStreamId, CreatePollCallback(kAnotherStreamId)); | 252 kRenderProcessId, kAnotherStreamId, CreatePollCallback(kAnotherStreamId)); |
224 | 253 |
225 base::TimeTicks last_blurt_time; | 254 base::TimeTicks last_blurt_time; |
226 ExpectTabWasRecentlyAudible(false, last_blurt_time); | 255 ExpectTabWasRecentlyAudible(false, last_blurt_time); |
| 256 ExpectNotCurrentlyAudible(); |
227 | 257 |
228 // Measure audible sound from the first stream and silence from the second. | 258 // Measure audible sound from the first stream and silence from the second. |
229 // The indicator turns on (i.e., tab was recently audible). | 259 // The tab becomes audible. |
230 ExpectWebContentsWillBeNotifiedOnce(true); | 260 ExpectRecentlyAudibleChangeNotification(true); |
| 261 ExpectCurrentlyAudibleChangeNotification(true); |
| 262 |
231 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power()); | 263 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power()); |
232 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); | 264 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); |
233 last_blurt_time = GetTestClockTime(); | 265 last_blurt_time = GetTestClockTime(); |
234 SimulatePollTimerFired(); | 266 SimulatePollTimerFired(); |
235 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 267 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
| 268 ExpectIsCurrentlyAudible(); |
236 | 269 |
237 // Halfway through the holding period, the second stream joins in. The | 270 // Halfway through the holding period, the second stream joins in. The |
238 // indicator stays on. | 271 // indicator stays on. |
239 AdvanceClock(holding_period() / 2); | 272 AdvanceClock(holding_period() / 2); |
240 SimulateOffTimerFired(); | 273 SimulateOffTimerFired(); |
241 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power()); | 274 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power()); |
242 last_blurt_time = GetTestClockTime(); | 275 last_blurt_time = GetTestClockTime(); |
243 SimulatePollTimerFired(); // Restarts holding period. | 276 SimulatePollTimerFired(); // Restarts holding period. |
244 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 277 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
| 278 ExpectIsCurrentlyAudible(); |
245 | 279 |
246 // Now, measure silence from both streams. After an entire holding period | 280 // Now, measure silence from both streams. After an entire holding period |
247 // has passed (since the second stream joined in), the indicator should turn | 281 // has passed (since the second stream joined in), the tab will no longer |
248 // off. | 282 // become audible nor recently audible. |
249 ExpectWebContentsWillBeNotifiedOnce(false); | 283 ExpectCurrentlyAudibleChangeNotification(false); |
| 284 ExpectRecentlyAudibleChangeNotification(false); |
| 285 |
250 AdvanceClock(holding_period()); | 286 AdvanceClock(holding_period()); |
251 SimulateOffTimerFired(); | 287 SimulateOffTimerFired(); |
252 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power()); | 288 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power()); |
253 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); | 289 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); |
254 SimulatePollTimerFired(); | 290 SimulatePollTimerFired(); |
255 ExpectTabWasRecentlyAudible(false, last_blurt_time); | 291 ExpectTabWasRecentlyAudible(false, last_blurt_time); |
| 292 ExpectNotCurrentlyAudible(); |
256 | 293 |
257 // Now, measure silence from the first stream and audible sound from the | 294 // Now, measure silence from the first stream and audible sound from the |
258 // second. The indicator turns back on. | 295 // second. The tab becomes audible again. |
259 ExpectWebContentsWillBeNotifiedOnce(true); | 296 ExpectRecentlyAudibleChangeNotification(true); |
| 297 ExpectCurrentlyAudibleChangeNotification(true); |
| 298 |
260 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power()); | 299 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power()); |
261 last_blurt_time = GetTestClockTime(); | 300 last_blurt_time = GetTestClockTime(); |
262 SimulatePollTimerFired(); | 301 SimulatePollTimerFired(); |
263 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 302 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
| 303 ExpectIsCurrentlyAudible(); |
264 | 304 |
265 // From here onwards, both streams are silent. Halfway through the holding | 305 // From here onwards, both streams are silent. Halfway through the holding |
266 // period, the indicator should not have changed. | 306 // period, the tab is no longer audible but stays as recently audible. |
| 307 ExpectCurrentlyAudibleChangeNotification(false); |
| 308 |
267 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); | 309 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power()); |
268 AdvanceClock(holding_period() / 2); | 310 AdvanceClock(holding_period() / 2); |
269 SimulatePollTimerFired(); | 311 SimulatePollTimerFired(); |
270 SimulateOffTimerFired(); | 312 SimulateOffTimerFired(); |
271 ExpectTabWasRecentlyAudible(true, last_blurt_time); | 313 ExpectTabWasRecentlyAudible(true, last_blurt_time); |
| 314 ExpectNotCurrentlyAudible(); |
272 | 315 |
273 // Just past the holding period, the indicator should be turned off. | 316 // Just past the holding period, the tab is no longer marked as recently |
274 ExpectWebContentsWillBeNotifiedOnce(false); | 317 // audible. |
| 318 ExpectRecentlyAudibleChangeNotification(false); |
| 319 |
275 AdvanceClock(holding_period() - (GetTestClockTime() - last_blurt_time)); | 320 AdvanceClock(holding_period() - (GetTestClockTime() - last_blurt_time)); |
276 SimulateOffTimerFired(); | 321 SimulateOffTimerFired(); |
277 ExpectTabWasRecentlyAudible(false, last_blurt_time); | 322 ExpectTabWasRecentlyAudible(false, last_blurt_time); |
| 323 ExpectNotCurrentlyAudible(); |
278 | 324 |
279 // Polling should not turn the indicator back while both streams are remaining | 325 // Polling should not turn the indicator back while both streams are remaining |
280 // silent. | 326 // silent. |
281 for (int i = 0; i < 100; ++i) { | 327 for (int i = 0; i < 100; ++i) { |
282 AdvanceClock(one_polling_interval()); | 328 AdvanceClock(one_polling_interval()); |
283 SimulatePollTimerFired(); | 329 SimulatePollTimerFired(); |
284 ExpectTabWasRecentlyAudible(false, last_blurt_time); | 330 ExpectTabWasRecentlyAudible(false, last_blurt_time); |
| 331 ExpectNotCurrentlyAudible(); |
285 } | 332 } |
286 } | 333 } |
287 | 334 |
288 TEST_F(AudioStreamMonitorTest, MultipleRendererProcesses) { | 335 TEST_F(AudioStreamMonitorTest, MultipleRendererProcesses) { |
289 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); | 336 StartMonitoring(kRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); |
290 StartMonitoring( | 337 StartMonitoring( |
291 kAnotherRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); | 338 kAnotherRenderProcessId, kStreamId, CreatePollCallback(kStreamId)); |
292 ExpectIsPolling(kRenderProcessId, kStreamId, true); | 339 ExpectIsPolling(kRenderProcessId, kStreamId, true); |
293 ExpectIsPolling(kAnotherRenderProcessId, kStreamId, true); | 340 ExpectIsPolling(kAnotherRenderProcessId, kStreamId, true); |
294 StopMonitoring(kAnotherRenderProcessId, kStreamId); | 341 StopMonitoring(kAnotherRenderProcessId, kStreamId); |
295 ExpectIsPolling(kRenderProcessId, kStreamId, true); | 342 ExpectIsPolling(kRenderProcessId, kStreamId, true); |
296 ExpectIsPolling(kAnotherRenderProcessId, kStreamId, false); | 343 ExpectIsPolling(kAnotherRenderProcessId, kStreamId, false); |
297 } | 344 } |
298 | 345 |
299 } // namespace content | 346 } // namespace content |
OLD | NEW |