AudioPolicyService.cpp revision 3fdb1267c1623773b4eb5e1b06d5859019275e40
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
44namespace android {
45
46static 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
52static 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()
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
94AudioPolicyService::~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
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) {
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
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) {
261        return 0;
262    }
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
344static 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
374status_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
402status_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
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");
445        return 0;
446    }
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");
456        return 0;
457    }
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");
501        return 0;
502    }
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
515status_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
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
529void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs, int delayMs)
530{
531    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
532}
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{
542    mTonePlaybackThread->startToneCommand(tone, stream);
543    return NO_ERROR;
544}
545
546status_t AudioPolicyService::stopTone()
547{
548    mTonePlaybackThread->stopToneCommand();
549    return NO_ERROR;
550}
551
552status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
553{
554    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
555}
556
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{
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
668status_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
702void 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
717void 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
729status_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
757status_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
784status_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
811void 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
890void AudioPolicyService::AudioCommandThread::exit()
891{
892    LOGV("AudioCommandThread::exit");
893    {
894        AutoMutex _l(mLock);
895        requestExit();
896        mWaitWorkCV.signal();
897    }
898    requestExitAndWait();
899}
900
901void 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