Commit 3a955110 authored by grunell's avatar grunell Committed by Commit bot

Activate and inactivate keyboard mic on ChromeOS.

Based on keyboard layout for opened and closed streams, keep count of those containing keyboard mic. Activate mic for first such stream, inactivate when last one is closed.

BUG=345296

Review URL: https://codereview.chromium.org/599443003

Cr-Commit-Position: refs/heads/master@{#296217}
parent 74595364
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#include "media/base/channel_layout.h" #include "media/base/channel_layout.h"
#include "media/base/scoped_histogram_timer.h" #include "media/base/scoped_histogram_timer.h"
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
#endif
namespace content { namespace content {
const int AudioInputDeviceManager::kFakeOpenSessionId = 1; const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
...@@ -28,6 +32,9 @@ AudioInputDeviceManager::AudioInputDeviceManager( ...@@ -28,6 +32,9 @@ AudioInputDeviceManager::AudioInputDeviceManager(
: listener_(NULL), : listener_(NULL),
next_capture_session_id_(kFirstSessionId), next_capture_session_id_(kFirstSessionId),
use_fake_device_(false), use_fake_device_(false),
#if defined(OS_CHROMEOS)
keyboard_mic_streams_count_(0),
#endif
audio_manager_(audio_manager) { audio_manager_(audio_manager) {
} }
...@@ -109,6 +116,43 @@ bool AudioInputDeviceManager::ShouldUseFakeDevice() const { ...@@ -109,6 +116,43 @@ bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
return use_fake_device_; return use_fake_device_;
} }
#if defined(OS_CHROMEOS)
void AudioInputDeviceManager::RegisterKeyboardMicStream(
const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
++keyboard_mic_streams_count_;
if (keyboard_mic_streams_count_ == 1) {
BrowserThread::PostTaskAndReply(
BrowserThread::UI,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
this,
true),
callback);
} else {
callback.Run();
}
}
void AudioInputDeviceManager::UnregisterKeyboardMicStream() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
--keyboard_mic_streams_count_;
DCHECK_GE(keyboard_mic_streams_count_, 0);
if (keyboard_mic_streams_count_ == 0) {
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
base::Bind(
&AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread,
this,
false));
}
}
#endif
void AudioInputDeviceManager::EnumerateOnDeviceThread( void AudioInputDeviceManager::EnumerateOnDeviceThread(
MediaStreamType stream_type) { MediaStreamType stream_type) {
SCOPED_UMA_HISTOGRAM_TIMER( SCOPED_UMA_HISTOGRAM_TIMER(
...@@ -250,4 +294,13 @@ void AudioInputDeviceManager::GetFakeDeviceNames( ...@@ -250,4 +294,13 @@ void AudioInputDeviceManager::GetFakeDeviceNames(
kFakeDeviceId2)); kFakeDeviceId2));
} }
#if defined(OS_CHROMEOS)
void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
bool active) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
}
#endif
} // namespace content } // namespace content
...@@ -56,6 +56,17 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider { ...@@ -56,6 +56,17 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
void UseFakeDevice(); void UseFakeDevice();
bool ShouldUseFakeDevice() const; bool ShouldUseFakeDevice() const;
#if defined(OS_CHROMEOS)
// Registers and unregisters that a stream using keyboard mic has been opened
// or closed. Keeps count of how many such streams are open and activates and
// inactivates the keyboard mic accordingly. The (in)activation is done on the
// UI thread and for the register case a callback must therefor be provided
// which is called when activated.
// Called on the IO thread.
void RegisterKeyboardMicStream(const base::Closure& callback);
void UnregisterKeyboardMicStream();
#endif
private: private:
// Used by the unittests to get a list of fake devices. // Used by the unittests to get a list of fake devices.
friend class MediaStreamDispatcherHostTest; friend class MediaStreamDispatcherHostTest;
...@@ -87,12 +98,22 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider { ...@@ -87,12 +98,22 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// device is found, it will return devices_.end(). // device is found, it will return devices_.end().
StreamDeviceList::iterator GetDevice(int session_id); StreamDeviceList::iterator GetDevice(int session_id);
#if defined(OS_CHROMEOS)
// Calls Cras audio handler and sets keyboard mic active status.
void SetKeyboardMicStreamActiveOnUIThread(bool active);
#endif
// Only accessed on Browser::IO thread. // Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_; MediaStreamProviderListener* listener_;
int next_capture_session_id_; int next_capture_session_id_;
bool use_fake_device_; bool use_fake_device_;
StreamDeviceList devices_; StreamDeviceList devices_;
#if defined(OS_CHROMEOS)
// Keeps count of how many streams are using keyboard mic.
int keyboard_mic_streams_count_;
#endif
media::AudioManager* const audio_manager_; // Weak. media::AudioManager* const audio_manager_; // Weak.
// The message loop of media stream device thread that this object runs on. // The message loop of media stream device thread that this object runs on.
......
...@@ -56,12 +56,16 @@ struct AudioInputRendererHost::AudioEntry { ...@@ -56,12 +56,16 @@ struct AudioInputRendererHost::AudioEntry {
// Set to true after we called Close() for the controller. // Set to true after we called Close() for the controller.
bool pending_close; bool pending_close;
// If this entry's layout has a keyboard mic channel.
bool has_keyboard_mic_;
}; };
AudioInputRendererHost::AudioEntry::AudioEntry() AudioInputRendererHost::AudioEntry::AudioEntry()
: stream_id(0), : stream_id(0),
shared_memory_segment_count(0), shared_memory_segment_count(0),
pending_close(false) { pending_close(false),
has_keyboard_mic_(false) {
} }
AudioInputRendererHost::AudioEntry::~AudioEntry() {} AudioInputRendererHost::AudioEntry::~AudioEntry() {}
...@@ -273,6 +277,32 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -273,6 +277,32 @@ void AudioInputRendererHost::OnCreateStream(
const AudioInputHostMsg_CreateStream_Config& config) { const AudioInputHostMsg_CreateStream_Config& config) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
#if defined(OS_CHROMEOS)
if (config.params.channel_layout() ==
media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
media_stream_manager_->audio_input_device_manager()
->RegisterKeyboardMicStream(
base::Bind(&AudioInputRendererHost::DoCreateStream,
this,
stream_id,
render_view_id,
session_id,
config));
} else {
DoCreateStream(stream_id, render_view_id, session_id, config);
}
#else
DoCreateStream(stream_id, render_view_id, session_id, config);
#endif
}
void AudioInputRendererHost::DoCreateStream(
int stream_id,
int render_view_id,
int session_id,
const AudioInputHostMsg_CreateStream_Config& config) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::ostringstream oss; std::ostringstream oss;
oss << "[stream_id=" << stream_id << "] " oss << "[stream_id=" << stream_id << "] "
<< "AIRH::OnCreateStream(render_view_id=" << render_view_id << "AIRH::OnCreateStream(render_view_id=" << render_view_id
...@@ -282,6 +312,7 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -282,6 +312,7 @@ void AudioInputRendererHost::OnCreateStream(
// media::AudioParameters is validated in the deserializer. // media::AudioParameters is validated in the deserializer.
if (LookupById(stream_id) != NULL) { if (LookupById(stream_id) != NULL) {
SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS); SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
MaybeUnregisterKeyboardMicStream(config);
return; return;
} }
...@@ -305,6 +336,7 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -305,6 +336,7 @@ void AudioInputRendererHost::OnCreateStream(
SendErrorMessage(stream_id, PERMISSION_DENIED); SendErrorMessage(stream_id, PERMISSION_DENIED);
DLOG(WARNING) << "No permission has been granted to input stream with " DLOG(WARNING) << "No permission has been granted to input stream with "
<< "session_id=" << session_id; << "session_id=" << session_id;
MaybeUnregisterKeyboardMicStream(config);
return; return;
} }
...@@ -329,6 +361,7 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -329,6 +361,7 @@ void AudioInputRendererHost::OnCreateStream(
!entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) { !entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) {
// If creation of shared memory failed then send an error message. // If creation of shared memory failed then send an error message.
SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED); SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED);
MaybeUnregisterKeyboardMicStream(config);
return; return;
} }
...@@ -337,6 +370,7 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -337,6 +370,7 @@ void AudioInputRendererHost::OnCreateStream(
if (!writer->Init()) { if (!writer->Init()) {
SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
MaybeUnregisterKeyboardMicStream(config);
return; return;
} }
...@@ -369,6 +403,7 @@ void AudioInputRendererHost::OnCreateStream( ...@@ -369,6 +403,7 @@ void AudioInputRendererHost::OnCreateStream(
if (!entry->controller.get()) { if (!entry->controller.get()) {
SendErrorMessage(stream_id, STREAM_CREATE_ERROR); SendErrorMessage(stream_id, STREAM_CREATE_ERROR);
MaybeUnregisterKeyboardMicStream(config);
return; return;
} }
...@@ -461,6 +496,13 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { ...@@ -461,6 +496,13 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true);
#if defined(OS_CHROMEOS)
if (entry->has_keyboard_mic_) {
media_stream_manager_->audio_input_device_manager()
->UnregisterKeyboardMicStream();
}
#endif
// Delete the entry when this method goes out of scope. // Delete the entry when this method goes out of scope.
scoped_ptr<AudioEntry> entry_deleter(entry); scoped_ptr<AudioEntry> entry_deleter(entry);
...@@ -502,4 +544,15 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController( ...@@ -502,4 +544,15 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
return NULL; return NULL;
} }
void AudioInputRendererHost::MaybeUnregisterKeyboardMicStream(
const AudioInputHostMsg_CreateStream_Config& config) {
#if defined(OS_CHROMEOS)
if (config.params.channel_layout() ==
media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) {
media_stream_manager_->audio_input_device_manager()
->UnregisterKeyboardMicStream();
}
#endif
}
} // namespace content } // namespace content
...@@ -136,12 +136,20 @@ class CONTENT_EXPORT AudioInputRendererHost ...@@ -136,12 +136,20 @@ class CONTENT_EXPORT AudioInputRendererHost
// Audio related IPC message handlers. // Audio related IPC message handlers.
// For ChromeOS: Checks if the stream should contain keyboard mic, if so
// registers to AudioInputDeviceManager. Then calls DoCreateStream.
// For non-ChromeOS: Just calls DoCreateStream.
void OnCreateStream(int stream_id,
int render_view_id,
int session_id,
const AudioInputHostMsg_CreateStream_Config& config);
// Creates an audio input stream with the specified format whose data is // Creates an audio input stream with the specified format whose data is
// consumed by an entity in the render view referenced by |render_view_id|. // consumed by an entity in the render view referenced by |render_view_id|.
// |session_id| is used to find out which device to be used for the stream. // |session_id| is used to find out which device to be used for the stream.
// Upon success/failure, the peer is notified via the // Upon success/failure, the peer is notified via the
// NotifyStreamCreated message. // NotifyStreamCreated message.
void OnCreateStream(int stream_id, void DoCreateStream(int stream_id,
int render_view_id, int render_view_id,
int session_id, int session_id,
const AudioInputHostMsg_CreateStream_Config& config); const AudioInputHostMsg_CreateStream_Config& config);
...@@ -196,6 +204,11 @@ class CONTENT_EXPORT AudioInputRendererHost ...@@ -196,6 +204,11 @@ class CONTENT_EXPORT AudioInputRendererHost
// event is received. // event is received.
AudioEntry* LookupByController(media::AudioInputController* controller); AudioEntry* LookupByController(media::AudioInputController* controller);
// If ChromeOS and |config|'s layout has keyboard mic, unregister in
// AudioInputDeviceManager.
void MaybeUnregisterKeyboardMicStream(
const AudioInputHostMsg_CreateStream_Config& config);
// Used to create an AudioInputController. // Used to create an AudioInputController.
media::AudioManager* audio_manager_; media::AudioManager* audio_manager_;
......
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