AudioPolicyService.cpp revision 8b1e80bf1e9f214feea219cfe981ba533b806003
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#include "Configuration.h"
21#undef __STRICT_ANSI__
22#define __STDINT_LIMITS
23#define __STDC_LIMIT_MACROS
24#include <stdint.h>
25
26#include <sys/time.h>
27#include <binder/IServiceManager.h>
28#include <utils/Log.h>
29#include <cutils/properties.h>
30#include <binder/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33#include "AudioPolicyService.h"
34#include "ServiceUtilities.h"
35#include <hardware_legacy/power.h>
36#include <media/AudioEffect.h>
37#include <media/EffectsFactoryApi.h>
38
39#include <hardware/hardware.h>
40#include <system/audio.h>
41#include <system/audio_policy.h>
42#include <hardware/audio_policy.h>
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 kDumpLockSleepUs = 20000;
51
52static const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds
53
54namespace {
55    extern struct audio_policy_service_ops aps_ops;
56};
57
58// ----------------------------------------------------------------------------
59
60AudioPolicyService::AudioPolicyService()
61    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
62      mAudioPolicyManager(NULL), mAudioPolicyClient(NULL), mPhoneState(AUDIO_MODE_INVALID)
63{
64    char value[PROPERTY_VALUE_MAX];
65    const struct hw_module_t *module;
66    int forced_val;
67    int rc;
68
69    {
70        Mutex::Autolock _l(mLock);
71
72        // start tone playback thread
73        mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
74        // start audio commands thread
75        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
76        // start output activity command thread
77        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
78
79#ifdef USE_LEGACY_AUDIO_POLICY
80        ALOGI("AudioPolicyService CSTOR in legacy mode");
81
82        /* instantiate the audio policy manager */
83        rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
84        if (rc) {
85            return;
86        }
87        rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
88        ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
89        if (rc) {
90            return;
91        }
92
93        rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
94                                                   &mpAudioPolicy);
95        ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
96        if (rc) {
97            return;
98        }
99
100        rc = mpAudioPolicy->init_check(mpAudioPolicy);
101        ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
102        if (rc) {
103            return;
104        }
105        ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
106#else
107        ALOGI("AudioPolicyService CSTOR in new mode");
108
109        mAudioPolicyClient = new AudioPolicyClient(this);
110        mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
111#endif
112    }
113    // load audio processing modules
114    sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
115    {
116        Mutex::Autolock _l(mLock);
117        mAudioPolicyEffects = audioPolicyEffects;
118    }
119}
120
121AudioPolicyService::~AudioPolicyService()
122{
123    mTonePlaybackThread->exit();
124    mAudioCommandThread->exit();
125    mOutputCommandThread->exit();
126
127#ifdef USE_LEGACY_AUDIO_POLICY
128    if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) {
129        mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
130    }
131    if (mpAudioPolicyDev != NULL) {
132        audio_policy_dev_close(mpAudioPolicyDev);
133    }
134#else
135    destroyAudioPolicyManager(mAudioPolicyManager);
136    delete mAudioPolicyClient;
137#endif
138
139    mNotificationClients.clear();
140    mAudioPolicyEffects.clear();
141}
142
143// A notification client is always registered by AudioSystem when the client process
144// connects to AudioPolicyService.
145void AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
146{
147
148    Mutex::Autolock _l(mLock);
149
150    uid_t uid = IPCThreadState::self()->getCallingUid();
151    if (mNotificationClients.indexOfKey(uid) < 0) {
152        sp<NotificationClient> notificationClient = new NotificationClient(this,
153                                                                           client,
154                                                                           uid);
155        ALOGV("registerClient() client %p, uid %d", client.get(), uid);
156
157        mNotificationClients.add(uid, notificationClient);
158
159        sp<IBinder> binder = client->asBinder();
160        binder->linkToDeath(notificationClient);
161    }
162}
163
164// removeNotificationClient() is called when the client process dies.
165void AudioPolicyService::removeNotificationClient(uid_t uid)
166{
167    Mutex::Autolock _l(mLock);
168
169    mNotificationClients.removeItem(uid);
170
171#ifndef USE_LEGACY_AUDIO_POLICY
172        if (mAudioPolicyManager) {
173            mAudioPolicyManager->clearAudioPatches(uid);
174        }
175#endif
176}
177
178void AudioPolicyService::onAudioPortListUpdate()
179{
180    mOutputCommandThread->updateAudioPortListCommand();
181}
182
183void AudioPolicyService::doOnAudioPortListUpdate()
184{
185    Mutex::Autolock _l(mLock);
186    for (size_t i = 0; i < mNotificationClients.size(); i++) {
187        mNotificationClients.valueAt(i)->onAudioPortListUpdate();
188    }
189}
190
191void AudioPolicyService::onAudioPatchListUpdate()
192{
193    mOutputCommandThread->updateAudioPatchListCommand();
194}
195
196status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
197                                                audio_patch_handle_t *handle,
198                                                int delayMs)
199{
200    return mAudioCommandThread->createAudioPatchCommand(patch, handle, delayMs);
201}
202
203status_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle,
204                                                 int delayMs)
205{
206    return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs);
207}
208
209void AudioPolicyService::doOnAudioPatchListUpdate()
210{
211    Mutex::Autolock _l(mLock);
212    for (size_t i = 0; i < mNotificationClients.size(); i++) {
213        mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
214    }
215}
216
217status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config,
218                                                      int delayMs)
219{
220    return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
221}
222
223AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
224                                                     const sp<IAudioPolicyServiceClient>& client,
225                                                     uid_t uid)
226    : mService(service), mUid(uid), mAudioPolicyServiceClient(client)
227{
228}
229
230AudioPolicyService::NotificationClient::~NotificationClient()
231{
232}
233
234void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused)
235{
236    sp<NotificationClient> keep(this);
237    sp<AudioPolicyService> service = mService.promote();
238    if (service != 0) {
239        service->removeNotificationClient(mUid);
240    }
241}
242
243void AudioPolicyService::NotificationClient::onAudioPortListUpdate()
244{
245    if (mAudioPolicyServiceClient != 0) {
246        mAudioPolicyServiceClient->onAudioPortListUpdate();
247    }
248}
249
250void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
251{
252    if (mAudioPolicyServiceClient != 0) {
253        mAudioPolicyServiceClient->onAudioPatchListUpdate();
254    }
255}
256
257void AudioPolicyService::binderDied(const wp<IBinder>& who) {
258    ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
259            IPCThreadState::self()->getCallingPid());
260}
261
262static bool tryLock(Mutex& mutex)
263{
264    bool locked = false;
265    for (int i = 0; i < kDumpLockRetries; ++i) {
266        if (mutex.tryLock() == NO_ERROR) {
267            locked = true;
268            break;
269        }
270        usleep(kDumpLockSleepUs);
271    }
272    return locked;
273}
274
275status_t AudioPolicyService::dumpInternals(int fd)
276{
277    const size_t SIZE = 256;
278    char buffer[SIZE];
279    String8 result;
280
281#ifdef USE_LEGACY_AUDIO_POLICY
282    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
283#else
284    snprintf(buffer, SIZE, "AudioPolicyManager: %p\n", mAudioPolicyManager);
285#endif
286    result.append(buffer);
287    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
288    result.append(buffer);
289    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
290    result.append(buffer);
291
292    write(fd, result.string(), result.size());
293    return NO_ERROR;
294}
295
296status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused)
297{
298    if (!dumpAllowed()) {
299        dumpPermissionDenial(fd);
300    } else {
301        bool locked = tryLock(mLock);
302        if (!locked) {
303            String8 result(kDeadlockedString);
304            write(fd, result.string(), result.size());
305        }
306
307        dumpInternals(fd);
308        if (mAudioCommandThread != 0) {
309            mAudioCommandThread->dump(fd);
310        }
311        if (mTonePlaybackThread != 0) {
312            mTonePlaybackThread->dump(fd);
313        }
314
315#ifdef USE_LEGACY_AUDIO_POLICY
316        if (mpAudioPolicy) {
317            mpAudioPolicy->dump(mpAudioPolicy, fd);
318        }
319#else
320        if (mAudioPolicyManager) {
321            mAudioPolicyManager->dump(fd);
322        }
323#endif
324
325        if (locked) mLock.unlock();
326    }
327    return NO_ERROR;
328}
329
330status_t AudioPolicyService::dumpPermissionDenial(int fd)
331{
332    const size_t SIZE = 256;
333    char buffer[SIZE];
334    String8 result;
335    snprintf(buffer, SIZE, "Permission Denial: "
336            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
337            IPCThreadState::self()->getCallingPid(),
338            IPCThreadState::self()->getCallingUid());
339    result.append(buffer);
340    write(fd, result.string(), result.size());
341    return NO_ERROR;
342}
343
344status_t AudioPolicyService::onTransact(
345        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
346{
347    return BnAudioPolicyService::onTransact(code, data, reply, flags);
348}
349
350
351// -----------  AudioPolicyService::AudioCommandThread implementation ----------
352
353AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
354                                                           const wp<AudioPolicyService>& service)
355    : Thread(false), mName(name), mService(service)
356{
357    mpToneGenerator = NULL;
358}
359
360
361AudioPolicyService::AudioCommandThread::~AudioCommandThread()
362{
363    if (!mAudioCommands.isEmpty()) {
364        release_wake_lock(mName.string());
365    }
366    mAudioCommands.clear();
367    delete mpToneGenerator;
368}
369
370void AudioPolicyService::AudioCommandThread::onFirstRef()
371{
372    run(mName.string(), ANDROID_PRIORITY_AUDIO);
373}
374
375bool AudioPolicyService::AudioCommandThread::threadLoop()
376{
377    nsecs_t waitTime = INT64_MAX;
378
379    mLock.lock();
380    while (!exitPending())
381    {
382        sp<AudioPolicyService> svc;
383        while (!mAudioCommands.isEmpty() && !exitPending()) {
384            nsecs_t curTime = systemTime();
385            // commands are sorted by increasing time stamp: execute them from index 0 and up
386            if (mAudioCommands[0]->mTime <= curTime) {
387                sp<AudioCommand> command = mAudioCommands[0];
388                mAudioCommands.removeAt(0);
389                mLastCommand = command;
390
391                switch (command->mCommand) {
392                case START_TONE: {
393                    mLock.unlock();
394                    ToneData *data = (ToneData *)command->mParam.get();
395                    ALOGV("AudioCommandThread() processing start tone %d on stream %d",
396                            data->mType, data->mStream);
397                    delete mpToneGenerator;
398                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
399                    mpToneGenerator->startTone(data->mType);
400                    mLock.lock();
401                    }break;
402                case STOP_TONE: {
403                    mLock.unlock();
404                    ALOGV("AudioCommandThread() processing stop tone");
405                    if (mpToneGenerator != NULL) {
406                        mpToneGenerator->stopTone();
407                        delete mpToneGenerator;
408                        mpToneGenerator = NULL;
409                    }
410                    mLock.lock();
411                    }break;
412                case SET_VOLUME: {
413                    VolumeData *data = (VolumeData *)command->mParam.get();
414                    ALOGV("AudioCommandThread() processing set volume stream %d, \
415                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
416                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
417                                                                    data->mVolume,
418                                                                    data->mIO);
419                    }break;
420                case SET_PARAMETERS: {
421                    ParametersData *data = (ParametersData *)command->mParam.get();
422                    ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
423                            data->mKeyValuePairs.string(), data->mIO);
424                    command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
425                    }break;
426                case SET_VOICE_VOLUME: {
427                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
428                    ALOGV("AudioCommandThread() processing set voice volume volume %f",
429                            data->mVolume);
430                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
431                    }break;
432                case STOP_OUTPUT: {
433                    StopOutputData *data = (StopOutputData *)command->mParam.get();
434                    ALOGV("AudioCommandThread() processing stop output %d",
435                            data->mIO);
436                    svc = mService.promote();
437                    if (svc == 0) {
438                        break;
439                    }
440                    mLock.unlock();
441                    svc->doStopOutput(data->mIO, data->mStream, data->mSession);
442                    mLock.lock();
443                    }break;
444                case RELEASE_OUTPUT: {
445                    ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get();
446                    ALOGV("AudioCommandThread() processing release output %d",
447                            data->mIO);
448                    svc = mService.promote();
449                    if (svc == 0) {
450                        break;
451                    }
452                    mLock.unlock();
453                    svc->doReleaseOutput(data->mIO);
454                    mLock.lock();
455                    }break;
456                case CREATE_AUDIO_PATCH: {
457                    CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get();
458                    ALOGV("AudioCommandThread() processing create audio patch");
459                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
460                    if (af == 0) {
461                        command->mStatus = PERMISSION_DENIED;
462                    } else {
463                        command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
464                    }
465                    } break;
466                case RELEASE_AUDIO_PATCH: {
467                    ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mParam.get();
468                    ALOGV("AudioCommandThread() processing release audio patch");
469                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
470                    if (af == 0) {
471                        command->mStatus = PERMISSION_DENIED;
472                    } else {
473                        command->mStatus = af->releaseAudioPatch(data->mHandle);
474                    }
475                    } break;
476                case UPDATE_AUDIOPORT_LIST: {
477                    ALOGV("AudioCommandThread() processing update audio port list");
478                    svc = mService.promote();
479                    if (svc == 0) {
480                        break;
481                    }
482                    mLock.unlock();
483                    svc->doOnAudioPortListUpdate();
484                    mLock.lock();
485                    }break;
486                case UPDATE_AUDIOPATCH_LIST: {
487                    ALOGV("AudioCommandThread() processing update audio patch list");
488                    svc = mService.promote();
489                    if (svc == 0) {
490                        break;
491                    }
492                    mLock.unlock();
493                    svc->doOnAudioPatchListUpdate();
494                    mLock.lock();
495                    }break;
496                case SET_AUDIOPORT_CONFIG: {
497                    SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
498                    ALOGV("AudioCommandThread() processing set port config");
499                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
500                    if (af == 0) {
501                        command->mStatus = PERMISSION_DENIED;
502                    } else {
503                        command->mStatus = af->setAudioPortConfig(&data->mConfig);
504                    }
505                    } break;
506                default:
507                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
508                }
509                {
510                    Mutex::Autolock _l(command->mLock);
511                    if (command->mWaitStatus) {
512                        command->mWaitStatus = false;
513                        command->mCond.signal();
514                    }
515                }
516                waitTime = INT64_MAX;
517            } else {
518                waitTime = mAudioCommands[0]->mTime - curTime;
519                break;
520            }
521        }
522        // release mLock before releasing strong reference on the service as
523        // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock.
524        mLock.unlock();
525        svc.clear();
526        mLock.lock();
527        if (!exitPending() && mAudioCommands.isEmpty()) {
528            // release delayed commands wake lock
529            release_wake_lock(mName.string());
530            ALOGV("AudioCommandThread() going to sleep");
531            mWaitWorkCV.waitRelative(mLock, waitTime);
532            ALOGV("AudioCommandThread() waking up");
533        }
534    }
535    // release delayed commands wake lock before quitting
536    if (!mAudioCommands.isEmpty()) {
537        release_wake_lock(mName.string());
538    }
539    mLock.unlock();
540    return false;
541}
542
543status_t AudioPolicyService::AudioCommandThread::dump(int fd)
544{
545    const size_t SIZE = 256;
546    char buffer[SIZE];
547    String8 result;
548
549    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
550    result.append(buffer);
551    write(fd, result.string(), result.size());
552
553    bool locked = tryLock(mLock);
554    if (!locked) {
555        String8 result2(kCmdDeadlockedString);
556        write(fd, result2.string(), result2.size());
557    }
558
559    snprintf(buffer, SIZE, "- Commands:\n");
560    result = String8(buffer);
561    result.append("   Command Time        Wait pParam\n");
562    for (size_t i = 0; i < mAudioCommands.size(); i++) {
563        mAudioCommands[i]->dump(buffer, SIZE);
564        result.append(buffer);
565    }
566    result.append("  Last Command\n");
567    if (mLastCommand != 0) {
568        mLastCommand->dump(buffer, SIZE);
569        result.append(buffer);
570    } else {
571        result.append("     none\n");
572    }
573
574    write(fd, result.string(), result.size());
575
576    if (locked) mLock.unlock();
577
578    return NO_ERROR;
579}
580
581void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
582        audio_stream_type_t stream)
583{
584    sp<AudioCommand> command = new AudioCommand();
585    command->mCommand = START_TONE;
586    sp<ToneData> data = new ToneData();
587    data->mType = type;
588    data->mStream = stream;
589    command->mParam = data;
590    ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
591    sendCommand(command);
592}
593
594void AudioPolicyService::AudioCommandThread::stopToneCommand()
595{
596    sp<AudioCommand> command = new AudioCommand();
597    command->mCommand = STOP_TONE;
598    ALOGV("AudioCommandThread() adding tone stop");
599    sendCommand(command);
600}
601
602status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
603                                                               float volume,
604                                                               audio_io_handle_t output,
605                                                               int delayMs)
606{
607    sp<AudioCommand> command = new AudioCommand();
608    command->mCommand = SET_VOLUME;
609    sp<VolumeData> data = new VolumeData();
610    data->mStream = stream;
611    data->mVolume = volume;
612    data->mIO = output;
613    command->mParam = data;
614    command->mWaitStatus = true;
615    ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
616            stream, volume, output);
617    return sendCommand(command, delayMs);
618}
619
620status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
621                                                                   const char *keyValuePairs,
622                                                                   int delayMs)
623{
624    sp<AudioCommand> command = new AudioCommand();
625    command->mCommand = SET_PARAMETERS;
626    sp<ParametersData> data = new ParametersData();
627    data->mIO = ioHandle;
628    data->mKeyValuePairs = String8(keyValuePairs);
629    command->mParam = data;
630    command->mWaitStatus = true;
631    ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
632            keyValuePairs, ioHandle, delayMs);
633    return sendCommand(command, delayMs);
634}
635
636status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
637{
638    sp<AudioCommand> command = new AudioCommand();
639    command->mCommand = SET_VOICE_VOLUME;
640    sp<VoiceVolumeData> data = new VoiceVolumeData();
641    data->mVolume = volume;
642    command->mParam = data;
643    command->mWaitStatus = true;
644    ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
645    return sendCommand(command, delayMs);
646}
647
648void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
649                                                               audio_stream_type_t stream,
650                                                               int session)
651{
652    sp<AudioCommand> command = new AudioCommand();
653    command->mCommand = STOP_OUTPUT;
654    sp<StopOutputData> data = new StopOutputData();
655    data->mIO = output;
656    data->mStream = stream;
657    data->mSession = session;
658    command->mParam = data;
659    ALOGV("AudioCommandThread() adding stop output %d", output);
660    sendCommand(command);
661}
662
663void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
664{
665    sp<AudioCommand> command = new AudioCommand();
666    command->mCommand = RELEASE_OUTPUT;
667    sp<ReleaseOutputData> data = new ReleaseOutputData();
668    data->mIO = output;
669    command->mParam = data;
670    ALOGV("AudioCommandThread() adding release output %d", output);
671    sendCommand(command);
672}
673
674status_t AudioPolicyService::AudioCommandThread::createAudioPatchCommand(
675                                                const struct audio_patch *patch,
676                                                audio_patch_handle_t *handle,
677                                                int delayMs)
678{
679    status_t status = NO_ERROR;
680
681    sp<AudioCommand> command = new AudioCommand();
682    command->mCommand = CREATE_AUDIO_PATCH;
683    CreateAudioPatchData *data = new CreateAudioPatchData();
684    data->mPatch = *patch;
685    data->mHandle = *handle;
686    command->mParam = data;
687    command->mWaitStatus = true;
688    ALOGV("AudioCommandThread() adding create patch delay %d", delayMs);
689    status = sendCommand(command, delayMs);
690    if (status == NO_ERROR) {
691        *handle = data->mHandle;
692    }
693    return status;
694}
695
696status_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle,
697                                                 int delayMs)
698{
699    sp<AudioCommand> command = new AudioCommand();
700    command->mCommand = RELEASE_AUDIO_PATCH;
701    ReleaseAudioPatchData *data = new ReleaseAudioPatchData();
702    data->mHandle = handle;
703    command->mParam = data;
704    command->mWaitStatus = true;
705    ALOGV("AudioCommandThread() adding release patch delay %d", delayMs);
706    return sendCommand(command, delayMs);
707}
708
709void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand()
710{
711    sp<AudioCommand> command = new AudioCommand();
712    command->mCommand = UPDATE_AUDIOPORT_LIST;
713    ALOGV("AudioCommandThread() adding update audio port list");
714    sendCommand(command);
715}
716
717void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand()
718{
719    sp<AudioCommand>command = new AudioCommand();
720    command->mCommand = UPDATE_AUDIOPATCH_LIST;
721    ALOGV("AudioCommandThread() adding update audio patch list");
722    sendCommand(command);
723}
724
725status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
726                                            const struct audio_port_config *config, int delayMs)
727{
728    sp<AudioCommand> command = new AudioCommand();
729    command->mCommand = SET_AUDIOPORT_CONFIG;
730    SetAudioPortConfigData *data = new SetAudioPortConfigData();
731    data->mConfig = *config;
732    command->mParam = data;
733    command->mWaitStatus = true;
734    ALOGV("AudioCommandThread() adding set port config delay %d", delayMs);
735    return sendCommand(command, delayMs);
736}
737
738status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
739{
740    {
741        Mutex::Autolock _l(mLock);
742        insertCommand_l(command, delayMs);
743        mWaitWorkCV.signal();
744    }
745    Mutex::Autolock _l(command->mLock);
746    while (command->mWaitStatus) {
747        nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs);
748        if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) {
749            command->mStatus = TIMED_OUT;
750            command->mWaitStatus = false;
751        }
752    }
753    return command->mStatus;
754}
755
756// insertCommand_l() must be called with mLock held
757void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs)
758{
759    ssize_t i;  // not size_t because i will count down to -1
760    Vector < sp<AudioCommand> > removedCommands;
761    command->mTime = systemTime() + milliseconds(delayMs);
762
763    // acquire wake lock to make sure delayed commands are processed
764    if (mAudioCommands.isEmpty()) {
765        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
766    }
767
768    // check same pending commands with later time stamps and eliminate them
769    for (i = mAudioCommands.size()-1; i >= 0; i--) {
770        sp<AudioCommand> command2 = mAudioCommands[i];
771        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
772        if (command2->mTime <= command->mTime) break;
773
774        // create audio patch or release audio patch commands are equivalent
775        // with regard to filtering
776        if ((command->mCommand == CREATE_AUDIO_PATCH) ||
777                (command->mCommand == RELEASE_AUDIO_PATCH)) {
778            if ((command2->mCommand != CREATE_AUDIO_PATCH) &&
779                    (command2->mCommand != RELEASE_AUDIO_PATCH)) {
780                continue;
781            }
782        } else if (command2->mCommand != command->mCommand) continue;
783
784        switch (command->mCommand) {
785        case SET_PARAMETERS: {
786            ParametersData *data = (ParametersData *)command->mParam.get();
787            ParametersData *data2 = (ParametersData *)command2->mParam.get();
788            if (data->mIO != data2->mIO) break;
789            ALOGV("Comparing parameter command %s to new command %s",
790                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
791            AudioParameter param = AudioParameter(data->mKeyValuePairs);
792            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
793            for (size_t j = 0; j < param.size(); j++) {
794                String8 key;
795                String8 value;
796                param.getAt(j, key, value);
797                for (size_t k = 0; k < param2.size(); k++) {
798                    String8 key2;
799                    String8 value2;
800                    param2.getAt(k, key2, value2);
801                    if (key2 == key) {
802                        param2.remove(key2);
803                        ALOGV("Filtering out parameter %s", key2.string());
804                        break;
805                    }
806                }
807            }
808            // if all keys have been filtered out, remove the command.
809            // otherwise, update the key value pairs
810            if (param2.size() == 0) {
811                removedCommands.add(command2);
812            } else {
813                data2->mKeyValuePairs = param2.toString();
814            }
815            command->mTime = command2->mTime;
816            // force delayMs to non 0 so that code below does not request to wait for
817            // command status as the command is now delayed
818            delayMs = 1;
819        } break;
820
821        case SET_VOLUME: {
822            VolumeData *data = (VolumeData *)command->mParam.get();
823            VolumeData *data2 = (VolumeData *)command2->mParam.get();
824            if (data->mIO != data2->mIO) break;
825            if (data->mStream != data2->mStream) break;
826            ALOGV("Filtering out volume command on output %d for stream %d",
827                    data->mIO, data->mStream);
828            removedCommands.add(command2);
829            command->mTime = command2->mTime;
830            // force delayMs to non 0 so that code below does not request to wait for
831            // command status as the command is now delayed
832            delayMs = 1;
833        } break;
834
835        case CREATE_AUDIO_PATCH:
836        case RELEASE_AUDIO_PATCH: {
837            audio_patch_handle_t handle;
838            if (command->mCommand == CREATE_AUDIO_PATCH) {
839                handle = ((CreateAudioPatchData *)command->mParam.get())->mHandle;
840            } else {
841                handle = ((ReleaseAudioPatchData *)command->mParam.get())->mHandle;
842            }
843            audio_patch_handle_t handle2;
844            if (command2->mCommand == CREATE_AUDIO_PATCH) {
845                handle2 = ((CreateAudioPatchData *)command2->mParam.get())->mHandle;
846            } else {
847                handle2 = ((ReleaseAudioPatchData *)command2->mParam.get())->mHandle;
848            }
849            if (handle != handle2) break;
850            ALOGV("Filtering out %s audio patch command for handle %d",
851                  (command->mCommand == CREATE_AUDIO_PATCH) ? "create" : "release", handle);
852            removedCommands.add(command2);
853            command->mTime = command2->mTime;
854            // force delayMs to non 0 so that code below does not request to wait for
855            // command status as the command is now delayed
856            delayMs = 1;
857        } break;
858
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].get() == removedCommands[j].get()) {
871                ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
872                mAudioCommands.removeAt(k);
873                break;
874            }
875        }
876    }
877    removedCommands.clear();
878
879    // Disable wait for status if delay is not 0
880    if (delayMs != 0) {
881        command->mWaitStatus = false;
882    }
883
884    // insert command at the right place according to its time stamp
885    ALOGV("inserting command: %d at index %zd, num commands %zu",
886            command->mCommand, i+1, mAudioCommands.size());
887    mAudioCommands.insertAt(command, i + 1);
888}
889
890void AudioPolicyService::AudioCommandThread::exit()
891{
892    ALOGV("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.get());
909}
910
911/******* helpers for the service_ops callbacks defined below *********/
912void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
913                                       const char *keyValuePairs,
914                                       int delayMs)
915{
916    mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
917                                           delayMs);
918}
919
920int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
921                                        float volume,
922                                        audio_io_handle_t output,
923                                        int delayMs)
924{
925    return (int)mAudioCommandThread->volumeCommand(stream, volume,
926                                                   output, delayMs);
927}
928
929int AudioPolicyService::startTone(audio_policy_tone_t tone,
930                                  audio_stream_type_t stream)
931{
932    if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) {
933        ALOGE("startTone: illegal tone requested (%d)", tone);
934    }
935    if (stream != AUDIO_STREAM_VOICE_CALL) {
936        ALOGE("startTone: illegal stream (%d) requested for tone %d", stream,
937            tone);
938    }
939    mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
940                                          AUDIO_STREAM_VOICE_CALL);
941    return 0;
942}
943
944int AudioPolicyService::stopTone()
945{
946    mTonePlaybackThread->stopToneCommand();
947    return 0;
948}
949
950int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
951{
952    return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
953}
954
955extern "C" {
956audio_module_handle_t aps_load_hw_module(void *service __unused,
957                                             const char *name);
958audio_io_handle_t aps_open_output(void *service __unused,
959                                         audio_devices_t *pDevices,
960                                         uint32_t *pSamplingRate,
961                                         audio_format_t *pFormat,
962                                         audio_channel_mask_t *pChannelMask,
963                                         uint32_t *pLatencyMs,
964                                         audio_output_flags_t flags);
965
966audio_io_handle_t aps_open_output_on_module(void *service __unused,
967                                                   audio_module_handle_t module,
968                                                   audio_devices_t *pDevices,
969                                                   uint32_t *pSamplingRate,
970                                                   audio_format_t *pFormat,
971                                                   audio_channel_mask_t *pChannelMask,
972                                                   uint32_t *pLatencyMs,
973                                                   audio_output_flags_t flags,
974                                                   const audio_offload_info_t *offloadInfo);
975audio_io_handle_t aps_open_dup_output(void *service __unused,
976                                                 audio_io_handle_t output1,
977                                                 audio_io_handle_t output2);
978int aps_close_output(void *service __unused, audio_io_handle_t output);
979int aps_suspend_output(void *service __unused, audio_io_handle_t output);
980int aps_restore_output(void *service __unused, audio_io_handle_t output);
981audio_io_handle_t aps_open_input(void *service __unused,
982                                        audio_devices_t *pDevices,
983                                        uint32_t *pSamplingRate,
984                                        audio_format_t *pFormat,
985                                        audio_channel_mask_t *pChannelMask,
986                                        audio_in_acoustics_t acoustics __unused);
987audio_io_handle_t aps_open_input_on_module(void *service __unused,
988                                                  audio_module_handle_t module,
989                                                  audio_devices_t *pDevices,
990                                                  uint32_t *pSamplingRate,
991                                                  audio_format_t *pFormat,
992                                                  audio_channel_mask_t *pChannelMask);
993int aps_close_input(void *service __unused, audio_io_handle_t input);
994int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream);
995int aps_move_effects(void *service __unused, int session,
996                                audio_io_handle_t src_output,
997                                audio_io_handle_t dst_output);
998char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle,
999                                     const char *keys);
1000void aps_set_parameters(void *service, audio_io_handle_t io_handle,
1001                                   const char *kv_pairs, int delay_ms);
1002int aps_set_stream_volume(void *service, audio_stream_type_t stream,
1003                                     float volume, audio_io_handle_t output,
1004                                     int delay_ms);
1005int aps_start_tone(void *service, audio_policy_tone_t tone,
1006                              audio_stream_type_t stream);
1007int aps_stop_tone(void *service);
1008int aps_set_voice_volume(void *service, float volume, int delay_ms);
1009};
1010
1011namespace {
1012    struct audio_policy_service_ops aps_ops = {
1013        .open_output           = aps_open_output,
1014        .open_duplicate_output = aps_open_dup_output,
1015        .close_output          = aps_close_output,
1016        .suspend_output        = aps_suspend_output,
1017        .restore_output        = aps_restore_output,
1018        .open_input            = aps_open_input,
1019        .close_input           = aps_close_input,
1020        .set_stream_volume     = aps_set_stream_volume,
1021        .invalidate_stream     = aps_invalidate_stream,
1022        .set_parameters        = aps_set_parameters,
1023        .get_parameters        = aps_get_parameters,
1024        .start_tone            = aps_start_tone,
1025        .stop_tone             = aps_stop_tone,
1026        .set_voice_volume      = aps_set_voice_volume,
1027        .move_effects          = aps_move_effects,
1028        .load_hw_module        = aps_load_hw_module,
1029        .open_output_on_module = aps_open_output_on_module,
1030        .open_input_on_module  = aps_open_input_on_module,
1031    };
1032}; // namespace <unnamed>
1033
1034}; // namespace android
1035