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