blob: 97236973e64023e1821b99936b9c3227626c7a00 [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
Eric Laurent23490ef2009-08-27 00:48:47 -070019
20#undef __STRICT_ANSI__
21#define __STDINT_LIMITS
22#define __STDC_LIMIT_MACROS
23#include <stdint.h>
24
25#include <sys/time.h>
Eric Laurent9d91ad52009-07-17 12:17:14 -070026#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"
Eric Laurenta2e32692009-07-24 06:58:44 -070033#include "AudioPolicyManagerGeneric.h"
Eric Laurent9d91ad52009-07-17 12:17:14 -070034#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
Eric Laurent7f698b42009-11-02 10:29:02 -080046static 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
Eric Laurent9d91ad52009-07-17 12:17:14 -070052static 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()
Eric Laurenta2e32692009-07-24 06:58:44 -070065 : BnAudioPolicyService() , mpPolicyManager(NULL)
Eric Laurent9d91ad52009-07-17 12:17:14 -070066{
Eric Laurent9d91ad52009-07-17 12:17:14 -070067 char value[PROPERTY_VALUE_MAX];
68
Eric Laurent9d91ad52009-07-17 12:17:14 -070069 // start tone playback thread
Eric Laurent23490ef2009-08-27 00:48:47 -070070 mTonePlaybackThread = new AudioCommandThread();
Eric Laurent9d91ad52009-07-17 12:17:14 -070071 // start audio commands thread
72 mAudioCommandThread = new AudioCommandThread();
73
Eric Laurenta2e32692009-07-24 06:58:44 -070074#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
Eric Laurent9d91ad52009-07-17 12:17:14 -070088
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{
Eric Laurent23490ef2009-08-27 00:48:47 -070096 mTonePlaybackThread->exit();
97 mTonePlaybackThread.clear();
Eric Laurent9d91ad52009-07-17 12:17:14 -070098 mAudioCommandThread->exit();
99 mAudioCommandThread.clear();
100
101 if (mpPolicyManager) {
Eric Laurenta2e32692009-07-24 06:58:44 -0700102 delete mpPolicyManager;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700103 }
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) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700217 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700218 }
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) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700261 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700262 }
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
Eric Laurent7f698b42009-11-02 10:29:02 -0800344static 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
Eric Laurent9d91ad52009-07-17 12:17:14 -0700374status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
375{
376 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
Eric Laurent7f698b42009-11-02 10:29:02 -0800377 dumpPermissionDenial(fd);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700378 } else {
Eric Laurent7f698b42009-11-02 10:29:02 -0800379 bool locked = tryLock(mLock);
380 if (!locked) {
381 String8 result(kDeadlockedString);
382 write(fd, result.string(), result.size());
383 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700384
Eric Laurent7f698b42009-11-02 10:29:02 -0800385 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();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700398 }
399 return NO_ERROR;
400}
401
Eric Laurent7f698b42009-11-02 10:29:02 -0800402status_t AudioPolicyService::dumpPermissionDenial(int fd)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700403{
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");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700445 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700446 }
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");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700456 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700457 }
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");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700501 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700502 }
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
Eric Laurent23490ef2009-08-27 00:48:47 -0700515status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700516{
Eric Laurent23490ef2009-08-27 00:48:47 -0700517 return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700518}
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
Eric Laurent23490ef2009-08-27 00:48:47 -0700529void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700530{
Eric Laurent23490ef2009-08-27 00:48:47 -0700531 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700532}
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{
Eric Laurent23490ef2009-08-27 00:48:47 -0700542 mTonePlaybackThread->startToneCommand(tone, stream);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700543 return NO_ERROR;
544}
545
546status_t AudioPolicyService::stopTone()
547{
Eric Laurent23490ef2009-08-27 00:48:47 -0700548 mTonePlaybackThread->stopToneCommand();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700549 return NO_ERROR;
550}
551
Eric Laurent63da2b62009-10-21 08:14:22 -0700552status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
553{
554 return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
555}
Eric Laurent9d91ad52009-07-17 12:17:14 -0700556
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{
Eric Laurent23490ef2009-08-27 00:48:47 -0700584 nsecs_t waitTime = INT64_MAX;
585
Eric Laurent9d91ad52009-07-17 12:17:14 -0700586 mLock.lock();
587 while (!exitPending())
588 {
589 while(!mAudioCommands.isEmpty()) {
Eric Laurent23490ef2009-08-27 00:48:47 -0700590 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 switch (command->mCommand) {
596 case START_TONE: {
597 mLock.unlock();
598 ToneData *data = (ToneData *)command->mParam;
599 LOGV("AudioCommandThread() processing start tone %d on stream %d",
600 data->mType, data->mStream);
601 if (mpToneGenerator != NULL)
602 delete mpToneGenerator;
603 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
604 mpToneGenerator->startTone(data->mType);
605 delete data;
606 mLock.lock();
607 }break;
608 case STOP_TONE: {
609 mLock.unlock();
610 LOGV("AudioCommandThread() processing stop tone");
611 if (mpToneGenerator != NULL) {
612 mpToneGenerator->stopTone();
613 delete mpToneGenerator;
614 mpToneGenerator = NULL;
615 }
616 mLock.lock();
617 }break;
618 case SET_VOLUME: {
619 VolumeData *data = (VolumeData *)command->mParam;
620 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
621 command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
622 if (command->mWaitStatus) {
623 command->mCond.signal();
624 mWaitWorkCV.wait(mLock);
625 }
626 delete data;
627 }break;
628 case SET_PARAMETERS: {
629 ParametersData *data = (ParametersData *)command->mParam;
630 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
631 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
632 if (command->mWaitStatus) {
633 command->mCond.signal();
634 mWaitWorkCV.wait(mLock);
635 }
636 delete data;
637 }break;
Eric Laurent63da2b62009-10-21 08:14:22 -0700638 case SET_VOICE_VOLUME: {
639 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
640 LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
641 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
642 if (command->mWaitStatus) {
643 command->mCond.signal();
644 mWaitWorkCV.wait(mLock);
645 }
646 delete data;
647 }break;
Eric Laurent23490ef2009-08-27 00:48:47 -0700648 default:
649 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700650 }
Eric Laurent23490ef2009-08-27 00:48:47 -0700651 delete command;
652 waitTime = INT64_MAX;
653 } else {
654 waitTime = mAudioCommands[0]->mTime - curTime;
655 break;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700656 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700657 }
658 LOGV("AudioCommandThread() going to sleep");
Eric Laurent23490ef2009-08-27 00:48:47 -0700659 mWaitWorkCV.waitRelative(mLock, waitTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700660 LOGV("AudioCommandThread() waking up");
661 }
662 mLock.unlock();
663 return false;
664}
665
Eric Laurent7f698b42009-11-02 10:29:02 -0800666status_t AudioPolicyService::AudioCommandThread::dump(int fd)
667{
668 const size_t SIZE = 256;
669 char buffer[SIZE];
670 String8 result;
671
672 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
673 result.append(buffer);
674 write(fd, result.string(), result.size());
675
676 bool locked = tryLock(mLock);
677 if (!locked) {
678 String8 result2(kCmdDeadlockedString);
679 write(fd, result2.string(), result2.size());
680 }
681
682 snprintf(buffer, SIZE, "- Commands:\n");
683 result = String8(buffer);
684 result.append(" Command Time Status Wait pParam\n");
685 for (int i = 0; i < (int)mAudioCommands.size(); i++) {
686 mAudioCommands[i]->dump(buffer, SIZE);
687 result.append(buffer);
688 }
689 write(fd, result.string(), result.size());
690
691 if (locked) mLock.unlock();
692
693 return NO_ERROR;
694}
695
Eric Laurent9d91ad52009-07-17 12:17:14 -0700696void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
697{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700698 AudioCommand *command = new AudioCommand();
699 command->mCommand = START_TONE;
700 ToneData *data = new ToneData();
701 data->mType = type;
702 data->mStream = stream;
703 command->mParam = (void *)data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700704 command->mWaitStatus = false;
Eric Laurent63da2b62009-10-21 08:14:22 -0700705 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700706 insertCommand_l(command);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700707 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
708 mWaitWorkCV.signal();
709}
710
711void AudioPolicyService::AudioCommandThread::stopToneCommand()
712{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700713 AudioCommand *command = new AudioCommand();
714 command->mCommand = STOP_TONE;
715 command->mParam = NULL;
Eric Laurent23490ef2009-08-27 00:48:47 -0700716 command->mWaitStatus = false;
Eric Laurent63da2b62009-10-21 08:14:22 -0700717 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700718 insertCommand_l(command);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700719 LOGV("AudioCommandThread() adding tone stop");
720 mWaitWorkCV.signal();
721}
722
Eric Laurent23490ef2009-08-27 00:48:47 -0700723status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700724{
Eric Laurent23490ef2009-08-27 00:48:47 -0700725 status_t status = NO_ERROR;
726
Eric Laurent9d91ad52009-07-17 12:17:14 -0700727 AudioCommand *command = new AudioCommand();
728 command->mCommand = SET_VOLUME;
729 VolumeData *data = new VolumeData();
730 data->mStream = stream;
731 data->mVolume = volume;
732 data->mIO = output;
733 command->mParam = data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700734 if (delayMs == 0) {
735 command->mWaitStatus = true;
736 } else {
737 command->mWaitStatus = false;
738 }
Eric Laurent63da2b62009-10-21 08:14:22 -0700739 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700740 insertCommand_l(command, delayMs);
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700741 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700742 mWaitWorkCV.signal();
Eric Laurent23490ef2009-08-27 00:48:47 -0700743 if (command->mWaitStatus) {
744 command->mCond.wait(mLock);
745 status = command->mStatus;
746 mWaitWorkCV.signal();
747 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700748 return status;
749}
750
Eric Laurent23490ef2009-08-27 00:48:47 -0700751status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700752{
Eric Laurent23490ef2009-08-27 00:48:47 -0700753 status_t status = NO_ERROR;
754
Eric Laurent9d91ad52009-07-17 12:17:14 -0700755 AudioCommand *command = new AudioCommand();
756 command->mCommand = SET_PARAMETERS;
757 ParametersData *data = new ParametersData();
758 data->mIO = ioHandle;
759 data->mKeyValuePairs = keyValuePairs;
760 command->mParam = data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700761 if (delayMs == 0) {
762 command->mWaitStatus = true;
763 } else {
764 command->mWaitStatus = false;
765 }
Eric Laurent63da2b62009-10-21 08:14:22 -0700766 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700767 insertCommand_l(command, delayMs);
768 LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700769 mWaitWorkCV.signal();
Eric Laurent23490ef2009-08-27 00:48:47 -0700770 if (command->mWaitStatus) {
771 command->mCond.wait(mLock);
772 status = command->mStatus;
773 mWaitWorkCV.signal();
774 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700775 return status;
776}
777
Eric Laurent63da2b62009-10-21 08:14:22 -0700778status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
779{
780 status_t status = NO_ERROR;
781
782 AudioCommand *command = new AudioCommand();
783 command->mCommand = SET_VOICE_VOLUME;
784 VoiceVolumeData *data = new VoiceVolumeData();
785 data->mVolume = volume;
786 command->mParam = data;
787 if (delayMs == 0) {
788 command->mWaitStatus = true;
789 } else {
790 command->mWaitStatus = false;
791 }
792 Mutex::Autolock _l(mLock);
793 insertCommand_l(command, delayMs);
794 LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
795 mWaitWorkCV.signal();
796 if (command->mWaitStatus) {
797 command->mCond.wait(mLock);
798 status = command->mStatus;
799 mWaitWorkCV.signal();
800 }
801 return status;
802}
803
Eric Laurent23490ef2009-08-27 00:48:47 -0700804// insertCommand_l() must be called with mLock held
805void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
806{
807 ssize_t i;
808 Vector <AudioCommand *> removedCommands;
809
810 command->mTime = systemTime() + milliseconds(delayMs);
811
812 // check same pending commands with later time stamps and eliminate them
813 for (i = mAudioCommands.size()-1; i >= 0; i--) {
814 AudioCommand *command2 = mAudioCommands[i];
815 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
816 if (command2->mTime <= command->mTime) break;
817 if (command2->mCommand != command->mCommand) continue;
818
819 switch (command->mCommand) {
820 case SET_PARAMETERS: {
821 ParametersData *data = (ParametersData *)command->mParam;
822 ParametersData *data2 = (ParametersData *)command2->mParam;
823 if (data->mIO != data2->mIO) break;
824 LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
825 AudioParameter param = AudioParameter(data->mKeyValuePairs);
826 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
827 for (size_t j = 0; j < param.size(); j++) {
828 String8 key;
829 String8 value;
830 param.getAt(j, key, value);
831 for (size_t k = 0; k < param2.size(); k++) {
832 String8 key2;
833 String8 value2;
834 param2.getAt(k, key2, value2);
835 if (key2 == key) {
836 param2.remove(key2);
837 LOGV("Filtering out parameter %s", key2.string());
838 break;
839 }
840 }
841 }
842 // if all keys have been filtered out, remove the command.
843 // otherwise, update the key value pairs
844 if (param2.size() == 0) {
845 removedCommands.add(command2);
846 } else {
847 data2->mKeyValuePairs = param2.toString();
848 }
849 } break;
850
851 case SET_VOLUME: {
852 VolumeData *data = (VolumeData *)command->mParam;
853 VolumeData *data2 = (VolumeData *)command2->mParam;
854 if (data->mIO != data2->mIO) break;
855 if (data->mStream != data2->mStream) break;
856 LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
857 removedCommands.add(command2);
858 } break;
859 case START_TONE:
860 case STOP_TONE:
861 default:
862 break;
863 }
864 }
865
866 // remove filtered commands
867 for (size_t j = 0; j < removedCommands.size(); j++) {
868 // removed commands always have time stamps greater than current command
869 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
870 if (mAudioCommands[k] == removedCommands[j]) {
871 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
872 mAudioCommands.removeAt(k);
873 break;
874 }
875 }
876 }
877 removedCommands.clear();
878
879 // insert command at the right place according to its time stamp
880 LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
881 mAudioCommands.insertAt(command, i + 1);
882}
883
Eric Laurent9d91ad52009-07-17 12:17:14 -0700884void AudioPolicyService::AudioCommandThread::exit()
885{
886 LOGV("AudioCommandThread::exit");
887 {
888 AutoMutex _l(mLock);
889 requestExit();
890 mWaitWorkCV.signal();
891 }
892 requestExitAndWait();
893}
894
Eric Laurent7f698b42009-11-02 10:29:02 -0800895void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
896{
897 snprintf(buffer, size, " %02d %06d.%03d %03d %01u %p\n",
898 mCommand,
899 (int)ns2s(mTime),
900 (int)ns2ms(mTime)%1000,
901 mStatus,
902 mWaitStatus,
903 mParam);
904}
905
Eric Laurent9d91ad52009-07-17 12:17:14 -0700906}; // namespace android