blob: d99f66a580d9a5ba1f4044a4cb52af8b481f057c [file] [log] [blame]
Eric Laurenta553c252009-07-17 12:17:14 -07001/*
2 * Copyright (C) 2009 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 "AudioPolicyService"
18//#define LOG_NDEBUG 0
Eric Laurent327c27b2009-08-27 00:48:47 -070019
20#undef __STRICT_ANSI__
21#define __STDINT_LIMITS
22#define __STDC_LIMIT_MACROS
23#include <stdint.h>
24
25#include <sys/time.h>
Eric Laurenta553c252009-07-17 12:17:14 -070026#include <binder/IServiceManager.h>
27#include <utils/Log.h>
28#include <cutils/properties.h>
29#include <binder/IPCThreadState.h>
30#include <utils/String16.h>
31#include <utils/threads.h>
32#include "AudioPolicyService.h"
33#include <cutils/properties.h>
Eric Laurentcef3cd72009-12-10 01:03:50 -080034#include <hardware_legacy/power.h>
Eric Laurent464d5b32011-06-17 21:29:58 -070035#include <media/AudioEffect.h>
36#include <media/EffectsFactoryApi.h>
Eric Laurenta553c252009-07-17 12:17:14 -070037
Dima Zavin24fc2fb2011-04-19 22:30:36 -070038#include <hardware/hardware.h>
Dima Zavin34bb4192011-05-11 14:15:23 -070039#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070040#include <system/audio_policy.h>
Dima Zavin24fc2fb2011-04-19 22:30:36 -070041#include <hardware/audio_policy.h>
Eric Laurent464d5b32011-06-17 21:29:58 -070042#include <audio_effects/audio_effects_conf.h>
Dima Zavin24fc2fb2011-04-19 22:30:36 -070043
Eric Laurenta553c252009-07-17 12:17:14 -070044namespace android {
45
Eric Laurentcef3cd72009-12-10 01:03:50 -080046static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
47static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
Eric Laurentf4ee40e2009-11-02 10:29:02 -080048
49static const int kDumpLockRetries = 50;
50static const int kDumpLockSleep = 20000;
51
Eric Laurenta553c252009-07-17 12:17:14 -070052static bool checkPermission() {
Eric Laurenta553c252009-07-17 12:17:14 -070053 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
54 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
55 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
56 return ok;
57}
58
Dima Zavin24fc2fb2011-04-19 22:30:36 -070059namespace {
60 extern struct audio_policy_service_ops aps_ops;
61};
62
Eric Laurenta553c252009-07-17 12:17:14 -070063// ----------------------------------------------------------------------------
64
65AudioPolicyService::AudioPolicyService()
Dima Zavin24fc2fb2011-04-19 22:30:36 -070066 : BnAudioPolicyService() , mpAudioPolicyDev(NULL) , mpAudioPolicy(NULL)
Eric Laurenta553c252009-07-17 12:17:14 -070067{
Eric Laurenta553c252009-07-17 12:17:14 -070068 char value[PROPERTY_VALUE_MAX];
Dima Zavin24fc2fb2011-04-19 22:30:36 -070069 const struct hw_module_t *module;
70 int forced_val;
71 int rc;
Eric Laurenta553c252009-07-17 12:17:14 -070072
Eric Laurent01635942011-01-18 18:39:02 -080073 Mutex::Autolock _l(mLock);
74
Eric Laurenta553c252009-07-17 12:17:14 -070075 // start tone playback thread
Eric Laurentcef3cd72009-12-10 01:03:50 -080076 mTonePlaybackThread = new AudioCommandThread(String8(""));
Eric Laurenta553c252009-07-17 12:17:14 -070077 // start audio commands thread
Eric Laurentcef3cd72009-12-10 01:03:50 -080078 mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
Eric Laurenta553c252009-07-17 12:17:14 -070079
Dima Zavin24fc2fb2011-04-19 22:30:36 -070080 /* instantiate the audio policy manager */
81 rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
82 if (rc)
83 return;
Eric Laurenta553c252009-07-17 12:17:14 -070084
Dima Zavin24fc2fb2011-04-19 22:30:36 -070085 rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
86 LOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
87 if (rc)
88 return;
Eric Laurent01635942011-01-18 18:39:02 -080089
Dima Zavin24fc2fb2011-04-19 22:30:36 -070090 rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
91 &mpAudioPolicy);
92 LOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
93 if (rc)
94 return;
95
96 rc = mpAudioPolicy->init_check(mpAudioPolicy);
97 LOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
98 if (rc)
99 return;
100
101 property_get("ro.camera.sound.forced", value, "0");
102 forced_val = strtol(value, NULL, 0);
103 mpAudioPolicy->set_can_mute_enforced_audible(mpAudioPolicy, !forced_val);
104
Steve Block6215d3f2012-01-04 20:05:49 +0000105 ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
Eric Laurent464d5b32011-06-17 21:29:58 -0700106
107 // load audio pre processing modules
108 if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
109 loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
110 } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
111 loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
112 }
Eric Laurenta553c252009-07-17 12:17:14 -0700113}
114
115AudioPolicyService::~AudioPolicyService()
116{
Eric Laurent327c27b2009-08-27 00:48:47 -0700117 mTonePlaybackThread->exit();
118 mTonePlaybackThread.clear();
Eric Laurenta553c252009-07-17 12:17:14 -0700119 mAudioCommandThread->exit();
120 mAudioCommandThread.clear();
121
Eric Laurent464d5b32011-06-17 21:29:58 -0700122
123 // release audio pre processing resources
124 for (size_t i = 0; i < mInputSources.size(); i++) {
125 InputSourceDesc *source = mInputSources.valueAt(i);
126 Vector <EffectDesc *> effects = source->mEffects;
127 for (size_t j = 0; j < effects.size(); j++) {
128 delete effects[j]->mName;
129 Vector <effect_param_t *> params = effects[j]->mParams;
130 for (size_t k = 0; k < params.size(); k++) {
131 delete params[k];
132 }
133 params.clear();
134 delete effects[j];
135 }
136 effects.clear();
137 delete source;
138 }
139 mInputSources.clear();
140
141 for (size_t i = 0; i < mInputs.size(); i++) {
142 mInputs.valueAt(i)->mEffects.clear();
143 delete mInputs.valueAt(i);
144 }
145 mInputs.clear();
146
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700147 if (mpAudioPolicy && mpAudioPolicyDev)
148 mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
149 if (mpAudioPolicyDev)
150 audio_policy_dev_close(mpAudioPolicyDev);
Eric Laurenta553c252009-07-17 12:17:14 -0700151}
152
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700153status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
154 audio_policy_dev_state_t state,
Eric Laurenta553c252009-07-17 12:17:14 -0700155 const char *device_address)
156{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700157 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700158 return NO_INIT;
159 }
160 if (!checkPermission()) {
161 return PERMISSION_DENIED;
162 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700163 if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
Eric Laurenta553c252009-07-17 12:17:14 -0700164 return BAD_VALUE;
165 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700166 if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
167 state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
Eric Laurenta553c252009-07-17 12:17:14 -0700168 return BAD_VALUE;
169 }
170
Steve Block71f2cf12011-10-20 11:56:00 +0100171 ALOGV("setDeviceConnectionState() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700172 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700173 return mpAudioPolicy->set_device_connection_state(mpAudioPolicy, device,
174 state, device_address);
Eric Laurenta553c252009-07-17 12:17:14 -0700175}
176
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700177audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
178 audio_devices_t device,
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700179 const char *device_address)
Eric Laurenta553c252009-07-17 12:17:14 -0700180{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700181 if (mpAudioPolicy == NULL) {
182 return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
Eric Laurenta553c252009-07-17 12:17:14 -0700183 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700184 return mpAudioPolicy->get_device_connection_state(mpAudioPolicy, device,
185 device_address);
Eric Laurenta553c252009-07-17 12:17:14 -0700186}
187
188status_t AudioPolicyService::setPhoneState(int state)
189{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700190 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700191 return NO_INIT;
192 }
193 if (!checkPermission()) {
194 return PERMISSION_DENIED;
195 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700196 if (state < 0 || state >= AUDIO_MODE_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700197 return BAD_VALUE;
198 }
199
Steve Block71f2cf12011-10-20 11:56:00 +0100200 ALOGV("setPhoneState() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700201
202 // TODO: check if it is more appropriate to do it in platform specific policy manager
203 AudioSystem::setMode(state);
204
205 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700206 mpAudioPolicy->set_phone_state(mpAudioPolicy, state);
Eric Laurenta553c252009-07-17 12:17:14 -0700207 return NO_ERROR;
208}
209
210status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
211{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700212 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700213 return NO_INIT;
214 }
215 if (!checkPermission()) {
216 return PERMISSION_DENIED;
217 }
218
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700219 mpAudioPolicy->set_ringer_mode(mpAudioPolicy, mode, mask);
Eric Laurenta553c252009-07-17 12:17:14 -0700220 return NO_ERROR;
221}
222
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700223status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
224 audio_policy_forced_cfg_t config)
Eric Laurenta553c252009-07-17 12:17:14 -0700225{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700226 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700227 return NO_INIT;
228 }
229 if (!checkPermission()) {
230 return PERMISSION_DENIED;
231 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700232 if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700233 return BAD_VALUE;
234 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700235 if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700236 return BAD_VALUE;
237 }
Steve Block71f2cf12011-10-20 11:56:00 +0100238 ALOGV("setForceUse() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700239 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700240 mpAudioPolicy->set_force_use(mpAudioPolicy, usage, config);
Eric Laurenta553c252009-07-17 12:17:14 -0700241 return NO_ERROR;
242}
243
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700244audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage)
Eric Laurenta553c252009-07-17 12:17:14 -0700245{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700246 if (mpAudioPolicy == NULL) {
247 return AUDIO_POLICY_FORCE_NONE;
Eric Laurenta553c252009-07-17 12:17:14 -0700248 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700249 if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
250 return AUDIO_POLICY_FORCE_NONE;
Eric Laurenta553c252009-07-17 12:17:14 -0700251 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700252 return mpAudioPolicy->get_force_use(mpAudioPolicy, usage);
Eric Laurenta553c252009-07-17 12:17:14 -0700253}
254
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700255audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream,
Eric Laurenta553c252009-07-17 12:17:14 -0700256 uint32_t samplingRate,
257 uint32_t format,
258 uint32_t channels,
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700259 audio_policy_output_flags_t flags)
Eric Laurenta553c252009-07-17 12:17:14 -0700260{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700261 if (mpAudioPolicy == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700262 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -0700263 }
Steve Block71f2cf12011-10-20 11:56:00 +0100264 ALOGV("getOutput() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700265 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700266 return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channels, flags);
Eric Laurenta553c252009-07-17 12:17:14 -0700267}
268
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700269status_t AudioPolicyService::startOutput(audio_io_handle_t output,
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700270 audio_stream_type_t stream,
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700271 int session)
Eric Laurenta553c252009-07-17 12:17:14 -0700272{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700273 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700274 return NO_INIT;
275 }
Steve Block71f2cf12011-10-20 11:56:00 +0100276 ALOGV("startOutput() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700277 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700278 return mpAudioPolicy->start_output(mpAudioPolicy, output, stream, session);
Eric Laurenta553c252009-07-17 12:17:14 -0700279}
280
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700281status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700282 audio_stream_type_t stream,
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700283 int session)
Eric Laurenta553c252009-07-17 12:17:14 -0700284{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700285 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700286 return NO_INIT;
287 }
Steve Block71f2cf12011-10-20 11:56:00 +0100288 ALOGV("stopOutput() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700289 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700290 return mpAudioPolicy->stop_output(mpAudioPolicy, output, stream, session);
Eric Laurenta553c252009-07-17 12:17:14 -0700291}
292
293void AudioPolicyService::releaseOutput(audio_io_handle_t output)
294{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700295 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700296 return;
297 }
Steve Block71f2cf12011-10-20 11:56:00 +0100298 ALOGV("releaseOutput() tid %d", gettid());
Eric Laurenta553c252009-07-17 12:17:14 -0700299 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700300 mpAudioPolicy->release_output(mpAudioPolicy, output);
Eric Laurenta553c252009-07-17 12:17:14 -0700301}
302
303audio_io_handle_t AudioPolicyService::getInput(int inputSource,
304 uint32_t samplingRate,
305 uint32_t format,
306 uint32_t channels,
Eric Laurent464d5b32011-06-17 21:29:58 -0700307 audio_in_acoustics_t acoustics,
308 int audioSession)
Eric Laurenta553c252009-07-17 12:17:14 -0700309{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700310 if (mpAudioPolicy == NULL) {
Eric Laurentddb78e72009-07-28 08:44:33 -0700311 return 0;
Eric Laurenta553c252009-07-17 12:17:14 -0700312 }
313 Mutex::Autolock _l(mLock);
Eric Laurent464d5b32011-06-17 21:29:58 -0700314 audio_io_handle_t input = mpAudioPolicy->get_input(mpAudioPolicy, inputSource, samplingRate,
315 format, channels, acoustics);
316
317 if (input == 0) {
318 return input;
319 }
320 // create audio pre processors according to input source
321 ssize_t index = mInputSources.indexOfKey((audio_source_t)inputSource);
322 if (index < 0) {
323 return input;
324 }
325 ssize_t idx = mInputs.indexOfKey(input);
326 InputDesc *inputDesc;
327 if (idx < 0) {
328 inputDesc = new InputDesc();
329 inputDesc->mSessionId = audioSession;
330 mInputs.add(input, inputDesc);
331 } else {
332 inputDesc = mInputs.valueAt(idx);
333 }
334
335 Vector <EffectDesc *> effects = mInputSources.valueAt(index)->mEffects;
336 for (size_t i = 0; i < effects.size(); i++) {
337 EffectDesc *effect = effects[i];
338 sp<AudioEffect> fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
339 status_t status = fx->initCheck();
340 if (status != NO_ERROR && status != ALREADY_EXISTS) {
341 LOGW("Failed to create Fx %s on input %d", effect->mName, input);
342 // fx goes out of scope and strong ref on AudioEffect is released
343 continue;
344 }
345 for (size_t j = 0; j < effect->mParams.size(); j++) {
346 fx->setParameter(effect->mParams[j]);
347 }
348 inputDesc->mEffects.add(fx);
349 }
350 setPreProcessorEnabled(inputDesc, true);
351 return input;
Eric Laurenta553c252009-07-17 12:17:14 -0700352}
353
354status_t AudioPolicyService::startInput(audio_io_handle_t input)
355{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700356 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700357 return NO_INIT;
358 }
359 Mutex::Autolock _l(mLock);
Eric Laurent464d5b32011-06-17 21:29:58 -0700360
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700361 return mpAudioPolicy->start_input(mpAudioPolicy, input);
Eric Laurenta553c252009-07-17 12:17:14 -0700362}
363
364status_t AudioPolicyService::stopInput(audio_io_handle_t input)
365{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700366 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700367 return NO_INIT;
368 }
369 Mutex::Autolock _l(mLock);
Eric Laurent464d5b32011-06-17 21:29:58 -0700370
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700371 return mpAudioPolicy->stop_input(mpAudioPolicy, input);
Eric Laurenta553c252009-07-17 12:17:14 -0700372}
373
374void AudioPolicyService::releaseInput(audio_io_handle_t input)
375{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700376 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700377 return;
378 }
379 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700380 mpAudioPolicy->release_input(mpAudioPolicy, input);
Eric Laurent464d5b32011-06-17 21:29:58 -0700381
382 ssize_t index = mInputs.indexOfKey(input);
383 if (index < 0) {
384 return;
385 }
386 InputDesc *inputDesc = mInputs.valueAt(index);
387 setPreProcessorEnabled(inputDesc, false);
388 inputDesc->mEffects.clear();
389 delete inputDesc;
390 mInputs.removeItemsAt(index);
Eric Laurenta553c252009-07-17 12:17:14 -0700391}
392
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700393status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
Eric Laurenta553c252009-07-17 12:17:14 -0700394 int indexMin,
395 int indexMax)
396{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700397 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700398 return NO_INIT;
399 }
400 if (!checkPermission()) {
401 return PERMISSION_DENIED;
402 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700403 if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700404 return BAD_VALUE;
405 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700406 mpAudioPolicy->init_stream_volume(mpAudioPolicy, stream, indexMin, indexMax);
Eric Laurenta553c252009-07-17 12:17:14 -0700407 return NO_ERROR;
408}
409
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700410status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, int index)
Eric Laurenta553c252009-07-17 12:17:14 -0700411{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700412 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700413 return NO_INIT;
414 }
415 if (!checkPermission()) {
416 return PERMISSION_DENIED;
417 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700418 if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700419 return BAD_VALUE;
420 }
421
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700422 return mpAudioPolicy->set_stream_volume_index(mpAudioPolicy, stream, index);
Eric Laurenta553c252009-07-17 12:17:14 -0700423}
424
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700425status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, int *index)
Eric Laurenta553c252009-07-17 12:17:14 -0700426{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700427 if (mpAudioPolicy == NULL) {
Eric Laurenta553c252009-07-17 12:17:14 -0700428 return NO_INIT;
429 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700430 if (stream < 0 || stream >= AUDIO_STREAM_CNT) {
Eric Laurenta553c252009-07-17 12:17:14 -0700431 return BAD_VALUE;
432 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700433 return mpAudioPolicy->get_stream_volume_index(mpAudioPolicy, stream, index);
Eric Laurenta553c252009-07-17 12:17:14 -0700434}
435
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700436uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700437{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700438 if (mpAudioPolicy == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700439 return 0;
440 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700441 return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700442}
443
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700444uint32_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800445{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700446 if (mpAudioPolicy == NULL) {
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800447 return 0;
448 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700449 return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800450}
451
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700452audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
453{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700454 if (mpAudioPolicy == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700455 return NO_INIT;
456 }
457 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700458 return mpAudioPolicy->get_output_for_effect(mpAudioPolicy, desc);
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700459}
460
461status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
Eric Laurent464d5b32011-06-17 21:29:58 -0700462 audio_io_handle_t io,
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700463 uint32_t strategy,
464 int session,
465 int id)
466{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700467 if (mpAudioPolicy == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700468 return NO_INIT;
469 }
Eric Laurent464d5b32011-06-17 21:29:58 -0700470 return mpAudioPolicy->register_effect(mpAudioPolicy, desc, io, strategy, session, id);
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700471}
472
473status_t AudioPolicyService::unregisterEffect(int id)
474{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700475 if (mpAudioPolicy == NULL) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700476 return NO_INIT;
477 }
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700478 return mpAudioPolicy->unregister_effect(mpAudioPolicy, id);
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700479}
480
Eric Laurent6752ec82011-08-10 10:37:50 -0700481status_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
482{
483 if (mpAudioPolicy == NULL) {
484 return NO_INIT;
485 }
486 return mpAudioPolicy->set_effect_enabled(mpAudioPolicy, id, enabled);
487}
488
Eric Laurent25101b02011-02-02 09:33:30 -0800489bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
490{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700491 if (mpAudioPolicy == NULL) {
Eric Laurent25101b02011-02-02 09:33:30 -0800492 return 0;
493 }
494 Mutex::Autolock _l(mLock);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700495 return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
Eric Laurent25101b02011-02-02 09:33:30 -0800496}
497
Eric Laurent0f7f4ec2011-07-24 13:36:09 -0700498status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
499 effect_descriptor_t *descriptors,
500 uint32_t *count)
501{
502
503 if (mpAudioPolicy == NULL) {
504 *count = 0;
505 return NO_INIT;
506 }
507 Mutex::Autolock _l(mLock);
508 status_t status = NO_ERROR;
509
510 size_t index;
511 for (index = 0; index < mInputs.size(); index++) {
512 if (mInputs.valueAt(index)->mSessionId == audioSession) {
513 break;
514 }
515 }
516 if (index == mInputs.size()) {
517 *count = 0;
518 return BAD_VALUE;
519 }
520 Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
521
522 for (size_t i = 0; i < effects.size(); i++) {
523 effect_descriptor_t desc = effects[i]->descriptor();
524 if (i < *count) {
525 memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
526 }
527 }
528 if (effects.size() > *count) {
529 status = NO_MEMORY;
530 }
531 *count = effects.size();
532 return status;
533}
534
Eric Laurenta553c252009-07-17 12:17:14 -0700535void AudioPolicyService::binderDied(const wp<IBinder>& who) {
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700536 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
537 IPCThreadState::self()->getCallingPid());
Eric Laurenta553c252009-07-17 12:17:14 -0700538}
539
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800540static bool tryLock(Mutex& mutex)
541{
542 bool locked = false;
543 for (int i = 0; i < kDumpLockRetries; ++i) {
544 if (mutex.tryLock() == NO_ERROR) {
545 locked = true;
546 break;
547 }
548 usleep(kDumpLockSleep);
549 }
550 return locked;
551}
552
553status_t AudioPolicyService::dumpInternals(int fd)
554{
555 const size_t SIZE = 256;
556 char buffer[SIZE];
557 String8 result;
558
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700559 snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800560 result.append(buffer);
561 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
562 result.append(buffer);
563 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
564 result.append(buffer);
565
566 write(fd, result.string(), result.size());
567 return NO_ERROR;
568}
569
Eric Laurenta553c252009-07-17 12:17:14 -0700570status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
571{
572 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800573 dumpPermissionDenial(fd);
Eric Laurenta553c252009-07-17 12:17:14 -0700574 } else {
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800575 bool locked = tryLock(mLock);
576 if (!locked) {
577 String8 result(kDeadlockedString);
578 write(fd, result.string(), result.size());
579 }
Eric Laurenta553c252009-07-17 12:17:14 -0700580
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800581 dumpInternals(fd);
582 if (mAudioCommandThread != NULL) {
583 mAudioCommandThread->dump(fd);
584 }
585 if (mTonePlaybackThread != NULL) {
586 mTonePlaybackThread->dump(fd);
587 }
588
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700589 if (mpAudioPolicy) {
590 mpAudioPolicy->dump(mpAudioPolicy, fd);
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800591 }
592
593 if (locked) mLock.unlock();
Eric Laurenta553c252009-07-17 12:17:14 -0700594 }
595 return NO_ERROR;
596}
597
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800598status_t AudioPolicyService::dumpPermissionDenial(int fd)
Eric Laurenta553c252009-07-17 12:17:14 -0700599{
600 const size_t SIZE = 256;
601 char buffer[SIZE];
602 String8 result;
603 snprintf(buffer, SIZE, "Permission Denial: "
604 "can't dump AudioPolicyService from pid=%d, uid=%d\n",
605 IPCThreadState::self()->getCallingPid(),
606 IPCThreadState::self()->getCallingUid());
607 result.append(buffer);
608 write(fd, result.string(), result.size());
609 return NO_ERROR;
610}
611
Eric Laurent464d5b32011-06-17 21:29:58 -0700612void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled)
613{
614 Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects;
615 for (size_t i = 0; i < fxVector.size(); i++) {
616 sp<AudioEffect> fx = fxVector.itemAt(i);
617 fx->setEnabled(enabled);
618 }
619}
620
Eric Laurenta553c252009-07-17 12:17:14 -0700621status_t AudioPolicyService::onTransact(
622 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
623{
624 return BnAudioPolicyService::onTransact(code, data, reply, flags);
625}
626
627
Eric Laurenta553c252009-07-17 12:17:14 -0700628// ----------- AudioPolicyService::AudioCommandThread implementation ----------
629
Eric Laurentcef3cd72009-12-10 01:03:50 -0800630AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
631 : Thread(false), mName(name)
Eric Laurenta553c252009-07-17 12:17:14 -0700632{
633 mpToneGenerator = NULL;
634}
635
636
637AudioPolicyService::AudioCommandThread::~AudioCommandThread()
638{
Eric Laurentcef3cd72009-12-10 01:03:50 -0800639 if (mName != "" && !mAudioCommands.isEmpty()) {
640 release_wake_lock(mName.string());
641 }
Eric Laurenta553c252009-07-17 12:17:14 -0700642 mAudioCommands.clear();
643 if (mpToneGenerator != NULL) delete mpToneGenerator;
644}
645
646void AudioPolicyService::AudioCommandThread::onFirstRef()
647{
Eric Laurentcef3cd72009-12-10 01:03:50 -0800648 if (mName != "") {
649 run(mName.string(), ANDROID_PRIORITY_AUDIO);
650 } else {
651 run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
652 }
Eric Laurenta553c252009-07-17 12:17:14 -0700653}
654
655bool AudioPolicyService::AudioCommandThread::threadLoop()
656{
Eric Laurent327c27b2009-08-27 00:48:47 -0700657 nsecs_t waitTime = INT64_MAX;
658
Eric Laurenta553c252009-07-17 12:17:14 -0700659 mLock.lock();
660 while (!exitPending())
661 {
662 while(!mAudioCommands.isEmpty()) {
Eric Laurent327c27b2009-08-27 00:48:47 -0700663 nsecs_t curTime = systemTime();
664 // commands are sorted by increasing time stamp: execute them from index 0 and up
665 if (mAudioCommands[0]->mTime <= curTime) {
666 AudioCommand *command = mAudioCommands[0];
667 mAudioCommands.removeAt(0);
Eric Laurent3fdb1262009-11-07 00:01:32 -0800668 mLastCommand = *command;
669
Eric Laurent327c27b2009-08-27 00:48:47 -0700670 switch (command->mCommand) {
671 case START_TONE: {
672 mLock.unlock();
673 ToneData *data = (ToneData *)command->mParam;
Steve Block71f2cf12011-10-20 11:56:00 +0100674 ALOGV("AudioCommandThread() processing start tone %d on stream %d",
Eric Laurent327c27b2009-08-27 00:48:47 -0700675 data->mType, data->mStream);
676 if (mpToneGenerator != NULL)
677 delete mpToneGenerator;
678 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
679 mpToneGenerator->startTone(data->mType);
680 delete data;
681 mLock.lock();
682 }break;
683 case STOP_TONE: {
684 mLock.unlock();
Steve Block71f2cf12011-10-20 11:56:00 +0100685 ALOGV("AudioCommandThread() processing stop tone");
Eric Laurent327c27b2009-08-27 00:48:47 -0700686 if (mpToneGenerator != NULL) {
687 mpToneGenerator->stopTone();
688 delete mpToneGenerator;
689 mpToneGenerator = NULL;
690 }
691 mLock.lock();
692 }break;
693 case SET_VOLUME: {
694 VolumeData *data = (VolumeData *)command->mParam;
Steve Block71f2cf12011-10-20 11:56:00 +0100695 ALOGV("AudioCommandThread() processing set volume stream %d, \
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700696 volume %f, output %d", data->mStream, data->mVolume, data->mIO);
697 command->mStatus = AudioSystem::setStreamVolume(data->mStream,
698 data->mVolume,
699 data->mIO);
Eric Laurent327c27b2009-08-27 00:48:47 -0700700 if (command->mWaitStatus) {
701 command->mCond.signal();
702 mWaitWorkCV.wait(mLock);
703 }
704 delete data;
705 }break;
706 case SET_PARAMETERS: {
707 ParametersData *data = (ParametersData *)command->mParam;
Steve Block71f2cf12011-10-20 11:56:00 +0100708 ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700709 data->mKeyValuePairs.string(), data->mIO);
Eric Laurent327c27b2009-08-27 00:48:47 -0700710 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
711 if (command->mWaitStatus) {
712 command->mCond.signal();
713 mWaitWorkCV.wait(mLock);
714 }
715 delete data;
716 }break;
Eric Laurent415f3e22009-10-21 08:14:22 -0700717 case SET_VOICE_VOLUME: {
718 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
Steve Block71f2cf12011-10-20 11:56:00 +0100719 ALOGV("AudioCommandThread() processing set voice volume volume %f",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700720 data->mVolume);
Eric Laurent415f3e22009-10-21 08:14:22 -0700721 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
722 if (command->mWaitStatus) {
723 command->mCond.signal();
724 mWaitWorkCV.wait(mLock);
725 }
726 delete data;
727 }break;
Eric Laurent327c27b2009-08-27 00:48:47 -0700728 default:
729 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
Eric Laurenta553c252009-07-17 12:17:14 -0700730 }
Eric Laurent327c27b2009-08-27 00:48:47 -0700731 delete command;
732 waitTime = INT64_MAX;
733 } else {
734 waitTime = mAudioCommands[0]->mTime - curTime;
735 break;
Eric Laurenta553c252009-07-17 12:17:14 -0700736 }
Eric Laurenta553c252009-07-17 12:17:14 -0700737 }
Eric Laurentcef3cd72009-12-10 01:03:50 -0800738 // release delayed commands wake lock
739 if (mName != "" && mAudioCommands.isEmpty()) {
740 release_wake_lock(mName.string());
741 }
Steve Block71f2cf12011-10-20 11:56:00 +0100742 ALOGV("AudioCommandThread() going to sleep");
Eric Laurent327c27b2009-08-27 00:48:47 -0700743 mWaitWorkCV.waitRelative(mLock, waitTime);
Steve Block71f2cf12011-10-20 11:56:00 +0100744 ALOGV("AudioCommandThread() waking up");
Eric Laurenta553c252009-07-17 12:17:14 -0700745 }
746 mLock.unlock();
747 return false;
748}
749
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800750status_t AudioPolicyService::AudioCommandThread::dump(int fd)
751{
752 const size_t SIZE = 256;
753 char buffer[SIZE];
754 String8 result;
755
756 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
757 result.append(buffer);
758 write(fd, result.string(), result.size());
759
760 bool locked = tryLock(mLock);
761 if (!locked) {
762 String8 result2(kCmdDeadlockedString);
763 write(fd, result2.string(), result2.size());
764 }
765
766 snprintf(buffer, SIZE, "- Commands:\n");
767 result = String8(buffer);
Eric Laurent3fdb1262009-11-07 00:01:32 -0800768 result.append(" Command Time Wait pParam\n");
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800769 for (int i = 0; i < (int)mAudioCommands.size(); i++) {
770 mAudioCommands[i]->dump(buffer, SIZE);
771 result.append(buffer);
772 }
Eric Laurent3fdb1262009-11-07 00:01:32 -0800773 result.append(" Last Command\n");
774 mLastCommand.dump(buffer, SIZE);
775 result.append(buffer);
776
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800777 write(fd, result.string(), result.size());
778
779 if (locked) mLock.unlock();
780
781 return NO_ERROR;
782}
783
Eric Laurenta553c252009-07-17 12:17:14 -0700784void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
785{
Eric Laurenta553c252009-07-17 12:17:14 -0700786 AudioCommand *command = new AudioCommand();
787 command->mCommand = START_TONE;
788 ToneData *data = new ToneData();
789 data->mType = type;
790 data->mStream = stream;
791 command->mParam = (void *)data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700792 command->mWaitStatus = false;
Eric Laurent415f3e22009-10-21 08:14:22 -0700793 Mutex::Autolock _l(mLock);
Eric Laurent327c27b2009-08-27 00:48:47 -0700794 insertCommand_l(command);
Steve Block71f2cf12011-10-20 11:56:00 +0100795 ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
Eric Laurenta553c252009-07-17 12:17:14 -0700796 mWaitWorkCV.signal();
797}
798
799void AudioPolicyService::AudioCommandThread::stopToneCommand()
800{
Eric Laurenta553c252009-07-17 12:17:14 -0700801 AudioCommand *command = new AudioCommand();
802 command->mCommand = STOP_TONE;
803 command->mParam = NULL;
Eric Laurent327c27b2009-08-27 00:48:47 -0700804 command->mWaitStatus = false;
Eric Laurent415f3e22009-10-21 08:14:22 -0700805 Mutex::Autolock _l(mLock);
Eric Laurent327c27b2009-08-27 00:48:47 -0700806 insertCommand_l(command);
Steve Block71f2cf12011-10-20 11:56:00 +0100807 ALOGV("AudioCommandThread() adding tone stop");
Eric Laurenta553c252009-07-17 12:17:14 -0700808 mWaitWorkCV.signal();
809}
810
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700811status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
812 float volume,
813 int output,
814 int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700815{
Eric Laurent327c27b2009-08-27 00:48:47 -0700816 status_t status = NO_ERROR;
817
Eric Laurenta553c252009-07-17 12:17:14 -0700818 AudioCommand *command = new AudioCommand();
819 command->mCommand = SET_VOLUME;
820 VolumeData *data = new VolumeData();
821 data->mStream = stream;
822 data->mVolume = volume;
823 data->mIO = output;
824 command->mParam = data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700825 if (delayMs == 0) {
826 command->mWaitStatus = true;
827 } else {
828 command->mWaitStatus = false;
829 }
Eric Laurent415f3e22009-10-21 08:14:22 -0700830 Mutex::Autolock _l(mLock);
Eric Laurent327c27b2009-08-27 00:48:47 -0700831 insertCommand_l(command, delayMs);
Steve Block71f2cf12011-10-20 11:56:00 +0100832 ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700833 stream, volume, output);
Eric Laurenta553c252009-07-17 12:17:14 -0700834 mWaitWorkCV.signal();
Eric Laurent327c27b2009-08-27 00:48:47 -0700835 if (command->mWaitStatus) {
836 command->mCond.wait(mLock);
837 status = command->mStatus;
838 mWaitWorkCV.signal();
839 }
Eric Laurenta553c252009-07-17 12:17:14 -0700840 return status;
841}
842
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700843status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700844 const char *keyValuePairs,
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700845 int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700846{
Eric Laurent327c27b2009-08-27 00:48:47 -0700847 status_t status = NO_ERROR;
848
Eric Laurenta553c252009-07-17 12:17:14 -0700849 AudioCommand *command = new AudioCommand();
850 command->mCommand = SET_PARAMETERS;
851 ParametersData *data = new ParametersData();
852 data->mIO = ioHandle;
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700853 data->mKeyValuePairs = String8(keyValuePairs);
Eric Laurenta553c252009-07-17 12:17:14 -0700854 command->mParam = data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700855 if (delayMs == 0) {
856 command->mWaitStatus = true;
857 } else {
858 command->mWaitStatus = false;
859 }
Eric Laurent415f3e22009-10-21 08:14:22 -0700860 Mutex::Autolock _l(mLock);
Eric Laurent327c27b2009-08-27 00:48:47 -0700861 insertCommand_l(command, delayMs);
Steve Block71f2cf12011-10-20 11:56:00 +0100862 ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700863 keyValuePairs, ioHandle, delayMs);
Eric Laurenta553c252009-07-17 12:17:14 -0700864 mWaitWorkCV.signal();
Eric Laurent327c27b2009-08-27 00:48:47 -0700865 if (command->mWaitStatus) {
866 command->mCond.wait(mLock);
867 status = command->mStatus;
868 mWaitWorkCV.signal();
869 }
Eric Laurenta553c252009-07-17 12:17:14 -0700870 return status;
871}
872
Eric Laurent415f3e22009-10-21 08:14:22 -0700873status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
874{
875 status_t status = NO_ERROR;
876
877 AudioCommand *command = new AudioCommand();
878 command->mCommand = SET_VOICE_VOLUME;
879 VoiceVolumeData *data = new VoiceVolumeData();
880 data->mVolume = volume;
881 command->mParam = data;
882 if (delayMs == 0) {
883 command->mWaitStatus = true;
884 } else {
885 command->mWaitStatus = false;
886 }
887 Mutex::Autolock _l(mLock);
888 insertCommand_l(command, delayMs);
Steve Block71f2cf12011-10-20 11:56:00 +0100889 ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
Eric Laurent415f3e22009-10-21 08:14:22 -0700890 mWaitWorkCV.signal();
891 if (command->mWaitStatus) {
892 command->mCond.wait(mLock);
893 status = command->mStatus;
894 mWaitWorkCV.signal();
895 }
896 return status;
897}
898
Eric Laurent327c27b2009-08-27 00:48:47 -0700899// insertCommand_l() must be called with mLock held
900void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
901{
902 ssize_t i;
903 Vector <AudioCommand *> removedCommands;
904
905 command->mTime = systemTime() + milliseconds(delayMs);
906
Eric Laurentcef3cd72009-12-10 01:03:50 -0800907 // acquire wake lock to make sure delayed commands are processed
908 if (mName != "" && mAudioCommands.isEmpty()) {
909 acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
910 }
911
Eric Laurent327c27b2009-08-27 00:48:47 -0700912 // check same pending commands with later time stamps and eliminate them
913 for (i = mAudioCommands.size()-1; i >= 0; i--) {
914 AudioCommand *command2 = mAudioCommands[i];
915 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
916 if (command2->mTime <= command->mTime) break;
917 if (command2->mCommand != command->mCommand) continue;
918
919 switch (command->mCommand) {
920 case SET_PARAMETERS: {
921 ParametersData *data = (ParametersData *)command->mParam;
922 ParametersData *data2 = (ParametersData *)command2->mParam;
923 if (data->mIO != data2->mIO) break;
Steve Block71f2cf12011-10-20 11:56:00 +0100924 ALOGV("Comparing parameter command %s to new command %s",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700925 data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
Eric Laurent327c27b2009-08-27 00:48:47 -0700926 AudioParameter param = AudioParameter(data->mKeyValuePairs);
927 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
928 for (size_t j = 0; j < param.size(); j++) {
929 String8 key;
930 String8 value;
931 param.getAt(j, key, value);
932 for (size_t k = 0; k < param2.size(); k++) {
933 String8 key2;
934 String8 value2;
935 param2.getAt(k, key2, value2);
936 if (key2 == key) {
937 param2.remove(key2);
Steve Block71f2cf12011-10-20 11:56:00 +0100938 ALOGV("Filtering out parameter %s", key2.string());
Eric Laurent327c27b2009-08-27 00:48:47 -0700939 break;
940 }
941 }
942 }
943 // if all keys have been filtered out, remove the command.
944 // otherwise, update the key value pairs
945 if (param2.size() == 0) {
946 removedCommands.add(command2);
947 } else {
948 data2->mKeyValuePairs = param2.toString();
949 }
950 } break;
951
952 case SET_VOLUME: {
953 VolumeData *data = (VolumeData *)command->mParam;
954 VolumeData *data2 = (VolumeData *)command2->mParam;
955 if (data->mIO != data2->mIO) break;
956 if (data->mStream != data2->mStream) break;
Steve Block71f2cf12011-10-20 11:56:00 +0100957 ALOGV("Filtering out volume command on output %d for stream %d",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700958 data->mIO, data->mStream);
Eric Laurent327c27b2009-08-27 00:48:47 -0700959 removedCommands.add(command2);
960 } break;
961 case START_TONE:
962 case STOP_TONE:
963 default:
964 break;
965 }
966 }
967
968 // remove filtered commands
969 for (size_t j = 0; j < removedCommands.size(); j++) {
970 // removed commands always have time stamps greater than current command
971 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
972 if (mAudioCommands[k] == removedCommands[j]) {
Steve Block71f2cf12011-10-20 11:56:00 +0100973 ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
Eric Laurent327c27b2009-08-27 00:48:47 -0700974 mAudioCommands.removeAt(k);
975 break;
976 }
977 }
978 }
979 removedCommands.clear();
980
981 // insert command at the right place according to its time stamp
Steve Block71f2cf12011-10-20 11:56:00 +0100982 ALOGV("inserting command: %d at index %d, num commands %d",
Eric Laurent8ed6ed02010-07-13 04:45:46 -0700983 command->mCommand, (int)i+1, mAudioCommands.size());
Eric Laurent327c27b2009-08-27 00:48:47 -0700984 mAudioCommands.insertAt(command, i + 1);
985}
986
Eric Laurenta553c252009-07-17 12:17:14 -0700987void AudioPolicyService::AudioCommandThread::exit()
988{
Steve Block71f2cf12011-10-20 11:56:00 +0100989 ALOGV("AudioCommandThread::exit");
Eric Laurenta553c252009-07-17 12:17:14 -0700990 {
991 AutoMutex _l(mLock);
992 requestExit();
993 mWaitWorkCV.signal();
994 }
995 requestExitAndWait();
996}
997
Eric Laurentf4ee40e2009-11-02 10:29:02 -0800998void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
999{
Eric Laurent3fdb1262009-11-07 00:01:32 -08001000 snprintf(buffer, size, " %02d %06d.%03d %01u %p\n",
Eric Laurentf4ee40e2009-11-02 10:29:02 -08001001 mCommand,
1002 (int)ns2s(mTime),
1003 (int)ns2ms(mTime)%1000,
Eric Laurentf4ee40e2009-11-02 10:29:02 -08001004 mWaitStatus,
1005 mParam);
1006}
1007
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001008/******* helpers for the service_ops callbacks defined below *********/
1009void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
1010 const char *keyValuePairs,
1011 int delayMs)
1012{
1013 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs,
1014 delayMs);
1015}
1016
1017int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
1018 float volume,
1019 audio_io_handle_t output,
1020 int delayMs)
1021{
1022 return (int)mAudioCommandThread->volumeCommand((int)stream, volume,
1023 (int)output, delayMs);
1024}
1025
1026int AudioPolicyService::startTone(audio_policy_tone_t tone,
1027 audio_stream_type_t stream)
1028{
1029 if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION)
1030 LOGE("startTone: illegal tone requested (%d)", tone);
1031 if (stream != AUDIO_STREAM_VOICE_CALL)
1032 LOGE("startTone: illegal stream (%d) requested for tone %d", stream,
1033 tone);
1034 mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
1035 AUDIO_STREAM_VOICE_CALL);
1036 return 0;
1037}
1038
1039int AudioPolicyService::stopTone()
1040{
1041 mTonePlaybackThread->stopToneCommand();
1042 return 0;
1043}
1044
1045int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
1046{
1047 return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
1048}
1049
Eric Laurent464d5b32011-06-17 21:29:58 -07001050// ----------------------------------------------------------------------------
1051// Audio pre-processing configuration
1052// ----------------------------------------------------------------------------
1053
1054const char *AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
1055 MIC_SRC_TAG,
1056 VOICE_UL_SRC_TAG,
1057 VOICE_DL_SRC_TAG,
1058 VOICE_CALL_SRC_TAG,
1059 CAMCORDER_SRC_TAG,
1060 VOICE_REC_SRC_TAG,
1061 VOICE_COMM_SRC_TAG
1062};
1063
1064// returns the audio_source_t enum corresponding to the input source name or
1065// AUDIO_SOURCE_CNT is no match found
1066audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
1067{
1068 int i;
1069 for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
1070 if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
Steve Block71f2cf12011-10-20 11:56:00 +01001071 ALOGV("inputSourceNameToEnum found source %s %d", name, i);
Eric Laurent464d5b32011-06-17 21:29:58 -07001072 break;
1073 }
1074 }
1075 return (audio_source_t)i;
1076}
1077
1078size_t AudioPolicyService::growParamSize(char *param,
1079 size_t size,
1080 size_t *curSize,
1081 size_t *totSize)
1082{
1083 // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
1084 size_t pos = ((*curSize - 1 ) / size + 1) * size;
1085
1086 if (pos + size > *totSize) {
1087 while (pos + size > *totSize) {
1088 *totSize += ((*totSize + 7) / 8) * 4;
1089 }
1090 param = (char *)realloc(param, *totSize);
1091 }
1092 *curSize = pos + size;
1093 return pos;
1094}
1095
1096size_t AudioPolicyService::readParamValue(cnode *node,
1097 char *param,
1098 size_t *curSize,
1099 size_t *totSize)
1100{
1101 if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
1102 size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
1103 *(short *)((char *)param + pos) = (short)atoi(node->value);
Steve Block71f2cf12011-10-20 11:56:00 +01001104 ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
Eric Laurent464d5b32011-06-17 21:29:58 -07001105 return sizeof(short);
1106 } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
1107 size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
1108 *(int *)((char *)param + pos) = atoi(node->value);
Steve Block71f2cf12011-10-20 11:56:00 +01001109 ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
Eric Laurent464d5b32011-06-17 21:29:58 -07001110 return sizeof(int);
1111 } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
1112 size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
1113 *(float *)((char *)param + pos) = (float)atof(node->value);
Steve Block71f2cf12011-10-20 11:56:00 +01001114 ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
Eric Laurent464d5b32011-06-17 21:29:58 -07001115 return sizeof(float);
1116 } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
1117 size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
1118 if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
1119 *(bool *)((char *)param + pos) = false;
1120 } else {
1121 *(bool *)((char *)param + pos) = true;
1122 }
Steve Block71f2cf12011-10-20 11:56:00 +01001123 ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
Eric Laurent464d5b32011-06-17 21:29:58 -07001124 return sizeof(bool);
1125 } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
1126 size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
1127 if (*curSize + len + 1 > *totSize) {
1128 *totSize = *curSize + len + 1;
1129 param = (char *)realloc(param, *totSize);
1130 }
1131 strncpy(param + *curSize, node->value, len);
1132 *curSize += len;
1133 param[*curSize] = '\0';
Steve Block71f2cf12011-10-20 11:56:00 +01001134 ALOGV("readParamValue() reading string %s", param + *curSize - len);
Eric Laurent464d5b32011-06-17 21:29:58 -07001135 return len;
1136 }
1137 LOGW("readParamValue() unknown param type %s", node->name);
1138 return 0;
1139}
1140
1141effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
1142{
1143 cnode *param;
1144 cnode *value;
1145 size_t curSize = sizeof(effect_param_t);
1146 size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
1147 effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
1148
1149 param = config_find(root, PARAM_TAG);
1150 value = config_find(root, VALUE_TAG);
1151 if (param == NULL && value == NULL) {
1152 // try to parse simple parameter form {int int}
1153 param = root->first_child;
1154 if (param) {
1155 // Note: that a pair of random strings is read as 0 0
1156 int *ptr = (int *)fx_param->data;
1157 int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
1158 LOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
1159 *ptr++ = atoi(param->name);
1160 *ptr = atoi(param->value);
1161 fx_param->psize = sizeof(int);
1162 fx_param->vsize = sizeof(int);
1163 return fx_param;
1164 }
1165 }
1166 if (param == NULL || value == NULL) {
1167 LOGW("loadEffectParameter() invalid parameter description %s", root->name);
1168 goto error;
1169 }
1170
1171 fx_param->psize = 0;
1172 param = param->first_child;
1173 while (param) {
Steve Block71f2cf12011-10-20 11:56:00 +01001174 ALOGV("loadEffectParameter() reading param of type %s", param->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001175 size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
1176 if (size == 0) {
1177 goto error;
1178 }
1179 fx_param->psize += size;
1180 param = param->next;
1181 }
1182
1183 // align start of value field on 32 bit boundary
1184 curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
1185
1186 fx_param->vsize = 0;
1187 value = value->first_child;
1188 while (value) {
Steve Block71f2cf12011-10-20 11:56:00 +01001189 ALOGV("loadEffectParameter() reading value of type %s", value->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001190 size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
1191 if (size == 0) {
1192 goto error;
1193 }
1194 fx_param->vsize += size;
1195 value = value->next;
1196 }
1197
1198 return fx_param;
1199
1200error:
1201 delete fx_param;
1202 return NULL;
1203}
1204
1205void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
1206{
1207 cnode *node = root->first_child;
1208 while (node) {
Steve Block71f2cf12011-10-20 11:56:00 +01001209 ALOGV("loadEffectParameters() loading param %s", node->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001210 effect_param_t *param = loadEffectParameter(node);
1211 if (param == NULL) {
1212 node = node->next;
1213 continue;
1214 }
1215 params.add(param);
1216 node = node->next;
1217 }
1218}
1219
1220AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
1221 cnode *root,
1222 const Vector <EffectDesc *>& effects)
1223{
1224 cnode *node = root->first_child;
1225 if (node == NULL) {
1226 LOGW("loadInputSource() empty element %s", root->name);
1227 return NULL;
1228 }
1229 InputSourceDesc *source = new InputSourceDesc();
1230 while (node) {
1231 size_t i;
1232 for (i = 0; i < effects.size(); i++) {
1233 if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
Steve Block71f2cf12011-10-20 11:56:00 +01001234 ALOGV("loadInputSource() found effect %s in list", node->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001235 break;
1236 }
1237 }
1238 if (i == effects.size()) {
Steve Block71f2cf12011-10-20 11:56:00 +01001239 ALOGV("loadInputSource() effect %s not in list", node->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001240 node = node->next;
1241 continue;
1242 }
1243 EffectDesc *effect = new EffectDesc(*effects[i]);
1244 loadEffectParameters(node, effect->mParams);
Steve Block71f2cf12011-10-20 11:56:00 +01001245 ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
Eric Laurent464d5b32011-06-17 21:29:58 -07001246 source->mEffects.add(effect);
1247 node = node->next;
1248 }
1249 if (source->mEffects.size() == 0) {
1250 LOGW("loadInputSource() no valid effects found in source %s", root->name);
1251 delete source;
1252 return NULL;
1253 }
1254 return source;
1255}
1256
1257status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
1258{
1259 cnode *node = config_find(root, PREPROCESSING_TAG);
1260 if (node == NULL) {
1261 return -ENOENT;
1262 }
1263 node = node->first_child;
1264 while (node) {
1265 audio_source_t source = inputSourceNameToEnum(node->name);
1266 if (source == AUDIO_SOURCE_CNT) {
1267 LOGW("loadInputSources() invalid input source %s", node->name);
1268 node = node->next;
1269 continue;
1270 }
Steve Block71f2cf12011-10-20 11:56:00 +01001271 ALOGV("loadInputSources() loading input source %s", node->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001272 InputSourceDesc *desc = loadInputSource(node, effects);
1273 if (desc == NULL) {
1274 node = node->next;
1275 continue;
1276 }
1277 mInputSources.add(source, desc);
1278 node = node->next;
1279 }
1280 return NO_ERROR;
1281}
1282
1283AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
1284{
1285 cnode *node = config_find(root, UUID_TAG);
1286 if (node == NULL) {
1287 return NULL;
1288 }
1289 effect_uuid_t uuid;
1290 if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
1291 LOGW("loadEffect() invalid uuid %s", node->value);
1292 return NULL;
1293 }
1294 EffectDesc *effect = new EffectDesc();
1295 effect->mName = strdup(root->name);
1296 memcpy(&effect->mUuid, &uuid, sizeof(effect_uuid_t));
1297
1298 return effect;
1299}
1300
1301status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
1302{
1303 cnode *node = config_find(root, EFFECTS_TAG);
1304 if (node == NULL) {
1305 return -ENOENT;
1306 }
1307 node = node->first_child;
1308 while (node) {
Steve Block71f2cf12011-10-20 11:56:00 +01001309 ALOGV("loadEffects() loading effect %s", node->name);
Eric Laurent464d5b32011-06-17 21:29:58 -07001310 EffectDesc *effect = loadEffect(node);
1311 if (effect == NULL) {
1312 node = node->next;
1313 continue;
1314 }
1315 effects.add(effect);
1316 node = node->next;
1317 }
1318 return NO_ERROR;
1319}
1320
1321status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
1322{
1323 cnode *root;
1324 char *data;
1325
1326 data = (char *)load_file(path, NULL);
1327 if (data == NULL) {
1328 return -ENODEV;
1329 }
1330 root = config_node("", "");
1331 config_load(root, data);
1332
1333 Vector <EffectDesc *> effects;
1334 loadEffects(root, effects);
1335 loadInputSources(root, effects);
1336
1337 config_free(root);
1338 free(root);
1339 free(data);
1340
1341 return NO_ERROR;
1342}
1343
Dima Zavin24fc2fb2011-04-19 22:30:36 -07001344/* implementation of the interface to the policy manager */
1345extern "C" {
1346
1347static audio_io_handle_t aps_open_output(void *service,
1348 uint32_t *pDevices,
1349 uint32_t *pSamplingRate,
1350 uint32_t *pFormat,
1351 uint32_t *pChannels,
1352 uint32_t *pLatencyMs,
1353 audio_policy_output_flags_t flags)
1354{
1355 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1356 if (af == NULL) {
1357 LOGW("%s: could not get AudioFlinger", __func__);
1358 return 0;
1359 }
1360
1361 return af->openOutput(pDevices, pSamplingRate, pFormat, pChannels,
1362 pLatencyMs, flags);
1363}
1364
1365static audio_io_handle_t aps_open_dup_output(void *service,
1366 audio_io_handle_t output1,
1367 audio_io_handle_t output2)
1368{
1369 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1370 if (af == NULL) {
1371 LOGW("%s: could not get AudioFlinger", __func__);
1372 return 0;
1373 }
1374 return af->openDuplicateOutput(output1, output2);
1375}
1376
1377static int aps_close_output(void *service, audio_io_handle_t output)
1378{
1379 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1380 if (af == NULL)
1381 return PERMISSION_DENIED;
1382
1383 return af->closeOutput(output);
1384}
1385
1386static int aps_suspend_output(void *service, audio_io_handle_t output)
1387{
1388 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1389 if (af == NULL) {
1390 LOGW("%s: could not get AudioFlinger", __func__);
1391 return PERMISSION_DENIED;
1392 }
1393
1394 return af->suspendOutput(output);
1395}
1396
1397static int aps_restore_output(void *service, audio_io_handle_t output)
1398{
1399 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1400 if (af == NULL) {
1401 LOGW("%s: could not get AudioFlinger", __func__);
1402 return PERMISSION_DENIED;
1403 }
1404
1405 return af->restoreOutput(output);
1406}
1407
1408static audio_io_handle_t aps_open_input(void *service,
1409 uint32_t *pDevices,
1410 uint32_t *pSamplingRate,
1411 uint32_t *pFormat,
1412 uint32_t *pChannels,
1413 uint32_t acoustics)
1414{
1415 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1416 if (af == NULL) {
1417 LOGW("%s: could not get AudioFlinger", __func__);
1418 return 0;
1419 }
1420
1421 return af->openInput(pDevices, pSamplingRate, pFormat, pChannels,
1422 acoustics);
1423}
1424
1425static int aps_close_input(void *service, audio_io_handle_t input)
1426{
1427 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1428 if (af == NULL)
1429 return PERMISSION_DENIED;
1430
1431 return af->closeInput(input);
1432}
1433
1434static int aps_set_stream_output(void *service, audio_stream_type_t stream,
1435 audio_io_handle_t output)
1436{
1437 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1438 if (af == NULL)
1439 return PERMISSION_DENIED;
1440
1441 return af->setStreamOutput(stream, output);
1442}
1443
1444static int aps_move_effects(void *service, int session,
1445 audio_io_handle_t src_output,
1446 audio_io_handle_t dst_output)
1447{
1448 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
1449 if (af == NULL)
1450 return PERMISSION_DENIED;
1451
1452 return af->moveEffects(session, (int)src_output, (int)dst_output);
1453}
1454
1455static char * aps_get_parameters(void *service, audio_io_handle_t io_handle,
1456 const char *keys)
1457{
1458 String8 result = AudioSystem::getParameters(io_handle, String8(keys));
1459 return strdup(result.string());
1460}
1461
1462static void aps_set_parameters(void *service, audio_io_handle_t io_handle,
1463 const char *kv_pairs, int delay_ms)
1464{
1465 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1466
1467 audioPolicyService->setParameters(io_handle, kv_pairs, delay_ms);
1468}
1469
1470static int aps_set_stream_volume(void *service, audio_stream_type_t stream,
1471 float volume, audio_io_handle_t output,
1472 int delay_ms)
1473{
1474 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1475
1476 return audioPolicyService->setStreamVolume(stream, volume, output,
1477 delay_ms);
1478}
1479
1480static int aps_start_tone(void *service, audio_policy_tone_t tone,
1481 audio_stream_type_t stream)
1482{
1483 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1484
1485 return audioPolicyService->startTone(tone, stream);
1486}
1487
1488static int aps_stop_tone(void *service)
1489{
1490 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1491
1492 return audioPolicyService->stopTone();
1493}
1494
1495static int aps_set_voice_volume(void *service, float volume, int delay_ms)
1496{
1497 AudioPolicyService *audioPolicyService = (AudioPolicyService *)service;
1498
1499 return audioPolicyService->setVoiceVolume(volume, delay_ms);
1500}
1501
1502}; // extern "C"
1503
1504namespace {
1505 struct audio_policy_service_ops aps_ops = {
1506 open_output : aps_open_output,
1507 open_duplicate_output : aps_open_dup_output,
1508 close_output : aps_close_output,
1509 suspend_output : aps_suspend_output,
1510 restore_output : aps_restore_output,
1511 open_input : aps_open_input,
1512 close_input : aps_close_input,
1513 set_stream_volume : aps_set_stream_volume,
1514 set_stream_output : aps_set_stream_output,
1515 set_parameters : aps_set_parameters,
1516 get_parameters : aps_get_parameters,
1517 start_tone : aps_start_tone,
1518 stop_tone : aps_stop_tone,
1519 set_voice_volume : aps_set_voice_volume,
1520 move_effects : aps_move_effects,
1521 };
1522}; // namespace <unnamed>
1523
Eric Laurenta553c252009-07-17 12:17:14 -07001524}; // namespace android