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