AudioPolicyService.cpp revision 2d388eccc9dc085337c7a03a68467cbee6b809e1
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AudioPolicyService"
18//#define LOG_NDEBUG 0
19
20#include "Configuration.h"
21#undef __STRICT_ANSI__
22#define __STDINT_LIMITS
23#define __STDC_LIMIT_MACROS
24#include <stdint.h>
25
26#include <sys/time.h>
27#include <binder/IServiceManager.h>
28#include <utils/Log.h>
29#include <cutils/properties.h>
30#include <binder/IPCThreadState.h>
31#include <utils/String16.h>
32#include <utils/threads.h>
33#include "AudioPolicyService.h"
34#include "ServiceUtilities.h"
35#include <hardware_legacy/power.h>
36#include <media/AudioEffect.h>
37#include <media/EffectsFactoryApi.h>
38
39#include <hardware/hardware.h>
40#include <system/audio.h>
41#include <system/audio_policy.h>
42#include <hardware/audio_policy.h>
43#include <audio_effects/audio_effects_conf.h>
44#include <media/AudioParameter.h>
45
46namespace android {
47
48static const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n";
49static const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n";
50
51static const int kDumpLockRetries = 50;
52static const int kDumpLockSleepUs = 20000;
53
54static const nsecs_t kAudioCommandTimeout = 3000000000LL; // 3 seconds
55
56namespace {
57    extern struct audio_policy_service_ops aps_ops;
58};
59
60// ----------------------------------------------------------------------------
61
62AudioPolicyService::AudioPolicyService()
63    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL)
64{
65    char value[PROPERTY_VALUE_MAX];
66    const struct hw_module_t *module;
67    int forced_val;
68    int rc;
69
70    Mutex::Autolock _l(mLock);
71
72    // start tone playback thread
73    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
74    // start audio commands thread
75    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
76    // start output activity command thread
77    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
78    /* instantiate the audio policy manager */
79    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
80    if (rc) {
81        return;
82    }
83
84    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
85    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
86    if (rc) {
87        return;
88    }
89
90    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
91                                               &mpAudioPolicy);
92    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
93    if (rc) {
94        return;
95    }
96
97    rc = mpAudioPolicy->init_check(mpAudioPolicy);
98    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
99    if (rc) {
100        return;
101    }
102
103    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
104
105    // load audio pre processing modules
106    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
107        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
108    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
109        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
110    }
111}
112
113AudioPolicyService::~AudioPolicyService()
114{
115    mTonePlaybackThread->exit();
116    mTonePlaybackThread.clear();
117    mAudioCommandThread->exit();
118    mAudioCommandThread.clear();
119
120
121    // release audio pre processing resources
122    for (size_t i = 0; i < mInputSources.size(); i++) {
123        delete mInputSources.valueAt(i);
124    }
125    mInputSources.clear();
126
127    for (size_t i = 0; i < mInputs.size(); i++) {
128        mInputs.valueAt(i)->mEffects.clear();
129        delete mInputs.valueAt(i);
130    }
131    mInputs.clear();
132
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}
140
141
142void AudioPolicyService::binderDied(const wp<IBinder>& who) {
143    ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
144            IPCThreadState::self()->getCallingPid());
145}
146
147static bool tryLock(Mutex& mutex)
148{
149    bool locked = false;
150    for (int i = 0; i < kDumpLockRetries; ++i) {
151        if (mutex.tryLock() == NO_ERROR) {
152            locked = true;
153            break;
154        }
155        usleep(kDumpLockSleepUs);
156    }
157    return locked;
158}
159
160status_t AudioPolicyService::dumpInternals(int fd)
161{
162    const size_t SIZE = 256;
163    char buffer[SIZE];
164    String8 result;
165
166    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
167    result.append(buffer);
168    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
169    result.append(buffer);
170    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
171    result.append(buffer);
172
173    write(fd, result.string(), result.size());
174    return NO_ERROR;
175}
176
177status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused)
178{
179    if (!dumpAllowed()) {
180        dumpPermissionDenial(fd);
181    } else {
182        bool locked = tryLock(mLock);
183        if (!locked) {
184            String8 result(kDeadlockedString);
185            write(fd, result.string(), result.size());
186        }
187
188        dumpInternals(fd);
189        if (mAudioCommandThread != 0) {
190            mAudioCommandThread->dump(fd);
191        }
192        if (mTonePlaybackThread != 0) {
193            mTonePlaybackThread->dump(fd);
194        }
195
196        if (mpAudioPolicy) {
197            mpAudioPolicy->dump(mpAudioPolicy, fd);
198        }
199
200        if (locked) mLock.unlock();
201    }
202    return NO_ERROR;
203}
204
205status_t AudioPolicyService::dumpPermissionDenial(int fd)
206{
207    const size_t SIZE = 256;
208    char buffer[SIZE];
209    String8 result;
210    snprintf(buffer, SIZE, "Permission Denial: "
211            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
212            IPCThreadState::self()->getCallingPid(),
213            IPCThreadState::self()->getCallingUid());
214    result.append(buffer);
215    write(fd, result.string(), result.size());
216    return NO_ERROR;
217}
218
219void AudioPolicyService::setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled)
220{
221    const Vector<sp<AudioEffect> > &fxVector = inputDesc->mEffects;
222    for (size_t i = 0; i < fxVector.size(); i++) {
223        fxVector.itemAt(i)->setEnabled(enabled);
224    }
225}
226
227status_t AudioPolicyService::onTransact(
228        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
229{
230    return BnAudioPolicyService::onTransact(code, data, reply, flags);
231}
232
233
234// -----------  AudioPolicyService::AudioCommandThread implementation ----------
235
236AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
237                                                           const wp<AudioPolicyService>& service)
238    : Thread(false), mName(name), mService(service)
239{
240    mpToneGenerator = NULL;
241}
242
243
244AudioPolicyService::AudioCommandThread::~AudioCommandThread()
245{
246    if (!mAudioCommands.isEmpty()) {
247        release_wake_lock(mName.string());
248    }
249    mAudioCommands.clear();
250    delete mpToneGenerator;
251}
252
253void AudioPolicyService::AudioCommandThread::onFirstRef()
254{
255    run(mName.string(), ANDROID_PRIORITY_AUDIO);
256}
257
258bool AudioPolicyService::AudioCommandThread::threadLoop()
259{
260    nsecs_t waitTime = INT64_MAX;
261
262    mLock.lock();
263    while (!exitPending())
264    {
265        while (!mAudioCommands.isEmpty()) {
266            nsecs_t curTime = systemTime();
267            // commands are sorted by increasing time stamp: execute them from index 0 and up
268            if (mAudioCommands[0]->mTime <= curTime) {
269                AudioCommand *command = mAudioCommands[0];
270                mAudioCommands.removeAt(0);
271                mLastCommand = *command;
272
273                switch (command->mCommand) {
274                case START_TONE: {
275                    mLock.unlock();
276                    ToneData *data = (ToneData *)command->mParam;
277                    ALOGV("AudioCommandThread() processing start tone %d on stream %d",
278                            data->mType, data->mStream);
279                    delete mpToneGenerator;
280                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
281                    mpToneGenerator->startTone(data->mType);
282                    delete data;
283                    mLock.lock();
284                    }break;
285                case STOP_TONE: {
286                    mLock.unlock();
287                    ALOGV("AudioCommandThread() processing stop tone");
288                    if (mpToneGenerator != NULL) {
289                        mpToneGenerator->stopTone();
290                        delete mpToneGenerator;
291                        mpToneGenerator = NULL;
292                    }
293                    mLock.lock();
294                    }break;
295                case SET_VOLUME: {
296                    VolumeData *data = (VolumeData *)command->mParam;
297                    ALOGV("AudioCommandThread() processing set volume stream %d, \
298                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
299                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
300                                                                    data->mVolume,
301                                                                    data->mIO);
302                    if (command->mWaitStatus) {
303                        command->mCond.signal();
304                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
305                    }
306                    delete data;
307                    }break;
308                case SET_PARAMETERS: {
309                    ParametersData *data = (ParametersData *)command->mParam;
310                    ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
311                            data->mKeyValuePairs.string(), data->mIO);
312                    command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
313                    if (command->mWaitStatus) {
314                        command->mCond.signal();
315                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
316                    }
317                    delete data;
318                    }break;
319                case SET_VOICE_VOLUME: {
320                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
321                    ALOGV("AudioCommandThread() processing set voice volume volume %f",
322                            data->mVolume);
323                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
324                    if (command->mWaitStatus) {
325                        command->mCond.signal();
326                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
327                    }
328                    delete data;
329                    }break;
330                case STOP_OUTPUT: {
331                    StopOutputData *data = (StopOutputData *)command->mParam;
332                    ALOGV("AudioCommandThread() processing stop output %d",
333                            data->mIO);
334                    sp<AudioPolicyService> svc = mService.promote();
335                    if (svc == 0) {
336                        break;
337                    }
338                    mLock.unlock();
339                    svc->doStopOutput(data->mIO, data->mStream, data->mSession);
340                    mLock.lock();
341                    delete data;
342                    }break;
343                case RELEASE_OUTPUT: {
344                    ReleaseOutputData *data = (ReleaseOutputData *)command->mParam;
345                    ALOGV("AudioCommandThread() processing release output %d",
346                            data->mIO);
347                    sp<AudioPolicyService> svc = mService.promote();
348                    if (svc == 0) {
349                        break;
350                    }
351                    mLock.unlock();
352                    svc->doReleaseOutput(data->mIO);
353                    mLock.lock();
354                    delete data;
355                    }break;
356                default:
357                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
358                }
359                delete command;
360                waitTime = INT64_MAX;
361            } else {
362                waitTime = mAudioCommands[0]->mTime - curTime;
363                break;
364            }
365        }
366        // release delayed commands wake lock
367        if (mAudioCommands.isEmpty()) {
368            release_wake_lock(mName.string());
369        }
370        ALOGV("AudioCommandThread() going to sleep");
371        mWaitWorkCV.waitRelative(mLock, waitTime);
372        ALOGV("AudioCommandThread() waking up");
373    }
374    mLock.unlock();
375    return false;
376}
377
378status_t AudioPolicyService::AudioCommandThread::dump(int fd)
379{
380    const size_t SIZE = 256;
381    char buffer[SIZE];
382    String8 result;
383
384    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
385    result.append(buffer);
386    write(fd, result.string(), result.size());
387
388    bool locked = tryLock(mLock);
389    if (!locked) {
390        String8 result2(kCmdDeadlockedString);
391        write(fd, result2.string(), result2.size());
392    }
393
394    snprintf(buffer, SIZE, "- Commands:\n");
395    result = String8(buffer);
396    result.append("   Command Time        Wait pParam\n");
397    for (size_t i = 0; i < mAudioCommands.size(); i++) {
398        mAudioCommands[i]->dump(buffer, SIZE);
399        result.append(buffer);
400    }
401    result.append("  Last Command\n");
402    mLastCommand.dump(buffer, SIZE);
403    result.append(buffer);
404
405    write(fd, result.string(), result.size());
406
407    if (locked) mLock.unlock();
408
409    return NO_ERROR;
410}
411
412void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
413        audio_stream_type_t stream)
414{
415    AudioCommand *command = new AudioCommand();
416    command->mCommand = START_TONE;
417    ToneData *data = new ToneData();
418    data->mType = type;
419    data->mStream = stream;
420    command->mParam = (void *)data;
421    Mutex::Autolock _l(mLock);
422    insertCommand_l(command);
423    ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
424    mWaitWorkCV.signal();
425}
426
427void AudioPolicyService::AudioCommandThread::stopToneCommand()
428{
429    AudioCommand *command = new AudioCommand();
430    command->mCommand = STOP_TONE;
431    command->mParam = NULL;
432    Mutex::Autolock _l(mLock);
433    insertCommand_l(command);
434    ALOGV("AudioCommandThread() adding tone stop");
435    mWaitWorkCV.signal();
436}
437
438status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
439                                                               float volume,
440                                                               audio_io_handle_t output,
441                                                               int delayMs)
442{
443    status_t status = NO_ERROR;
444
445    AudioCommand *command = new AudioCommand();
446    command->mCommand = SET_VOLUME;
447    VolumeData *data = new VolumeData();
448    data->mStream = stream;
449    data->mVolume = volume;
450    data->mIO = output;
451    command->mParam = data;
452    Mutex::Autolock _l(mLock);
453    insertCommand_l(command, delayMs);
454    ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
455            stream, volume, output);
456    mWaitWorkCV.signal();
457    if (command->mWaitStatus) {
458        command->mCond.wait(mLock);
459        status =  command->mStatus;
460        command->mCond.signal();
461    }
462    return status;
463}
464
465status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
466                                                                   const char *keyValuePairs,
467                                                                   int delayMs)
468{
469    status_t status = NO_ERROR;
470
471    AudioCommand *command = new AudioCommand();
472    command->mCommand = SET_PARAMETERS;
473    ParametersData *data = new ParametersData();
474    data->mIO = ioHandle;
475    data->mKeyValuePairs = String8(keyValuePairs);
476    command->mParam = data;
477    Mutex::Autolock _l(mLock);
478    insertCommand_l(command, delayMs);
479    ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
480            keyValuePairs, ioHandle, delayMs);
481    mWaitWorkCV.signal();
482    if (command->mWaitStatus) {
483        command->mCond.wait(mLock);
484        status =  command->mStatus;
485        command->mCond.signal();
486    }
487    return status;
488}
489
490status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
491{
492    status_t status = NO_ERROR;
493
494    AudioCommand *command = new AudioCommand();
495    command->mCommand = SET_VOICE_VOLUME;
496    VoiceVolumeData *data = new VoiceVolumeData();
497    data->mVolume = volume;
498    command->mParam = data;
499    Mutex::Autolock _l(mLock);
500    insertCommand_l(command, delayMs);
501    ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
502    mWaitWorkCV.signal();
503    if (command->mWaitStatus) {
504        command->mCond.wait(mLock);
505        status =  command->mStatus;
506        command->mCond.signal();
507    }
508    return status;
509}
510
511void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
512                                                               audio_stream_type_t stream,
513                                                               int session)
514{
515    AudioCommand *command = new AudioCommand();
516    command->mCommand = STOP_OUTPUT;
517    StopOutputData *data = new StopOutputData();
518    data->mIO = output;
519    data->mStream = stream;
520    data->mSession = session;
521    command->mParam = (void *)data;
522    Mutex::Autolock _l(mLock);
523    insertCommand_l(command);
524    ALOGV("AudioCommandThread() adding stop output %d", output);
525    mWaitWorkCV.signal();
526}
527
528void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
529{
530    AudioCommand *command = new AudioCommand();
531    command->mCommand = RELEASE_OUTPUT;
532    ReleaseOutputData *data = new ReleaseOutputData();
533    data->mIO = output;
534    command->mParam = (void *)data;
535    Mutex::Autolock _l(mLock);
536    insertCommand_l(command);
537    ALOGV("AudioCommandThread() adding release output %d", output);
538    mWaitWorkCV.signal();
539}
540
541// insertCommand_l() must be called with mLock held
542void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
543{
544    ssize_t i;  // not size_t because i will count down to -1
545    Vector <AudioCommand *> removedCommands;
546    command->mTime = systemTime() + milliseconds(delayMs);
547
548    // acquire wake lock to make sure delayed commands are processed
549    if (mAudioCommands.isEmpty()) {
550        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
551    }
552
553    // check same pending commands with later time stamps and eliminate them
554    for (i = mAudioCommands.size()-1; i >= 0; i--) {
555        AudioCommand *command2 = mAudioCommands[i];
556        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
557        if (command2->mTime <= command->mTime) break;
558        if (command2->mCommand != command->mCommand) continue;
559
560        switch (command->mCommand) {
561        case SET_PARAMETERS: {
562            ParametersData *data = (ParametersData *)command->mParam;
563            ParametersData *data2 = (ParametersData *)command2->mParam;
564            if (data->mIO != data2->mIO) break;
565            ALOGV("Comparing parameter command %s to new command %s",
566                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
567            AudioParameter param = AudioParameter(data->mKeyValuePairs);
568            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
569            for (size_t j = 0; j < param.size(); j++) {
570                String8 key;
571                String8 value;
572                param.getAt(j, key, value);
573                for (size_t k = 0; k < param2.size(); k++) {
574                    String8 key2;
575                    String8 value2;
576                    param2.getAt(k, key2, value2);
577                    if (key2 == key) {
578                        param2.remove(key2);
579                        ALOGV("Filtering out parameter %s", key2.string());
580                        break;
581                    }
582                }
583            }
584            // if all keys have been filtered out, remove the command.
585            // otherwise, update the key value pairs
586            if (param2.size() == 0) {
587                removedCommands.add(command2);
588            } else {
589                data2->mKeyValuePairs = param2.toString();
590            }
591            command->mTime = command2->mTime;
592            // force delayMs to non 0 so that code below does not request to wait for
593            // command status as the command is now delayed
594            delayMs = 1;
595        } break;
596
597        case SET_VOLUME: {
598            VolumeData *data = (VolumeData *)command->mParam;
599            VolumeData *data2 = (VolumeData *)command2->mParam;
600            if (data->mIO != data2->mIO) break;
601            if (data->mStream != data2->mStream) break;
602            ALOGV("Filtering out volume command on output %d for stream %d",
603                    data->mIO, data->mStream);
604            removedCommands.add(command2);
605            command->mTime = command2->mTime;
606            // force delayMs to non 0 so that code below does not request to wait for
607            // command status as the command is now delayed
608            delayMs = 1;
609        } break;
610        case START_TONE:
611        case STOP_TONE:
612        default:
613            break;
614        }
615    }
616
617    // remove filtered commands
618    for (size_t j = 0; j < removedCommands.size(); j++) {
619        // removed commands always have time stamps greater than current command
620        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
621            if (mAudioCommands[k] == removedCommands[j]) {
622                ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
623                mAudioCommands.removeAt(k);
624                break;
625            }
626        }
627    }
628    removedCommands.clear();
629
630    // wait for status only if delay is 0
631    if (delayMs == 0) {
632        command->mWaitStatus = true;
633    } else {
634        command->mWaitStatus = false;
635    }
636
637    // insert command at the right place according to its time stamp
638    ALOGV("inserting command: %d at index %d, num commands %d",
639            command->mCommand, (int)i+1, mAudioCommands.size());
640    mAudioCommands.insertAt(command, i + 1);
641}
642
643void AudioPolicyService::AudioCommandThread::exit()
644{
645    ALOGV("AudioCommandThread::exit");
646    {
647        AutoMutex _l(mLock);
648        requestExit();
649        mWaitWorkCV.signal();
650    }
651    requestExitAndWait();
652}
653
654void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
655{
656    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
657            mCommand,
658            (int)ns2s(mTime),
659            (int)ns2ms(mTime)%1000,
660            mWaitStatus,
661            mParam);
662}
663
664/******* helpers for the service_ops callbacks defined below *********/
665void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
666                                       const char *keyValuePairs,
667                                       int delayMs)
668{
669    mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
670                                           delayMs);
671}
672
673int AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
674                                        float volume,
675                                        audio_io_handle_t output,
676                                        int delayMs)
677{
678    return (int)mAudioCommandThread->volumeCommand(stream, volume,
679                                                   output, delayMs);
680}
681
682int AudioPolicyService::startTone(audio_policy_tone_t tone,
683                                  audio_stream_type_t stream)
684{
685    if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) {
686        ALOGE("startTone: illegal tone requested (%d)", tone);
687    }
688    if (stream != AUDIO_STREAM_VOICE_CALL) {
689        ALOGE("startTone: illegal stream (%d) requested for tone %d", stream,
690            tone);
691    }
692    mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
693                                          AUDIO_STREAM_VOICE_CALL);
694    return 0;
695}
696
697int AudioPolicyService::stopTone()
698{
699    mTonePlaybackThread->stopToneCommand();
700    return 0;
701}
702
703int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
704{
705    return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
706}
707
708// ----------------------------------------------------------------------------
709// Audio pre-processing configuration
710// ----------------------------------------------------------------------------
711
712/*static*/ const char * const AudioPolicyService::kInputSourceNames[AUDIO_SOURCE_CNT -1] = {
713    MIC_SRC_TAG,
714    VOICE_UL_SRC_TAG,
715    VOICE_DL_SRC_TAG,
716    VOICE_CALL_SRC_TAG,
717    CAMCORDER_SRC_TAG,
718    VOICE_REC_SRC_TAG,
719    VOICE_COMM_SRC_TAG
720};
721
722// returns the audio_source_t enum corresponding to the input source name or
723// AUDIO_SOURCE_CNT is no match found
724audio_source_t AudioPolicyService::inputSourceNameToEnum(const char *name)
725{
726    int i;
727    for (i = AUDIO_SOURCE_MIC; i < AUDIO_SOURCE_CNT; i++) {
728        if (strcmp(name, kInputSourceNames[i - AUDIO_SOURCE_MIC]) == 0) {
729            ALOGV("inputSourceNameToEnum found source %s %d", name, i);
730            break;
731        }
732    }
733    return (audio_source_t)i;
734}
735
736size_t AudioPolicyService::growParamSize(char *param,
737                                         size_t size,
738                                         size_t *curSize,
739                                         size_t *totSize)
740{
741    // *curSize is at least sizeof(effect_param_t) + 2 * sizeof(int)
742    size_t pos = ((*curSize - 1 ) / size + 1) * size;
743
744    if (pos + size > *totSize) {
745        while (pos + size > *totSize) {
746            *totSize += ((*totSize + 7) / 8) * 4;
747        }
748        param = (char *)realloc(param, *totSize);
749    }
750    *curSize = pos + size;
751    return pos;
752}
753
754size_t AudioPolicyService::readParamValue(cnode *node,
755                                          char *param,
756                                          size_t *curSize,
757                                          size_t *totSize)
758{
759    if (strncmp(node->name, SHORT_TAG, sizeof(SHORT_TAG) + 1) == 0) {
760        size_t pos = growParamSize(param, sizeof(short), curSize, totSize);
761        *(short *)((char *)param + pos) = (short)atoi(node->value);
762        ALOGV("readParamValue() reading short %d", *(short *)((char *)param + pos));
763        return sizeof(short);
764    } else if (strncmp(node->name, INT_TAG, sizeof(INT_TAG) + 1) == 0) {
765        size_t pos = growParamSize(param, sizeof(int), curSize, totSize);
766        *(int *)((char *)param + pos) = atoi(node->value);
767        ALOGV("readParamValue() reading int %d", *(int *)((char *)param + pos));
768        return sizeof(int);
769    } else if (strncmp(node->name, FLOAT_TAG, sizeof(FLOAT_TAG) + 1) == 0) {
770        size_t pos = growParamSize(param, sizeof(float), curSize, totSize);
771        *(float *)((char *)param + pos) = (float)atof(node->value);
772        ALOGV("readParamValue() reading float %f",*(float *)((char *)param + pos));
773        return sizeof(float);
774    } else if (strncmp(node->name, BOOL_TAG, sizeof(BOOL_TAG) + 1) == 0) {
775        size_t pos = growParamSize(param, sizeof(bool), curSize, totSize);
776        if (strncmp(node->value, "false", strlen("false") + 1) == 0) {
777            *(bool *)((char *)param + pos) = false;
778        } else {
779            *(bool *)((char *)param + pos) = true;
780        }
781        ALOGV("readParamValue() reading bool %s",*(bool *)((char *)param + pos) ? "true" : "false");
782        return sizeof(bool);
783    } else if (strncmp(node->name, STRING_TAG, sizeof(STRING_TAG) + 1) == 0) {
784        size_t len = strnlen(node->value, EFFECT_STRING_LEN_MAX);
785        if (*curSize + len + 1 > *totSize) {
786            *totSize = *curSize + len + 1;
787            param = (char *)realloc(param, *totSize);
788        }
789        strncpy(param + *curSize, node->value, len);
790        *curSize += len;
791        param[*curSize] = '\0';
792        ALOGV("readParamValue() reading string %s", param + *curSize - len);
793        return len;
794    }
795    ALOGW("readParamValue() unknown param type %s", node->name);
796    return 0;
797}
798
799effect_param_t *AudioPolicyService::loadEffectParameter(cnode *root)
800{
801    cnode *param;
802    cnode *value;
803    size_t curSize = sizeof(effect_param_t);
804    size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int);
805    effect_param_t *fx_param = (effect_param_t *)malloc(totSize);
806
807    param = config_find(root, PARAM_TAG);
808    value = config_find(root, VALUE_TAG);
809    if (param == NULL && value == NULL) {
810        // try to parse simple parameter form {int int}
811        param = root->first_child;
812        if (param != NULL) {
813            // Note: that a pair of random strings is read as 0 0
814            int *ptr = (int *)fx_param->data;
815            int *ptr2 = (int *)((char *)param + sizeof(effect_param_t));
816            ALOGW("loadEffectParameter() ptr %p ptr2 %p", ptr, ptr2);
817            *ptr++ = atoi(param->name);
818            *ptr = atoi(param->value);
819            fx_param->psize = sizeof(int);
820            fx_param->vsize = sizeof(int);
821            return fx_param;
822        }
823    }
824    if (param == NULL || value == NULL) {
825        ALOGW("loadEffectParameter() invalid parameter description %s", root->name);
826        goto error;
827    }
828
829    fx_param->psize = 0;
830    param = param->first_child;
831    while (param) {
832        ALOGV("loadEffectParameter() reading param of type %s", param->name);
833        size_t size = readParamValue(param, (char *)fx_param, &curSize, &totSize);
834        if (size == 0) {
835            goto error;
836        }
837        fx_param->psize += size;
838        param = param->next;
839    }
840
841    // align start of value field on 32 bit boundary
842    curSize = ((curSize - 1 ) / sizeof(int) + 1) * sizeof(int);
843
844    fx_param->vsize = 0;
845    value = value->first_child;
846    while (value) {
847        ALOGV("loadEffectParameter() reading value of type %s", value->name);
848        size_t size = readParamValue(value, (char *)fx_param, &curSize, &totSize);
849        if (size == 0) {
850            goto error;
851        }
852        fx_param->vsize += size;
853        value = value->next;
854    }
855
856    return fx_param;
857
858error:
859    delete fx_param;
860    return NULL;
861}
862
863void AudioPolicyService::loadEffectParameters(cnode *root, Vector <effect_param_t *>& params)
864{
865    cnode *node = root->first_child;
866    while (node) {
867        ALOGV("loadEffectParameters() loading param %s", node->name);
868        effect_param_t *param = loadEffectParameter(node);
869        if (param == NULL) {
870            node = node->next;
871            continue;
872        }
873        params.add(param);
874        node = node->next;
875    }
876}
877
878AudioPolicyService::InputSourceDesc *AudioPolicyService::loadInputSource(
879                                                            cnode *root,
880                                                            const Vector <EffectDesc *>& effects)
881{
882    cnode *node = root->first_child;
883    if (node == NULL) {
884        ALOGW("loadInputSource() empty element %s", root->name);
885        return NULL;
886    }
887    InputSourceDesc *source = new InputSourceDesc();
888    while (node) {
889        size_t i;
890        for (i = 0; i < effects.size(); i++) {
891            if (strncmp(effects[i]->mName, node->name, EFFECT_STRING_LEN_MAX) == 0) {
892                ALOGV("loadInputSource() found effect %s in list", node->name);
893                break;
894            }
895        }
896        if (i == effects.size()) {
897            ALOGV("loadInputSource() effect %s not in list", node->name);
898            node = node->next;
899            continue;
900        }
901        EffectDesc *effect = new EffectDesc(*effects[i]);   // deep copy
902        loadEffectParameters(node, effect->mParams);
903        ALOGV("loadInputSource() adding effect %s uuid %08x", effect->mName, effect->mUuid.timeLow);
904        source->mEffects.add(effect);
905        node = node->next;
906    }
907    if (source->mEffects.size() == 0) {
908        ALOGW("loadInputSource() no valid effects found in source %s", root->name);
909        delete source;
910        return NULL;
911    }
912    return source;
913}
914
915status_t AudioPolicyService::loadInputSources(cnode *root, const Vector <EffectDesc *>& effects)
916{
917    cnode *node = config_find(root, PREPROCESSING_TAG);
918    if (node == NULL) {
919        return -ENOENT;
920    }
921    node = node->first_child;
922    while (node) {
923        audio_source_t source = inputSourceNameToEnum(node->name);
924        if (source == AUDIO_SOURCE_CNT) {
925            ALOGW("loadInputSources() invalid input source %s", node->name);
926            node = node->next;
927            continue;
928        }
929        ALOGV("loadInputSources() loading input source %s", node->name);
930        InputSourceDesc *desc = loadInputSource(node, effects);
931        if (desc == NULL) {
932            node = node->next;
933            continue;
934        }
935        mInputSources.add(source, desc);
936        node = node->next;
937    }
938    return NO_ERROR;
939}
940
941AudioPolicyService::EffectDesc *AudioPolicyService::loadEffect(cnode *root)
942{
943    cnode *node = config_find(root, UUID_TAG);
944    if (node == NULL) {
945        return NULL;
946    }
947    effect_uuid_t uuid;
948    if (AudioEffect::stringToGuid(node->value, &uuid) != NO_ERROR) {
949        ALOGW("loadEffect() invalid uuid %s", node->value);
950        return NULL;
951    }
952    return new EffectDesc(root->name, uuid);
953}
954
955status_t AudioPolicyService::loadEffects(cnode *root, Vector <EffectDesc *>& effects)
956{
957    cnode *node = config_find(root, EFFECTS_TAG);
958    if (node == NULL) {
959        return -ENOENT;
960    }
961    node = node->first_child;
962    while (node) {
963        ALOGV("loadEffects() loading effect %s", node->name);
964        EffectDesc *effect = loadEffect(node);
965        if (effect == NULL) {
966            node = node->next;
967            continue;
968        }
969        effects.add(effect);
970        node = node->next;
971    }
972    return NO_ERROR;
973}
974
975status_t AudioPolicyService::loadPreProcessorConfig(const char *path)
976{
977    cnode *root;
978    char *data;
979
980    data = (char *)load_file(path, NULL);
981    if (data == NULL) {
982        return -ENODEV;
983    }
984    root = config_node("", "");
985    config_load(root, data);
986
987    Vector <EffectDesc *> effects;
988    loadEffects(root, effects);
989    loadInputSources(root, effects);
990
991    // delete effects to fix memory leak.
992    // as effects is local var and valgrind would treat this as memory leak
993    // and although it only did in mediaserver init, but free it in case mediaserver reboot
994    size_t i;
995    for (i = 0; i < effects.size(); i++) {
996      delete effects[i];
997    }
998
999    config_free(root);
1000    free(root);
1001    free(data);
1002
1003    return NO_ERROR;
1004}
1005
1006extern "C" {
1007audio_module_handle_t aps_load_hw_module(void *service __unused,
1008                                             const char *name);
1009audio_io_handle_t aps_open_output(void *service __unused,
1010                                         audio_devices_t *pDevices,
1011                                         uint32_t *pSamplingRate,
1012                                         audio_format_t *pFormat,
1013                                         audio_channel_mask_t *pChannelMask,
1014                                         uint32_t *pLatencyMs,
1015                                         audio_output_flags_t flags);
1016
1017audio_io_handle_t aps_open_output_on_module(void *service __unused,
1018                                                   audio_module_handle_t module,
1019                                                   audio_devices_t *pDevices,
1020                                                   uint32_t *pSamplingRate,
1021                                                   audio_format_t *pFormat,
1022                                                   audio_channel_mask_t *pChannelMask,
1023                                                   uint32_t *pLatencyMs,
1024                                                   audio_output_flags_t flags,
1025                                                   const audio_offload_info_t *offloadInfo);
1026audio_io_handle_t aps_open_dup_output(void *service __unused,
1027                                                 audio_io_handle_t output1,
1028                                                 audio_io_handle_t output2);
1029int aps_close_output(void *service __unused, audio_io_handle_t output);
1030int aps_suspend_output(void *service __unused, audio_io_handle_t output);
1031int aps_restore_output(void *service __unused, audio_io_handle_t output);
1032audio_io_handle_t aps_open_input(void *service __unused,
1033                                        audio_devices_t *pDevices,
1034                                        uint32_t *pSamplingRate,
1035                                        audio_format_t *pFormat,
1036                                        audio_channel_mask_t *pChannelMask,
1037                                        audio_in_acoustics_t acoustics __unused);
1038audio_io_handle_t aps_open_input_on_module(void *service __unused,
1039                                                  audio_module_handle_t module,
1040                                                  audio_devices_t *pDevices,
1041                                                  uint32_t *pSamplingRate,
1042                                                  audio_format_t *pFormat,
1043                                                  audio_channel_mask_t *pChannelMask);
1044int aps_close_input(void *service __unused, audio_io_handle_t input);
1045int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream);
1046int aps_move_effects(void *service __unused, int session,
1047                                audio_io_handle_t src_output,
1048                                audio_io_handle_t dst_output);
1049char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle,
1050                                     const char *keys);
1051void aps_set_parameters(void *service, audio_io_handle_t io_handle,
1052                                   const char *kv_pairs, int delay_ms);
1053int aps_set_stream_volume(void *service, audio_stream_type_t stream,
1054                                     float volume, audio_io_handle_t output,
1055                                     int delay_ms);
1056int aps_start_tone(void *service, audio_policy_tone_t tone,
1057                              audio_stream_type_t stream);
1058int aps_stop_tone(void *service);
1059int aps_set_voice_volume(void *service, float volume, int delay_ms);
1060};
1061
1062namespace {
1063    struct audio_policy_service_ops aps_ops = {
1064        .open_output           = aps_open_output,
1065        .open_duplicate_output = aps_open_dup_output,
1066        .close_output          = aps_close_output,
1067        .suspend_output        = aps_suspend_output,
1068        .restore_output        = aps_restore_output,
1069        .open_input            = aps_open_input,
1070        .close_input           = aps_close_input,
1071        .set_stream_volume     = aps_set_stream_volume,
1072        .invalidate_stream     = aps_invalidate_stream,
1073        .set_parameters        = aps_set_parameters,
1074        .get_parameters        = aps_get_parameters,
1075        .start_tone            = aps_start_tone,
1076        .stop_tone             = aps_stop_tone,
1077        .set_voice_volume      = aps_set_voice_volume,
1078        .move_effects          = aps_move_effects,
1079        .load_hw_module        = aps_load_hw_module,
1080        .open_output_on_module = aps_open_output_on_module,
1081        .open_input_on_module  = aps_open_input_on_module,
1082    };
1083}; // namespace <unnamed>
1084
1085}; // namespace android
1086