blob: 22de4639ca48a12be0a213465988ead30324f889 [file] [log] [blame]
The Android Open Source Project2729ea92008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2006-2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioSystem"
18#include <utils/Log.h>
19#include <utils/IServiceManager.h>
20#include <media/AudioSystem.h>
21#include <media/AudioTrack.h>
22#include <math.h>
23
24namespace android {
25
26// client singleton for AudioFlinger binder interface
27Mutex AudioSystem::gLock;
28sp<IAudioFlinger> AudioSystem::gAudioFlinger;
29sp<AudioSystem::DeathNotifier> AudioSystem::gDeathNotifier;
30audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
31
32// establish binder interface to AudioFlinger service
33const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
34{
35 Mutex::Autolock _l(gLock);
36 if (gAudioFlinger.get() == 0) {
37 sp<IServiceManager> sm = defaultServiceManager();
38 sp<IBinder> binder;
39 do {
40 binder = sm->getService(String16("media.audio_flinger"));
41 if (binder != 0)
42 break;
43 LOGW("AudioFlinger not published, waiting...");
44 usleep(500000); // 0.5 s
45 } while(true);
46 if (gDeathNotifier == NULL) {
47 gDeathNotifier = new DeathNotifier();
48 } else {
49 if (gAudioErrorCallback) {
50 gAudioErrorCallback(NO_ERROR);
51 }
52 }
53 binder->linkToDeath(gDeathNotifier);
54 gAudioFlinger = interface_cast<IAudioFlinger>(binder);
55 }
56 LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
57 return gAudioFlinger;
58}
59
60// routing helper functions
61status_t AudioSystem::speakerphone(bool state) {
62 uint32_t routes = state ? ROUTE_SPEAKER : ROUTE_EARPIECE;
63 return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
64}
65
66status_t AudioSystem::isSpeakerphoneOn(bool* state) {
67 uint32_t routes = 0;
68 status_t s = getRouting(MODE_IN_CALL, &routes);
69 *state = !!(routes & ROUTE_SPEAKER);
70 return s;
71}
72
73status_t AudioSystem::bluetoothSco(bool state) {
74 uint32_t mask = ROUTE_BLUETOOTH;
75 uint32_t routes = state ? mask : ROUTE_EARPIECE;
76 return setRouting(MODE_IN_CALL, routes, ROUTE_ALL);
77}
78
79status_t AudioSystem::isBluetoothScoOn(bool* state) {
80 uint32_t routes = 0;
81 status_t s = getRouting(MODE_IN_CALL, &routes);
82 *state = !!(routes & ROUTE_BLUETOOTH);
83 return s;
84}
85
86status_t AudioSystem::muteMicrophone(bool state) {
87 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
88 if (af == 0) return PERMISSION_DENIED;
89 return af->setMicMute(state);
90}
91
92status_t AudioSystem::isMicrophoneMuted(bool* state) {
93 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
94 if (af == 0) return PERMISSION_DENIED;
95 *state = af->getMicMute();
96 return NO_ERROR;
97}
98
99status_t AudioSystem::setMasterVolume(float value)
100{
101 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
102 if (af == 0) return PERMISSION_DENIED;
103 af->setMasterVolume(value);
104 return NO_ERROR;
105}
106
107status_t AudioSystem::setMasterMute(bool mute)
108{
109 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
110 if (af == 0) return PERMISSION_DENIED;
111 af->setMasterMute(mute);
112 return NO_ERROR;
113}
114
115status_t AudioSystem::getMasterVolume(float* volume)
116{
117 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
118 if (af == 0) return PERMISSION_DENIED;
119 *volume = af->masterVolume();
120 return NO_ERROR;
121}
122
123status_t AudioSystem::getMasterMute(bool* mute)
124{
125 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
126 if (af == 0) return PERMISSION_DENIED;
127 *mute = af->masterMute();
128 return NO_ERROR;
129}
130
131status_t AudioSystem::setStreamVolume(int stream, float value)
132{
133 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
134 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
135 if (af == 0) return PERMISSION_DENIED;
136 af->setStreamVolume(stream, value);
137 return NO_ERROR;
138}
139
140status_t AudioSystem::setStreamMute(int stream, bool mute)
141{
142 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
143 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
144 if (af == 0) return PERMISSION_DENIED;
145 af->setStreamMute(stream, mute);
146 return NO_ERROR;
147}
148
149status_t AudioSystem::getStreamVolume(int stream, float* volume)
150{
151 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
152 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
153 if (af == 0) return PERMISSION_DENIED;
154 *volume = af->streamVolume(stream);
155 return NO_ERROR;
156}
157
158status_t AudioSystem::getStreamMute(int stream, bool* mute)
159{
160 if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
161 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
162 if (af == 0) return PERMISSION_DENIED;
163 *mute = af->streamMute(stream);
164 return NO_ERROR;
165}
166
167status_t AudioSystem::setMode(int mode)
168{
169 if (mode >= NUM_MODES) return BAD_VALUE;
170 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
171 if (af == 0) return PERMISSION_DENIED;
172 return af->setMode(mode);
173}
174
175status_t AudioSystem::getMode(int* mode)
176{
177 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
178 if (af == 0) return PERMISSION_DENIED;
179 *mode = af->getMode();
180 return NO_ERROR;
181}
182
183status_t AudioSystem::setRouting(int mode, uint32_t routes, uint32_t mask)
184{
185 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
186 if (af == 0) return PERMISSION_DENIED;
187 return af->setRouting(mode, routes, mask);
188}
189
190status_t AudioSystem::getRouting(int mode, uint32_t* routes)
191{
192 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
193 if (af == 0) return PERMISSION_DENIED;
194 uint32_t r = af->getRouting(mode);
195 *routes = r;
196 return NO_ERROR;
197}
198
199status_t AudioSystem::isMusicActive(bool* state) {
200 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
201 if (af == 0) return PERMISSION_DENIED;
202 *state = af->isMusicActive();
203 return NO_ERROR;
204}
205
206// Temporary interface, do not use
207// TODO: Replace with a more generic key:value get/set mechanism
208status_t AudioSystem::setParameter(const char* key, const char* value) {
209 const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
210 if (af == 0) return PERMISSION_DENIED;
211 return af->setParameter(key, value);
212}
213
214// convert volume steps to natural log scale
215
216// change this value to change volume scaling
217static const float dBPerStep = 0.5f;
218// shouldn't need to touch these
219static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f;
220static const float dBConvertInverse = 1.0f / dBConvert;
221
222float AudioSystem::linearToLog(int volume)
223{
224 // float v = volume ? exp(float(100 - volume) * dBConvert) : 0;
225 // LOGD("linearToLog(%d)=%f", volume, v);
226 // return v;
227 return volume ? exp(float(100 - volume) * dBConvert) : 0;
228}
229
230int AudioSystem::logToLinear(float volume)
231{
232 // int v = volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
233 // LOGD("logTolinear(%d)=%f", v, volume);
234 // return v;
235 return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
236}
237
238// ---------------------------------------------------------------------------
239
240void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) {
241 Mutex::Autolock _l(AudioSystem::gLock);
242 AudioSystem::gAudioFlinger.clear();
243 if (gAudioErrorCallback) {
244 gAudioErrorCallback(DEAD_OBJECT);
245 }
246 LOGW("AudioFlinger server died!");
247}
248
249void AudioSystem::setErrorCallback(audio_error_callback cb) {
250 Mutex::Autolock _l(AudioSystem::gLock);
251 gAudioErrorCallback = cb;
252}
253
254}; // namespace android
255