| 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 |