blob: f71c99c0c4ae053a2d4c18e8ca46c32fadc22d2d [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 Laurent9d91ad52009-07-17 12:17:14 -070046static bool checkPermission() {
47#ifndef HAVE_ANDROID_OS
48 return true;
49#endif
50 if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
51 bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
52 if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
53 return ok;
54}
55
56// ----------------------------------------------------------------------------
57
58AudioPolicyService::AudioPolicyService()
Eric Laurenta2e32692009-07-24 06:58:44 -070059 : BnAudioPolicyService() , mpPolicyManager(NULL)
Eric Laurent9d91ad52009-07-17 12:17:14 -070060{
Eric Laurent9d91ad52009-07-17 12:17:14 -070061 char value[PROPERTY_VALUE_MAX];
62
Eric Laurent9d91ad52009-07-17 12:17:14 -070063 // start tone playback thread
Eric Laurent23490ef2009-08-27 00:48:47 -070064 mTonePlaybackThread = new AudioCommandThread();
Eric Laurent9d91ad52009-07-17 12:17:14 -070065 // start audio commands thread
66 mAudioCommandThread = new AudioCommandThread();
67
Eric Laurenta2e32692009-07-24 06:58:44 -070068#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
69 mpPolicyManager = new AudioPolicyManagerGeneric(this);
70 LOGV("build for GENERIC_AUDIO - using generic audio policy");
71#else
72 // if running in emulation - use the emulator driver
73 if (property_get("ro.kernel.qemu", value, 0)) {
74 LOGV("Running in emulation - using generic audio policy");
75 mpPolicyManager = new AudioPolicyManagerGeneric(this);
76 }
77 else {
78 LOGV("Using hardware specific audio policy");
79 mpPolicyManager = createAudioPolicyManager(this);
80 }
81#endif
Eric Laurent9d91ad52009-07-17 12:17:14 -070082
83 // load properties
84 property_get("ro.camera.sound.forced", value, "0");
85 mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
86}
87
88AudioPolicyService::~AudioPolicyService()
89{
Eric Laurent23490ef2009-08-27 00:48:47 -070090 mTonePlaybackThread->exit();
91 mTonePlaybackThread.clear();
Eric Laurent9d91ad52009-07-17 12:17:14 -070092 mAudioCommandThread->exit();
93 mAudioCommandThread.clear();
94
95 if (mpPolicyManager) {
Eric Laurenta2e32692009-07-24 06:58:44 -070096 delete mpPolicyManager;
Eric Laurent9d91ad52009-07-17 12:17:14 -070097 }
98}
99
100
101status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
102 AudioSystem::device_connection_state state,
103 const char *device_address)
104{
105 if (mpPolicyManager == NULL) {
106 return NO_INIT;
107 }
108 if (!checkPermission()) {
109 return PERMISSION_DENIED;
110 }
111 if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
112 return BAD_VALUE;
113 }
114 if (state != AudioSystem::DEVICE_STATE_AVAILABLE && state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
115 return BAD_VALUE;
116 }
117
118 LOGV("setDeviceConnectionState() tid %d", gettid());
119 Mutex::Autolock _l(mLock);
120 return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
121}
122
123AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(AudioSystem::audio_devices device,
124 const char *device_address)
125{
126 if (mpPolicyManager == NULL) {
127 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
128 }
129 if (!checkPermission()) {
130 return AudioSystem::DEVICE_STATE_UNAVAILABLE;
131 }
132 return mpPolicyManager->getDeviceConnectionState(device, device_address);
133}
134
135status_t AudioPolicyService::setPhoneState(int state)
136{
137 if (mpPolicyManager == NULL) {
138 return NO_INIT;
139 }
140 if (!checkPermission()) {
141 return PERMISSION_DENIED;
142 }
143 if (state < 0 || state >= AudioSystem::NUM_MODES) {
144 return BAD_VALUE;
145 }
146
147 LOGV("setPhoneState() tid %d", gettid());
148
149 // TODO: check if it is more appropriate to do it in platform specific policy manager
150 AudioSystem::setMode(state);
151
152 Mutex::Autolock _l(mLock);
153 mpPolicyManager->setPhoneState(state);
154 return NO_ERROR;
155}
156
157status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
158{
159 if (mpPolicyManager == NULL) {
160 return NO_INIT;
161 }
162 if (!checkPermission()) {
163 return PERMISSION_DENIED;
164 }
165
166 mpPolicyManager->setRingerMode(mode, mask);
167 return NO_ERROR;
168}
169
170status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
171{
172 if (mpPolicyManager == NULL) {
173 return NO_INIT;
174 }
175 if (!checkPermission()) {
176 return PERMISSION_DENIED;
177 }
178 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
179 return BAD_VALUE;
180 }
181 if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
182 return BAD_VALUE;
183 }
184 LOGV("setForceUse() tid %d", gettid());
185 Mutex::Autolock _l(mLock);
186 mpPolicyManager->setForceUse(usage, config);
187 return NO_ERROR;
188}
189
190AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
191{
192 if (mpPolicyManager == NULL) {
193 return AudioSystem::FORCE_NONE;
194 }
195 if (!checkPermission()) {
196 return AudioSystem::FORCE_NONE;
197 }
198 if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
199 return AudioSystem::FORCE_NONE;
200 }
201 return mpPolicyManager->getForceUse(usage);
202}
203
204audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
205 uint32_t samplingRate,
206 uint32_t format,
207 uint32_t channels,
208 AudioSystem::output_flags flags)
209{
210 if (mpPolicyManager == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700211 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700212 }
213 LOGV("getOutput() tid %d", gettid());
214 Mutex::Autolock _l(mLock);
215 return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
216}
217
218status_t AudioPolicyService::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
219{
220 if (mpPolicyManager == NULL) {
221 return NO_INIT;
222 }
223 LOGV("startOutput() tid %d", gettid());
224 Mutex::Autolock _l(mLock);
225 return mpPolicyManager->startOutput(output, stream);
226}
227
228status_t AudioPolicyService::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
229{
230 if (mpPolicyManager == NULL) {
231 return NO_INIT;
232 }
233 LOGV("stopOutput() tid %d", gettid());
234 Mutex::Autolock _l(mLock);
235 return mpPolicyManager->stopOutput(output, stream);
236}
237
238void AudioPolicyService::releaseOutput(audio_io_handle_t output)
239{
240 if (mpPolicyManager == NULL) {
241 return;
242 }
243 LOGV("releaseOutput() tid %d", gettid());
244 Mutex::Autolock _l(mLock);
245 mpPolicyManager->releaseOutput(output);
246}
247
248audio_io_handle_t AudioPolicyService::getInput(int inputSource,
249 uint32_t samplingRate,
250 uint32_t format,
251 uint32_t channels,
252 AudioSystem::audio_in_acoustics acoustics)
253{
254 if (mpPolicyManager == NULL) {
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700255 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700256 }
257 Mutex::Autolock _l(mLock);
258 return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
259}
260
261status_t AudioPolicyService::startInput(audio_io_handle_t input)
262{
263 if (mpPolicyManager == NULL) {
264 return NO_INIT;
265 }
266 Mutex::Autolock _l(mLock);
267 return mpPolicyManager->startInput(input);
268}
269
270status_t AudioPolicyService::stopInput(audio_io_handle_t input)
271{
272 if (mpPolicyManager == NULL) {
273 return NO_INIT;
274 }
275 Mutex::Autolock _l(mLock);
276 return mpPolicyManager->stopInput(input);
277}
278
279void AudioPolicyService::releaseInput(audio_io_handle_t input)
280{
281 if (mpPolicyManager == NULL) {
282 return;
283 }
284 Mutex::Autolock _l(mLock);
285 mpPolicyManager->releaseInput(input);
286}
287
288status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
289 int indexMin,
290 int indexMax)
291{
292 if (mpPolicyManager == NULL) {
293 return NO_INIT;
294 }
295 if (!checkPermission()) {
296 return PERMISSION_DENIED;
297 }
298 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
299 return BAD_VALUE;
300 }
301 mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
302 return NO_ERROR;
303}
304
305status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
306{
307 if (mpPolicyManager == NULL) {
308 return NO_INIT;
309 }
310 if (!checkPermission()) {
311 return PERMISSION_DENIED;
312 }
313 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
314 return BAD_VALUE;
315 }
316
317 return mpPolicyManager->setStreamVolumeIndex(stream, index);
318}
319
320status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
321{
322 if (mpPolicyManager == NULL) {
323 return NO_INIT;
324 }
325 if (!checkPermission()) {
326 return PERMISSION_DENIED;
327 }
328 if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
329 return BAD_VALUE;
330 }
331 return mpPolicyManager->getStreamVolumeIndex(stream, index);
332}
333
334void AudioPolicyService::binderDied(const wp<IBinder>& who) {
335 LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
336}
337
338status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
339{
340 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
341 dumpPermissionDenial(fd, args);
342 } else {
343
344 }
345 return NO_ERROR;
346}
347
348status_t AudioPolicyService::dumpPermissionDenial(int fd, const Vector<String16>& args)
349{
350 const size_t SIZE = 256;
351 char buffer[SIZE];
352 String8 result;
353 snprintf(buffer, SIZE, "Permission Denial: "
354 "can't dump AudioPolicyService from pid=%d, uid=%d\n",
355 IPCThreadState::self()->getCallingPid(),
356 IPCThreadState::self()->getCallingUid());
357 result.append(buffer);
358 write(fd, result.string(), result.size());
359 return NO_ERROR;
360}
361
362status_t AudioPolicyService::onTransact(
363 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
364{
365 return BnAudioPolicyService::onTransact(code, data, reply, flags);
366}
367
368
369// ----------------------------------------------------------------------------
370void AudioPolicyService::instantiate() {
371 defaultServiceManager()->addService(
372 String16("media.audio_policy"), new AudioPolicyService());
373}
374
375
376// ----------------------------------------------------------------------------
377// AudioPolicyClientInterface implementation
378// ----------------------------------------------------------------------------
379
380
381audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
382 uint32_t *pSamplingRate,
383 uint32_t *pFormat,
384 uint32_t *pChannels,
385 uint32_t *pLatencyMs,
386 AudioSystem::output_flags flags)
387{
388 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
389 if (af == 0) {
390 LOGW("openOutput() could not get AudioFlinger");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700391 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700392 }
393
394 return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags);
395}
396
397audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2)
398{
399 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
400 if (af == 0) {
401 LOGW("openDuplicateOutput() could not get AudioFlinger");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700402 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700403 }
404 return af->openDuplicateOutput(output1, output2);
405}
406
407status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
408{
409 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
410 if (af == 0) return PERMISSION_DENIED;
411
412 return af->closeOutput(output);
413}
414
415
416status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
417{
418 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
419 if (af == 0) {
420 LOGW("suspendOutput() could not get AudioFlinger");
421 return PERMISSION_DENIED;
422 }
423
424 return af->suspendOutput(output);
425}
426
427status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
428{
429 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
430 if (af == 0) {
431 LOGW("restoreOutput() could not get AudioFlinger");
432 return PERMISSION_DENIED;
433 }
434
435 return af->restoreOutput(output);
436}
437
438audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
439 uint32_t *pSamplingRate,
440 uint32_t *pFormat,
441 uint32_t *pChannels,
442 uint32_t acoustics)
443{
444 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
445 if (af == 0) {
446 LOGW("openInput() could not get AudioFlinger");
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700447 return 0;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700448 }
449
450 return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
451}
452
453status_t AudioPolicyService::closeInput(audio_io_handle_t input)
454{
455 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
456 if (af == 0) return PERMISSION_DENIED;
457
458 return af->closeInput(input);
459}
460
Eric Laurent23490ef2009-08-27 00:48:47 -0700461status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700462{
Eric Laurent23490ef2009-08-27 00:48:47 -0700463 return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700464}
465
466status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output)
467{
468 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
469 if (af == 0) return PERMISSION_DENIED;
470
471 return af->setStreamOutput(stream, output);
472}
473
474
Eric Laurent23490ef2009-08-27 00:48:47 -0700475void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700476{
Eric Laurent23490ef2009-08-27 00:48:47 -0700477 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700478}
479
480String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
481{
482 String8 result = AudioSystem::getParameters(ioHandle, keys);
483 return result;
484}
485
486status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream)
487{
Eric Laurent23490ef2009-08-27 00:48:47 -0700488 mTonePlaybackThread->startToneCommand(tone, stream);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700489 return NO_ERROR;
490}
491
492status_t AudioPolicyService::stopTone()
493{
Eric Laurent23490ef2009-08-27 00:48:47 -0700494 mTonePlaybackThread->stopToneCommand();
Eric Laurent9d91ad52009-07-17 12:17:14 -0700495 return NO_ERROR;
496}
497
Eric Laurent63da2b62009-10-21 08:14:22 -0700498status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
499{
500 return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
501}
Eric Laurent9d91ad52009-07-17 12:17:14 -0700502
503// ----------- AudioPolicyService::AudioCommandThread implementation ----------
504
505AudioPolicyService::AudioCommandThread::AudioCommandThread()
506 : Thread(false)
507{
508 mpToneGenerator = NULL;
509}
510
511
512AudioPolicyService::AudioCommandThread::~AudioCommandThread()
513{
514 mAudioCommands.clear();
515 if (mpToneGenerator != NULL) delete mpToneGenerator;
516}
517
518void AudioPolicyService::AudioCommandThread::onFirstRef()
519{
520 const size_t SIZE = 256;
521 char buffer[SIZE];
522
523 snprintf(buffer, SIZE, "AudioCommandThread");
524
525 run(buffer, ANDROID_PRIORITY_AUDIO);
526}
527
528bool AudioPolicyService::AudioCommandThread::threadLoop()
529{
Eric Laurent23490ef2009-08-27 00:48:47 -0700530 nsecs_t waitTime = INT64_MAX;
531
Eric Laurent9d91ad52009-07-17 12:17:14 -0700532 mLock.lock();
533 while (!exitPending())
534 {
535 while(!mAudioCommands.isEmpty()) {
Eric Laurent23490ef2009-08-27 00:48:47 -0700536 nsecs_t curTime = systemTime();
537 // commands are sorted by increasing time stamp: execute them from index 0 and up
538 if (mAudioCommands[0]->mTime <= curTime) {
539 AudioCommand *command = mAudioCommands[0];
540 mAudioCommands.removeAt(0);
541 switch (command->mCommand) {
542 case START_TONE: {
543 mLock.unlock();
544 ToneData *data = (ToneData *)command->mParam;
545 LOGV("AudioCommandThread() processing start tone %d on stream %d",
546 data->mType, data->mStream);
547 if (mpToneGenerator != NULL)
548 delete mpToneGenerator;
549 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
550 mpToneGenerator->startTone(data->mType);
551 delete data;
552 mLock.lock();
553 }break;
554 case STOP_TONE: {
555 mLock.unlock();
556 LOGV("AudioCommandThread() processing stop tone");
557 if (mpToneGenerator != NULL) {
558 mpToneGenerator->stopTone();
559 delete mpToneGenerator;
560 mpToneGenerator = NULL;
561 }
562 mLock.lock();
563 }break;
564 case SET_VOLUME: {
565 VolumeData *data = (VolumeData *)command->mParam;
566 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
567 command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
568 if (command->mWaitStatus) {
569 command->mCond.signal();
570 mWaitWorkCV.wait(mLock);
571 }
572 delete data;
573 }break;
574 case SET_PARAMETERS: {
575 ParametersData *data = (ParametersData *)command->mParam;
576 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
577 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
578 if (command->mWaitStatus) {
579 command->mCond.signal();
580 mWaitWorkCV.wait(mLock);
581 }
582 delete data;
583 }break;
Eric Laurent63da2b62009-10-21 08:14:22 -0700584 case SET_VOICE_VOLUME: {
585 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
586 LOGV("AudioCommandThread() processing set voice volume volume %f", data->mVolume);
587 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
588 if (command->mWaitStatus) {
589 command->mCond.signal();
590 mWaitWorkCV.wait(mLock);
591 }
592 delete data;
593 }break;
Eric Laurent23490ef2009-08-27 00:48:47 -0700594 default:
595 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700596 }
Eric Laurent23490ef2009-08-27 00:48:47 -0700597 delete command;
598 waitTime = INT64_MAX;
599 } else {
600 waitTime = mAudioCommands[0]->mTime - curTime;
601 break;
Eric Laurent9d91ad52009-07-17 12:17:14 -0700602 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700603 }
604 LOGV("AudioCommandThread() going to sleep");
Eric Laurent23490ef2009-08-27 00:48:47 -0700605 mWaitWorkCV.waitRelative(mLock, waitTime);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700606 LOGV("AudioCommandThread() waking up");
607 }
608 mLock.unlock();
609 return false;
610}
611
612void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
613{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700614 AudioCommand *command = new AudioCommand();
615 command->mCommand = START_TONE;
616 ToneData *data = new ToneData();
617 data->mType = type;
618 data->mStream = stream;
619 command->mParam = (void *)data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700620 command->mWaitStatus = false;
Eric Laurent63da2b62009-10-21 08:14:22 -0700621 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700622 insertCommand_l(command);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700623 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
624 mWaitWorkCV.signal();
625}
626
627void AudioPolicyService::AudioCommandThread::stopToneCommand()
628{
Eric Laurent9d91ad52009-07-17 12:17:14 -0700629 AudioCommand *command = new AudioCommand();
630 command->mCommand = STOP_TONE;
631 command->mParam = NULL;
Eric Laurent23490ef2009-08-27 00:48:47 -0700632 command->mWaitStatus = false;
Eric Laurent63da2b62009-10-21 08:14:22 -0700633 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700634 insertCommand_l(command);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700635 LOGV("AudioCommandThread() adding tone stop");
636 mWaitWorkCV.signal();
637}
638
Eric Laurent23490ef2009-08-27 00:48:47 -0700639status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700640{
Eric Laurent23490ef2009-08-27 00:48:47 -0700641 status_t status = NO_ERROR;
642
Eric Laurent9d91ad52009-07-17 12:17:14 -0700643 AudioCommand *command = new AudioCommand();
644 command->mCommand = SET_VOLUME;
645 VolumeData *data = new VolumeData();
646 data->mStream = stream;
647 data->mVolume = volume;
648 data->mIO = output;
649 command->mParam = data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700650 if (delayMs == 0) {
651 command->mWaitStatus = true;
652 } else {
653 command->mWaitStatus = false;
654 }
Eric Laurent63da2b62009-10-21 08:14:22 -0700655 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700656 insertCommand_l(command, delayMs);
Eric Laurente0e9ecc2009-07-28 08:44:33 -0700657 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700658 mWaitWorkCV.signal();
Eric Laurent23490ef2009-08-27 00:48:47 -0700659 if (command->mWaitStatus) {
660 command->mCond.wait(mLock);
661 status = command->mStatus;
662 mWaitWorkCV.signal();
663 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700664 return status;
665}
666
Eric Laurent23490ef2009-08-27 00:48:47 -0700667status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurent9d91ad52009-07-17 12:17:14 -0700668{
Eric Laurent23490ef2009-08-27 00:48:47 -0700669 status_t status = NO_ERROR;
670
Eric Laurent9d91ad52009-07-17 12:17:14 -0700671 AudioCommand *command = new AudioCommand();
672 command->mCommand = SET_PARAMETERS;
673 ParametersData *data = new ParametersData();
674 data->mIO = ioHandle;
675 data->mKeyValuePairs = keyValuePairs;
676 command->mParam = data;
Eric Laurent23490ef2009-08-27 00:48:47 -0700677 if (delayMs == 0) {
678 command->mWaitStatus = true;
679 } else {
680 command->mWaitStatus = false;
681 }
Eric Laurent63da2b62009-10-21 08:14:22 -0700682 Mutex::Autolock _l(mLock);
Eric Laurent23490ef2009-08-27 00:48:47 -0700683 insertCommand_l(command, delayMs);
684 LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
Eric Laurent9d91ad52009-07-17 12:17:14 -0700685 mWaitWorkCV.signal();
Eric Laurent23490ef2009-08-27 00:48:47 -0700686 if (command->mWaitStatus) {
687 command->mCond.wait(mLock);
688 status = command->mStatus;
689 mWaitWorkCV.signal();
690 }
Eric Laurent9d91ad52009-07-17 12:17:14 -0700691 return status;
692}
693
Eric Laurent63da2b62009-10-21 08:14:22 -0700694status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
695{
696 status_t status = NO_ERROR;
697
698 AudioCommand *command = new AudioCommand();
699 command->mCommand = SET_VOICE_VOLUME;
700 VoiceVolumeData *data = new VoiceVolumeData();
701 data->mVolume = volume;
702 command->mParam = data;
703 if (delayMs == 0) {
704 command->mWaitStatus = true;
705 } else {
706 command->mWaitStatus = false;
707 }
708 Mutex::Autolock _l(mLock);
709 insertCommand_l(command, delayMs);
710 LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
711 mWaitWorkCV.signal();
712 if (command->mWaitStatus) {
713 command->mCond.wait(mLock);
714 status = command->mStatus;
715 mWaitWorkCV.signal();
716 }
717 return status;
718}
719
Eric Laurent23490ef2009-08-27 00:48:47 -0700720// insertCommand_l() must be called with mLock held
721void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
722{
723 ssize_t i;
724 Vector <AudioCommand *> removedCommands;
725
726 command->mTime = systemTime() + milliseconds(delayMs);
727
728 // check same pending commands with later time stamps and eliminate them
729 for (i = mAudioCommands.size()-1; i >= 0; i--) {
730 AudioCommand *command2 = mAudioCommands[i];
731 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
732 if (command2->mTime <= command->mTime) break;
733 if (command2->mCommand != command->mCommand) continue;
734
735 switch (command->mCommand) {
736 case SET_PARAMETERS: {
737 ParametersData *data = (ParametersData *)command->mParam;
738 ParametersData *data2 = (ParametersData *)command2->mParam;
739 if (data->mIO != data2->mIO) break;
740 LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
741 AudioParameter param = AudioParameter(data->mKeyValuePairs);
742 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
743 for (size_t j = 0; j < param.size(); j++) {
744 String8 key;
745 String8 value;
746 param.getAt(j, key, value);
747 for (size_t k = 0; k < param2.size(); k++) {
748 String8 key2;
749 String8 value2;
750 param2.getAt(k, key2, value2);
751 if (key2 == key) {
752 param2.remove(key2);
753 LOGV("Filtering out parameter %s", key2.string());
754 break;
755 }
756 }
757 }
758 // if all keys have been filtered out, remove the command.
759 // otherwise, update the key value pairs
760 if (param2.size() == 0) {
761 removedCommands.add(command2);
762 } else {
763 data2->mKeyValuePairs = param2.toString();
764 }
765 } break;
766
767 case SET_VOLUME: {
768 VolumeData *data = (VolumeData *)command->mParam;
769 VolumeData *data2 = (VolumeData *)command2->mParam;
770 if (data->mIO != data2->mIO) break;
771 if (data->mStream != data2->mStream) break;
772 LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
773 removedCommands.add(command2);
774 } break;
775 case START_TONE:
776 case STOP_TONE:
777 default:
778 break;
779 }
780 }
781
782 // remove filtered commands
783 for (size_t j = 0; j < removedCommands.size(); j++) {
784 // removed commands always have time stamps greater than current command
785 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
786 if (mAudioCommands[k] == removedCommands[j]) {
787 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
788 mAudioCommands.removeAt(k);
789 break;
790 }
791 }
792 }
793 removedCommands.clear();
794
795 // insert command at the right place according to its time stamp
796 LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
797 mAudioCommands.insertAt(command, i + 1);
798}
799
Eric Laurent9d91ad52009-07-17 12:17:14 -0700800void AudioPolicyService::AudioCommandThread::exit()
801{
802 LOGV("AudioCommandThread::exit");
803 {
804 AutoMutex _l(mLock);
805 requestExit();
806 mWaitWorkCV.signal();
807 }
808 requestExitAndWait();
809}
810
811}; // namespace android