1 /*
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
44 namespace android {
45
46 static const char* kDeadlockedString = "AudioPolicyService may be deadlocked\n";
47 static const char* kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
48
49 static const int kDumpLockRetries = 50;
50 static const int kDumpLockSleep = 20000;
51
checkPermission()52 static 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
AudioPolicyService()64 AudioPolicyService::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
~AudioPolicyService()94 AudioPolicyService::~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
setDeviceConnectionState(AudioSystem::audio_devices device,AudioSystem::device_connection_state state,const char * device_address)107 status_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
getDeviceConnectionState(AudioSystem::audio_devices device,const char * device_address)129 AudioSystem::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
setPhoneState(int state)141 status_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
setRingerMode(uint32_t mode,uint32_t mask)163 status_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
setForceUse(AudioSystem::force_use usage,AudioSystem::forced_config config)176 status_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
getForceUse(AudioSystem::force_use usage)196 AudioSystem::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
getOutput(AudioSystem::stream_type stream,uint32_t samplingRate,uint32_t format,uint32_t channels,AudioSystem::output_flags flags)210 audio_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
startOutput(audio_io_handle_t output,AudioSystem::stream_type stream)224 status_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
stopOutput(audio_io_handle_t output,AudioSystem::stream_type stream)234 status_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
releaseOutput(audio_io_handle_t output)244 void 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
getInput(int inputSource,uint32_t samplingRate,uint32_t format,uint32_t channels,AudioSystem::audio_in_acoustics acoustics)254 audio_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
startInput(audio_io_handle_t input)267 status_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
stopInput(audio_io_handle_t input)276 status_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
releaseInput(audio_io_handle_t input)285 void 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
initStreamVolume(AudioSystem::stream_type stream,int indexMin,int indexMax)294 status_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
setStreamVolumeIndex(AudioSystem::stream_type stream,int index)311 status_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
getStreamVolumeIndex(AudioSystem::stream_type stream,int * index)326 status_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
binderDied(const wp<IBinder> & who)340 void AudioPolicyService::binderDied(const wp<IBinder>& who) {
341 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
342 }
343
tryLock(Mutex & mutex)344 static 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
dumpInternals(int fd)357 status_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
dump(int fd,const Vector<String16> & args)374 status_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
dumpPermissionDenial(int fd)402 status_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
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)416 status_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 // ----------------------------------------------------------------------------
instantiate()424 void AudioPolicyService::instantiate() {
425 defaultServiceManager()->addService(
426 String16("media.audio_policy"), new AudioPolicyService());
427 }
428
429
430 // ----------------------------------------------------------------------------
431 // AudioPolicyClientInterface implementation
432 // ----------------------------------------------------------------------------
433
434
openOutput(uint32_t * pDevices,uint32_t * pSamplingRate,uint32_t * pFormat,uint32_t * pChannels,uint32_t * pLatencyMs,AudioSystem::output_flags flags)435 audio_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
openDuplicateOutput(audio_io_handle_t output1,audio_io_handle_t output2)451 audio_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
closeOutput(audio_io_handle_t output)461 status_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
suspendOutput(audio_io_handle_t output)470 status_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
restoreOutput(audio_io_handle_t output)481 status_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
openInput(uint32_t * pDevices,uint32_t * pSamplingRate,uint32_t * pFormat,uint32_t * pChannels,uint32_t acoustics)492 audio_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
closeInput(audio_io_handle_t input)507 status_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
setStreamVolume(AudioSystem::stream_type stream,float volume,audio_io_handle_t output,int delayMs)515 status_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
setStreamOutput(AudioSystem::stream_type stream,audio_io_handle_t output)520 status_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
setParameters(audio_io_handle_t ioHandle,const String8 & keyValuePairs,int delayMs)529 void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
530 {
531 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
532 }
533
getParameters(audio_io_handle_t ioHandle,const String8 & keys)534 String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
535 {
536 String8 result = AudioSystem::getParameters(ioHandle, keys);
537 return result;
538 }
539
startTone(ToneGenerator::tone_type tone,AudioSystem::stream_type stream)540 status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
541 {
542 mTonePlaybackThread->startToneCommand(tone, stream);
543 return NO_ERROR;
544 }
545
stopTone()546 status_t AudioPolicyService::stopTone()
547 {
548 mTonePlaybackThread->stopToneCommand();
549 return NO_ERROR;
550 }
551
setVoiceVolume(float volume,int delayMs)552 status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
553 {
554 return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
555 }
556
557 // ----------- AudioPolicyService::AudioCommandThread implementation ----------
558
AudioCommandThread()559 AudioPolicyService::AudioCommandThread::AudioCommandThread()
560 : Thread(false)
561 {
562 mpToneGenerator = NULL;
563 }
564
565
~AudioCommandThread()566 AudioPolicyService::AudioCommandThread::~AudioCommandThread()
567 {
568 mAudioCommands.clear();
569 if (mpToneGenerator != NULL) delete mpToneGenerator;
570 }
571
onFirstRef()572 void 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
threadLoop()582 bool 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
dump(int fd)668 status_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
startToneCommand(int type,int stream)702 void 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
stopToneCommand()717 void 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
volumeCommand(int stream,float volume,int output,int delayMs)729 status_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
parametersCommand(int ioHandle,const String8 & keyValuePairs,int delayMs)757 status_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
voiceVolumeCommand(float volume,int delayMs)784 status_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
insertCommand_l(AudioCommand * command,int delayMs)811 void 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
exit()890 void AudioPolicyService::AudioCommandThread::exit()
891 {
892 LOGV("AudioCommandThread::exit");
893 {
894 AutoMutex _l(mLock);
895 requestExit();
896 mWaitWorkCV.signal();
897 }
898 requestExitAndWait();
899 }
900
dump(char * buffer,size_t size)901 void 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
912