Handle the dual microphones and dual cameras cases. Activate the proper microphone when user activates the front or rear camera on basking devices.
BUG=698327 TEST=See the feature spec document in the bug. TBR=dalecurtis@chromium.org Review-Url: https://codereview.chromium.org/2721733003 Cr-Commit-Position: refs/heads/master@{#454933}
This commit is contained in:
@ -135,16 +135,40 @@ void AudioDetailedView::UpdateAudioDevices() {
|
|||||||
output_devices_.clear();
|
output_devices_.clear();
|
||||||
input_devices_.clear();
|
input_devices_.clear();
|
||||||
chromeos::AudioDeviceList devices;
|
chromeos::AudioDeviceList devices;
|
||||||
CrasAudioHandler::Get()->GetAudioDevices(&devices);
|
CrasAudioHandler* audio_handler = CrasAudioHandler::Get();
|
||||||
|
audio_handler->GetAudioDevices(&devices);
|
||||||
|
bool has_dual_internal_mic = audio_handler->HasDualInternalMic();
|
||||||
|
bool is_front_or_rear_mic_active = false;
|
||||||
for (size_t i = 0; i < devices.size(); ++i) {
|
for (size_t i = 0; i < devices.size(); ++i) {
|
||||||
// Don't display keyboard mic or aokr type.
|
// Don't display keyboard mic or aokr type.
|
||||||
if (!devices[i].is_for_simple_usage())
|
if (!devices[i].is_for_simple_usage())
|
||||||
continue;
|
continue;
|
||||||
if (devices[i].is_input)
|
if (devices[i].is_input) {
|
||||||
|
// Do not expose the internal front and rear mic to UI.
|
||||||
|
if (has_dual_internal_mic &&
|
||||||
|
audio_handler->IsFrontOrRearMic(devices[i])) {
|
||||||
|
if (devices[i].active)
|
||||||
|
is_front_or_rear_mic_active = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
input_devices_.push_back(devices[i]);
|
input_devices_.push_back(devices[i]);
|
||||||
else
|
} else {
|
||||||
output_devices_.push_back(devices[i]);
|
output_devices_.push_back(devices[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose the dual internal mics as one device (internal mic) to user.
|
||||||
|
if (has_dual_internal_mic) {
|
||||||
|
// Create stub internal mic entry for UI rendering, which representing
|
||||||
|
// both internal front and rear mics.
|
||||||
|
chromeos::AudioDevice internal_mic;
|
||||||
|
internal_mic.is_input = true;
|
||||||
|
internal_mic.stable_device_id_version = 2;
|
||||||
|
internal_mic.type = chromeos::AUDIO_TYPE_INTERNAL_MIC;
|
||||||
|
internal_mic.active = is_front_or_rear_mic_active;
|
||||||
|
input_devices_.push_back(internal_mic);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateScrollableList();
|
UpdateScrollableList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,8 +214,14 @@ void AudioDetailedView::HandleViewClicked(views::View* view) {
|
|||||||
if (iter == device_map_.end())
|
if (iter == device_map_.end())
|
||||||
return;
|
return;
|
||||||
chromeos::AudioDevice device = iter->second;
|
chromeos::AudioDevice device = iter->second;
|
||||||
CrasAudioHandler::Get()->SwitchToDevice(device, true,
|
CrasAudioHandler* audio_handler = CrasAudioHandler::Get();
|
||||||
CrasAudioHandler::ACTIVATE_BY_USER);
|
if (device.type == chromeos::AUDIO_TYPE_INTERNAL_MIC &&
|
||||||
|
audio_handler->HasDualInternalMic()) {
|
||||||
|
audio_handler->SwitchToFrontOrRearMic();
|
||||||
|
} else {
|
||||||
|
audio_handler->SwitchToDevice(device, true,
|
||||||
|
CrasAudioHandler::ACTIVATE_BY_USER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tray
|
} // namespace tray
|
||||||
|
@ -171,6 +171,7 @@ test("chromeos_unittests") {
|
|||||||
"//crypto:test_support",
|
"//crypto:test_support",
|
||||||
"//dbus:test_support",
|
"//dbus:test_support",
|
||||||
"//google_apis",
|
"//google_apis",
|
||||||
|
"//media/base:video_facing",
|
||||||
"//net",
|
"//net",
|
||||||
"//net:test_support",
|
"//net:test_support",
|
||||||
"//testing/gmock",
|
"//testing/gmock",
|
||||||
|
@ -186,4 +186,16 @@ std::string AudioDevice::ToString() const {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AudioDevice::IsExternalDevice() const {
|
||||||
|
if (!is_for_simple_usage())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (is_input) {
|
||||||
|
return (type != AUDIO_TYPE_INTERNAL_MIC && type != AUDIO_TYPE_FRONT_MIC &&
|
||||||
|
type != AUDIO_TYPE_REAR_MIC);
|
||||||
|
} else {
|
||||||
|
return (type != AUDIO_TYPE_INTERNAL_SPEAKER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chromeos
|
} // namespace chromeos
|
||||||
|
@ -63,6 +63,8 @@ struct CHROMEOS_EXPORT AudioDevice {
|
|||||||
type == AUDIO_TYPE_LINEOUT);
|
type == AUDIO_TYPE_LINEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsExternalDevice() const;
|
||||||
|
|
||||||
bool is_input = false;
|
bool is_input = false;
|
||||||
|
|
||||||
// Id of this audio device. The legacy |id| is assigned to be unique everytime
|
// Id of this audio device. The legacy |id| is assigned to be unique everytime
|
||||||
|
@ -41,7 +41,7 @@ const std::vector<double> kStereoToMono = {0.5, 0.5, 0.5, 0.5};
|
|||||||
// Mixer matrix, [1, 0; 0, 1]
|
// Mixer matrix, [1, 0; 0, 1]
|
||||||
const std::vector<double> kStereoToStereo = {1, 0, 0, 1};
|
const std::vector<double> kStereoToStereo = {1, 0, 0, 1};
|
||||||
|
|
||||||
static CrasAudioHandler* g_cras_audio_handler = NULL;
|
static CrasAudioHandler* g_cras_audio_handler = nullptr;
|
||||||
|
|
||||||
bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) {
|
bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) {
|
||||||
return a.stable_device_id == b.stable_device_id && a.is_input == b.is_input &&
|
return a.stable_device_id == b.stable_device_id && a.is_input == b.is_input &&
|
||||||
@ -111,12 +111,12 @@ void CrasAudioHandler::InitializeForTesting() {
|
|||||||
void CrasAudioHandler::Shutdown() {
|
void CrasAudioHandler::Shutdown() {
|
||||||
CHECK(g_cras_audio_handler);
|
CHECK(g_cras_audio_handler);
|
||||||
delete g_cras_audio_handler;
|
delete g_cras_audio_handler;
|
||||||
g_cras_audio_handler = NULL;
|
g_cras_audio_handler = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool CrasAudioHandler::IsInitialized() {
|
bool CrasAudioHandler::IsInitialized() {
|
||||||
return g_cras_audio_handler != NULL;
|
return g_cras_audio_handler != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@ -127,11 +127,80 @@ CrasAudioHandler* CrasAudioHandler::Get() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::OnVideoCaptureStarted(media::VideoFacingMode facing) {
|
void CrasAudioHandler::OnVideoCaptureStarted(media::VideoFacingMode facing) {
|
||||||
// TODO(jennyz): Switch active audio device according to video facing.
|
// Do nothing if the device doesn't have both front and rear microphones.
|
||||||
|
if (!HasDualInternalMic())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool camera_is_already_on = IsCameraOn();
|
||||||
|
switch (facing) {
|
||||||
|
case media::MEDIA_VIDEO_FACING_USER:
|
||||||
|
front_camera_on_ = true;
|
||||||
|
break;
|
||||||
|
case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
|
||||||
|
rear_camera_on_ = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_IF(WARNING, facing == media::NUM_MEDIA_VIDEO_FACING_MODES)
|
||||||
|
<< "On the device with dual microphone, got video capture "
|
||||||
|
<< "notification with invalid camera facing mode value";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the camera is already on before this notification, don't change active
|
||||||
|
// input. In the case that both cameras are turned on at the same time, we
|
||||||
|
// won't change the active input after the first camera is turned on. We only
|
||||||
|
// support the use case of one camera on at a time. The third party
|
||||||
|
// developer can turn on/off both microphones with extension api if they like
|
||||||
|
// to.
|
||||||
|
if (camera_is_already_on)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the current active input is an external device, keep it.
|
||||||
|
const AudioDevice* active_input = GetDeviceFromId(active_input_node_id_);
|
||||||
|
if (active_input && active_input->IsExternalDevice())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Activate the correct mic for the current active camera.
|
||||||
|
ActivateMicForCamera(facing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::OnVideoCaptureStopped(media::VideoFacingMode facing) {
|
void CrasAudioHandler::OnVideoCaptureStopped(media::VideoFacingMode facing) {
|
||||||
// TODO(jennyz): Switch active audio device according to video facing.
|
// Do nothing if the device doesn't have both front and rear microphones.
|
||||||
|
if (!HasDualInternalMic())
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (facing) {
|
||||||
|
case media::MEDIA_VIDEO_FACING_USER:
|
||||||
|
front_camera_on_ = false;
|
||||||
|
break;
|
||||||
|
case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
|
||||||
|
rear_camera_on_ = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_IF(WARNING, facing == media::NUM_MEDIA_VIDEO_FACING_MODES)
|
||||||
|
<< "On the device with dual microphone, got video capture "
|
||||||
|
<< "notification with invalid camera facing mode value";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not all cameras are turned off, don't change active input. In the case
|
||||||
|
// that both cameras are turned on at the same time before one of them is
|
||||||
|
// stopped, we won't change active input until all of them are stopped.
|
||||||
|
// We only support the use case of one camera on at a time. The third party
|
||||||
|
// developer can turn on/off both microphones with extension api if they like
|
||||||
|
// to.
|
||||||
|
if (IsCameraOn())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the current active input is an external device, keep it.
|
||||||
|
const AudioDevice* active_input = GetDeviceFromId(active_input_node_id_);
|
||||||
|
if (active_input && active_input->IsExternalDevice())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Switch to front mic properly.
|
||||||
|
DeviceActivateType activated_by =
|
||||||
|
HasExternalDevice(true) ? ACTIVATE_BY_USER : ACTIVATE_BY_PRIORITY;
|
||||||
|
SwitchToDevice(*GetDeviceByType(AUDIO_TYPE_FRONT_MIC), true, activated_by);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::AddAudioObserver(AudioObserver* observer) {
|
void CrasAudioHandler::AddAudioObserver(AudioObserver* observer) {
|
||||||
@ -143,7 +212,7 @@ void CrasAudioHandler::RemoveAudioObserver(AudioObserver* observer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CrasAudioHandler::HasKeyboardMic() {
|
bool CrasAudioHandler::HasKeyboardMic() {
|
||||||
return GetKeyboardMic() != NULL;
|
return GetKeyboardMic() != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrasAudioHandler::IsOutputMuted() {
|
bool CrasAudioHandler::IsOutputMuted() {
|
||||||
@ -218,9 +287,10 @@ uint64_t CrasAudioHandler::GetPrimaryActiveInputNode() const {
|
|||||||
|
|
||||||
void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const {
|
void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const {
|
||||||
device_list->clear();
|
device_list->clear();
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it)
|
const AudioDevice& device = item.second;
|
||||||
device_list->push_back(it->second);
|
device_list->push_back(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CrasAudioHandler::GetPrimaryActiveOutputDevice(AudioDevice* device) const {
|
bool CrasAudioHandler::GetPrimaryActiveOutputDevice(AudioDevice* device) const {
|
||||||
@ -347,10 +417,8 @@ void CrasAudioHandler::SetActiveDevices(const AudioDeviceList& devices,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::SwapInternalSpeakerLeftRightChannel(bool swap) {
|
void CrasAudioHandler::SwapInternalSpeakerLeftRightChannel(bool swap) {
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end();
|
const AudioDevice& device = item.second;
|
||||||
++it) {
|
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (!device.is_input && device.type == AUDIO_TYPE_INTERNAL_SPEAKER) {
|
if (!device.is_input && device.type == AUDIO_TYPE_INTERNAL_SPEAKER) {
|
||||||
chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->SwapLeftRight(
|
chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->SwapLeftRight(
|
||||||
device.id, swap);
|
device.id, swap);
|
||||||
@ -387,10 +455,8 @@ bool CrasAudioHandler::has_alternative_output() const {
|
|||||||
|
|
||||||
void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) {
|
void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) {
|
||||||
// Set all active devices to the same volume.
|
// Set all active devices to the same volume.
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end();
|
const AudioDevice& device = item.second;
|
||||||
it++) {
|
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (!device.is_input && device.active)
|
if (!device.is_input && device.active)
|
||||||
SetOutputNodeVolumePercent(device.id, volume_percent);
|
SetOutputNodeVolumePercent(device.id, volume_percent);
|
||||||
}
|
}
|
||||||
@ -406,10 +472,8 @@ void CrasAudioHandler::SetOutputVolumePercentWithoutNotifyingObservers(
|
|||||||
// TODO: Rename the 'Percent' to something more meaningful.
|
// TODO: Rename the 'Percent' to something more meaningful.
|
||||||
void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
|
void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
|
||||||
// TODO(jennyz): Should we set all input devices' gain to the same level?
|
// TODO(jennyz): Should we set all input devices' gain to the same level?
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end();
|
const AudioDevice& device = item.second;
|
||||||
it++) {
|
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (device.is_input && device.active)
|
if (device.is_input && device.active)
|
||||||
SetInputNodeGainPercent(active_input_node_id_, gain_percent);
|
SetInputNodeGainPercent(active_input_node_id_, gain_percent);
|
||||||
}
|
}
|
||||||
@ -424,10 +488,8 @@ void CrasAudioHandler::SetOutputMute(bool mute_on) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Save the mute state for all active output audio devices.
|
// Save the mute state for all active output audio devices.
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end();
|
const AudioDevice& device = item.second;
|
||||||
it++) {
|
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (!device.is_input && device.active) {
|
if (!device.is_input && device.active) {
|
||||||
audio_pref_handler_->SetMuteValue(device, output_mute_on_);
|
audio_pref_handler_->SetMuteValue(device, output_mute_on_);
|
||||||
}
|
}
|
||||||
@ -468,9 +530,8 @@ void CrasAudioHandler::SetActiveDevice(const AudioDevice& active_device,
|
|||||||
NotifyActiveNodeChanged(active_device.is_input);
|
NotifyActiveNodeChanged(active_device.is_input);
|
||||||
|
|
||||||
// Save active state for the nodes.
|
// Save active state for the nodes.
|
||||||
for (AudioDeviceMap::iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
const AudioDevice& device = item.second;
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (device.is_input != active_device.is_input)
|
if (device.is_input != active_device.is_input)
|
||||||
continue;
|
continue;
|
||||||
SaveDeviceState(device, device.active, activate_by);
|
SaveDeviceState(device, device.active, activate_by);
|
||||||
@ -604,7 +665,7 @@ CrasAudioHandler::~CrasAudioHandler() {
|
|||||||
RemoveObserver(this);
|
RemoveObserver(this);
|
||||||
if (audio_pref_handler_.get())
|
if (audio_pref_handler_.get())
|
||||||
audio_pref_handler_->RemoveAudioPrefObserver(this);
|
audio_pref_handler_->RemoveAudioPrefObserver(this);
|
||||||
audio_pref_handler_ = NULL;
|
audio_pref_handler_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::AudioClientRestarted() {
|
void CrasAudioHandler::AudioClientRestarted() {
|
||||||
@ -712,28 +773,28 @@ void CrasAudioHandler::EmitLoginPromptVisibleCalled() {
|
|||||||
const AudioDevice* CrasAudioHandler::GetDeviceFromId(uint64_t device_id) const {
|
const AudioDevice* CrasAudioHandler::GetDeviceFromId(uint64_t device_id) const {
|
||||||
AudioDeviceMap::const_iterator it = audio_devices_.find(device_id);
|
AudioDeviceMap::const_iterator it = audio_devices_.find(device_id);
|
||||||
if (it == audio_devices_.end())
|
if (it == audio_devices_.end())
|
||||||
return NULL;
|
return nullptr;
|
||||||
|
|
||||||
return &(it->second);
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
const AudioDevice* CrasAudioHandler::GetDeviceFromStableDeviceId(
|
const AudioDevice* CrasAudioHandler::GetDeviceFromStableDeviceId(
|
||||||
uint64_t stable_device_id) const {
|
uint64_t stable_device_id) const {
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
const AudioDevice& device = item.second;
|
||||||
if (it->second.stable_device_id == stable_device_id)
|
if (device.stable_device_id == stable_device_id)
|
||||||
return &(it->second);
|
return &device;
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AudioDevice* CrasAudioHandler::GetKeyboardMic() const {
|
const AudioDevice* CrasAudioHandler::GetKeyboardMic() const {
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); it++) {
|
const AudioDevice& device = item.second;
|
||||||
if (it->second.is_input && it->second.type == AUDIO_TYPE_KEYBOARD_MIC)
|
if (device.is_input && device.type == AUDIO_TYPE_KEYBOARD_MIC)
|
||||||
return &(it->second);
|
return &device;
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::SetupAudioInputState() {
|
void CrasAudioHandler::SetupAudioInputState() {
|
||||||
@ -940,13 +1001,13 @@ bool CrasAudioHandler::ChangeActiveDevice(
|
|||||||
// Reset all other input or output devices' active status. The active audio
|
// Reset all other input or output devices' active status. The active audio
|
||||||
// device from the previous user session can be remembered by cras, but not
|
// device from the previous user session can be remembered by cras, but not
|
||||||
// in chrome. see crbug.com/273271.
|
// in chrome. see crbug.com/273271.
|
||||||
for (AudioDeviceMap::iterator it = audio_devices_.begin();
|
for (auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
AudioDevice& device = item.second;
|
||||||
if (it->second.is_input == new_active_device.is_input &&
|
if (device.is_input == new_active_device.is_input &&
|
||||||
it->second.id != new_active_device.id) {
|
device.id != new_active_device.id) {
|
||||||
it->second.active = false;
|
device.active = false;
|
||||||
} else if (it->second.is_input == new_active_device.is_input &&
|
} else if (device.is_input == new_active_device.is_input &&
|
||||||
it->second.id == new_active_device.id) {
|
device.id == new_active_device.id) {
|
||||||
found_new_active_device = true;
|
found_new_active_device = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -982,9 +1043,8 @@ bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
|
|||||||
bool* device_removed,
|
bool* device_removed,
|
||||||
bool* active_device_removed) {
|
bool* active_device_removed) {
|
||||||
*device_removed = false;
|
*device_removed = false;
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
const AudioDevice& device = item.second;
|
||||||
const AudioDevice& device = it->second;
|
|
||||||
if (is_input != device.is_input)
|
if (is_input != device.is_input)
|
||||||
continue;
|
continue;
|
||||||
if (!IsDeviceInList(device, new_nodes)) {
|
if (!IsDeviceInList(device, new_nodes)) {
|
||||||
@ -999,12 +1059,12 @@ bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
|
|||||||
bool new_or_changed_device = false;
|
bool new_or_changed_device = false;
|
||||||
while (!new_discovered->empty())
|
while (!new_discovered->empty())
|
||||||
new_discovered->pop();
|
new_discovered->pop();
|
||||||
for (AudioNodeList::const_iterator it = new_nodes.begin();
|
|
||||||
it != new_nodes.end(); ++it) {
|
for (const AudioNode& node : new_nodes) {
|
||||||
if (is_input != it->is_input)
|
if (is_input != node.is_input)
|
||||||
continue;
|
continue;
|
||||||
// Check if the new device is not in the old device list.
|
// Check if the new device is not in the old device list.
|
||||||
AudioDevice device(*it);
|
AudioDevice device(node);
|
||||||
DeviceStatus status = CheckDeviceStatus(device);
|
DeviceStatus status = CheckDeviceStatus(device);
|
||||||
if (status == NEW_DEVICE)
|
if (status == NEW_DEVICE)
|
||||||
new_discovered->push(device);
|
new_discovered->push(device);
|
||||||
@ -1047,9 +1107,8 @@ bool CrasAudioHandler::GetActiveDeviceFromUserPref(bool is_input,
|
|||||||
AudioDevice* active_device) {
|
AudioDevice* active_device) {
|
||||||
bool found_active_device = false;
|
bool found_active_device = false;
|
||||||
bool last_active_device_activate_by_user = false;
|
bool last_active_device_activate_by_user = false;
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
const AudioDevice& device = item.second;
|
||||||
AudioDevice device = it->second;
|
|
||||||
if (device.is_input != is_input || !device.is_for_simple_usage())
|
if (device.is_input != is_input || !device.is_for_simple_usage())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1183,8 +1242,17 @@ void CrasAudioHandler::HandleHotPlugDevice(
|
|||||||
void CrasAudioHandler::SwitchToTopPriorityDevice(bool is_input) {
|
void CrasAudioHandler::SwitchToTopPriorityDevice(bool is_input) {
|
||||||
AudioDevice top_device =
|
AudioDevice top_device =
|
||||||
is_input ? input_devices_pq_.top() : output_devices_pq_.top();
|
is_input ? input_devices_pq_.top() : output_devices_pq_.top();
|
||||||
if (top_device.is_for_simple_usage())
|
if (!top_device.is_for_simple_usage())
|
||||||
SwitchToDevice(top_device, true, ACTIVATE_BY_PRIORITY);
|
return;
|
||||||
|
|
||||||
|
// For the dual camera and dual microphone case, choose microphone
|
||||||
|
// that is consistent to the active camera.
|
||||||
|
if (IsFrontOrRearMic(top_device) && HasDualInternalMic() && IsCameraOn()) {
|
||||||
|
ActivateInternalMicForActiveCamera();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchToDevice(top_device, true, ACTIVATE_BY_PRIORITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrasAudioHandler::SwitchToPreviousActiveDeviceIfAvailable(bool is_input) {
|
void CrasAudioHandler::SwitchToPreviousActiveDeviceIfAvailable(bool is_input) {
|
||||||
@ -1204,9 +1272,9 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive(
|
|||||||
const AudioNodeList& nodes) {
|
const AudioNodeList& nodes) {
|
||||||
size_t old_output_device_size = 0;
|
size_t old_output_device_size = 0;
|
||||||
size_t old_input_device_size = 0;
|
size_t old_input_device_size = 0;
|
||||||
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
|
for (const auto& item : audio_devices_) {
|
||||||
it != audio_devices_.end(); ++it) {
|
const AudioDevice& device = item.second;
|
||||||
if (it->second.is_input)
|
if (device.is_input)
|
||||||
++old_input_device_size;
|
++old_input_device_size;
|
||||||
else
|
else
|
||||||
++old_output_device_size;
|
++old_output_device_size;
|
||||||
@ -1423,4 +1491,94 @@ void CrasAudioHandler::SetHDMIRediscoverGracePeriodForTesting(
|
|||||||
hdmi_rediscover_grace_period_duration_in_ms_ = duration_in_ms;
|
hdmi_rediscover_grace_period_duration_in_ms_ = duration_in_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CrasAudioHandler::ActivateMicForCamera(
|
||||||
|
media::VideoFacingMode camera_facing) {
|
||||||
|
const AudioDevice* mic = GetMicForCamera(camera_facing);
|
||||||
|
if (!mic || mic->active)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SwitchToDevice(*mic, true, ACTIVATE_BY_CAMERA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CrasAudioHandler::ActivateInternalMicForActiveCamera() {
|
||||||
|
DCHECK(IsCameraOn());
|
||||||
|
if (HasDualInternalMic()) {
|
||||||
|
media::VideoFacingMode facing = front_camera_on_
|
||||||
|
? media::MEDIA_VIDEO_FACING_USER
|
||||||
|
: media::MEDIA_VIDEO_FACING_ENVIRONMENT;
|
||||||
|
ActivateMicForCamera(facing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For the dual microphone case, from user point of view, they only see internal
|
||||||
|
// microphone in UI. Chrome will make the best decision on which one to pick.
|
||||||
|
// If the camera is off, the front microphone should be picked as the default
|
||||||
|
// active microphone. Otherwise, it will switch to the microphone that
|
||||||
|
// matches the active camera, i.e. front microphone for front camera and
|
||||||
|
// rear microphone for rear camera.
|
||||||
|
void CrasAudioHandler::SwitchToFrontOrRearMic() {
|
||||||
|
DCHECK(HasDualInternalMic());
|
||||||
|
if (IsCameraOn()) {
|
||||||
|
ActivateInternalMicForActiveCamera();
|
||||||
|
} else {
|
||||||
|
SwitchToDevice(*GetDeviceByType(AUDIO_TYPE_FRONT_MIC), true,
|
||||||
|
ACTIVATE_BY_USER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const AudioDevice* CrasAudioHandler::GetMicForCamera(
|
||||||
|
media::VideoFacingMode camera_facing) {
|
||||||
|
switch (camera_facing) {
|
||||||
|
case media::MEDIA_VIDEO_FACING_USER:
|
||||||
|
return GetDeviceByType(AUDIO_TYPE_FRONT_MIC);
|
||||||
|
case media::MEDIA_VIDEO_FACING_ENVIRONMENT:
|
||||||
|
return GetDeviceByType(AUDIO_TYPE_REAR_MIC);
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AudioDevice* CrasAudioHandler::GetDeviceByType(AudioDeviceType type) {
|
||||||
|
for (const auto& item : audio_devices_) {
|
||||||
|
const AudioDevice& device = item.second;
|
||||||
|
if (device.type == type)
|
||||||
|
return &device;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrasAudioHandler::HasDualInternalMic() const {
|
||||||
|
bool has_front_mic = false;
|
||||||
|
bool has_rear_mic = false;
|
||||||
|
for (const auto& item : audio_devices_) {
|
||||||
|
const AudioDevice& device = item.second;
|
||||||
|
if (device.type == AUDIO_TYPE_FRONT_MIC)
|
||||||
|
has_front_mic = true;
|
||||||
|
else if (device.type == AUDIO_TYPE_REAR_MIC)
|
||||||
|
has_rear_mic = true;
|
||||||
|
if (has_front_mic && has_rear_mic)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return has_front_mic && has_rear_mic;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrasAudioHandler::IsFrontOrRearMic(const AudioDevice& device) const {
|
||||||
|
return device.is_input && (device.type == AUDIO_TYPE_FRONT_MIC ||
|
||||||
|
device.type == AUDIO_TYPE_REAR_MIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrasAudioHandler::IsCameraOn() const {
|
||||||
|
return front_camera_on_ || rear_camera_on_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CrasAudioHandler::HasExternalDevice(bool is_input) const {
|
||||||
|
for (const auto& item : audio_devices_) {
|
||||||
|
const AudioDevice& device = item.second;
|
||||||
|
if (is_input == device.is_input && device.IsExternalDevice())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chromeos
|
} // namespace chromeos
|
||||||
|
@ -87,6 +87,7 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
|
|||||||
ACTIVATE_BY_PRIORITY = 0,
|
ACTIVATE_BY_PRIORITY = 0,
|
||||||
ACTIVATE_BY_USER,
|
ACTIVATE_BY_USER,
|
||||||
ACTIVATE_BY_RESTORE_PREVIOUS_STATE,
|
ACTIVATE_BY_RESTORE_PREVIOUS_STATE,
|
||||||
|
ACTIVATE_BY_CAMERA
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sets the global instance. Must be called before any calls to Get().
|
// Sets the global instance. Must be called before any calls to Get().
|
||||||
@ -261,6 +262,16 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
|
|||||||
|
|
||||||
const AudioDevice* GetDeviceFromId(uint64_t device_id) const;
|
const AudioDevice* GetDeviceFromId(uint64_t device_id) const;
|
||||||
|
|
||||||
|
// Returns true the device has dual internal microphones(front and rear).
|
||||||
|
bool HasDualInternalMic() const;
|
||||||
|
|
||||||
|
// Returns true if |device| is front or rear microphone.
|
||||||
|
bool IsFrontOrRearMic(const AudioDevice& device) const;
|
||||||
|
|
||||||
|
// Switches to either front or rear microphone depending on the
|
||||||
|
// the use case. It should be called from a user initiated action.
|
||||||
|
void SwitchToFrontOrRearMic();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit CrasAudioHandler(
|
explicit CrasAudioHandler(
|
||||||
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler);
|
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler);
|
||||||
@ -439,6 +450,27 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
|
|||||||
// to the top priority device.
|
// to the top priority device.
|
||||||
void SwitchToPreviousActiveDeviceIfAvailable(bool is_input);
|
void SwitchToPreviousActiveDeviceIfAvailable(bool is_input);
|
||||||
|
|
||||||
|
// Activates the internal mic attached with the camera specified by
|
||||||
|
// |camera_facing|.
|
||||||
|
void ActivateMicForCamera(media::VideoFacingMode camera_facing);
|
||||||
|
|
||||||
|
// Activates the front or rear mic that is consistent with the active camera.
|
||||||
|
// Note: This should only be called for the dural camera/mic use case.
|
||||||
|
void ActivateInternalMicForActiveCamera();
|
||||||
|
|
||||||
|
// Returns the microphone for the camera with |camera_facing|.
|
||||||
|
const AudioDevice* GetMicForCamera(media::VideoFacingMode camera_facing);
|
||||||
|
|
||||||
|
// Returns the device matched with |type|. Assuming there is only one device
|
||||||
|
// matched the |type|, if there is more than one matched devices, it will
|
||||||
|
// return the first one found.
|
||||||
|
const AudioDevice* GetDeviceByType(AudioDeviceType type);
|
||||||
|
|
||||||
|
bool IsCameraOn() const;
|
||||||
|
|
||||||
|
// Returns true if there are any external devices.
|
||||||
|
bool HasExternalDevice(bool is_input) const;
|
||||||
|
|
||||||
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_;
|
scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler_;
|
||||||
base::ObserverList<AudioObserver> observers_;
|
base::ObserverList<AudioObserver> observers_;
|
||||||
|
|
||||||
@ -483,6 +515,9 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
|
|||||||
int init_volume_;
|
int init_volume_;
|
||||||
uint64_t init_node_id_;
|
uint64_t init_node_id_;
|
||||||
|
|
||||||
|
bool front_camera_on_ = false;
|
||||||
|
bool rear_camera_on_ = false;
|
||||||
|
|
||||||
base::WeakPtrFactory<CrasAudioHandler> weak_ptr_factory_;
|
base::WeakPtrFactory<CrasAudioHandler> weak_ptr_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CrasAudioHandler);
|
DISALLOW_COPY_AND_ASSIGN(CrasAudioHandler);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "chromeos/dbus/audio_node.h"
|
#include "chromeos/dbus/audio_node.h"
|
||||||
#include "chromeos/dbus/dbus_thread_manager.h"
|
#include "chromeos/dbus/dbus_thread_manager.h"
|
||||||
#include "chromeos/dbus/fake_cras_audio_client.h"
|
#include "chromeos/dbus/fake_cras_audio_client.h"
|
||||||
|
#include "media/base/video_facing.h"
|
||||||
#include "testing/gtest/include/gtest/gtest.h"
|
#include "testing/gtest/include/gtest/gtest.h"
|
||||||
|
|
||||||
namespace chromeos {
|
namespace chromeos {
|
||||||
@ -36,6 +37,8 @@ const uint64_t kUSBHeadphoneId1 = 10007;
|
|||||||
const uint64_t kUSBHeadphoneId2 = 10008;
|
const uint64_t kUSBHeadphoneId2 = 10008;
|
||||||
const uint64_t kMicJackId = 10009;
|
const uint64_t kMicJackId = 10009;
|
||||||
const uint64_t kKeyboardMicId = 10010;
|
const uint64_t kKeyboardMicId = 10010;
|
||||||
|
const uint64_t kFrontMicId = 10011;
|
||||||
|
const uint64_t kRearMicId = 10012;
|
||||||
const uint64_t kOtherTypeOutputId = 90001;
|
const uint64_t kOtherTypeOutputId = 90001;
|
||||||
const uint64_t kOtherTypeInputId = 90002;
|
const uint64_t kOtherTypeInputId = 90002;
|
||||||
const uint64_t kUSBJabraSpeakerOutputId1 = 90003;
|
const uint64_t kUSBJabraSpeakerOutputId1 = 90003;
|
||||||
@ -71,6 +74,12 @@ const AudioNodeInfo kKeyboardMic[] = {{true, kKeyboardMicId,
|
|||||||
"Fake Keyboard Mic", "KEYBOARD_MIC",
|
"Fake Keyboard Mic", "KEYBOARD_MIC",
|
||||||
"Keyboard Mic"}};
|
"Keyboard Mic"}};
|
||||||
|
|
||||||
|
const AudioNodeInfo kFrontMic[] = {
|
||||||
|
{true, kFrontMicId, "Fake Front Mic", "FRONT_MIC", "Front Mic"}};
|
||||||
|
|
||||||
|
const AudioNodeInfo kRearMic[] = {
|
||||||
|
{true, kRearMicId, "Fake Rear Mic", "REAR_MIC", "Rear Mic"}};
|
||||||
|
|
||||||
const AudioNodeInfo kOtherTypeOutput[] = {{false, kOtherTypeOutputId,
|
const AudioNodeInfo kOtherTypeOutput[] = {{false, kOtherTypeOutputId,
|
||||||
"Output Device", "SOME_OTHER_TYPE",
|
"Output Device", "SOME_OTHER_TYPE",
|
||||||
"Other Type Output Device"}};
|
"Other Type Output Device"}};
|
||||||
@ -211,6 +220,32 @@ class TestObserver : public chromeos::CrasAudioHandler::AudioObserver {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(TestObserver);
|
DISALLOW_COPY_AND_ASSIGN(TestObserver);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FakeVideoCaptureManager {
|
||||||
|
public:
|
||||||
|
FakeVideoCaptureManager() {}
|
||||||
|
virtual ~FakeVideoCaptureManager() {}
|
||||||
|
|
||||||
|
void AddObserver(media::VideoCaptureObserver* observer) {
|
||||||
|
observers_.AddObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAllObservers() { observers_.Clear(); }
|
||||||
|
|
||||||
|
void NotifyVideoCaptureStarted(media::VideoFacingMode facing) {
|
||||||
|
for (auto& observer : observers_)
|
||||||
|
observer.OnVideoCaptureStarted(facing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NotifyVideoCaptureStopped(media::VideoFacingMode facing) {
|
||||||
|
for (auto& observer : observers_)
|
||||||
|
observer.OnVideoCaptureStopped(facing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base::ObserverList<media::VideoCaptureObserver> observers_;
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FakeVideoCaptureManager);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// Test param is the version of stabel device id used by audio node.
|
// Test param is the version of stabel device id used by audio node.
|
||||||
@ -219,11 +254,15 @@ class CrasAudioHandlerTest : public testing::TestWithParam<int> {
|
|||||||
CrasAudioHandlerTest() {}
|
CrasAudioHandlerTest() {}
|
||||||
~CrasAudioHandlerTest() override {}
|
~CrasAudioHandlerTest() override {}
|
||||||
|
|
||||||
void SetUp() override {}
|
void SetUp() override {
|
||||||
|
video_capture_manager_.reset(new FakeVideoCaptureManager);
|
||||||
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
void TearDown() override {
|
||||||
cras_audio_handler_->RemoveAudioObserver(test_observer_.get());
|
cras_audio_handler_->RemoveAudioObserver(test_observer_.get());
|
||||||
test_observer_.reset();
|
test_observer_.reset();
|
||||||
|
video_capture_manager_->RemoveAllObservers();
|
||||||
|
video_capture_manager_.reset();
|
||||||
CrasAudioHandler::Shutdown();
|
CrasAudioHandler::Shutdown();
|
||||||
audio_pref_handler_ = nullptr;
|
audio_pref_handler_ = nullptr;
|
||||||
DBusThreadManager::Shutdown();
|
DBusThreadManager::Shutdown();
|
||||||
@ -257,6 +296,7 @@ class CrasAudioHandlerTest : public testing::TestWithParam<int> {
|
|||||||
cras_audio_handler_ = CrasAudioHandler::Get();
|
cras_audio_handler_ = CrasAudioHandler::Get();
|
||||||
test_observer_.reset(new TestObserver);
|
test_observer_.reset(new TestObserver);
|
||||||
cras_audio_handler_->AddAudioObserver(test_observer_.get());
|
cras_audio_handler_->AddAudioObserver(test_observer_.get());
|
||||||
|
video_capture_manager_->AddObserver(cras_audio_handler_);
|
||||||
base::RunLoop().RunUntilIdle();
|
base::RunLoop().RunUntilIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,12 +388,33 @@ class CrasAudioHandlerTest : public testing::TestWithParam<int> {
|
|||||||
base::RunLoop().RunUntilIdle();
|
base::RunLoop().RunUntilIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StartFrontFacingCamera() {
|
||||||
|
video_capture_manager_->NotifyVideoCaptureStarted(
|
||||||
|
media::MEDIA_VIDEO_FACING_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopFrontFacingCamera() {
|
||||||
|
video_capture_manager_->NotifyVideoCaptureStopped(
|
||||||
|
media::MEDIA_VIDEO_FACING_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRearFacingCamera() {
|
||||||
|
video_capture_manager_->NotifyVideoCaptureStarted(
|
||||||
|
media::MEDIA_VIDEO_FACING_ENVIRONMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopRearFacingCamera() {
|
||||||
|
video_capture_manager_->NotifyVideoCaptureStopped(
|
||||||
|
media::MEDIA_VIDEO_FACING_ENVIRONMENT);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
base::MessageLoopForUI message_loop_;
|
base::MessageLoopForUI message_loop_;
|
||||||
CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned.
|
CrasAudioHandler* cras_audio_handler_ = nullptr; // Not owned.
|
||||||
FakeCrasAudioClient* fake_cras_audio_client_ = nullptr; // Not owned.
|
FakeCrasAudioClient* fake_cras_audio_client_ = nullptr; // Not owned.
|
||||||
std::unique_ptr<TestObserver> test_observer_;
|
std::unique_ptr<TestObserver> test_observer_;
|
||||||
scoped_refptr<AudioDevicesPrefHandlerStub> audio_pref_handler_;
|
scoped_refptr<AudioDevicesPrefHandlerStub> audio_pref_handler_;
|
||||||
|
std::unique_ptr<FakeVideoCaptureManager> video_capture_manager_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(CrasAudioHandlerTest);
|
DISALLOW_COPY_AND_ASSIGN(CrasAudioHandlerTest);
|
||||||
@ -3680,4 +3741,191 @@ TEST_P(CrasAudioHandlerTest, HDMIOutputUnplugDuringSuspension) {
|
|||||||
EXPECT_TRUE(test_observer_->output_mute_by_system());
|
EXPECT_TRUE(test_observer_->output_mute_by_system());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, FrontCameraStartStop) {
|
||||||
|
AudioNodeList audio_nodes = GenerateAudioNodeList({kFrontMic, kRearMic});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the front facing camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the front facing camera.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, RearCameraStartStop) {
|
||||||
|
AudioNodeList audio_nodes = GenerateAudioNodeList({kFrontMic, kRearMic});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the rear facing camera.
|
||||||
|
StartRearFacingCamera();
|
||||||
|
// Verify the active input is switched to the rear mic.
|
||||||
|
EXPECT_EQ(kRearMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the rear facing camera.
|
||||||
|
StopRearFacingCamera();
|
||||||
|
// Verify the active input is switched back to front mic.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, SwitchFrontRearCamera) {
|
||||||
|
AudioNodeList audio_nodes = GenerateAudioNodeList({kFrontMic, kRearMic});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the front facing camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Simulates the camera app switching from front camera to rear camera.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
StartRearFacingCamera();
|
||||||
|
|
||||||
|
// Verify the rear mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kRearMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, StartFrontCameraWithActiveExternalInput) {
|
||||||
|
AudioNodeList audio_nodes =
|
||||||
|
GenerateAudioNodeList({kFrontMic, kRearMic, kMicJack});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the mic Jack has been selected as the active input.
|
||||||
|
EXPECT_EQ(kMicJackId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the front facing camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the mic Jack has been selected as the active input.
|
||||||
|
EXPECT_EQ(kMicJackId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the front facing camera.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
// Verify the mic Jack remains as the active input.
|
||||||
|
EXPECT_EQ(kMicJackId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, StartFrontCameraWithInactiveExternalInput) {
|
||||||
|
AudioNodeList audio_nodes =
|
||||||
|
GenerateAudioNodeList({kFrontMic, kRearMic, kMicJack});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the mic Jack has been selected as the active input.
|
||||||
|
EXPECT_EQ(kMicJackId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Change the active input to internal mic.
|
||||||
|
cras_audio_handler_->SwitchToFrontOrRearMic();
|
||||||
|
// Verify the active input has been switched to front mic.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Start the front facing camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the front facing camera.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
// Verify the active input remains as front mic.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, StartFrontCameraWithoutDualMic) {
|
||||||
|
AudioNodeList audio_nodes = GenerateAudioNodeList({kInternalMic});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the mic Jack has been selected as the active input.
|
||||||
|
EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_FALSE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the front facing camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the internal mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the front facing camera.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
// Verify the active input remains as interanl mic.
|
||||||
|
EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(CrasAudioHandlerTest, FrontRearCameraBothOn) {
|
||||||
|
AudioNodeList audio_nodes = GenerateAudioNodeList({kFrontMic, kRearMic});
|
||||||
|
SetUpCrasAudioHandler(audio_nodes);
|
||||||
|
|
||||||
|
// Verify the audio devices size.
|
||||||
|
AudioDeviceList audio_devices;
|
||||||
|
cras_audio_handler_->GetAudioDevices(&audio_devices);
|
||||||
|
EXPECT_EQ(audio_nodes.size(), audio_devices.size());
|
||||||
|
|
||||||
|
// Verify the front mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
EXPECT_TRUE(cras_audio_handler_->HasDualInternalMic());
|
||||||
|
|
||||||
|
// Start the rear facing camera.
|
||||||
|
StartRearFacingCamera();
|
||||||
|
// Verify the rear mic has been selected as the active input.
|
||||||
|
EXPECT_EQ(kRearMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Start front camera without stopping the front camera.
|
||||||
|
StartFrontFacingCamera();
|
||||||
|
// Verify the active microphone does not change.
|
||||||
|
EXPECT_EQ(kRearMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the front mic.
|
||||||
|
StopFrontFacingCamera();
|
||||||
|
// Verity the active mic does not change when there is still camera on.
|
||||||
|
EXPECT_EQ(kRearMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
|
||||||
|
// Stop the rear mic.
|
||||||
|
StopRearFacingCamera();
|
||||||
|
// Verify the actice mic changes to front mic after both cameras stop.
|
||||||
|
EXPECT_EQ(kFrontMicId, cras_audio_handler_->GetPrimaryActiveInputNode());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace chromeos
|
} // namespace chromeos
|
||||||
|
@ -342,6 +342,7 @@ target(link_target_type, "base") {
|
|||||||
source_set("video_facing") {
|
source_set("video_facing") {
|
||||||
visibility = [
|
visibility = [
|
||||||
"//chromeos",
|
"//chromeos",
|
||||||
|
"//chromeos:chromeos_unittests",
|
||||||
"//content/browser",
|
"//content/browser",
|
||||||
"//content/public/common:common_sources",
|
"//content/public/common:common_sources",
|
||||||
"//media/base",
|
"//media/base",
|
||||||
|
Reference in New Issue
Block a user