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

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host_unittest.cc

Issue 1323403005: Allow AudioOutputDevice objects to be initialized with a specific hardware output device and store … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Palmer's comments Created 5 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "base/bind.h" 5 #include "base/bind.h"
6 #include "base/command_line.h" 6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/run_loop.h" 8 #include "base/run_loop.h"
9 #include "base/sync_socket.h" 9 #include "base/sync_socket.h"
10 #include "content/browser/media/capture/audio_mirroring_manager.h" 10 #include "content/browser/media/capture/audio_mirroring_manager.h"
(...skipping 14 matching lines...) Expand all
25 using ::testing::_; 25 using ::testing::_;
26 using ::testing::Assign; 26 using ::testing::Assign;
27 using ::testing::DoAll; 27 using ::testing::DoAll;
28 using ::testing::NotNull; 28 using ::testing::NotNull;
29 29
30 namespace { 30 namespace {
31 const int kRenderProcessId = 1; 31 const int kRenderProcessId = 1;
32 const int kRenderFrameId = 5; 32 const int kRenderFrameId = 5;
33 const int kStreamId = 50; 33 const int kStreamId = 50;
34 const int kBadStreamId = 99; 34 const int kBadStreamId = 99;
35 const int kSwitchOutputDeviceRequestId = 1; 35 const url::Origin kSecurityOrigin(GURL("http://localhost"));
36 const GURL kSecurityOrigin("http://localhost"); 36 const url::Origin kDefaultSecurityOrigin;
37 const std::string kDefaultDeviceID = ""; 37 const std::string kDefaultDeviceID;
38 const std::string kBadDeviceID = "bad-device-id"; 38 const std::string kBadDeviceID =
39 "badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad1";
40 const std::string kInvalidDeviceID = "invalid-device-id";
39 } // namespace 41 } // namespace
40 42
41 namespace content { 43 namespace content {
42 44
43 class MockAudioMirroringManager : public AudioMirroringManager { 45 class MockAudioMirroringManager : public AudioMirroringManager {
44 public: 46 public:
45 MockAudioMirroringManager() {} 47 MockAudioMirroringManager() {}
46 virtual ~MockAudioMirroringManager() {} 48 virtual ~MockAudioMirroringManager() {}
47 49
48 MOCK_METHOD3(AddDiverter, 50 MOCK_METHOD3(AddDiverter,
(...skipping 15 matching lines...) Expand all
64 const ResourceContext::SaltCallback& salt_callback) 66 const ResourceContext::SaltCallback& salt_callback)
65 : AudioRendererHost(kRenderProcessId, 67 : AudioRendererHost(kRenderProcessId,
66 audio_manager, 68 audio_manager,
67 mirroring_manager, 69 mirroring_manager,
68 media_internals, 70 media_internals,
69 media_stream_manager, 71 media_stream_manager,
70 salt_callback), 72 salt_callback),
71 shared_memory_length_(0) {} 73 shared_memory_length_(0) {}
72 74
73 // A list of mock methods. 75 // A list of mock methods.
76 MOCK_METHOD3(OnDeviceAuthorized,
77 void(int stream_id,
78 bool success,
79 const media::AudioParameters& output_params));
74 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 80 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
75 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); 81 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
76 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); 82 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
77 MOCK_METHOD1(OnStreamError, void(int stream_id)); 83 MOCK_METHOD1(OnStreamError, void(int stream_id));
78 MOCK_METHOD3(OnOutputDeviceSwitched, 84 MOCK_METHOD2(OnOutputDeviceSwitched,
79 void(int stream_id, 85 void(int stream_id, media::SwitchOutputDeviceResult result));
80 int request_id,
81 media::SwitchOutputDeviceResult result));
82 86
83 private: 87 private:
84 virtual ~MockAudioRendererHost() { 88 virtual ~MockAudioRendererHost() {
85 // Make sure all audio streams have been deleted. 89 // Make sure all audio streams have been deleted.
86 EXPECT_TRUE(audio_entries_.empty()); 90 EXPECT_TRUE(audio_entries_.empty());
87 } 91 }
88 92
89 // This method is used to dispatch IPC messages to the renderer. We intercept 93 // This method is used to dispatch IPC messages to the renderer. We intercept
90 // these messages here and dispatch to our mock methods to verify the 94 // these messages here and dispatch to our mock methods to verify the
91 // conversation between this object and the renderer. 95 // conversation between this object and the renderer.
92 virtual bool Send(IPC::Message* message) { 96 virtual bool Send(IPC::Message* message) {
93 CHECK(message); 97 CHECK(message);
94 98
95 // In this method we dispatch the messages to the according handlers as if 99 // In this method we dispatch the messages to the according handlers as if
96 // we are the renderer. 100 // we are the renderer.
97 bool handled = true; 101 bool handled = true;
98 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) 102 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
103 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
104 OnNotifyDeviceAuthorized)
99 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated, 105 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
100 OnNotifyStreamCreated) 106 OnNotifyStreamCreated)
101 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, 107 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
102 OnNotifyStreamStateChanged) 108 OnNotifyStreamStateChanged)
103 IPC_MESSAGE_HANDLER(AudioMsg_NotifyOutputDeviceSwitched, 109 IPC_MESSAGE_HANDLER(AudioMsg_NotifyOutputDeviceSwitched,
104 OnNotifyOutputDeviceSwitched) 110 OnNotifyOutputDeviceSwitched)
105 IPC_MESSAGE_UNHANDLED(handled = false) 111 IPC_MESSAGE_UNHANDLED(handled = false)
106 IPC_END_MESSAGE_MAP() 112 IPC_END_MESSAGE_MAP()
107 EXPECT_TRUE(handled); 113 EXPECT_TRUE(handled);
108 114
109 delete message; 115 delete message;
110 return true; 116 return true;
111 } 117 }
112 118
119 void OnNotifyDeviceAuthorized(int stream_id,
120 bool success,
121 const media::AudioParameters& output_params) {
122 OnDeviceAuthorized(stream_id, success, output_params);
123 }
124
113 void OnNotifyStreamCreated( 125 void OnNotifyStreamCreated(
114 int stream_id, base::SharedMemoryHandle handle, 126 int stream_id, base::SharedMemoryHandle handle,
115 base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) { 127 base::SyncSocket::TransitDescriptor socket_descriptor, uint32 length) {
116 // Maps the shared memory. 128 // Maps the shared memory.
117 shared_memory_.reset(new base::SharedMemory(handle, false)); 129 shared_memory_.reset(new base::SharedMemory(handle, false));
118 CHECK(shared_memory_->Map(length)); 130 CHECK(shared_memory_->Map(length));
119 CHECK(shared_memory_->memory()); 131 CHECK(shared_memory_->memory());
120 shared_memory_length_ = length; 132 shared_memory_length_ = length;
121 133
122 // Create the SyncSocket using the handle. 134 // Create the SyncSocket using the handle.
(...skipping 17 matching lines...) Expand all
140 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: 152 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR:
141 OnStreamError(stream_id); 153 OnStreamError(stream_id);
142 break; 154 break;
143 default: 155 default:
144 FAIL() << "Unknown stream state"; 156 FAIL() << "Unknown stream state";
145 break; 157 break;
146 } 158 }
147 } 159 }
148 160
149 void OnNotifyOutputDeviceSwitched(int stream_id, 161 void OnNotifyOutputDeviceSwitched(int stream_id,
150 int request_id,
151 media::SwitchOutputDeviceResult result) { 162 media::SwitchOutputDeviceResult result) {
152 switch (result) { 163 switch (result) {
153 case media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS: 164 case media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS:
154 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND: 165 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_FOUND:
155 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED: 166 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED:
156 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE: 167 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL:
157 case media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_SUPPORTED: 168 OnOutputDeviceSwitched(stream_id, result);
158 OnOutputDeviceSwitched(stream_id, request_id, result);
159 break; 169 break;
160 default: 170 default:
161 FAIL() << "Unknown SwitchOutputDevice result"; 171 FAIL() << "Unknown SwitchOutputDevice result";
162 break; 172 break;
163 } 173 }
164 } 174 }
165 175
166 scoped_ptr<base::SharedMemory> shared_memory_; 176 scoped_ptr<base::SharedMemory> shared_memory_;
167 scoped_ptr<base::SyncSocket> sync_socket_; 177 scoped_ptr<base::SyncSocket> sync_socket_;
168 uint32 shared_memory_length_; 178 uint32 shared_memory_length_;
169 179
170 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost); 180 DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
171 }; 181 };
172 182
173 namespace { 183 namespace {
174 std::string ReturnMockSalt() { 184 std::string ReturnMockSalt() {
175 return std::string(); 185 return std::string();
176 } 186 }
177 187
178 ResourceContext::SaltCallback GetMockSaltCallback() { 188 ResourceContext::SaltCallback GetMockSaltCallback() {
179 return base::Bind(&ReturnMockSalt); 189 return base::Bind(&ReturnMockSalt);
180 } 190 }
191
192 void WaitForEnumeration(base::RunLoop* loop,
193 const AudioOutputDeviceEnumeration& e) {
194 loop->Quit();
181 } 195 }
196 } // namespace
182 197
183 class AudioRendererHostTest : public testing::Test { 198 class AudioRendererHostTest : public testing::Test {
184 public: 199 public:
185 AudioRendererHostTest() { 200 AudioRendererHostTest() {
186 audio_manager_.reset(media::AudioManager::CreateForTesting()); 201 audio_manager_.reset(media::AudioManager::CreateForTesting());
187 base::CommandLine::ForCurrentProcess()->AppendSwitch( 202 base::CommandLine::ForCurrentProcess()->AppendSwitch(
188 switches::kUseFakeDeviceForMediaStream); 203 switches::kUseFakeDeviceForMediaStream);
189 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); 204 media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
205
206 // Enable caching to make enumerations run in a single thread
207 media_stream_manager_->audio_output_device_enumerator()->SetCachePolicy(
208 AudioOutputDeviceEnumerator::CACHE_POLICY_MANUAL_INVALIDATION);
209 base::RunLoop().RunUntilIdle();
210 base::RunLoop run_loop;
211 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
212 base::Bind(&WaitForEnumeration, &run_loop));
213 run_loop.Run();
214
190 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_, 215 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
191 MediaInternals::GetInstance(), 216 MediaInternals::GetInstance(),
192 media_stream_manager_.get(), 217 media_stream_manager_.get(),
193 GetMockSaltCallback()); 218 GetMockSaltCallback());
194 219
195 // Simulate IPC channel connected. 220 // Simulate IPC channel connected.
196 host_->set_peer_process_for_testing(base::Process::Current()); 221 host_->set_peer_process_for_testing(base::Process::Current());
197 } 222 }
198 223
199 ~AudioRendererHostTest() override { 224 ~AudioRendererHostTest() override {
200 // Simulate closing the IPC channel and give the audio thread time to close 225 // Simulate closing the IPC channel and give the audio thread time to close
201 // the underlying streams. 226 // the underlying streams.
202 host_->OnChannelClosing(); 227 host_->OnChannelClosing();
203 SyncWithAudioThread(); 228 SyncWithAudioThread();
204 229
205 // Release the reference to the mock object. The object will be destructed 230 // Release the reference to the mock object. The object will be destructed
206 // on message_loop_. 231 // on message_loop_.
207 host_ = NULL; 232 host_ = NULL;
208 } 233 }
209 234
210 protected: 235 protected:
211 void Create(bool unified_stream) { 236 void Create(bool unified_stream) {
237 EXPECT_CALL(*host_.get(), OnDeviceAuthorized(kStreamId, true, _));
212 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _)); 238 EXPECT_CALL(*host_.get(), OnStreamCreated(kStreamId, _));
213 239
214 EXPECT_CALL(mirroring_manager_, 240 EXPECT_CALL(mirroring_manager_,
215 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull())) 241 AddDiverter(kRenderProcessId, kRenderFrameId, NotNull()))
216 .RetiresOnSaturation(); 242 .RetiresOnSaturation();
217 243
218 // Send a create stream message to the audio output stream and wait until 244 // Send a create stream message to the audio output stream and wait until
219 // we receive the created message. 245 // we receive the created message.
220 media::AudioParameters params( 246 media::AudioParameters params(
221 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, 247 media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
222 media::AudioParameters::kAudioCDSampleRate, 16, 248 media::AudioParameters::kAudioCDSampleRate, 16,
223 media::AudioParameters::kAudioCDSampleRate / 10); 249 media::AudioParameters::kAudioCDSampleRate / 10);
224 int session_id = 0; 250 int session_id = 0;
225 if (unified_stream) { 251 if (unified_stream) {
226 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to 252 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
227 // pass the permission check. 253 // pass the permission check.
228 session_id = AudioInputDeviceManager::kFakeOpenSessionId; 254 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
229 } 255 }
230 host_->OnCreateStream(kStreamId, kRenderFrameId, session_id, params); 256 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
257 kDefaultDeviceID,
258 kDefaultSecurityOrigin);
259 host_->OnCreateStream(kStreamId, kRenderFrameId, params);
231 260
232 // At some point in the future, a corresponding RemoveDiverter() call must 261 // At some point in the future, a corresponding RemoveDiverter() call must
233 // be made. 262 // be made.
234 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 263 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
235 .RetiresOnSaturation(); 264 .RetiresOnSaturation();
236 SyncWithAudioThread(); 265 SyncWithAudioThread();
237 } 266 }
238 267
239 void Close() { 268 void Close() {
240 // Send a message to AudioRendererHost to tell it we want to close the 269 // Send a message to AudioRendererHost to tell it we want to close the
(...skipping 13 matching lines...) Expand all
254 host_->OnPauseStream(kStreamId); 283 host_->OnPauseStream(kStreamId);
255 SyncWithAudioThread(); 284 SyncWithAudioThread();
256 } 285 }
257 286
258 void SetVolume(double volume) { 287 void SetVolume(double volume) {
259 host_->OnSetVolume(kStreamId, volume); 288 host_->OnSetVolume(kStreamId, volume);
260 SyncWithAudioThread(); 289 SyncWithAudioThread();
261 } 290 }
262 291
263 void SwitchOutputDevice(int stream_id, 292 void SwitchOutputDevice(int stream_id,
264 std::string device_id, 293 const std::string& device_id,
294 const url::Origin& security_origin,
265 media::SwitchOutputDeviceResult expected_result) { 295 media::SwitchOutputDeviceResult expected_result) {
266 EXPECT_CALL(*host_.get(), 296 EXPECT_CALL(*host_.get(),
267 OnOutputDeviceSwitched(stream_id, kSwitchOutputDeviceRequestId, 297 OnOutputDeviceSwitched(stream_id, expected_result));
268 expected_result));
269 host_->OnSwitchOutputDevice(stream_id, kRenderFrameId, device_id, 298 host_->OnSwitchOutputDevice(stream_id, kRenderFrameId, device_id,
270 kSecurityOrigin, kSwitchOutputDeviceRequestId); 299 security_origin);
271 SyncWithAudioThread(); 300 SyncWithAudioThread();
272 } 301 }
273 302
274 void SimulateError() { 303 void SimulateError() {
275 EXPECT_EQ(1u, host_->audio_entries_.size()) 304 EXPECT_EQ(1u, host_->audio_entries_.size())
276 << "Calls Create() before calling this method"; 305 << "Calls Create() before calling this method";
277 306
278 // Expect an error signal sent through IPC. 307 // Expect an error signal sent through IPC.
279 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId)); 308 EXPECT_CALL(*host_.get(), OnStreamError(kStreamId));
280 309
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 TEST_F(AudioRendererHostTest, SetVolume) { 366 TEST_F(AudioRendererHostTest, SetVolume) {
338 Create(false); 367 Create(false);
339 SetVolume(0.5); 368 SetVolume(0.5);
340 Play(); 369 Play();
341 Pause(); 370 Pause();
342 Close(); 371 Close();
343 } 372 }
344 373
345 TEST_F(AudioRendererHostTest, SwitchOutputDevice) { 374 TEST_F(AudioRendererHostTest, SwitchOutputDevice) {
346 Create(false); 375 Create(false);
347 SwitchOutputDevice(kStreamId, kDefaultDeviceID, 376 SwitchOutputDevice(kStreamId, kDefaultDeviceID, kDefaultSecurityOrigin,
348 media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS); 377 media::SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS);
349 Close(); 378 Close();
350 } 379 }
351 380
352 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNotAuthorized) { 381 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNotAuthorized) {
353 Create(false); 382 Create(false);
354 SwitchOutputDevice(kStreamId, kBadDeviceID, 383 SwitchOutputDevice(kStreamId, kBadDeviceID, kSecurityOrigin,
355 media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED); 384 media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_AUTHORIZED);
356 Close(); 385 Close();
357 } 386 }
358 387
388 TEST_F(AudioRendererHostTest, SwitchOutputDeviceInvalidDeviceId) {
389 Create(false);
390 SwitchOutputDevice(kStreamId, kInvalidDeviceID, kSecurityOrigin,
391 media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
392 Close();
393 }
394
359 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNoStream) { 395 TEST_F(AudioRendererHostTest, SwitchOutputDeviceNoStream) {
360 Create(false); 396 Create(false);
361 SwitchOutputDevice(kBadStreamId, kDefaultDeviceID, 397 SwitchOutputDevice(kBadStreamId, kDefaultDeviceID, kDefaultSecurityOrigin,
362 media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE); 398 media::SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
363 Close(); 399 Close();
364 } 400 }
365 401
366 // Simulate the case where a stream is not properly closed. 402 // Simulate the case where a stream is not properly closed.
367 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) { 403 TEST_F(AudioRendererHostTest, CreatePlayAndShutdown) {
368 Create(false); 404 Create(false);
369 Play(); 405 Play();
370 } 406 }
371 407
372 // Simulate the case where a stream is not properly closed. 408 // Simulate the case where a stream is not properly closed.
(...skipping 20 matching lines...) Expand all
393 } 429 }
394 430
395 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) { 431 TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
396 Create(true); 432 Create(true);
397 Close(); 433 Close();
398 } 434 }
399 435
400 // TODO(hclam): Add tests for data conversation in low latency mode. 436 // TODO(hclam): Add tests for data conversation in low latency mode.
401 437
402 } // namespace content 438 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698