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