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

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

Issue 1896883002: Mojo interfaces needed for switching audio rendering stream creation and closing from IPC to Mojo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 "content/browser/renderer_host/media/audio_renderer_host.h" 5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/run_loop.h" 14 #include "base/run_loop.h"
15 #include "base/sync_socket.h" 15 #include "base/sync_socket.h"
16 #include "content/browser/media/audio_output_impl.h"
16 #include "content/browser/media/capture/audio_mirroring_manager.h" 17 #include "content/browser/media/capture/audio_mirroring_manager.h"
17 #include "content/browser/media/media_internals.h" 18 #include "content/browser/media/media_internals.h"
18 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 19 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
19 #include "content/browser/renderer_host/media/media_stream_manager.h" 20 #include "content/browser/renderer_host/media/media_stream_manager.h"
20 #include "content/common/media/audio_messages.h" 21 #include "content/common/media/audio_messages.h"
21 #include "content/public/common/content_switches.h" 22 #include "content/public/common/content_switches.h"
22 #include "content/public/test/test_browser_thread_bundle.h" 23 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "ipc/ipc_message_utils.h" 24 #include "ipc/ipc_message_utils.h"
24 #include "media/audio/audio_manager.h" 25 #include "media/audio/audio_manager.h"
25 #include "media/base/bind_to_current_loop.h" 26 #include "media/base/bind_to_current_loop.h"
26 #include "media/base/media_switches.h" 27 #include "media/base/media_switches.h"
28 #include "media/mojo/common/media_type_converters.h"
29 #include "mojo/edk/embedder/embedder.h"
27 #include "testing/gmock/include/gmock/gmock.h" 30 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h" 31 #include "testing/gtest/include/gtest/gtest.h"
29 32
30 using ::testing::_; 33 using ::testing::_;
31 using ::testing::Assign; 34 using ::testing::Assign;
32 using ::testing::DoAll; 35 using ::testing::DoAll;
33 using ::testing::NotNull; 36 using ::testing::NotNull;
34 37
35 namespace { 38 namespace {
36 const int kRenderProcessId = 1; 39 const int kRenderProcessId = 1;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 MediaStreamManager* media_stream_manager, 71 MediaStreamManager* media_stream_manager,
69 const ResourceContext::SaltCallback& salt_callback) 72 const ResourceContext::SaltCallback& salt_callback)
70 : AudioRendererHost(kRenderProcessId, 73 : AudioRendererHost(kRenderProcessId,
71 audio_manager, 74 audio_manager,
72 mirroring_manager, 75 mirroring_manager,
73 media_internals, 76 media_internals,
74 media_stream_manager, 77 media_stream_manager,
75 salt_callback), 78 salt_callback),
76 shared_memory_length_(0) {} 79 shared_memory_length_(0) {}
77 80
81 AudioOutputImpl* Init(scoped_refptr<MockAudioRendererHost> host) {
82 media::interfaces::AudioOutputPtr* stream = new media::interfaces::Audio OutputPtr();
83 audio_output_impl_ = (new AudioOutputImpl(0,
84 mojo::GetProxy(stream)));
85 return audio_output_impl_;
86 }
78 // A list of mock methods. 87 // A list of mock methods.
79 MOCK_METHOD4(OnDeviceAuthorized, 88 MOCK_METHOD4(OnDeviceAuthorized,
80 void(int stream_id, 89 void(int stream_id,
81 media::OutputDeviceStatus device_status, 90 media::OutputDeviceStatus device_status,
82 const media::AudioParameters& output_params, 91 const media::AudioParameters& output_params,
83 const std::string& matched_device_id)); 92 const std::string& matched_device_id));
84 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length)); 93 MOCK_METHOD2(OnStreamCreated, void(int stream_id, int length));
85 MOCK_METHOD1(OnStreamPlaying, void(int stream_id)); 94 MOCK_METHOD1(OnStreamPlaying, void(int stream_id));
86 MOCK_METHOD1(OnStreamPaused, void(int stream_id)); 95 MOCK_METHOD1(OnStreamPaused, void(int stream_id));
87 MOCK_METHOD1(OnStreamError, void(int stream_id)); 96 MOCK_METHOD1(OnStreamError, void(int stream_id));
88 97
98 void OnNotifyStreamCreated(
99 int stream_id,
100 base::SharedMemoryHandle handle,
101 base::SyncSocket::TransitDescriptor socket_descriptor,
102 uint32_t length) {
103 // Maps the shared memory.
104 shared_memory_.reset(new base::SharedMemory(handle, false));
105 CHECK(shared_memory_->Map(length));
106 CHECK(shared_memory_->memory());
107 shared_memory_length_ = length;
108
109 // Create the SyncSocket using the handle.
110 base::SyncSocket::Handle sync_socket_handle =
111 base::SyncSocket::UnwrapHandle(socket_descriptor);
112 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
113
114 // And then delegate the call to the mock method.
115 OnStreamCreated(stream_id, length);
116 }
117
89 private: 118 private:
90 virtual ~MockAudioRendererHost() { 119 virtual ~MockAudioRendererHost() {
91 // Make sure all audio streams have been deleted. 120 // Make sure all audio streams have been deleted.
92 EXPECT_TRUE(audio_entries_.empty()); 121 EXPECT_TRUE(audio_entries_.empty());
93 } 122 }
94 123
95 // This method is used to dispatch IPC messages to the renderer. We intercept 124 // This method is used to dispatch IPC messages to the renderer. We intercept
96 // these messages here and dispatch to our mock methods to verify the 125 // these messages here and dispatch to our mock methods to verify the
97 // conversation between this object and the renderer. 126 // conversation between this object and the renderer.
98 virtual bool Send(IPC::Message* message) { 127 virtual bool Send(IPC::Message* message) {
99 CHECK(message); 128 CHECK(message);
100 129
101 // In this method we dispatch the messages to the according handlers as if 130 // In this method we dispatch the messages to the according handlers as if
102 // we are the renderer. 131 // we are the renderer.
103 bool handled = true; 132 bool handled = true;
104 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message) 133 IPC_BEGIN_MESSAGE_MAP(MockAudioRendererHost, *message)
105 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized, 134 IPC_MESSAGE_HANDLER(AudioMsg_NotifyDeviceAuthorized,
106 OnNotifyDeviceAuthorized) 135 OnNotifyDeviceAuthorized)
107 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamCreated,
108 OnNotifyStreamCreated)
109 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged, 136 IPC_MESSAGE_HANDLER(AudioMsg_NotifyStreamStateChanged,
110 OnNotifyStreamStateChanged) 137 OnNotifyStreamStateChanged)
111 IPC_MESSAGE_UNHANDLED(handled = false) 138 IPC_MESSAGE_UNHANDLED(handled = false)
112 IPC_END_MESSAGE_MAP() 139 IPC_END_MESSAGE_MAP()
113 EXPECT_TRUE(handled); 140 EXPECT_TRUE(handled);
114 141
115 delete message; 142 delete message;
116 return true; 143 return true;
117 } 144 }
118 145
119 void OnNotifyDeviceAuthorized(int stream_id, 146 void OnNotifyDeviceAuthorized(int stream_id,
120 media::OutputDeviceStatus device_status, 147 media::OutputDeviceStatus device_status,
121 const media::AudioParameters& output_params, 148 const media::AudioParameters& output_params,
122 const std::string& matched_device_id) { 149 const std::string& matched_device_id) {
123 OnDeviceAuthorized(stream_id, device_status, output_params, 150 OnDeviceAuthorized(stream_id, device_status, output_params,
124 matched_device_id); 151 matched_device_id);
125 } 152 }
126 153
127 void OnNotifyStreamCreated(
128 int stream_id,
129 base::SharedMemoryHandle handle,
130 base::SyncSocket::TransitDescriptor socket_descriptor,
131 uint32_t length) {
132 // Maps the shared memory.
133 shared_memory_.reset(new base::SharedMemory(handle, false));
134 CHECK(shared_memory_->Map(length));
135 CHECK(shared_memory_->memory());
136 shared_memory_length_ = length;
137
138 // Create the SyncSocket using the handle.
139 base::SyncSocket::Handle sync_socket_handle =
140 base::SyncSocket::UnwrapHandle(socket_descriptor);
141 sync_socket_.reset(new base::SyncSocket(sync_socket_handle));
142
143 // And then delegate the call to the mock method.
144 OnStreamCreated(stream_id, length);
145 }
146
147 void OnNotifyStreamStateChanged(int stream_id, 154 void OnNotifyStreamStateChanged(int stream_id,
148 media::AudioOutputIPCDelegateState state) { 155 media::AudioOutputIPCDelegateState state) {
149 switch (state) { 156 switch (state) {
150 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING: 157 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PLAYING:
151 OnStreamPlaying(stream_id); 158 OnStreamPlaying(stream_id);
152 break; 159 break;
153 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED: 160 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_PAUSED:
154 OnStreamPaused(stream_id); 161 OnStreamPaused(stream_id);
155 break; 162 break;
156 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR: 163 case media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 base::RunLoop run_loop; 206 base::RunLoop run_loop;
200 media_stream_manager_->audio_output_device_enumerator()->Enumerate( 207 media_stream_manager_->audio_output_device_enumerator()->Enumerate(
201 base::Bind(&WaitForEnumeration, &run_loop)); 208 base::Bind(&WaitForEnumeration, &run_loop));
202 run_loop.Run(); 209 run_loop.Run();
203 210
204 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_, 211 host_ = new MockAudioRendererHost(audio_manager_.get(), &mirroring_manager_,
205 MediaInternals::GetInstance(), 212 MediaInternals::GetInstance(),
206 media_stream_manager_.get(), 213 media_stream_manager_.get(),
207 GetMockSaltCallback()); 214 GetMockSaltCallback());
208 215
216 audio_output_impl_.reset(host_->Init(host_.get()));
217
209 // Simulate IPC channel connected. 218 // Simulate IPC channel connected.
210 host_->set_peer_process_for_testing(base::Process::Current()); 219 host_->set_peer_process_for_testing(base::Process::Current());
211 } 220 }
212 221
213 ~AudioRendererHostTest() override { 222 ~AudioRendererHostTest() override {
214 // Simulate closing the IPC channel and give the audio thread time to close 223 // Simulate closing the IPC channel and give the audio thread time to close
215 // the underlying streams. 224 // the underlying streams.
216 host_->OnChannelClosing(); 225 host_->OnChannelClosing();
217 SyncWithAudioThread(); 226 SyncWithAudioThread();
218 227
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 media::AudioParameters::kAudioCDSampleRate / 10); 263 media::AudioParameters::kAudioCDSampleRate / 10);
255 int session_id = 0; 264 int session_id = 0;
256 if (unified_stream) { 265 if (unified_stream) {
257 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to 266 // Use AudioInputDeviceManager::kFakeOpenSessionId as the session id to
258 // pass the permission check. 267 // pass the permission check.
259 session_id = AudioInputDeviceManager::kFakeOpenSessionId; 268 session_id = AudioInputDeviceManager::kFakeOpenSessionId;
260 } 269 }
261 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id, 270 host_->OnRequestDeviceAuthorization(kStreamId, kRenderFrameId, session_id,
262 device_id, security_origin); 271 device_id, security_origin);
263 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) { 272 if (expected_device_status == media::OUTPUT_DEVICE_STATUS_OK) {
264 host_->OnCreateStream(kStreamId, kRenderFrameId, params); 273 host_->CreateStream(kStreamId, kRenderFrameId, params,
274 base::Bind(&AudioRendererHostTest::CreateCallback,
275 base::Unretained(this)));
265 276
266 // At some point in the future, a corresponding RemoveDiverter() call must 277 // At some point in the future, a corresponding RemoveDiverter() call must
267 // be made. 278 // be made.
268 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull())) 279 EXPECT_CALL(mirroring_manager_, RemoveDiverter(NotNull()))
269 .RetiresOnSaturation(); 280 .RetiresOnSaturation();
270 } 281 }
271 SyncWithAudioThread(); 282 SyncWithAudioThread();
272 } 283 }
273 284
285 void CreateCallback(int stream_id,
286 media::interfaces::AudioOutputStreamPtr stream,
287 mojo::ScopedSharedBufferHandle shared_buffer,
288 mojo::ScopedHandle socket_descriptor) {
289 base::SharedMemoryHandle shared_memory_handle;
290 size_t length;
291 MojoResult pass_shared_memory_result = mojo::edk::PassSharedMemoryHandle(
292 shared_buffer.release().value(), &shared_memory_handle, &length, nullptr );
293
294 if (pass_shared_memory_result != MOJO_RESULT_OK) {
295 LOG(ERROR) << "Failed to pass shared memory. Closing: "
296 << pass_shared_memory_result;
297 return;
298 }
299 mojo::edk::ScopedPlatformHandle platform_handle;
300
301 MojoResult pass_platform_handle_result = mojo::edk::PassWrappedPlatformHandl e(
302 socket_descriptor.release().value(), &platform_handle);
303
304 if (pass_platform_handle_result != MOJO_RESULT_OK) {
305 LOG(ERROR) << "Failed to pass transit descriptor. Closing: "
306 << pass_platform_handle_result;
307 return;
308 }
309
310 base::SyncSocket::TransitDescriptor descriptor;
311 #if defined(OS_WIN)
312 descriptor = platform_handle.release().handle;
313 #else
314 descriptor.fd = platform_handle.release().handle;
315 #endif
316
317 host_->OnNotifyStreamCreated(stream_id, shared_memory_handle, descriptor,
318 length);
319 streams_[stream_id] = make_scoped_ptr(
320 new media::interfaces::AudioOutputStreamPtr(std::move(stream)));
321
322 }
323
324
274 void Close() { 325 void Close() {
275 // Send a message to AudioRendererHost to tell it we want to close the 326 // Send a message to AudioRendererHost to tell it we want to close the
276 // stream. 327 // stream.
277 host_->OnCloseStream(kStreamId); 328 host_->OnCloseStream(kStreamId);
278 SyncWithAudioThread(); 329 SyncWithAudioThread();
279 } 330 }
280 331
281 void Play() { 332 void Play() {
282 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId)); 333 EXPECT_CALL(*host_.get(), OnStreamPlaying(kStreamId));
283 host_->OnPlayStream(kStreamId); 334 host_->OnPlayStream(kStreamId);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 void SyncWithAudioThread() { 368 void SyncWithAudioThread() {
318 base::RunLoop().RunUntilIdle(); 369 base::RunLoop().RunUntilIdle();
319 370
320 base::RunLoop run_loop; 371 base::RunLoop run_loop;
321 audio_manager_->GetTaskRunner()->PostTask( 372 audio_manager_->GetTaskRunner()->PostTask(
322 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure())); 373 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
323 run_loop.Run(); 374 run_loop.Run();
324 } 375 }
325 376
326 private: 377 private:
378 typedef std::map<int, std::unique_ptr<media::interfaces::AudioOutputStreamPt r>>
379 ScopedAudioOutputStreamPtrMap;
327 // MediaStreamManager uses a DestructionObserver, so it must outlive the 380 // MediaStreamManager uses a DestructionObserver, so it must outlive the
328 // TestBrowserThreadBundle. 381 // TestBrowserThreadBundle.
329 std::unique_ptr<MediaStreamManager> media_stream_manager_; 382 std::unique_ptr<MediaStreamManager> media_stream_manager_;
330 TestBrowserThreadBundle thread_bundle_; 383 TestBrowserThreadBundle thread_bundle_;
331 std::unique_ptr<media::AudioManager> audio_manager_; 384 std::unique_ptr<media::AudioManager> audio_manager_;
332 MockAudioMirroringManager mirroring_manager_; 385 MockAudioMirroringManager mirroring_manager_;
333 scoped_refptr<MockAudioRendererHost> host_; 386 scoped_refptr<MockAudioRendererHost> host_;
387 std::unique_ptr<AudioOutputImpl> audio_output_impl_;
388 ScopedAudioOutputStreamPtrMap streams_;
334 389
335 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest); 390 DISALLOW_COPY_AND_ASSIGN(AudioRendererHostTest);
336 }; 391 };
337 392
393
338 TEST_F(AudioRendererHostTest, CreateAndClose) { 394 TEST_F(AudioRendererHostTest, CreateAndClose) {
339 Create(); 395 Create();
340 Close(); 396 Close();
341 } 397 }
342 398
343 // Simulate the case where a stream is not properly closed. 399 // Simulate the case where a stream is not properly closed.
344 TEST_F(AudioRendererHostTest, CreateAndShutdown) { 400 TEST_F(AudioRendererHostTest, CreateAndShutdown) {
345 Create(); 401 Create();
346 } 402 }
347 403
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 } 462 }
407 463
408 TEST_F(AudioRendererHostTest, CreateInvalidDevice) { 464 TEST_F(AudioRendererHostTest, CreateInvalidDevice) {
409 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin))); 465 Create(false, kInvalidDeviceId, url::Origin(GURL(kSecurityOrigin)));
410 Close(); 466 Close();
411 } 467 }
412 468
413 // TODO(hclam): Add tests for data conversation in low latency mode. 469 // TODO(hclam): Add tests for data conversation in low latency mode.
414 470
415 } // namespace content 471 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698