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 @@
#include "media/base/channel_layout.h"
#include "media/base/scoped_histogram_timer.h"
#if defined(OS_CHROMEOS)
#include "chromeos/audio/cras_audio_handler.h"
#endif
namespace content {
const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
......@@ -28,6 +32,9 @@ AudioInputDeviceManager::AudioInputDeviceManager(
: listener_(NULL),
next_capture_session_id_(kFirstSessionId),
use_fake_device_(false),
#if defined(OS_CHROMEOS)
keyboard_mic_streams_count_(0),
#endif
audio_manager_(audio_manager) {
}
......@@ -109,6 +116,43 @@ bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
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(
MediaStreamType stream_type) {
SCOPED_UMA_HISTOGRAM_TIMER(
......@@ -250,4 +294,13 @@ void AudioInputDeviceManager::GetFakeDeviceNames(
kFakeDeviceId2));
}
#if defined(OS_CHROMEOS)
void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
bool active) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
chromeos::CrasAudioHandler::Get()->SetKeyboardMicActive(active);
}
#endif
} // namespace content
......@@ -56,6 +56,17 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
void UseFakeDevice();
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:
// Used by the unittests to get a list of fake devices.
friend class MediaStreamDispatcherHostTest;
......@@ -87,12 +98,22 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// device is found, it will return devices_.end().
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.
MediaStreamProviderListener* listener_;
int next_capture_session_id_;
bool use_fake_device_;
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.
// The message loop of media stream device thread that this object runs on.
......
......@@ -56,12 +56,16 @@ struct AudioInputRendererHost::AudioEntry {
// Set to true after we called Close() for the controller.
bool pending_close;
// If this entry's layout has a keyboard mic channel.
bool has_keyboard_mic_;
};
AudioInputRendererHost::AudioEntry::AudioEntry()
: stream_id(0),
shared_memory_segment_count(0),
pending_close(false) {
pending_close(false),
has_keyboard_mic_(false) {
}
AudioInputRendererHost::AudioEntry::~AudioEntry() {}
......@@ -273,6 +277,32 @@ void AudioInputRendererHost::OnCreateStream(
const AudioInputHostMsg_CreateStream_Config& config) {
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;
oss << "[stream_id=" << stream_id << "] "
<< "AIRH::OnCreateStream(render_view_id=" << render_view_id
......@@ -282,6 +312,7 @@ void AudioInputRendererHost::OnCreateStream(
// media::AudioParameters is validated in the deserializer.
if (LookupById(stream_id) != NULL) {
SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS);
MaybeUnregisterKeyboardMicStream(config);
return;
}
......@@ -305,6 +336,7 @@ void AudioInputRendererHost::OnCreateStream(
SendErrorMessage(stream_id, PERMISSION_DENIED);
DLOG(WARNING) << "No permission has been granted to input stream with "
<< "session_id=" << session_id;
MaybeUnregisterKeyboardMicStream(config);
return;
}
......@@ -329,6 +361,7 @@ void AudioInputRendererHost::OnCreateStream(
!entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) {
// If creation of shared memory failed then send an error message.
SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED);
MaybeUnregisterKeyboardMicStream(config);
return;
}
......@@ -337,6 +370,7 @@ void AudioInputRendererHost::OnCreateStream(
if (!writer->Init()) {
SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED);
MaybeUnregisterKeyboardMicStream(config);
return;
}
......@@ -369,6 +403,7 @@ void AudioInputRendererHost::OnCreateStream(
if (!entry->controller.get()) {
SendErrorMessage(stream_id, STREAM_CREATE_ERROR);
MaybeUnregisterKeyboardMicStream(config);
return;
}
......@@ -461,6 +496,13 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
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.
scoped_ptr<AudioEntry> entry_deleter(entry);
......@@ -502,4 +544,15 @@ AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
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
......@@ -136,12 +136,20 @@ class CONTENT_EXPORT AudioInputRendererHost
// 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
// 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.
// Upon success/failure, the peer is notified via the
// NotifyStreamCreated message.
void OnCreateStream(int stream_id,
void DoCreateStream(int stream_id,
int render_view_id,
int session_id,
const AudioInputHostMsg_CreateStream_Config& config);
......@@ -196,6 +204,11 @@ class CONTENT_EXPORT AudioInputRendererHost
// event is received.
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.
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