1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
/*
* 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;
const audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
~AUDIO_DEVICE_BIT_IN;
if (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION ||
inputSource == AUDIO_SOURCE_UNPROCESSED) {
#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" : "");
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;
}
} else if ((availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) &&
(inputSource == AUDIO_SOURCE_REMOTE_SUBMIX)) {
device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
}
ALOGV("getDeviceForInputSource() input source %d, device %08x", inputSource, device);
return device;
}
} // namespace android
|