blob: 4810a44e9e6128d0ebce795f10e69b389e25aa7d [file] [log] [blame]
Eric Laurent9d91ad52009-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
19#include <binder/IServiceManager.h>
20#include <utils/Log.h>
21#include <cutils/properties.h>
22#include <binder/IPCThreadState.h>
23#include <utils/String16.h>
24#include <utils/threads.h>
25#include "AudioPolicyService.h"
26#include <cutils/properties.h>
27#include <dlfcn.h>
28
29// ----------------------------------------------------------------------------
30// the sim build doesn't have gettid
31
32#ifndef HAVE_GETTID
33# define gettid getpid
34#endif
35
36namespace android {
37
38const char *AudioPolicyService::sAudioPolicyLibrary = "/system/lib/libaudiopolicy.so";
39const char *AudioPolicyService::sAudioPolicyGenericLibrary = "/system/lib/libaudiopolicygeneric.so";
40
41static bool checkPermission() {
42#ifndef HAVE_ANDROID_OS
43 return true;
44#endif
45 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
46 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
47 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
48 return ok;
49}
50
51// ----------------------------------------------------------------------------
52
53AudioPolicyService::AudioPolicyService()
54 : BnAudioPolicyService() , mpPolicyManager(NULL), mpPolicyManagerLibHandle(NULL)
55{
56 const char *audioPolicyLibrary;
57 char value[PROPERTY_VALUE_MAX];
58
59#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
60 audioPolicyLibrary = sAudioPolicyGenericLibrary;
61 LOGV("build for GENERIC_AUDIO - using generic audio policy");
62#else
63 // if running in emulation - use the emulator driver
64 if (property_get("ro.kernel.qemu", value, 0)) {
65 LOGV("Running in emulation - using generic audio policy");
66 audioPolicyLibrary = sAudioPolicyGenericLibrary;
67 }
68 else {
69 LOGV("Using hardware specific audio policy");
70 audioPolicyLibrary = sAudioPolicyLibrary;
71 }
72#endif
73
74
75 mpPolicyManagerLibHandle = dlopen(audioPolicyLibrary, RTLD_NOW | RTLD_LOCAL);
76 if (mpPolicyManagerLibHandle == NULL) {
77 LOGW("Could not load libaudio policy library");
78 return;
79 }
80
81 AudioPolicyInterface *(*createManager)(AudioPolicyClientInterface *) =
82 reinterpret_cast<AudioPolicyInterface* (*)(AudioPolicyClientInterface *)>(dlsym(mpPolicyManagerLibHandle, "createAudioPolicyManager"));
83
84 if (createManager == NULL ) {
85 LOGW("Could not get createAudioPolicyManager method");
86 return;
87 }
88
89 // start tone playback thread
90 mTonePlaybacThread = new AudioCommandThread();
91 // start audio commands thread
92 mAudioCommandThread = new AudioCommandThread();
93
94 mpPolicyManager = (*createManager)(this);
95
96 // load properties
97 property_get("ro.camera.sound.forced", value, "0");
98 mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
99}
100
101AudioPolicyService::~AudioPolicyService()
102{
103 mTonePlaybacThread->exit();
104 mTonePlaybacThread.clear();
105 mAudioCommandThread->exit();
106 mAudioCommandThread.clear();
107
108 if (mpPolicyManager) {
109 void(*destroyManager)(AudioPolicyInterface *) =
110 reinterpret_cast<void(*)(AudioPolicyInterface *)>(dlsym(mpPolicyManagerLibHandle, "destroyAudioPolicyManager"));
111
112 if (destroyManager == NULL ) {
113 LOGW("Could not get destroyAudioPolicyManager method");
114 return;
115 }
116 (*destroyManager)(mpPolicyManager);
117 }
118}
119
120
121status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
122 AudioSystem::device_connection_state state,
123 const char *device_address)
124{
125 if (mpPolicyManager == NULL) {
126 return NO_INIT;
127 }
128 if (!checkPermission()) {
129 return PERMISSION_DENIED;
130 }
131 if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
132 return BAD_VALUE;
133 }
134 if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
135 return BAD_VALUE;
136 }
137
138 LOGV("setDeviceConnectionState() tid %d", gettid());
139 Mutex::Autolock _l(mLock);
140 return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
141}
142
143AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
144 const char *device_address)
145{
146 if (mpPolicyManager == NULL) {
147 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
148 }
149 if (!checkPermission()) {
150 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
151 }
152 return mpPolicyManager->getDeviceConnectionState(device, device_address);
153}
154
155status_t AudioPolicyService::setPhoneState(int state)
156{
157 if (mpPolicyManager == NULL) {
158 return NO_INIT;
159 }
160 if (!checkPermission()) {
161 return PERMISSION_DENIED;
162 }
163 if (state < 0 || state >= AudioSystem::NUM_MODES) {
164 return BAD_VALUE;
165 }
166
167 LOGV("setPhoneState() tid %d", gettid());
168
169 // TODO: check if it is more appropriate to do it in platform specific policy manager
170 AudioSystem::setMode(state);
171
172 Mutex::Autolock _l(mLock);
173 mpPolicyManager->setPhoneState(state);
174 return NO_ERROR;
175}
176
177status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
178{
179 if (mpPolicyManager == NULL) {
180 return NO_INIT;
181 }
182 if (!checkPermission()) {
183 return PERMISSION_DENIED;
184 }
185
186 mpPolicyManager->setRingerMode(mode, mask);
187 return NO_ERROR;
188}
189
190status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
191{
192 if (mpPolicyManager == NULL) {
193 return NO_INIT;
194 }
195 if (!checkPermission()) {
196 return PERMISSION_DENIED;
197 }
198 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
199 return BAD_VALUE;
200 }
201 if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
202 return BAD_VALUE;
203 }
204 LOGV("setForceUse() tid %d", gettid());
205 Mutex::Autolock _l(mLock);
206 mpPolicyManager->setForceUse(usage, config);
207 return NO_ERROR;
208}
209
210AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
211{
212 if (mpPolicyManager == NULL) {
213 return AudioSystem::FORCE_NONE;
214 }
215 if (!checkPermission()) {
216 return AudioSystem::FORCE_NONE;
217 }
218 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
219 return AudioSystem::FORCE_NONE;
220 }
221 return mpPolicyManager->getForceUse(usage);
222}
223
224audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
225 uint32_t samplingRate,
226 uint32_t format,
227 uint32_t channels,
228 AudioSystem::output_flags flags)
229{
230 if (mpPolicyManager == NULL) {
231 return NULL;
232 }
233 LOGV("getOutput() tid %d", gettid());
234 Mutex::Autolock _l(mLock);
235 return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
236}
237
238status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
239{
240 if (mpPolicyManager == NULL) {
241 return NO_INIT;
242 }
243 LOGV("startOutput() tid %d", gettid());
244 Mutex::Autolock _l(mLock);
245 return mpPolicyManager->startOutput(output, stream);
246}
247
248status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
249{
250 if (mpPolicyManager == NULL) {
251 return NO_INIT;
252 }
253 LOGV("stopOutput() tid %d", gettid());
254 Mutex::Autolock _l(mLock);
255 return mpPolicyManager->stopOutput(output, stream);
256}
257
258void AudioPolicyService::releaseOutput(audio_io_handle_t output)
259{
260 if (mpPolicyManager == NULL) {
261 return;
262 }
263 LOGV("releaseOutput() tid %d", gettid());
264 Mutex::Autolock _l(mLock);
265 mpPolicyManager->releaseOutput(output);
266}
267
268audio_io_handle_t AudioPolicyService::getInput(int inputSource,
269 uint32_t samplingRate,
270 uint32_t format,
271 uint32_t channels,
272 AudioSystem::audio_in_acoustics acoustics)
273{
274 if (mpPolicyManager == NULL) {
275 return NULL;
276 }
277 Mutex::Autolock _l(mLock);
278 return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
279}
280
281status_t AudioPolicyService::startInput(audio_io_handle_t input)
282{
283 if (mpPolicyManager == NULL) {
284 return NO_INIT;
285 }
286 Mutex::Autolock _l(mLock);
287 return mpPolicyManager->startInput(input);
288}
289
290status_t AudioPolicyService::stopInput(audio_io_handle_t input)
291{
292 if (mpPolicyManager == NULL) {
293 return NO_INIT;
294 }
295 Mutex::Autolock _l(mLock);
296 return mpPolicyManager->stopInput(input);
297}
298
299void AudioPolicyService::releaseInput(audio_io_handle_t input)
300{
301 if (mpPolicyManager == NULL) {
302 return;
303 }
304 Mutex::Autolock _l(mLock);
305 mpPolicyManager->releaseInput(input);
306}
307
308status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
309 int indexMin,
310 int indexMax)
311{
312 if (mpPolicyManager == NULL) {
313 return NO_INIT;
314 }
315 if (!checkPermission()) {
316 return PERMISSION_DENIED;
317 }
318 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
319 return BAD_VALUE;
320 }
321 mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
322 return NO_ERROR;
323}
324
325status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
326{
327 if (mpPolicyManager == NULL) {
328 return NO_INIT;
329 }
330 if (!checkPermission()) {
331 return PERMISSION_DENIED;
332 }
333 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
334 return BAD_VALUE;
335 }
336
337 return mpPolicyManager->setStreamVolumeIndex(stream, index);
338}
339
340status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
341{
342 if (mpPolicyManager == NULL) {
343 return NO_INIT;
344 }
345 if (!checkPermission()) {
346 return PERMISSION_DENIED;
347 }
348 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
349 return BAD_VALUE;
350 }
351 return mpPolicyManager->getStreamVolumeIndex(stream, index);
352}
353
354void AudioPolicyService::binderDied(const wp<IBinder>& who) {
355 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
356}
357
358status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
359{
360 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
361 dumpPermissionDenial(fd, args);
362 } else {
363
364 }
365 return NO_ERROR;
366}
367
368status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
369{
370 const size_t SIZE = 256;
371 char buffer[SIZE];
372 String8 result;
373 snprintf(buffer, SIZE, "Permission Denial: "
374 "can't dump AudioPolicyService from pid=%d, uid=%d\n",
375 IPCThreadState::self()->getCallingPid(),
376 IPCThreadState::self()->getCallingUid());
377 result.append(buffer);
378 write(fd, result.string(), result.size());
379 return NO_ERROR;
380}
381
382status_t AudioPolicyService::onTransact(
383 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
384{
385 return BnAudioPolicyService::onTransact(code, data, reply, flags);
386}
387
388
389// ----------------------------------------------------------------------------
390void AudioPolicyService::instantiate() {
391 defaultServiceManager()->addService(
392 String16("media.audio_policy"), new AudioPolicyService());
393}
394
395
396// ----------------------------------------------------------------------------
397// AudioPolicyClientInterface implementation
398// ----------------------------------------------------------------------------
399
400
401audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
402 uint32_t *pSamplingRate,
403 uint32_t *pFormat,
404 uint32_t *pChannels,
405 uint32_t *pLatencyMs,
406 AudioSystem::output_flags flags)
407{
408 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
409 if (af == 0) {
410 LOGW("openOutput() could not get AudioFlinger");
411 return NULL;
412 }
413
414 return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
415}
416
417audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
418{
419 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
420 if (af == 0) {
421 LOGW("openDuplicateOutput() could not get AudioFlinger");
422 return NULL;
423 }
424 return af->openDuplicateOutput(output1, output2);
425}
426
427status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
428{
429 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
430 if (af == 0) return PERMISSION_DENIED;
431
432 return af->closeOutput(output);
433}
434
435
436status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
437{
438 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
439 if (af == 0) {
440 LOGW("suspendOutput() could not get AudioFlinger");
441 return PERMISSION_DENIED;
442 }
443
444 return af->suspendOutput(output);
445}
446
447status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
448{
449 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
450 if (af == 0) {
451 LOGW("restoreOutput() could not get AudioFlinger");
452 return PERMISSION_DENIED;
453 }
454
455 return af->restoreOutput(output);
456}
457
458audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
459 uint32_t *pSamplingRate,
460 uint32_t *pFormat,
461 uint32_t *pChannels,
462 uint32_t acoustics)
463{
464 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
465 if (af == 0) {
466 LOGW("openInput() could not get AudioFlinger");
467 return NULL;
468 }
469
470 return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
471}
472
473status_t AudioPolicyService::closeInput(audio_io_handle_t input)
474{
475 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
476 if (af == 0) return PERMISSION_DENIED;
477
478 return af->closeInput(input);
479}
480
481status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output)
482{
483 return mAudioCommandThread->volumeCommand((int)stream, volume, (void *)output);
484}
485
486status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
487{
488 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
489 if (af == 0) return PERMISSION_DENIED;
490
491 return af->setStreamOutput(stream, output);
492}
493
494
495void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
496{
497 mAudioCommandThread->parametersCommand((void *)ioHandle, keyValuePairs);
498}
499
500String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
501{
502 String8 result = AudioSystem::getParameters(ioHandle, keys);
503 return result;
504}
505
506status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
507{
508 mTonePlaybacThread->startToneCommand(tone, stream);
509 return NO_ERROR;
510}
511
512status_t AudioPolicyService::stopTone()
513{
514 mTonePlaybacThread->stopToneCommand();
515 return NO_ERROR;
516}
517
518
519// ----------- AudioPolicyService::AudioCommandThread implementation ----------
520
521AudioPolicyService::AudioCommandThread::AudioCommandThread()
522 : Thread(false)
523{
524 mpToneGenerator = NULL;
525}
526
527
528AudioPolicyService::AudioCommandThread::~AudioCommandThread()
529{
530 mAudioCommands.clear();
531 if (mpToneGenerator != NULL) delete mpToneGenerator;
532}
533
534void AudioPolicyService::AudioCommandThread::onFirstRef()
535{
536 const size_t SIZE = 256;
537 char buffer[SIZE];
538
539 snprintf(buffer, SIZE, "AudioCommandThread");
540
541 run(buffer, ANDROID_PRIORITY_AUDIO);
542}
543
544bool AudioPolicyService::AudioCommandThread::threadLoop()
545{
546 mLock.lock();
547 while (!exitPending())
548 {
549 while(!mAudioCommands.isEmpty()) {
550 AudioCommand *command = mAudioCommands[0];
551 mAudioCommands.removeAt(0);
552 switch (command->mCommand) {
553 case START_TONE: {
554 mLock.unlock();
555 ToneData *data = (ToneData *)command->mParam;
556 LOGV("AudioCommandThread() processing start tone %d on stream %d",
557 data->mType, data->mStream);
558 if (mpToneGenerator != NULL)
559 delete mpToneGenerator;
560 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
561 mpToneGenerator->startTone(data->mType);
562 delete data;
563 mLock.lock();
564 }break;
565 case STOP_TONE: {
566 mLock.unlock();
567 LOGV("AudioCommandThread() processing stop tone");
568 if (mpToneGenerator != NULL) {
569 mpToneGenerator->stopTone();
570 delete mpToneGenerator;
571 mpToneGenerator = NULL;
572 }
573 mLock.lock();
574 }break;
575 case SET_VOLUME: {
576 VolumeData *data = (VolumeData *)command->mParam;
577 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %p", data->mStream, data->mVolume, data->mIO);
578 mCommandStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
579 mCommandCond.signal();
580 mWaitWorkCV.wait(mLock);
581 delete data;
582 }break;
583 case SET_PARAMETERS: {
584 ParametersData *data = (ParametersData *)command->mParam;
585 LOGV("AudioCommandThread() processing set parameters string %s, io %p", data->mKeyValuePairs.string(), data->mIO);
586 mCommandStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
587 mCommandCond.signal();
588 mWaitWorkCV.wait(mLock);
589 delete data;
590 }break;
591 default:
592 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
593 }
594 delete command;
595 }
596 LOGV("AudioCommandThread() going to sleep");
597 mWaitWorkCV.wait(mLock);
598 LOGV("AudioCommandThread() waking up");
599 }
600 mLock.unlock();
601 return false;
602}
603
604void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
605{
606 Mutex::Autolock _l(mLock);
607 AudioCommand *command = new AudioCommand();
608 command->mCommand = START_TONE;
609 ToneData *data = new ToneData();
610 data->mType = type;
611 data->mStream = stream;
612 command->mParam = (void *)data;
613 mAudioCommands.add(command);
614 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
615 mWaitWorkCV.signal();
616}
617
618void AudioPolicyService::AudioCommandThread::stopToneCommand()
619{
620 Mutex::Autolock _l(mLock);
621 AudioCommand *command = new AudioCommand();
622 command->mCommand = STOP_TONE;
623 command->mParam = NULL;
624 mAudioCommands.add(command);
625 LOGV("AudioCommandThread() adding tone stop");
626 mWaitWorkCV.signal();
627}
628
629status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, void *output)
630{
631 Mutex::Autolock _l(mLock);
632 AudioCommand *command = new AudioCommand();
633 command->mCommand = SET_VOLUME;
634 VolumeData *data = new VolumeData();
635 data->mStream = stream;
636 data->mVolume = volume;
637 data->mIO = output;
638 command->mParam = data;
639 mAudioCommands.add(command);
640 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %p", stream, volume, output);
641 mWaitWorkCV.signal();
642 mCommandCond.wait(mLock);
643 status_t status = mCommandStatus;
644 mWaitWorkCV.signal();
645 return status;
646}
647
648status_t AudioPolicyService::AudioCommandThread::parametersCommand(void *ioHandle, const String8& keyValuePairs)
649{
650 Mutex::Autolock _l(mLock);
651 AudioCommand *command = new AudioCommand();
652 command->mCommand = SET_PARAMETERS;
653 ParametersData *data = new ParametersData();
654 data->mIO = ioHandle;
655 data->mKeyValuePairs = keyValuePairs;
656 command->mParam = data;
657 mAudioCommands.add(command);
658 LOGV("AudioCommandThread() adding set parameter string %s, io %p", keyValuePairs.string(), ioHandle);
659 mWaitWorkCV.signal();
660 mCommandCond.wait(mLock);
661 status_t status = mCommandStatus;
662 mWaitWorkCV.signal();
663 return status;
664}
665
666void AudioPolicyService::AudioCommandThread::exit()
667{
668 LOGV("AudioCommandThread::exit");
669 {
670 AutoMutex _l(mLock);
671 requestExit();
672 mWaitWorkCV.signal();
673 }
674 requestExitAndWait();
675}
676
677}; // namespace android