/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "ATVAudioPolicyManager"
//#define LOG_NDEBUG 0
#include <media/AudioParameter.h>
#include <media/mediarecorder.h>
#include <utils/Log.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/StrongPointer.h>
#include "AudioHardwareOutput.h"
#include "ATVAudioPolicyManager.h"
#ifdef REMOTE_CONTROL_INTERFACE
#include <IRemoteControlService.h>
#endif
namespace android {
extern AudioHardwareOutput gAudioHardwareOutput;
// ----------------------------------------------------------------------------
// Common audio policy manager code is implemented in AudioPolicyManager class
// ----------------------------------------------------------------------------
// --- class factory
extern "C" AudioPolicyInterface* createAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
{
return new ATVAudioPolicyManager(clientInterface);
}
extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
{
delete interface;
}
ATVAudioPolicyManager::ATVAudioPolicyManager(
AudioPolicyClientInterface *clientInterface)
: AudioPolicyManager(clientInterface), mForceSubmixInputSelection(false)
{
}
float ATVAudioPolicyManager::computeVolume(audio_stream_type_t stream,
int index,
audio_devices_t device)
{
// We only use master volume, so all audio flinger streams
// should be set to maximum
(void)stream;
(void)index;
(void)device;
return 0.0; // no attenuation == 0.0dB
}
status_t ATVAudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name)
{
audio_devices_t tmp = AUDIO_DEVICE_NONE;;
ALOGE("setDeviceConnectionState %08x %x %s", device, state,
device_address ? device_address : "(null)");
// If the input device is the remote submix and an address starting with "force=" was
// specified, enable "force=1" / disable "force=0" the forced selection of the remote submix
// input device over hardware input devices (e.g RemoteControl).
if (device == AUDIO_DEVICE_IN_REMOTE_SUBMIX && device_address) {
AudioParameter parameters = AudioParameter(String8(device_address));
int forceValue;
if (parameters.getInt(String8("force"), forceValue) == OK) {
mForceSubmixInputSelection = forceValue != 0;
}
}
if (audio_is_output_device(device)) {
switch (state) {
case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
tmp = mAvailableOutputDevices.types() | device;
break;
case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE:
tmp = mAvailableOutputDevices.types() & ~device;
break;
default:
ALOGE("setDeviceConnectionState() invalid state: %x", state);
return BAD_VALUE;
}
gAudioHardwareOutput.updateRouting(tmp);
tmp = mAvailableOutputDevices.types();
}
status_t ret = 0;
if (device != AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
ret = AudioPolicyManager::setDeviceConnectionState(
device, state, device_address, device_name);
}
if (audio_is_output_device(device)) {
if (tmp != mAvailableOutputDevices.types())
gAudioHardwareOutput.updateRouting(mAvailableOutputDevices.types());
}
return ret;
}
audio_devices_t ATVAudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
uint32_t device = AUDIO_DEVICE_NONE;
bool usePhysRemote = true;
if (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION) {
#ifdef REMOTE_CONTROL_INTERFACE
ALOGI("Using REMOTE_CONTROL_INTERFACE.");
// Check if remote is actually connected or we should move on
sp<IRemoteControlService> service = IRemoteControlService::getInstance();
if (service == NULL) {
ALOGV("getDeviceForInputSource No RemoteControl service detected, ignoring");
usePhysRemote = false;
} else if (!service->hasActiveRemote()) {
if (mForceSubmixInputSelection == false && service->hasConnectedRemotes()) {
ALOGV("getDeviceForInputSource connected remote and submix not forced");
usePhysRemote = true;
} else {
ALOGV("getDeviceForInputSource No active connected device, passing onto submix");
usePhysRemote = false;
}
}
#endif
ALOGV("getDeviceForInputSource %s %s", usePhysRemote ? "use physical" : "",
mForceSubmixInputSelection ? "use virtual" : "");
audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
~AUDIO_DEVICE_BIT_IN;
if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET &&
usePhysRemote) {
// User a wired headset (physical remote) if available, connected and active
ALOGV("Wired Headset available");
device = AUDIO_DEVICE_IN_WIRED_HEADSET;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX &&
mForceSubmixInputSelection) {
// REMOTE_SUBMIX should always be avaible, let's make sure it's being forced at the moment
ALOGV("Virtual remote available");
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
} else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
ALOGV("Use USB audio input");
device = AUDIO_DEVICE_IN_USB_DEVICE;
}
}
ALOGV("getDeviceForInputSource() input source %d, device %08x", inputSource, device);
return device;
}
} // namespace android