Commit b189f387 authored by xians@chromium.org's avatar xians@chromium.org

Refactor the AudioInputDeviceManager by removing the device thread.

With this patch, all the work will be done in the IO thread instead, this is needed by WASAPI.


Review URL: http://codereview.chromium.org/8677012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111641 0039d316-1c4b-4281-b951-d872f2087c98
parent 523e9a05
......@@ -21,37 +21,12 @@ const char AudioInputDeviceManager::kInvalidDeviceId[] = "";
// Starting id for the first capture session.
const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
// Helper function.
static bool IsValidAudioInputDevice(const media::AudioDeviceName& device) {
AudioManager* audio_manager = AudioManager::GetAudioManager();
if (!audio_manager)
return false;
// Get the up-to-date list of devices and verify the device is in the list.
media::AudioDeviceNames device_names;
audio_manager->GetAudioInputDeviceNames(&device_names);
if (!device_names.empty()) {
for (media::AudioDeviceNames::iterator iter = device_names.begin();
iter != device_names.end();
++iter) {
if (iter->device_name == device.device_name &&
iter->unique_id == device.unique_id)
return true;
}
}
// The device wasn't found.
return false;
}
AudioInputDeviceManager::AudioInputDeviceManager()
: audio_input_device_thread_("AudioInputDeviceManagerThread"),
listener_(NULL),
: listener_(NULL),
next_capture_session_id_(kFirstSessionId) {
audio_input_device_thread_.Start();
}
AudioInputDeviceManager::~AudioInputDeviceManager() {
audio_input_device_thread_.Stop();
}
void AudioInputDeviceManager::Register(MediaStreamProviderListener* listener) {
......@@ -70,259 +45,132 @@ void AudioInputDeviceManager::EnumerateDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
audio_input_device_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::EnumerateOnDeviceThread,
base::Unretained(this)));
}
int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Generate a new id for this device.
int audio_input_session_id = next_capture_session_id_++;
audio_input_device_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread,
base::Unretained(this), audio_input_session_id, device));
return audio_input_session_id;
}
void AudioInputDeviceManager::Close(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
audio_input_device_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::CloseOnDeviceThread,
base::Unretained(this), session_id));
}
void AudioInputDeviceManager::Start(
int session_id, AudioInputDeviceManagerEventHandler* event_handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(event_handler);
// Solution for not using MediaStreamManager. This is needed when Start() is
// called without using Open(), we post default device for test purpose.
// And we do not store the info for the kFakeOpenSessionId but return
// the callback immediately.
if (session_id == kFakeOpenSessionId) {
event_handler->OnDeviceStarted(session_id,
AudioManagerBase::kDefaultDeviceId);
return;
}
// If session has been started, post a callback with an error.
if (event_handlers_.find(session_id) != event_handlers_.end()) {
// Session has been started, post a callback with error.
event_handler->OnDeviceStarted(session_id, kInvalidDeviceId);
return;
}
// Add the event handler to the session.
event_handlers_.insert(std::make_pair(session_id, event_handler));
audio_input_device_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::StartOnDeviceThread,
base::Unretained(this), session_id));
}
void AudioInputDeviceManager::Stop(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
audio_input_device_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&AudioInputDeviceManager::StopOnDeviceThread,
base::Unretained(this), session_id));
}
void AudioInputDeviceManager::EnumerateOnDeviceThread() {
DCHECK(IsOnCaptureDeviceThread());
// Get the device list from system.
media::AudioDeviceNames device_names;
AudioManager::GetAudioManager()->GetAudioInputDeviceNames(&device_names);
StreamDeviceInfoArray devices;
StreamDeviceInfoArray* devices = new StreamDeviceInfoArray;
for (media::AudioDeviceNames::iterator it = device_names.begin();
it != device_names.end();
++it) {
devices.push_back(StreamDeviceInfo(kAudioCapture, it->device_name,
devices->push_back(StreamDeviceInfo(kAudioCapture, it->device_name,
it->unique_id, false));
}
// Returns the device list through the listener by posting a task on
// IO thread since MediaStreamManager handles the callback asynchronously.
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioInputDeviceManager::DevicesEnumeratedOnIOThread,
base::Unretained(this), devices));
base::Unretained(this),
devices));
}
void AudioInputDeviceManager::OpenOnDeviceThread(
int session_id, const StreamDeviceInfo& device) {
DCHECK(IsOnCaptureDeviceThread());
int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Generates a new id for this device.
int session_id = next_capture_session_id_++;
DCHECK(devices_.find(session_id) == devices_.end());
media::AudioDeviceName audio_input_device_name;
audio_input_device_name.device_name = device.name;
audio_input_device_name.unique_id = device.device_id;
// Check if the device is valid
if (!IsValidAudioInputDevice(audio_input_device_name)) {
SignalError(session_id, kDeviceNotAvailable);
return;
}
// Add the session_id and device to the list.
// Adds the session_id and device to the list.
devices_[session_id] = audio_input_device_name;
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::OpenedOnIOThread,
base::Unretained(this),
session_id));
}
void AudioInputDeviceManager::CloseOnDeviceThread(int session_id) {
DCHECK(IsOnCaptureDeviceThread());
DCHECK(devices_.find(session_id) != devices_.end());
devices_.erase(session_id);
// Returns the |session_id| through the listener by posting a task on
// IO thread since MediaStreamManager handles the callback asynchronously.
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::ClosedOnIOThread,
base::Bind(&AudioInputDeviceManager::OpenedOnIOThread,
base::Unretained(this),
session_id));
}
void AudioInputDeviceManager::StartOnDeviceThread(const int session_id) {
DCHECK(IsOnCaptureDeviceThread());
// Get the up-to-date device enumeration list from the OS and find out
// the unique id of the device.
std::string device_id = kInvalidDeviceId;
AudioInputDeviceMap::const_iterator it = devices_.find(session_id);
if (it != devices_.end()) {
media::AudioDeviceNames device_names;
AudioManager::GetAudioManager()->GetAudioInputDeviceNames(&device_names);
if (!device_names.empty()) {
int index = 0;
for (media::AudioDeviceNames::iterator iter = device_names.begin();
iter != device_names.end();
++iter, ++index) {
if (iter->device_name == it->second.device_name &&
iter->unique_id == it->second.unique_id) {
// Found the device.
device_id = iter->unique_id;
break;
}
}
}
}
// Posts the index to AudioInputRenderHost through the event handler.
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::StartedOnIOThread,
base::Unretained(this),
session_id,
device_id));
}
void AudioInputDeviceManager::StopOnDeviceThread(int session_id) {
DCHECK(IsOnCaptureDeviceThread());
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::StoppedOnIOThread,
base::Unretained(this),
session_id));
return session_id;
}
void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
const StreamDeviceInfoArray& devices) {
void AudioInputDeviceManager::Close(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (listener_)
listener_->DevicesEnumerated(kAudioCapture, devices);
}
DCHECK(listener_);
void AudioInputDeviceManager::OpenedOnIOThread(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (listener_)
listener_->Opened(kAudioCapture, session_id);
}
if (devices_.find(session_id) != devices_.end())
devices_.erase(session_id);
void AudioInputDeviceManager::ClosedOnIOThread(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Checks if the device has been stopped, if not, send stop signal.
EventHandlerMap::iterator it = event_handlers_.find(session_id);
if (it != event_handlers_.end()) {
// The device hasn't been stopped, send stop signal.
it->second->OnDeviceStopped(session_id);
event_handlers_.erase(session_id);
}
listener_->Closed(kAudioCapture, session_id);
}
void AudioInputDeviceManager::ErrorOnIOThread(int session_id,
MediaStreamProviderError error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (listener_)
listener_->Error(kAudioCapture, session_id, error);
// Posts a callback through the listener on IO thread since
// MediaStreamManager handles the callback asynchronously.
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&AudioInputDeviceManager::ClosedOnIOThread,
base::Unretained(this),
session_id));
}
void AudioInputDeviceManager::StartedOnIOThread(
int session_id, const std::string& device_id) {
void AudioInputDeviceManager::Start(
int session_id, AudioInputDeviceManagerEventHandler* event_handler) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(event_handler);
EventHandlerMap::iterator it = event_handlers_.find(session_id);
if (it == event_handlers_.end())
// Solution for not using MediaStreamManager. This is needed when Start() is
// called without using Open(), we post default device for test purpose.
// And we do not store the info for the kFakeOpenSessionId but return
// the callback immediately.
if (session_id == kFakeOpenSessionId) {
event_handler->OnDeviceStarted(session_id,
AudioManagerBase::kDefaultDeviceId);
return;
}
// Post a callback through the AudioInputRendererHost to notify the renderer
// device has been started.
it->second->OnDeviceStarted(session_id, device_id);
}
// Checks if the device has been opened or not.
std::string device_id = (devices_.find(session_id) == devices_.end()) ?
kInvalidDeviceId : devices_[session_id].unique_id;
void AudioInputDeviceManager::StoppedOnIOThread(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Erase the event handler referenced by the session_id.
event_handlers_.erase(session_id);
}
// Adds the event handler to the session if the session has not been started,
// otherwise post a |kInvalidDeviceId| to indicate that Start() fails.
if (event_handlers_.find(session_id) == event_handlers_.end())
event_handlers_.insert(std::make_pair(session_id, event_handler));
else
device_id = kInvalidDeviceId;
void AudioInputDeviceManager::SignalError(int session_id,
MediaStreamProviderError error) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::ErrorOnIOThread,
base::Unretained(this),
session_id,
error));
// Posts a callback through the AudioInputRendererHost to notify the renderer
// that the device has started.
event_handler->OnDeviceStarted(session_id, device_id);
}
bool AudioInputDeviceManager::IsOnCaptureDeviceThread() const {
return MessageLoop::current() == audio_input_device_thread_.message_loop();
void AudioInputDeviceManager::Stop(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// Erases the event handler referenced by the session_id.
event_handlers_.erase(session_id);
}
void AudioInputDeviceManager::UnregisterEventHandler(int session_id) {
void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
StreamDeviceInfoArray* devices) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
event_handlers_.erase(session_id);
// Ensures that |devices| gets deleted on exit.
scoped_ptr<StreamDeviceInfoArray> devices_array(devices);
if (listener_)
listener_->DevicesEnumerated(kAudioCapture, *devices_array);
}
bool AudioInputDeviceManager::HasEventHandler(int session_id) {
void AudioInputDeviceManager::OpenedOnIOThread(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
return event_handlers_.find(session_id) != event_handlers_.end();
if (listener_)
listener_->Opened(kAudioCapture, session_id);
}
MessageLoop* AudioInputDeviceManager::message_loop() {
return audio_input_device_thread_.message_loop();
void AudioInputDeviceManager::ClosedOnIOThread(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
if (listener_)
listener_->Closed(kAudioCapture, session_id);
}
} // namespace media_stream
......@@ -7,8 +7,7 @@
// browser IO thread, handles queries like enumerate/open/close from
// MediaStreamManager and start/stop from AudioInputRendererHost.
// All the queries come from the IO thread, while the work to enumerate devices
// is done on its own thread.
// All the queries and work are handled on the IO thread.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_DEVICE_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_DEVICE_MANAGER_H_
......@@ -52,46 +51,17 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// Stop the device referenced by the session id.
void Stop(int session_id);
// Function used for testing to mock platform dependent device code.
MessageLoop* message_loop();
private:
// Executed on audio_input_device_thread_.
void EnumerateOnDeviceThread();
void OpenOnDeviceThread(int session_id, const StreamDeviceInfo& device);
void CloseOnDeviceThread(int session_id);
void StartOnDeviceThread(int session_id);
void StopOnDeviceThread(int session_id);
// Executed on IO thread to call Listener.
void DevicesEnumeratedOnIOThread(const StreamDeviceInfoArray& devices);
void DevicesEnumeratedOnIOThread(StreamDeviceInfoArray* devices);
void OpenedOnIOThread(int session_id);
void ClosedOnIOThread(int session_id);
void ErrorOnIOThread(int session_id, MediaStreamProviderError error);
// Executed on IO thread to call the event handler.
void StartedOnIOThread(int session_id, const std::string& device_id);
void StoppedOnIOThread(int session_id);
// Executed on audio_input_device_thread_ to make sure
// MediaStreamProviderListener is called from IO thread.
void SignalError(int session_id, MediaStreamProviderError error);
// Helpers.
bool IsOnCaptureDeviceThread() const;
void UnregisterEventHandler(int session_id);
bool HasEventHandler(int session_id);
// Thread for all calls to AudioInputDeviceManager.
base::Thread audio_input_device_thread_;
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int next_capture_session_id_;
typedef std::map<int, AudioInputDeviceManagerEventHandler*> EventHandlerMap;
EventHandlerMap event_handlers_;
// Only accessed from audio_input_device_thread_.
typedef std::map<int, media::AudioDeviceName> AudioInputDeviceMap;
AudioInputDeviceMap devices_;
......
......@@ -53,13 +53,30 @@ class MockAudioInputDeviceManagerListener
class MockAudioInputDeviceManagerEventHandler
: public AudioInputDeviceManagerEventHandler {
public:
MockAudioInputDeviceManagerEventHandler() {}
explicit MockAudioInputDeviceManagerEventHandler(MessageLoop* message_loop)
: message_loop_(message_loop) {}
virtual ~MockAudioInputDeviceManagerEventHandler() {}
MOCK_METHOD2(OnDeviceStarted, void(int, const std::string&));
MOCK_METHOD1(OnDeviceStopped, void(int));
MOCK_METHOD2(DeviceStarted, void(int, const std::string&));
MOCK_METHOD1(DeviceStopped, void(int));
virtual void OnDeviceStarted(int session_id,
const std::string& device_id) {
message_loop_->PostTask(
FROM_HERE, base::Bind(
&MockAudioInputDeviceManagerEventHandler::DeviceStarted,
base::Unretained(this), session_id, device_id));
}
virtual void OnDeviceStopped(int session_id) {
message_loop_->PostTask(
FROM_HERE, base::Bind(
&MockAudioInputDeviceManagerEventHandler::DeviceStopped,
base::Unretained(this), session_id));
}
private:
MessageLoop* message_loop_;
DISALLOW_COPY_AND_ASSIGN(MockAudioInputDeviceManagerEventHandler);
};
......@@ -94,12 +111,13 @@ class AudioInputDeviceManagerTest: public testing::Test {
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
manager_->Register(audio_input_listener_.get());
// Get the enumerated device list from the AudioInputDeviceManager.
// Gets the enumerated device list from the AudioInputDeviceManager.
manager_->EnumerateDevices();
EXPECT_CALL(*audio_input_listener_, DevicesEnumerated(_))
.Times(1);
// Sync up the threads to make sure we get the list.
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
virtual void TearDown() {
......@@ -107,29 +125,6 @@ class AudioInputDeviceManagerTest: public testing::Test {
io_thread_.reset();
}
// Called on the AudioInputDeviceManager thread.
static void PostQuitMessageLoop(MessageLoop* message_loop) {
message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}
// Called on the main thread.
static void PostQuitOnAudioInputDeviceManagerThread(
MessageLoop* message_loop, AudioInputDeviceManager* manager) {
manager->message_loop()->PostTask(
FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop));
}
// SyncWithAudioInputDeviceManagerThread() waits until all pending tasks on
// the audio_input_device_manager thread are executed while also processing
// pending task in message_loop_ on the current thread.
void SyncWithAudioInputDeviceManagerThread() {
message_loop_->PostTask(
FROM_HERE,
base::Bind(&PostQuitOnAudioInputDeviceManagerThread,
message_loop_.get(),
manager_.get()));
message_loop_->Run();
}
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<AudioInputDeviceManager> manager_;
......@@ -139,7 +134,7 @@ class AudioInputDeviceManagerTest: public testing::Test {
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManagerTest);
};
// Test the devices can be opened and closed.
// Opens and closes the devices.
TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
if (!CanRunAudioInputDeviceTests())
return;
......@@ -148,7 +143,7 @@ TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
for (StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
iter != audio_input_listener_->devices_.end(); ++iter) {
// Open/close the devices.
// Opens/closes the devices.
int session_id = manager_->Open(*iter);
manager_->Close(session_id);
......@@ -157,11 +152,13 @@ TEST_F(AudioInputDeviceManagerTest, OpenAndCloseDevice) {
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, session_id))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
}
// Open multiple devices at one time and close them later.
// Opens multiple devices at one time and closes them later.
TEST_F(AudioInputDeviceManagerTest, OpenMultipleDevices) {
if (!CanRunAudioInputDeviceTests())
return;
......@@ -171,21 +168,23 @@ TEST_F(AudioInputDeviceManagerTest, OpenMultipleDevices) {
const int kDeviceSize = audio_input_listener_->devices_.size();
scoped_array<int> session_id(new int[kDeviceSize]);
// Open the devices in a loop.
// Opens the devices in a loop.
for (StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
iter != audio_input_listener_->devices_.end(); ++iter, ++index) {
// Open the devices.
// Opens the devices.
session_id[index] = manager_->Open(*iter);
// Expected mock call with expected return value.
// Expected mock call with expected returned value.
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture,
session_id[index]))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
// Check if the session_ids are unique
// Checks if the session_ids are unique.
for (int i = 0; i < kDeviceSize - 1; ++i) {
for (int k = i+1; k < kDeviceSize; ++k) {
EXPECT_TRUE(session_id[i] != session_id[k]);
......@@ -193,15 +192,17 @@ TEST_F(AudioInputDeviceManagerTest, OpenMultipleDevices) {
}
for (int i = 0; i < kDeviceSize; ++i) {
// Close the devices.
// Closes the devices.
manager_->Close(session_id[i]);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, session_id[i]))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
}
// Try to open a non-existing device.
// Opens a non-existing device.
TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
if (!CanRunAudioInputDeviceTests())
return;
......@@ -212,42 +213,21 @@ TEST_F(AudioInputDeviceManagerTest, OpenNotExistingDevice) {
std::string device_id("id_doesnt_exist");
StreamDeviceInfo dummy_device(stream_type, device_name, device_id, false);
// This should fail and trigger error code 'kDeviceNotAvailable'.
int session_id = manager_->Open(dummy_device);
EXPECT_CALL(*audio_input_listener_, Error(_, session_id, kDeviceNotAvailable))
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, session_id))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
}
// Try open an invalid device.
TEST_F(AudioInputDeviceManagerTest, OpenInvalidDevice) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
MediaStreamType stream_type = kAudioCapture;
std::string device_name;
std::string device_id;
device_name = audio_input_listener_->devices_.front().name;
device_id = "wrong_id";
StreamDeviceInfo invalid_device(stream_type, device_name, device_id, false);
// This should fail and trigger error code 'kDeviceNotAvailable'.
int session_id = manager_->Open(invalid_device);
EXPECT_CALL(*audio_input_listener_, Error(_, session_id, kDeviceNotAvailable))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
// Opening default device twice should work.
// Opens default device twice.
TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
// Open/close the default device twice.
// Opens and closes the default device twice.
int first_session_id = manager_->Open(
audio_input_listener_->devices_.front());
int second_session_id = manager_->Open(
......@@ -255,7 +235,7 @@ TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
manager_->Close(first_session_id);
manager_->Close(second_session_id);
// Expected mock calls with expected return values.
// Expected mock calls with expected returned values.
EXPECT_NE(first_session_id, second_session_id);
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, first_session_id))
.Times(1);
......@@ -265,11 +245,13 @@ TEST_F(AudioInputDeviceManagerTest, OpenDeviceTwice) {
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, second_session_id))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
// Waits for the callback.
message_loop_->RunAllPending();
}
// Test the Start and Close function after opening the devices.
TEST_F(AudioInputDeviceManagerTest, StartAndStopDevice) {
// Starts and closes the sessions after opening the devices.
TEST_F(AudioInputDeviceManagerTest, StartAndStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
......@@ -278,38 +260,41 @@ TEST_F(AudioInputDeviceManagerTest, StartAndStopDevice) {
const int kDeviceSize = audio_input_listener_->devices_.size();
scoped_array<int> session_id(new int[kDeviceSize]);
// Create the EventHandler for the sessions.
// Creates the EventHandler for the sessions.
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
audio_input_event_handler(new MockAudioInputDeviceManagerEventHandler());
audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
// Loop through the devices, and Open/start/stop/close each device.
// Loops through the devices and calls Open()/Start()/Stop()/Close() for
// each device.
for (StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
iter != audio_input_listener_->devices_.end(); ++iter, ++index) {
// Note that no stop device notification for Event Handler as we have
// Note that no DeviceStopped() notification for Event Handler as we have
// stopped the device before calling close.
// Open/start/stop/close the device.
session_id[index] = manager_->Open(*iter);
manager_->Start(session_id[index], audio_input_event_handler.get());
manager_->Stop(session_id[index]);
manager_->Close(session_id[index]);
// Expected mock calls with expected return values.
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture,
session_id[index]))
.Times(1);
message_loop_->RunAllPending();
manager_->Start(session_id[index], audio_input_event_handler.get());
EXPECT_CALL(*audio_input_event_handler,
OnDeviceStarted(session_id[index], iter->device_id))
DeviceStarted(session_id[index], iter->device_id))
.Times(1);
message_loop_->RunAllPending();
manager_->Stop(session_id[index]);
manager_->Close(session_id[index]);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture,
session_id[index]))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
message_loop_->RunAllPending();
}
}
// Test the behavior of calling Close without calling Stop.
TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopDevice) {
// Tests the behavior of calling Close() without calling Stop().
TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopSession) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
......@@ -318,40 +303,43 @@ TEST_F(AudioInputDeviceManagerTest, CloseWithoutStopDevice) {
const int kDeviceSize = audio_input_listener_->devices_.size();
scoped_array<int> session_id(new int[kDeviceSize]);
// Create the EventHandlers for the sessions.
// Creates the EventHandlers for the sessions.
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
audio_input_event_handler(new MockAudioInputDeviceManagerEventHandler());
audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
// Loop through the devices, and open/start/close the devices.
// Loop through the devices, and calls Open()/Start()/Close() for the devices.
// Note that we do not call stop.
for (StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
iter != audio_input_listener_->devices_.end(); ++iter, ++index) {
// Open/start/close the device.
// Calls Open()/Start()/Close() for each device.
session_id[index] = manager_->Open(*iter);
manager_->Start(session_id[index], audio_input_event_handler.get());
manager_->Close(session_id[index]);
// Expected mock calls with expected return values.
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture,
session_id[index]))
.Times(1);
message_loop_->RunAllPending();
manager_->Start(session_id[index], audio_input_event_handler.get());
EXPECT_CALL(*audio_input_event_handler,
OnDeviceStarted(session_id[index], iter->device_id))
DeviceStarted(session_id[index], iter->device_id))
.Times(1);
message_loop_->RunAllPending();
// Event Handler should get a stop device notification as no stop is called
// before closing the device.
manager_->Close(session_id[index]);
EXPECT_CALL(*audio_input_event_handler,
OnDeviceStopped(session_id[index]))
DeviceStopped(session_id[index]))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture,
session_id[index]))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
message_loop_->RunAllPending();
}
}
// Should be able to start the default device twice.
// Starts the same device twice.
TEST_F(AudioInputDeviceManagerTest, StartDeviceTwice) {
if (!CanRunAudioInputDeviceTests())
return;
......@@ -359,45 +347,123 @@ TEST_F(AudioInputDeviceManagerTest, StartDeviceTwice) {
// Create one EventHandler for each session.
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
first_audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler());
first_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
second_audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler());
second_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
// Open the default device twice.
StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
int first_session_id = manager_->Open(*iter);
int second_session_id = manager_->Open(*iter);
// Start/stop/close the default device twice.
manager_->Start(first_session_id, first_audio_input_event_handler.get());
manager_->Start(second_session_id, second_audio_input_event_handler.get());
manager_->Stop(first_session_id);
manager_->Stop(second_session_id);
manager_->Close(first_session_id);
manager_->Close(second_session_id);
// Expected mock calls with expected return values.
EXPECT_NE(first_session_id, second_session_id);
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, first_session_id))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, second_session_id))
.Times(1);
EXPECT_CALL(*first_audio_input_event_handler,
OnDeviceStarted(first_session_id,
message_loop_->RunAllPending();
// Calls Start()/Stop()/Close() for the default device twice.
manager_->Start(first_session_id, first_event_handler.get());
manager_->Start(second_session_id, second_event_handler.get());
EXPECT_CALL(*first_event_handler,
DeviceStarted(first_session_id,
AudioManagerBase::kDefaultDeviceId))
.Times(1);
EXPECT_CALL(*second_audio_input_event_handler,
OnDeviceStarted(second_session_id,
EXPECT_CALL(*second_event_handler,
DeviceStarted(second_session_id,
AudioManagerBase::kDefaultDeviceId))
.Times(1);
message_loop_->RunAllPending();
manager_->Stop(first_session_id);
manager_->Stop(second_session_id);
manager_->Close(first_session_id);
manager_->Close(second_session_id);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, first_session_id))
.Times(1);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, second_session_id))
.Times(1);
SyncWithAudioInputDeviceManagerThread();
message_loop_->RunAllPending();
}
// Starts an invalid session.
TEST_F(AudioInputDeviceManagerTest, StartInvalidSession) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
// Creates the EventHandlers for the sessions.
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
// Opens the first device.
StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
int session_id = manager_->Open(*iter);
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, session_id))
.Times(1);
message_loop_->RunAllPending();
// Starts a non-opened device.
// This should fail and trigger error code 'kDeviceNotAvailable'.
int invalid_session_id = session_id + 1;
manager_->Start(invalid_session_id, audio_input_event_handler.get());
EXPECT_CALL(*audio_input_event_handler,
DeviceStarted(invalid_session_id,
AudioInputDeviceManager::kInvalidDeviceId))
.Times(1);
message_loop_->RunAllPending();
manager_->Close(session_id);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, session_id))
.Times(1);
message_loop_->RunAllPending();
}
// Starts a session twice, the first time should succeed, while the second
// time should fail.
TEST_F(AudioInputDeviceManagerTest, StartSessionTwice) {
if (!CanRunAudioInputDeviceTests())
return;
InSequence s;
// Creates the EventHandlers for the sessions.
scoped_ptr<MockAudioInputDeviceManagerEventHandler>
audio_input_event_handler(
new MockAudioInputDeviceManagerEventHandler(message_loop_.get()));
// Opens the first device.
StreamDeviceInfoArray::const_iterator iter =
audio_input_listener_->devices_.begin();
int session_id = manager_->Open(*iter);
EXPECT_CALL(*audio_input_listener_, Opened(kAudioCapture, session_id))
.Times(1);
message_loop_->RunAllPending();
// Starts the session, it should succeed.
manager_->Start(session_id, audio_input_event_handler.get());
EXPECT_CALL(*audio_input_event_handler,
DeviceStarted(session_id,
AudioManagerBase::kDefaultDeviceId))
.Times(1);
message_loop_->RunAllPending();
// Starts the session for the second time, it should fail.
manager_->Start(session_id, audio_input_event_handler.get());
EXPECT_CALL(*audio_input_event_handler,
DeviceStarted(session_id,
AudioInputDeviceManager::kInvalidDeviceId))
.Times(1);
manager_->Stop(session_id);
manager_->Close(session_id);
EXPECT_CALL(*audio_input_listener_, Closed(kAudioCapture, session_id))
.Times(1);
message_loop_->RunAllPending();
}
} // namespace media_stream
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment