blob: aa48019929b4a8483bbb7a150b5d49ef6af6309e [file] [log] [blame]
Jean-Baptiste Querucc8c35c2009-11-12 18:45:53 -08001/*
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
20#undef __STRICT_ANSI__
21#define __STDINT_LIMITS
22#define __STDC_LIMIT_MACROS
23#include <stdint.h>
24
25#include <sys/time.h>
26#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 "AudioPolicyManagerGeneric.h"
34#include <cutils/properties.h>
35#include <dlfcn.h>
36
37// ----------------------------------------------------------------------------
38// the sim build doesn't have gettid
39
40#ifndef HAVE_GETTID
41# define gettid getpid
42#endif
43
44namespace android {
45
46static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
47static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
48
49static const int kDumpLockRetries = 50;
50static const int kDumpLockSleep = 20000;
51
52static bool checkPermission() {
53#ifndef HAVE_ANDROID_OS
54 return true;
55#endif
56 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
57 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
58 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
59 return ok;
60}
61
62// ----------------------------------------------------------------------------
63
64AudioPolicyService::AudioPolicyService()
65 : BnAudioPolicyService() , mpPolicyManager(NULL)
66{
67 char value[PROPERTY_VALUE_MAX];
68
69 // start tone playback thread
70 mTonePlaybackThread = new AudioCommandThread();
71 // start audio commands thread
72 mAudioCommandThread = new AudioCommandThread();
73
74#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
75 mpPolicyManager = new AudioPolicyManagerGeneric(this);
76 LOGV("build for GENERIC_AUDIO - using generic audio policy");
77#else
78 // if running in emulation - use the emulator driver
79 if (property_get("ro.kernel.qemu", value, 0)) {
80 LOGV("Running in emulation - using generic audio policy");
81 mpPolicyManager = new AudioPolicyManagerGeneric(this);
82 }
83 else {
84 LOGV("Using hardware specific audio policy");
85 mpPolicyManager = createAudioPolicyManager(this);
86 }
87#endif
88
89 // load properties
90 property_get("ro.camera.sound.forced", value, "0");
91 mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
92}
93
94AudioPolicyService::~AudioPolicyService()
95{
96 mTonePlaybackThread->exit();
97 mTonePlaybackThread.clear();
98 mAudioCommandThread->exit();
99 mAudioCommandThread.clear();
100
101 if (mpPolicyManager) {
102 delete mpPolicyManager;
103 }
104}
105
106
107status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
108 AudioSystem::device_connection_state state,
109 const char *device_address)
110{
111 if (mpPolicyManager == NULL) {
112 return NO_INIT;
113 }
114 if (!checkPermission()) {
115 return PERMISSION_DENIED;
116 }
117 if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
118 return BAD_VALUE;
119 }
120 if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
121 return BAD_VALUE;
122 }
123
124 LOGV("setDeviceConnectionState() tid %d", gettid());
125 Mutex::Autolock _l(mLock);
126 return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
127}
128
129AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
130 const char *device_address)
131{
132 if (mpPolicyManager == NULL) {
133 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
134 }
135 if (!checkPermission()) {
136 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
137 }
138 return mpPolicyManager->getDeviceConnectionState(device, device_address);
139}
140
141status_t AudioPolicyService::setPhoneState(int state)
142{
143 if (mpPolicyManager == NULL) {
144 return NO_INIT;
145 }
146 if (!checkPermission()) {
147 return PERMISSION_DENIED;
148 }
149 if (state < 0 || state >= AudioSystem::NUM_MODES) {
150 return BAD_VALUE;
151 }
152
153 LOGV("setPhoneState() tid %d", gettid());
154
155 // TODO: check if it is more appropriate to do it in platform specific policy manager
156 AudioSystem::setMode(state);
157
158 Mutex::Autolock _l(mLock);
159 mpPolicyManager->setPhoneState(state);
160 return NO_ERROR;
161}
162
163status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
164{
165 if (mpPolicyManager == NULL) {
166 return NO_INIT;
167 }
168 if (!checkPermission()) {
169 return PERMISSION_DENIED;
170 }
171
172 mpPolicyManager->setRingerMode(mode, mask);
173 return NO_ERROR;
174}
175
176status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
177{
178 if (mpPolicyManager == NULL) {
179 return NO_INIT;
180 }
181 if (!checkPermission()) {
182 return PERMISSION_DENIED;
183 }
184 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
185 return BAD_VALUE;
186 }
187 if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
188 return BAD_VALUE;
189 }
190 LOGV("setForceUse() tid %d", gettid());
191 Mutex::Autolock _l(mLock);
192 mpPolicyManager->setForceUse(usage, config);
193 return NO_ERROR;
194}
195
196AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
197{
198 if (mpPolicyManager == NULL) {
199 return AudioSystem::FORCE_NONE;
200 }
201 if (!checkPermission()) {
202 return AudioSystem::FORCE_NONE;
203 }
204 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
205 return AudioSystem::FORCE_NONE;
206 }
207 return mpPolicyManager->getForceUse(usage);
208}
209
210audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
211 uint32_t samplingRate,
212 uint32_t format,
213 uint32_t channels,
214 AudioSystem::output_flags flags)
215{
216 if (mpPolicyManager == NULL) {
217 return 0;
218 }
219 LOGV("getOutput() tid %d", gettid());
220 Mutex::Autolock _l(mLock);
221 return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
222}
223
224status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
225{
226 if (mpPolicyManager == NULL) {
227 return NO_INIT;
228 }
229 LOGV("startOutput() tid %d", gettid());
230 Mutex::Autolock _l(mLock);
231 return mpPolicyManager->startOutput(output, stream);
232}
233
234status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
235{
236 if (mpPolicyManager == NULL) {
237 return NO_INIT;
238 }
239 LOGV("stopOutput() tid %d", gettid());
240 Mutex::Autolock _l(mLock);
241 return mpPolicyManager->stopOutput(output, stream);
242}
243
244void AudioPolicyService::releaseOutput(audio_io_handle_t output)
245{
246 if (mpPolicyManager == NULL) {
247 return;
248 }
249 LOGV("releaseOutput() tid %d", gettid());
250 Mutex::Autolock _l(mLock);
251 mpPolicyManager->releaseOutput(output);
252}
253
254audio_io_handle_t AudioPolicyService::getInput(int inputSource,
255 uint32_t samplingRate,
256 uint32_t format,
257 uint32_t channels,
258 AudioSystem::audio_in_acoustics acoustics)
259{
260 if (mpPolicyManager == NULL) {
261 return 0;
262 }
263 Mutex::Autolock _l(mLock);
264 return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
265}
266
267status_t AudioPolicyService::startInput(audio_io_handle_t input)
268{
269 if (mpPolicyManager == NULL) {
270 return NO_INIT;
271 }
272 Mutex::Autolock _l(mLock);
273 return mpPolicyManager->startInput(input);
274}
275
276status_t AudioPolicyService::stopInput(audio_io_handle_t input)
277{
278 if (mpPolicyManager == NULL) {
279 return NO_INIT;
280 }
281 Mutex::Autolock _l(mLock);
282 return mpPolicyManager->stopInput(input);
283}
284
285void AudioPolicyService::releaseInput(audio_io_handle_t input)
286{
287 if (mpPolicyManager == NULL) {
288 return;
289 }
290 Mutex::Autolock _l(mLock);
291 mpPolicyManager->releaseInput(input);
292}
293
294status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
295 int indexMin,
296 int indexMax)
297{
298 if (mpPolicyManager == NULL) {
299 return NO_INIT;
300 }
301 if (!checkPermission()) {
302 return PERMISSION_DENIED;
303 }
304 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
305 return BAD_VALUE;
306 }
307 mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
308 return NO_ERROR;
309}
310
311status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
312{
313 if (mpPolicyManager == NULL) {
314 return NO_INIT;
315 }
316 if (!checkPermission()) {
317 return PERMISSION_DENIED;
318 }
319 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
320 return BAD_VALUE;
321 }
322
323 return mpPolicyManager->setStreamVolumeIndex(stream, index);
324}
325
326status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
327{
328 if (mpPolicyManager == NULL) {
329 return NO_INIT;
330 }
331 if (!checkPermission()) {
332 return PERMISSION_DENIED;
333 }
334 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
335 return BAD_VALUE;
336 }
337 return mpPolicyManager->getStreamVolumeIndex(stream, index);
338}
339
340void AudioPolicyService::binderDied(const wp<IBinder>& who) {
341 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
342}
343
344static bool tryLock(Mutex& mutex)
345{
346 bool locked = false;
347 for (int i = 0; i < kDumpLockRetries; ++i) {
348 if (mutex.tryLock() == NO_ERROR) {
349 locked = true;
350 break;
351 }
352 usleep(kDumpLockSleep);
353 }
354 return locked;
355}
356
357status_t AudioPolicyService::dumpInternals(int fd)
358{
359 const size_t SIZE = 256;
360 char buffer[SIZE];
361 String8 result;
362
363 snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
364 result.append(buffer);
365 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
366 result.append(buffer);
367 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
368 result.append(buffer);
369
370 write(fd, result.string(), result.size());
371 return NO_ERROR;
372}
373
374status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
375{
376 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
377 dumpPermissionDenial(fd);
378 } else {
379 bool locked = tryLock(mLock);
380 if (!locked) {
381 String8 result(kDeadlockedString);
382 write(fd, result.string(), result.size());
383 }
384
385 dumpInternals(fd);
386 if (mAudioCommandThread != NULL) {
387 mAudioCommandThread->dump(fd);
388 }
389 if (mTonePlaybackThread != NULL) {
390 mTonePlaybackThread->dump(fd);
391 }
392
393 if (mpPolicyManager) {
394 mpPolicyManager->dump(fd);
395 }
396
397 if (locked) mLock.unlock();
398 }
399 return NO_ERROR;
400}
401
402status_t AudioPolicyService::dumpPermissionDenial(int fd)
403{
404 const size_t SIZE = 256;
405 char buffer[SIZE];
406 String8 result;
407 snprintf(buffer, SIZE, "Permission Denial: "
408 "can't dump AudioPolicyService from pid=%d, uid=%d\n",
409 IPCThreadState::self()->getCallingPid(),
410 IPCThreadState::self()->getCallingUid());
411 result.append(buffer);
412 write(fd, result.string(), result.size());
413 return NO_ERROR;
414}
415
416status_t AudioPolicyService::onTransact(
417 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
418{
419 return BnAudioPolicyService::onTransact(code, data, reply, flags);
420}
421
422
423// ----------------------------------------------------------------------------
424void AudioPolicyService::instantiate() {
425 defaultServiceManager()->addService(
426 String16("media.audio_policy"), new AudioPolicyService());
427}
428
429
430// ----------------------------------------------------------------------------
431// AudioPolicyClientInterface implementation
432// ----------------------------------------------------------------------------
433
434
435audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
436 uint32_t *pSamplingRate,
437 uint32_t *pFormat,
438 uint32_t *pChannels,
439 uint32_t *pLatencyMs,
440 AudioSystem::output_flags flags)
441{
442 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
443 if (af == 0) {
444 LOGW("openOutput() could not get AudioFlinger");
445 return 0;
446 }
447
448 return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
449}
450
451audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
452{
453 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
454 if (af == 0) {
455 LOGW("openDuplicateOutput() could not get AudioFlinger");
456 return 0;
457 }
458 return af->openDuplicateOutput(output1, output2);
459}
460
461status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
462{
463 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
464 if (af == 0) return PERMISSION_DENIED;
465
466 return af->closeOutput(output);
467}
468
469
470status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
471{
472 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
473 if (af == 0) {
474 LOGW("suspendOutput() could not get AudioFlinger");
475 return PERMISSION_DENIED;
476 }
477
478 return af->suspendOutput(output);
479}
480
481status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
482{
483 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
484 if (af == 0) {
485 LOGW("restoreOutput() could not get AudioFlinger");
486 return PERMISSION_DENIED;
487 }
488
489 return af->restoreOutput(output);
490}
491
492audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
493 uint32_t *pSamplingRate,
494 uint32_t *pFormat,
495 uint32_t *pChannels,
496 uint32_t acoustics)
497{
498 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
499 if (af == 0) {
500 LOGW("openInput() could not get AudioFlinger");
501 return 0;
502 }
503
504 return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
505}
506
507status_t AudioPolicyService::closeInput(audio_io_handle_t input)
508{
509 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
510 if (af == 0) return PERMISSION_DENIED;
511
512 return af->closeInput(input);
513}
514
515status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
516{
517 return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
518}
519
520status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
521{
522 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
523 if (af == 0) return PERMISSION_DENIED;
524
525 return af->setStreamOutput(stream, output);
526}
527
528
529void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
530{
531 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
532}
533
534String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
535{
536 String8 result = AudioSystem::getParameters(ioHandle, keys);
537 return result;
538}
539
540status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
541{
542 mTonePlaybackThread->startToneCommand(tone, stream);
543 return NO_ERROR;
544}
545
546status_t AudioPolicyService::stopTone()
547{
548 mTonePlaybackThread->stopToneCommand();
549 return NO_ERROR;
550}
551
552status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
553{
554 return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
555}
556
557// ----------- AudioPolicyService::AudioCommandThread implementation ----------
558
559AudioPolicyService::AudioCommandThread::AudioCommandThread()
560 : Thread(false)
561{
562 mpToneGenerator = NULL;
563}
564
565
566AudioPolicyService::AudioCommandThread::~AudioCommandThread()
567{
568 mAudioCommands.clear();
569 if (mpToneGenerator != NULL) delete mpToneGenerator;
570}
571
572void AudioPolicyService::AudioCommandThread::onFirstRef()
573{
574 const size_t SIZE = 256;
575 char buffer[SIZE];
576
577 snprintf(buffer, SIZE, "AudioCommandThread");
578
579 run(buffer, ANDROID_PRIORITY_AUDIO);
580}
581
582bool AudioPolicyService::AudioCommandThread::threadLoop()
583{
584 nsecs_t waitTime = INT64_MAX;
585
586 mLock.lock();
587 while (!exitPending())
588 {
589 while(!mAudioCommands.isEmpty()) {
590 nsecs_t curTime = systemTime();
591 // commands are sorted by increasing time stamp: execute them from index 0 and up
592 if (mAudioCommands[0]->mTime <= curTime) {
593 AudioCommand *command = mAudioCommands[0];
594 mAudioCommands.removeAt(0);
595 mLastCommand = *command;
596
597 switch (command->mCommand) {
598 case START_TONE: {
599 mLock.unlock();
600 ToneData *data = (ToneData *)command->mParam;
601 LOGV("AudioCommandThread() processing start tone %d on stream %d",
602 data->mType, data->mStream);
603 if (mpToneGenerator != NULL)
604 delete mpToneGenerator;
605 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
606 mpToneGenerator->startTone(data->mType);
607 delete data;
608 mLock.lock();
609 }break;
610 case STOP_TONE: {
611 mLock.unlock();
612 LOGV("AudioCommandThread() processing stop tone");
613 if (mpToneGenerator != NULL) {
614 mpToneGenerator->stopTone();
615 delete mpToneGenerator;
616 mpToneGenerator = NULL;
617 }
618 mLock.lock();
619 }break;
620 case SET_VOLUME: {
621 VolumeData *data = (VolumeData *)command->mParam;
622 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
623 command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
624 if (command->mWaitStatus) {
625 command->mCond.signal();
626 mWaitWorkCV.wait(mLock);
627 }
628 delete data;
629 }break;
630 case SET_PARAMETERS: {
631 ParametersData *data = (ParametersData *)command->mParam;
632 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
633 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
634 if (command->mWaitStatus) {
635 command->mCond.signal();
636 mWaitWorkCV.wait(mLock);
637 }
638 delete data;
639 }break;
640 case SET_VOICE_VOLUME: {
641 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
642 LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
643 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
644 if (command->mWaitStatus) {
645 command->mCond.signal();
646 mWaitWorkCV.wait(mLock);
647 }
648 delete data;
649 }break;
650 default:
651 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
652 }
653 delete command;
654 waitTime = INT64_MAX;
655 } else {
656 waitTime = mAudioCommands[0]->mTime - curTime;
657 break;
658 }
659 }
660 LOGV("AudioCommandThread() going to sleep");
661 mWaitWorkCV.waitRelative(mLock, waitTime);
662 LOGV("AudioCommandThread() waking up");
663 }
664 mLock.unlock();
665 return false;
666}
667
668status_t AudioPolicyService::AudioCommandThread::dump(int fd)
669{
670 const size_t SIZE = 256;
671 char buffer[SIZE];
672 String8 result;
673
674 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
675 result.append(buffer);
676 write(fd, result.string(), result.size());
677
678 bool locked = tryLock(mLock);
679 if (!locked) {
680 String8 result2(kCmdDeadlockedString);
681 write(fd, result2.string(), result2.size());
682 }
683
684 snprintf(buffer, SIZE, "- Commands:\n");
685 result = String8(buffer);
686 result.append(" Command Time Wait pParam\n");
687 for (int i = 0; i < (int)mAudioCommands.size(); i++) {
688 mAudioCommands[i]->dump(buffer, SIZE);
689 result.append(buffer);
690 }
691 result.append(" Last Command\n");
692 mLastCommand.dump(buffer, SIZE);
693 result.append(buffer);
694
695 write(fd, result.string(), result.size());
696
697 if (locked) mLock.unlock();
698
699 return NO_ERROR;
700}
701
702void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
703{
704 AudioCommand *command = new AudioCommand();
705 command->mCommand = START_TONE;
706 ToneData *data = new ToneData();
707 data->mType = type;
708 data->mStream = stream;
709 command->mParam = (void *)data;
710 command->mWaitStatus = false;
711 Mutex::Autolock _l(mLock);
712 insertCommand_l(command);
713 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
714 mWaitWorkCV.signal();
715}
716
717void AudioPolicyService::AudioCommandThread::stopToneCommand()
718{
719 AudioCommand *command = new AudioCommand();
720 command->mCommand = STOP_TONE;
721 command->mParam = NULL;
722 command->mWaitStatus = false;
723 Mutex::Autolock _l(mLock);
724 insertCommand_l(command);
725 LOGV("AudioCommandThread() adding tone stop");
726 mWaitWorkCV.signal();
727}
728
729status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
730{
731 status_t status = NO_ERROR;
732
733 AudioCommand *command = new AudioCommand();
734 command->mCommand = SET_VOLUME;
735 VolumeData *data = new VolumeData();
736 data->mStream = stream;
737 data->mVolume = volume;
738 data->mIO = output;
739 command->mParam = data;
740 if (delayMs == 0) {
741 command->mWaitStatus = true;
742 } else {
743 command->mWaitStatus = false;
744 }
745 Mutex::Autolock _l(mLock);
746 insertCommand_l(command, delayMs);
747 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
748 mWaitWorkCV.signal();
749 if (command->mWaitStatus) {
750 command->mCond.wait(mLock);
751 status = command->mStatus;
752 mWaitWorkCV.signal();
753 }
754 return status;
755}
756
757status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
758{
759 status_t status = NO_ERROR;
760
761 AudioCommand *command = new AudioCommand();
762 command->mCommand = SET_PARAMETERS;
763 ParametersData *data = new ParametersData();
764 data->mIO = ioHandle;
765 data->mKeyValuePairs = keyValuePairs;
766 command->mParam = data;
767 if (delayMs == 0) {
768 command->mWaitStatus = true;
769 } else {
770 command->mWaitStatus = false;
771 }
772 Mutex::Autolock _l(mLock);
773 insertCommand_l(command, delayMs);
774 LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
775 mWaitWorkCV.signal();
776 if (command->mWaitStatus) {
777 command->mCond.wait(mLock);
778 status = command->mStatus;
779 mWaitWorkCV.signal();
780 }
781 return status;
782}
783
784status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
785{
786 status_t status = NO_ERROR;
787
788 AudioCommand *command = new AudioCommand();
789 command->mCommand = SET_VOICE_VOLUME;
790 VoiceVolumeData *data = new VoiceVolumeData();
791 data->mVolume = volume;
792 command->mParam = data;
793 if (delayMs == 0) {
794 command->mWaitStatus = true;
795 } else {
796 command->mWaitStatus = false;
797 }
798 Mutex::Autolock _l(mLock);
799 insertCommand_l(command, delayMs);
800 LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
801 mWaitWorkCV.signal();
802 if (command->mWaitStatus) {
803 command->mCond.wait(mLock);
804 status = command->mStatus;
805 mWaitWorkCV.signal();
806 }
807 return status;
808}
809
810// insertCommand_l() must be called with mLock held
811void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
812{
813 ssize_t i;
814 Vector <AudioCommand *> removedCommands;
815
816 command->mTime = systemTime() + milliseconds(delayMs);
817
818 // check same pending commands with later time stamps and eliminate them
819 for (i = mAudioCommands.size()-1; i >= 0; i--) {
820 AudioCommand *command2 = mAudioCommands[i];
821 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
822 if (command2->mTime <= command->mTime) break;
823 if (command2->mCommand != command->mCommand) continue;
824
825 switch (command->mCommand) {
826 case SET_PARAMETERS: {
827 ParametersData *data = (ParametersData *)command->mParam;
828 ParametersData *data2 = (ParametersData *)command2->mParam;
829 if (data->mIO != data2->mIO) break;
830 LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
831 AudioParameter param = AudioParameter(data->mKeyValuePairs);
832 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
833 for (size_t j = 0; j < param.size(); j++) {
834 String8 key;
835 String8 value;
836 param.getAt(j, key, value);
837 for (size_t k = 0; k < param2.size(); k++) {
838 String8 key2;
839 String8 value2;
840 param2.getAt(k, key2, value2);
841 if (key2 == key) {
842 param2.remove(key2);
843 LOGV("Filtering out parameter %s", key2.string());
844 break;
845 }
846 }
847 }
848 // if all keys have been filtered out, remove the command.
849 // otherwise, update the key value pairs
850 if (param2.size() == 0) {
851 removedCommands.add(command2);
852 } else {
853 data2->mKeyValuePairs = param2.toString();
854 }
855 } break;
856
857 case SET_VOLUME: {
858 VolumeData *data = (VolumeData *)command->mParam;
859 VolumeData *data2 = (VolumeData *)command2->mParam;
860 if (data->mIO != data2->mIO) break;
861 if (data->mStream != data2->mStream) break;
862 LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
863 removedCommands.add(command2);
864 } break;
865 case START_TONE:
866 case STOP_TONE:
867 default:
868 break;
869 }
870 }
871
872 // remove filtered commands
873 for (size_t j = 0; j < removedCommands.size(); j++) {
874 // removed commands always have time stamps greater than current command
875 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
876 if (mAudioCommands[k] == removedCommands[j]) {
877 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
878 mAudioCommands.removeAt(k);
879 break;
880 }
881 }
882 }
883 removedCommands.clear();
884
885 // insert command at the right place according to its time stamp
886 LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
887 mAudioCommands.insertAt(command, i + 1);
888}
889
890void AudioPolicyService::AudioCommandThread::exit()
891{
892 LOGV("AudioCommandThread::exit");
893 {
894 AutoMutex _l(mLock);
895 requestExit();
896 mWaitWorkCV.signal();
897 }
898 requestExitAndWait();
899}
900
901void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
902{
903 snprintf(buffer, size, " %02d %06d.%03d %01u %p\n",
904 mCommand,
905 (int)ns2s(mTime),
906 (int)ns2ms(mTime)%1000,
907 mWaitStatus,
908 mParam);
909}
910
911}; // namespace android