1 // Copyright (c) 2012 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 "base/basictypes.h" 6 #include "base/bind.h" 7 #include "base/environment.h" 8 #include "base/logging.h" 9 #include "base/memory/ref_counted.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/message_loop/message_loop.h" 12 #include "base/synchronization/waitable_event.h" 13 #include "media/audio/audio_manager_base.h" 14 #include "media/audio/audio_output_controller.h" 15 #include "media/audio/audio_parameters.h" 16 #include "media/base/audio_bus.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 using ::testing::_; 21 using ::testing::AtLeast; 22 using ::testing::DoAll; 23 using ::testing::Invoke; 24 using ::testing::NotNull; 25 using ::testing::Return; 26 27 namespace media { 28 29 static const int kSampleRate = AudioParameters::kAudioCDSampleRate; 30 static const int kBitsPerSample = 16; 31 static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO; 32 static const int kSamplesPerPacket = kSampleRate / 100; 33 static const double kTestVolume = 0.25; 34 35 class MockAudioOutputControllerEventHandler 36 : public AudioOutputController::EventHandler { 37 public: 38 MockAudioOutputControllerEventHandler() {} 39 40 MOCK_METHOD0(OnCreated, void()); 41 MOCK_METHOD0(OnPlaying, void()); 42 MOCK_METHOD2(OnPowerMeasured, void(float power_dbfs, bool clipped)); 43 MOCK_METHOD0(OnPaused, void()); 44 MOCK_METHOD0(OnError, void()); 45 MOCK_METHOD2(OnDeviceChange, void(int new_buffer_size, int new_sample_rate)); 46 47 private: 48 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerEventHandler); 49 }; 50 51 class MockAudioOutputControllerSyncReader 52 : public AudioOutputController::SyncReader { 53 public: 54 MockAudioOutputControllerSyncReader() {} 55 56 MOCK_METHOD1(UpdatePendingBytes, void(uint32 bytes)); 57 MOCK_METHOD2(Read, void(const AudioBus* source, AudioBus* dest)); 58 MOCK_METHOD0(Close, void()); 59 60 private: 61 DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader); 62 }; 63 64 class MockAudioOutputStream : public AudioOutputStream { 65 public: 66 MOCK_METHOD0(Open, bool()); 67 MOCK_METHOD1(Start, void(AudioSourceCallback* callback)); 68 MOCK_METHOD0(Stop, void()); 69 MOCK_METHOD1(SetVolume, void(double volume)); 70 MOCK_METHOD1(GetVolume, void(double* volume)); 71 MOCK_METHOD0(Close, void()); 72 73 // Set/get the callback passed to Start(). 74 AudioSourceCallback* callback() const { return callback_; } 75 void SetCallback(AudioSourceCallback* asc) { callback_ = asc; } 76 77 private: 78 AudioSourceCallback* callback_; 79 }; 80 81 ACTION_P(SignalEvent, event) { 82 event->Signal(); 83 } 84 85 static const float kBufferNonZeroData = 1.0f; 86 ACTION(PopulateBuffer) { 87 arg1->Zero(); 88 // Note: To confirm the buffer will be populated in these tests, it's 89 // sufficient that only the first float in channel 0 is set to the value. 90 arg1->channel(0)[0] = kBufferNonZeroData; 91 } 92 93 class AudioOutputControllerTest : public testing::Test { 94 public: 95 AudioOutputControllerTest() 96 : audio_manager_(AudioManager::CreateForTesting()), 97 create_event_(false, false), 98 play_event_(false, false), 99 read_event_(false, false), 100 pause_event_(false, false) { 101 } 102 103 virtual ~AudioOutputControllerTest() { 104 } 105 106 protected: 107 void Create(int samples_per_packet) { 108 EXPECT_FALSE(create_event_.IsSignaled()); 109 EXPECT_FALSE(play_event_.IsSignaled()); 110 EXPECT_FALSE(read_event_.IsSignaled()); 111 EXPECT_FALSE(pause_event_.IsSignaled()); 112 113 params_ = AudioParameters( 114 AudioParameters::AUDIO_FAKE, kChannelLayout, 115 kSampleRate, kBitsPerSample, samples_per_packet); 116 117 if (params_.IsValid()) { 118 EXPECT_CALL(mock_event_handler_, OnCreated()) 119 .WillOnce(SignalEvent(&create_event_)); 120 } 121 122 controller_ = AudioOutputController::Create( 123 audio_manager_.get(), &mock_event_handler_, params_, std::string(), 124 std::string(), &mock_sync_reader_); 125 if (controller_.get()) 126 controller_->SetVolume(kTestVolume); 127 128 EXPECT_EQ(params_.IsValid(), controller_.get() != NULL); 129 } 130 131 void Play() { 132 // Expect the event handler to receive one OnPlaying() call and one or more 133 // OnPowerMeasured() calls. 134 EXPECT_CALL(mock_event_handler_, OnPlaying()) 135 .WillOnce(SignalEvent(&play_event_)); 136 #if defined(AUDIO_POWER_MONITORING) 137 EXPECT_CALL(mock_event_handler_, OnPowerMeasured(_, false)) 138 .Times(AtLeast(1)); 139 #endif 140 141 // During playback, the mock pretends to provide audio data rendered and 142 // sent from the render process. 143 EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_)) 144 .Times(AtLeast(1)); 145 EXPECT_CALL(mock_sync_reader_, Read(_, _)) 146 .WillRepeatedly(DoAll(PopulateBuffer(), 147 SignalEvent(&read_event_))); 148 controller_->Play(); 149 } 150 151 void Pause() { 152 // Expect the event handler to receive one OnPaused() call. 153 EXPECT_CALL(mock_event_handler_, OnPaused()) 154 .WillOnce(SignalEvent(&pause_event_)); 155 156 controller_->Pause(); 157 } 158 159 void ChangeDevice() { 160 // Expect the event handler to receive one OnPaying() call and no OnPaused() 161 // call. 162 EXPECT_CALL(mock_event_handler_, OnPlaying()) 163 .WillOnce(SignalEvent(&play_event_)); 164 EXPECT_CALL(mock_event_handler_, OnPaused()) 165 .Times(0); 166 167 // Simulate a device change event to AudioOutputController from the 168 // AudioManager. 169 audio_manager_->GetMessageLoop()->PostTask( 170 FROM_HERE, 171 base::Bind(&AudioOutputController::OnDeviceChange, controller_)); 172 } 173 174 void Divert(bool was_playing, int num_times_to_be_started) { 175 if (was_playing) { 176 // Expect the handler to receive one OnPlaying() call as a result of the 177 // stream switching. 178 EXPECT_CALL(mock_event_handler_, OnPlaying()) 179 .WillOnce(SignalEvent(&play_event_)); 180 } 181 182 EXPECT_CALL(mock_stream_, Open()) 183 .WillOnce(Return(true)); 184 EXPECT_CALL(mock_stream_, SetVolume(kTestVolume)); 185 if (num_times_to_be_started > 0) { 186 EXPECT_CALL(mock_stream_, Start(NotNull())) 187 .Times(num_times_to_be_started) 188 .WillRepeatedly( 189 Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback)); 190 EXPECT_CALL(mock_stream_, Stop()) 191 .Times(num_times_to_be_started); 192 } 193 194 controller_->StartDiverting(&mock_stream_); 195 } 196 197 void ReadDivertedAudioData() { 198 scoped_ptr<AudioBus> dest = AudioBus::Create(params_); 199 ASSERT_TRUE(!!mock_stream_.callback()); 200 const int frames_read = 201 mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState()); 202 EXPECT_LT(0, frames_read); 203 EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]); 204 } 205 206 void Revert(bool was_playing) { 207 if (was_playing) { 208 // Expect the handler to receive one OnPlaying() call as a result of the 209 // stream switching back. 210 EXPECT_CALL(mock_event_handler_, OnPlaying()) 211 .WillOnce(SignalEvent(&play_event_)); 212 } 213 214 EXPECT_CALL(mock_stream_, Close()); 215 216 controller_->StopDiverting(); 217 } 218 219 void SwitchDevice(bool diverting) { 220 if (!diverting) { 221 // Expect the current stream to close and a new stream to start 222 // playing if not diverting. When diverting, nothing happens 223 // until diverting is stopped. 224 EXPECT_CALL(mock_event_handler_, OnPlaying()) 225 .WillOnce(SignalEvent(&play_event_)); 226 } 227 228 controller_->SwitchOutputDevice(AudioManagerBase::kDefaultDeviceName, 229 base::Bind(&base::DoNothing)); 230 } 231 232 void Close() { 233 EXPECT_CALL(mock_sync_reader_, Close()); 234 235 controller_->Close(base::MessageLoop::QuitClosure()); 236 base::MessageLoop::current()->Run(); 237 } 238 239 // These help make test sequences more readable. 240 void DivertNeverPlaying() { Divert(false, 0); } 241 void DivertWillEventuallyBeTwicePlayed() { Divert(false, 2); } 242 void DivertWhilePlaying() { Divert(true, 1); } 243 void RevertWasNotPlaying() { Revert(false); } 244 void RevertWhilePlaying() { Revert(true); } 245 246 // These synchronize the main thread with key events taking place on other 247 // threads. 248 void WaitForCreate() { create_event_.Wait(); } 249 void WaitForPlay() { play_event_.Wait(); } 250 void WaitForReads() { 251 // Note: Arbitrarily chosen, but more iterations causes tests to take 252 // significantly more time. 253 static const int kNumIterations = 3; 254 for (int i = 0; i < kNumIterations; ++i) { 255 read_event_.Wait(); 256 } 257 } 258 void WaitForPause() { pause_event_.Wait(); } 259 260 private: 261 base::MessageLoopForIO message_loop_; 262 scoped_ptr<AudioManager> audio_manager_; 263 MockAudioOutputControllerEventHandler mock_event_handler_; 264 MockAudioOutputControllerSyncReader mock_sync_reader_; 265 MockAudioOutputStream mock_stream_; 266 base::WaitableEvent create_event_; 267 base::WaitableEvent play_event_; 268 base::WaitableEvent read_event_; 269 base::WaitableEvent pause_event_; 270 AudioParameters params_; 271 scoped_refptr<AudioOutputController> controller_; 272 273 DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest); 274 }; 275 276 TEST_F(AudioOutputControllerTest, CreateAndClose) { 277 Create(kSamplesPerPacket); 278 Close(); 279 } 280 281 TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) { 282 Create(kSamplesPerPacket * 1000); 283 } 284 285 TEST_F(AudioOutputControllerTest, PlayAndClose) { 286 Create(kSamplesPerPacket); 287 WaitForCreate(); 288 Play(); 289 WaitForPlay(); 290 WaitForReads(); 291 Close(); 292 } 293 294 TEST_F(AudioOutputControllerTest, PlayPauseClose) { 295 Create(kSamplesPerPacket); 296 WaitForCreate(); 297 Play(); 298 WaitForPlay(); 299 WaitForReads(); 300 Pause(); 301 WaitForPause(); 302 Close(); 303 } 304 305 TEST_F(AudioOutputControllerTest, PlayPausePlayClose) { 306 Create(kSamplesPerPacket); 307 WaitForCreate(); 308 Play(); 309 WaitForPlay(); 310 WaitForReads(); 311 Pause(); 312 WaitForPause(); 313 Play(); 314 WaitForPlay(); 315 Close(); 316 } 317 318 TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) { 319 Create(kSamplesPerPacket); 320 WaitForCreate(); 321 Play(); 322 WaitForPlay(); 323 WaitForReads(); 324 ChangeDevice(); 325 WaitForPlay(); 326 WaitForReads(); 327 Close(); 328 } 329 330 TEST_F(AudioOutputControllerTest, PlaySwitchDeviceClose) { 331 Create(kSamplesPerPacket); 332 WaitForCreate(); 333 Play(); 334 WaitForPlay(); 335 WaitForReads(); 336 SwitchDevice(false); 337 WaitForPlay(); 338 WaitForReads(); 339 Close(); 340 } 341 342 TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) { 343 Create(kSamplesPerPacket); 344 WaitForCreate(); 345 Play(); 346 WaitForPlay(); 347 WaitForReads(); 348 DivertWhilePlaying(); 349 WaitForPlay(); 350 ReadDivertedAudioData(); 351 RevertWhilePlaying(); 352 WaitForPlay(); 353 WaitForReads(); 354 Close(); 355 } 356 357 TEST_F(AudioOutputControllerTest, PlayDivertSwitchDeviceRevertClose) { 358 Create(kSamplesPerPacket); 359 WaitForCreate(); 360 Play(); 361 WaitForPlay(); 362 WaitForReads(); 363 DivertWhilePlaying(); 364 WaitForPlay(); 365 SwitchDevice(true); 366 ReadDivertedAudioData(); 367 RevertWhilePlaying(); 368 WaitForPlay(); 369 WaitForReads(); 370 Close(); 371 } 372 373 TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) { 374 Create(kSamplesPerPacket); 375 WaitForCreate(); 376 Play(); 377 WaitForPlay(); 378 WaitForReads(); 379 DivertWhilePlaying(); 380 WaitForPlay(); 381 ReadDivertedAudioData(); 382 RevertWhilePlaying(); 383 WaitForPlay(); 384 WaitForReads(); 385 DivertWhilePlaying(); 386 WaitForPlay(); 387 ReadDivertedAudioData(); 388 RevertWhilePlaying(); 389 WaitForPlay(); 390 WaitForReads(); 391 Close(); 392 } 393 394 TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) { 395 Create(kSamplesPerPacket); 396 WaitForCreate(); 397 DivertWillEventuallyBeTwicePlayed(); 398 Play(); 399 WaitForPlay(); 400 ReadDivertedAudioData(); 401 Pause(); 402 WaitForPause(); 403 Play(); 404 WaitForPlay(); 405 ReadDivertedAudioData(); 406 RevertWhilePlaying(); 407 WaitForPlay(); 408 WaitForReads(); 409 Close(); 410 } 411 412 TEST_F(AudioOutputControllerTest, DivertRevertClose) { 413 Create(kSamplesPerPacket); 414 WaitForCreate(); 415 DivertNeverPlaying(); 416 RevertWasNotPlaying(); 417 Close(); 418 } 419 420 } // namespace media 421