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