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