blob: 5c3cc8e1e64277509293f61a97954a72d64f0ebc [file] [log] [blame]
Eric Laurenta553c252009-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 Laurent327c27b2009-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 Laurenta553c252009-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 Laurent4192cce2009-07-24 06:58:44 -070033#include "AudioPolicyManagerGeneric.h"
Eric Laurenta553c252009-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 Laurenta553c252009-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 Laurent4192cce2009-07-24 06:58:44 -070059 : BnAudioPolicyService() , mpPolicyManager(NULL)
Eric Laurenta553c252009-07-17 12:17:14 -070060{
Eric Laurenta553c252009-07-17 12:17:14 -070061 char value[PROPERTY_VALUE_MAX];
62
Eric Laurenta553c252009-07-17 12:17:14 -070063 // start tone playback thread
Eric Laurent327c27b2009-08-27 00:48:47 -070064 mTonePlaybackThread = new AudioCommandThread();
Eric Laurenta553c252009-07-17 12:17:14 -070065 // start audio commands thread
66 mAudioCommandThread = new AudioCommandThread();
67
Eric Laurent4192cce2009-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 Laurenta553c252009-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 Laurent327c27b2009-08-27 00:48:47 -070090 mTonePlaybackThread->exit();
91 mTonePlaybackThread.clear();
Eric Laurenta553c252009-07-17 12:17:14 -070092 mAudioCommandThread->exit();
93 mAudioCommandThread.clear();
94
95 if (mpPolicyManager) {
Eric Laurent4192cce2009-07-24 06:58:44 -070096 delete mpPolicyManager;
Eric Laurenta553c252009-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 Laurentddb78e72009-07-28 08:44:33 -0700211 return 0;
Eric Laurenta553c252009-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 Laurentddb78e72009-07-28 08:44:33 -0700255 return 0;
Eric Laurenta553c252009-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 Laurentddb78e72009-07-28 08:44:33 -0700391 return 0;
Eric Laurenta553c252009-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 Laurentddb78e72009-07-28 08:44:33 -0700402 return 0;
Eric Laurenta553c252009-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 Laurentddb78e72009-07-28 08:44:33 -0700447 return 0;
Eric Laurenta553c252009-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 Laurent327c27b2009-08-27 00:48:47 -0700461status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, float volume, audio_io_handle_t output, int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700462{
Eric Laurent327c27b2009-08-27 00:48:47 -0700463 return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
Eric Laurenta553c252009-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 Laurent327c27b2009-08-27 00:48:47 -0700475void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700476{
Eric Laurent327c27b2009-08-27 00:48:47 -0700477 mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
Eric Laurenta553c252009-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 Laurent327c27b2009-08-27 00:48:47 -0700488 mTonePlaybackThread->startToneCommand(tone, stream);
Eric Laurenta553c252009-07-17 12:17:14 -0700489 return NO_ERROR;
490}
491
492status_t AudioPolicyService::stopTone()
493{
Eric Laurent327c27b2009-08-27 00:48:47 -0700494 mTonePlaybackThread->stopToneCommand();
Eric Laurenta553c252009-07-17 12:17:14 -0700495 return NO_ERROR;
496}
497
498
499// ----------- AudioPolicyService::AudioCommandThread implementation ----------
500
501AudioPolicyService::AudioCommandThread::AudioCommandThread()
502 : Thread(false)
503{
504 mpToneGenerator = NULL;
505}
506
507
508AudioPolicyService::AudioCommandThread::~AudioCommandThread()
509{
510 mAudioCommands.clear();
511 if (mpToneGenerator != NULL) delete mpToneGenerator;
512}
513
514void AudioPolicyService::AudioCommandThread::onFirstRef()
515{
516 const size_t SIZE = 256;
517 char buffer[SIZE];
518
519 snprintf(buffer, SIZE, "AudioCommandThread");
520
521 run(buffer, ANDROID_PRIORITY_AUDIO);
522}
523
524bool AudioPolicyService::AudioCommandThread::threadLoop()
525{
Eric Laurent327c27b2009-08-27 00:48:47 -0700526 nsecs_t waitTime = INT64_MAX;
527
Eric Laurenta553c252009-07-17 12:17:14 -0700528 mLock.lock();
529 while (!exitPending())
530 {
531 while(!mAudioCommands.isEmpty()) {
Eric Laurent327c27b2009-08-27 00:48:47 -0700532 nsecs_t curTime = systemTime();
533 // commands are sorted by increasing time stamp: execute them from index 0 and up
534 if (mAudioCommands[0]->mTime <= curTime) {
535 AudioCommand *command = mAudioCommands[0];
536 mAudioCommands.removeAt(0);
537 switch (command->mCommand) {
538 case START_TONE: {
539 mLock.unlock();
540 ToneData *data = (ToneData *)command->mParam;
541 LOGV("AudioCommandThread() processing start tone %d on stream %d",
542 data->mType, data->mStream);
543 if (mpToneGenerator != NULL)
544 delete mpToneGenerator;
545 mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
546 mpToneGenerator->startTone(data->mType);
547 delete data;
548 mLock.lock();
549 }break;
550 case STOP_TONE: {
551 mLock.unlock();
552 LOGV("AudioCommandThread() processing stop tone");
553 if (mpToneGenerator != NULL) {
554 mpToneGenerator->stopTone();
555 delete mpToneGenerator;
556 mpToneGenerator = NULL;
557 }
558 mLock.lock();
559 }break;
560 case SET_VOLUME: {
561 VolumeData *data = (VolumeData *)command->mParam;
562 LOGV("AudioCommandThread() processing set volume stream %d, volume %f, output %d", data->mStream, data->mVolume, data->mIO);
563 command->mStatus = AudioSystem::setStreamVolume(data->mStream, data->mVolume, data->mIO);
564 if (command->mWaitStatus) {
565 command->mCond.signal();
566 mWaitWorkCV.wait(mLock);
567 }
568 delete data;
569 }break;
570 case SET_PARAMETERS: {
571 ParametersData *data = (ParametersData *)command->mParam;
572 LOGV("AudioCommandThread() processing set parameters string %s, io %d", data->mKeyValuePairs.string(), data->mIO);
573 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
574 if (command->mWaitStatus) {
575 command->mCond.signal();
576 mWaitWorkCV.wait(mLock);
577 }
578 delete data;
579 }break;
580 default:
581 LOGW("AudioCommandThread() unknown command %d", command->mCommand);
Eric Laurenta553c252009-07-17 12:17:14 -0700582 }
Eric Laurent327c27b2009-08-27 00:48:47 -0700583 delete command;
584 waitTime = INT64_MAX;
585 } else {
586 waitTime = mAudioCommands[0]->mTime - curTime;
587 break;
Eric Laurenta553c252009-07-17 12:17:14 -0700588 }
Eric Laurenta553c252009-07-17 12:17:14 -0700589 }
590 LOGV("AudioCommandThread() going to sleep");
Eric Laurent327c27b2009-08-27 00:48:47 -0700591 mWaitWorkCV.waitRelative(mLock, waitTime);
Eric Laurenta553c252009-07-17 12:17:14 -0700592 LOGV("AudioCommandThread() waking up");
593 }
594 mLock.unlock();
595 return false;
596}
597
598void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
599{
600 Mutex::Autolock _l(mLock);
601 AudioCommand *command = new AudioCommand();
602 command->mCommand = START_TONE;
603 ToneData *data = new ToneData();
604 data->mType = type;
605 data->mStream = stream;
606 command->mParam = (void *)data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700607 command->mWaitStatus = false;
608 insertCommand_l(command);
Eric Laurenta553c252009-07-17 12:17:14 -0700609 LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
610 mWaitWorkCV.signal();
611}
612
613void AudioPolicyService::AudioCommandThread::stopToneCommand()
614{
615 Mutex::Autolock _l(mLock);
616 AudioCommand *command = new AudioCommand();
617 command->mCommand = STOP_TONE;
618 command->mParam = NULL;
Eric Laurent327c27b2009-08-27 00:48:47 -0700619 command->mWaitStatus = false;
620 insertCommand_l(command);
Eric Laurenta553c252009-07-17 12:17:14 -0700621 LOGV("AudioCommandThread() adding tone stop");
622 mWaitWorkCV.signal();
623}
624
Eric Laurent327c27b2009-08-27 00:48:47 -0700625status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream, float volume, int output, int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700626{
Eric Laurent327c27b2009-08-27 00:48:47 -0700627 status_t status = NO_ERROR;
628
Eric Laurenta553c252009-07-17 12:17:14 -0700629 Mutex::Autolock _l(mLock);
630 AudioCommand *command = new AudioCommand();
631 command->mCommand = SET_VOLUME;
632 VolumeData *data = new VolumeData();
633 data->mStream = stream;
634 data->mVolume = volume;
635 data->mIO = output;
636 command->mParam = data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700637 if (delayMs == 0) {
638 command->mWaitStatus = true;
639 } else {
640 command->mWaitStatus = false;
641 }
642 insertCommand_l(command, delayMs);
Eric Laurentddb78e72009-07-28 08:44:33 -0700643 LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", stream, volume, output);
Eric Laurenta553c252009-07-17 12:17:14 -0700644 mWaitWorkCV.signal();
Eric Laurent327c27b2009-08-27 00:48:47 -0700645 if (command->mWaitStatus) {
646 command->mCond.wait(mLock);
647 status = command->mStatus;
648 mWaitWorkCV.signal();
649 }
Eric Laurenta553c252009-07-17 12:17:14 -0700650 return status;
651}
652
Eric Laurent327c27b2009-08-27 00:48:47 -0700653status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs)
Eric Laurenta553c252009-07-17 12:17:14 -0700654{
Eric Laurent327c27b2009-08-27 00:48:47 -0700655 status_t status = NO_ERROR;
656
Eric Laurenta553c252009-07-17 12:17:14 -0700657 Mutex::Autolock _l(mLock);
658 AudioCommand *command = new AudioCommand();
659 command->mCommand = SET_PARAMETERS;
660 ParametersData *data = new ParametersData();
661 data->mIO = ioHandle;
662 data->mKeyValuePairs = keyValuePairs;
663 command->mParam = data;
Eric Laurent327c27b2009-08-27 00:48:47 -0700664 if (delayMs == 0) {
665 command->mWaitStatus = true;
666 } else {
667 command->mWaitStatus = false;
668 }
669 insertCommand_l(command, delayMs);
670 LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", keyValuePairs.string(), ioHandle, delayMs);
Eric Laurenta553c252009-07-17 12:17:14 -0700671 mWaitWorkCV.signal();
Eric Laurent327c27b2009-08-27 00:48:47 -0700672 if (command->mWaitStatus) {
673 command->mCond.wait(mLock);
674 status = command->mStatus;
675 mWaitWorkCV.signal();
676 }
Eric Laurenta553c252009-07-17 12:17:14 -0700677 return status;
678}
679
Eric Laurent327c27b2009-08-27 00:48:47 -0700680// insertCommand_l() must be called with mLock held
681void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
682{
683 ssize_t i;
684 Vector <AudioCommand *> removedCommands;
685
686 command->mTime = systemTime() + milliseconds(delayMs);
687
688 // check same pending commands with later time stamps and eliminate them
689 for (i = mAudioCommands.size()-1; i >= 0; i--) {
690 AudioCommand *command2 = mAudioCommands[i];
691 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
692 if (command2->mTime <= command->mTime) break;
693 if (command2->mCommand != command->mCommand) continue;
694
695 switch (command->mCommand) {
696 case SET_PARAMETERS: {
697 ParametersData *data = (ParametersData *)command->mParam;
698 ParametersData *data2 = (ParametersData *)command2->mParam;
699 if (data->mIO != data2->mIO) break;
700 LOGV("Comparing parameter command %s to new command %s", data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
701 AudioParameter param = AudioParameter(data->mKeyValuePairs);
702 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
703 for (size_t j = 0; j < param.size(); j++) {
704 String8 key;
705 String8 value;
706 param.getAt(j, key, value);
707 for (size_t k = 0; k < param2.size(); k++) {
708 String8 key2;
709 String8 value2;
710 param2.getAt(k, key2, value2);
711 if (key2 == key) {
712 param2.remove(key2);
713 LOGV("Filtering out parameter %s", key2.string());
714 break;
715 }
716 }
717 }
718 // if all keys have been filtered out, remove the command.
719 // otherwise, update the key value pairs
720 if (param2.size() == 0) {
721 removedCommands.add(command2);
722 } else {
723 data2->mKeyValuePairs = param2.toString();
724 }
725 } break;
726
727 case SET_VOLUME: {
728 VolumeData *data = (VolumeData *)command->mParam;
729 VolumeData *data2 = (VolumeData *)command2->mParam;
730 if (data->mIO != data2->mIO) break;
731 if (data->mStream != data2->mStream) break;
732 LOGV("Filtering out volume command on output %d for stream %d", data->mIO, data->mStream);
733 removedCommands.add(command2);
734 } break;
735 case START_TONE:
736 case STOP_TONE:
737 default:
738 break;
739 }
740 }
741
742 // remove filtered commands
743 for (size_t j = 0; j < removedCommands.size(); j++) {
744 // removed commands always have time stamps greater than current command
745 for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
746 if (mAudioCommands[k] == removedCommands[j]) {
747 LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
748 mAudioCommands.removeAt(k);
749 break;
750 }
751 }
752 }
753 removedCommands.clear();
754
755 // insert command at the right place according to its time stamp
756 LOGV("inserting command: %d at index %ld, num commands %d", command->mCommand, i+1, mAudioCommands.size());
757 mAudioCommands.insertAt(command, i + 1);
758}
759
Eric Laurenta553c252009-07-17 12:17:14 -0700760void AudioPolicyService::AudioCommandThread::exit()
761{
762 LOGV("AudioCommandThread::exit");
763 {
764 AutoMutex _l(mLock);
765 requestExit();
766 mWaitWorkCV.signal();
767 }
768 requestExitAndWait();
769}
770
771}; // namespace android