AudioPolicyService.cpp revision 2d388eccc9dc085337c7a03a68467cbee6b809e1
165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/*
265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Copyright (C) 2009 The Android Open Source Project
365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * you may not use this file except in compliance with the License.
665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * You may obtain a copy of the License at
765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian *
1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Unless required by applicable law or agreed to in writing, software
1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * See the License for the specific language governing permissions and
1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * limitations under the License.
1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */
1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define LOG_TAG "AudioPolicyService"
1865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//#define LOG_NDEBUG 0
198951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "Configuration.h"
2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#undef __STRICT_ANSI__
2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define __STDINT_LIMITS
2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#define __STDC_LIMIT_MACROS
2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <stdint.h>
2565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/time.h>
2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/IServiceManager.h>
2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <utils/Log.h>
2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <cutils/properties.h>
30b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra#include <binder/IPCThreadState.h>
31bfa33aae4f54c0020a0568b16a3acb7b30b6ca3dJamie Gennis#include <utils/String16.h>
32df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <utils/threads.h>
3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioPolicyService.h"
3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "ServiceUtilities.h"
3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <hardware_legacy/power.h>
3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/AudioEffect.h>
3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/EffectsFactoryApi.h>
3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <hardware/hardware.h>
4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <system/audio.h>
415e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala#include <system/audio_policy.h>
428951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev#include <hardware/audio_policy.h>
4365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <audio_effects/audio_effects_conf.h>
4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <media/AudioParameter.h>
4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android {
4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n";
495e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvalastatic const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n";
5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
51b8a805261bf0282e992d3608035e47d05a898710Steve Blockstatic const int kDumpLockRetries = 50;
52b8a805261bf0282e992d3608035e47d05a898710Steve Blockstatic const int kDumpLockSleepUs = 20000;
5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic const nsecs_t kAudioCommandTimeout = 3000000000LL; // 3 seconds
5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace {
5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    extern struct audio_policy_service_ops aps_ops;
5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian};
5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ----------------------------------------------------------------------------
6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioPolicyService::AudioPolicyService()
6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL)
6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    char value[PROPERTY_VALUE_MAX];
6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const struct hw_module_t *module;
6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int forced_val;
6865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    int rc;
6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock _l(mLock);
7165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
7265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // start tone playback thread
7365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // start audio commands thread
758951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // start output activity command thread
77df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
788951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    /* instantiate the audio policy manager */
798951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (rc) {
818951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        return;
828951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
838951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
858951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
868951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (rc) {
8729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        return;
888951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
898951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
908951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
918951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev                                               &mpAudioPolicy);
928951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
9329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    if (rc) {
948951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        return;
958951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
968951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
978951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    rc = mpAudioPolicy->init_check(mpAudioPolicy);
988951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
998951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    if (rc) {
10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        return;
10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
10365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
10465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
10565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    // load audio pre processing modules
10629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        loadPreProcessorConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
10865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
10965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        loadPreProcessorConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
11365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioPolicyService::~AudioPolicyService()
11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mTonePlaybackThread->exit();
11665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mTonePlaybackThread.clear();
11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mAudioCommandThread->exit();
11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mAudioCommandThread.clear();
1198951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
1208951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
1218951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    // release audio pre processing resources
1228951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    for (size_t i = 0; i < mInputSources.size(); i++) {
12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        delete mInputSources.valueAt(i);
12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mInputSources.clear();
12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1278951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    for (size_t i = 0; i < mInputs.size(); i++) {
1288951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        mInputs.valueAt(i)->mEffects.clear();
1298951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        delete mInputs.valueAt(i);
1308951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    }
1318951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    mInputs.clear();
13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) {
13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
13508ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    }
13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (mpAudioPolicyDev != NULL) {
1375861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        audio_policy_dev_close(mpAudioPolicyDev);
1385861a9a98c641261c4807c976c750e4611b3a57dTyler Luu    }
13965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
14065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
1418951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev
14229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Blockvoid AudioPolicyService::binderDied(const wp<IBinder>& who) {
1438951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev    ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
1448951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            IPCThreadState::self()->getCallingPid());
1458951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev}
14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatic bool tryLock(Mutex& mutex)
14829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block{
14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    bool locked = false;
15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (int i = 0; i < kDumpLockRetries; ++i) {
15165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (mutex.tryLock() == NO_ERROR) {
15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            locked = true;
153a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li            break;
154a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li        }
155a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li        usleep(kDumpLockSleepUs);
156a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li    }
157df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    return locked;
158a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li}
159a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Li
160a3355430a36bbfa7b2c0d90eb30834f1c5dac337Wu-cheng Listatus_t AudioPolicyService::dumpInternals(int fd)
16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
16208ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    const size_t SIZE = 256;
16308ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    char buffer[SIZE];
16408ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    String8 result;
16508ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li
16608ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
16708ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    result.append(buffer);
16808ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
16908ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    result.append(buffer);
17008ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
17108ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    result.append(buffer);
1722fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li
1732fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    write(fd, result.string(), result.size());
1742fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    return NO_ERROR;
17508ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li}
17608ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li
17708ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Listatus_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused)
17808ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li{
17908ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    if (!dumpAllowed()) {
18008ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li        dumpPermissionDenial(fd);
18108ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li    } else {
18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        bool locked = tryLock(mLock);
18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (!locked) {
1848951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            String8 result(kDeadlockedString);
1858951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            write(fd, result.string(), result.size());
18629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        }
187b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li
188b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li        dumpInternals(fd);
1898951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        if (mAudioCommandThread != 0) {
1908951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev            mAudioCommandThread->dump(fd);
1918951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        }
1928951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev        if (mTonePlaybackThread != 0) {
1935861a9a98c641261c4807c976c750e4611b3a57dTyler Luu            mTonePlaybackThread->dump(fd);
1945861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        }
1955861a9a98c641261c4807c976c750e4611b3a57dTyler Luu
1965861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        if (mpAudioPolicy) {
1975861a9a98c641261c4807c976c750e4611b3a57dTyler Luu            mpAudioPolicy->dump(mpAudioPolicy, fd);
1985861a9a98c641261c4807c976c750e4611b3a57dTyler Luu        }
1995e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala
20065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        if (locked) mLock.unlock();
2012fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li    }
20265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
20365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
20465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
20565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t AudioPolicyService::dumpPermissionDenial(int fd)
20665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
20765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const size_t SIZE = 256;
20865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    char buffer[SIZE];
20965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    String8 result;
21065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    snprintf(buffer, SIZE, "Permission Denial: "
21165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
21265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            IPCThreadState::self()->getCallingPid(),
21365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            IPCThreadState::self()->getCallingUid());
21465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result.append(buffer);
21565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    write(fd, result.string(), result.size());
21665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
21765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
21865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
21965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioPolicyService::setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled)
22065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
22165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const Vector<sp<AudioEffect> > &fxVector = inputDesc->mEffects;
22265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (size_t i = 0; i < fxVector.size(); i++) {
22365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        fxVector.itemAt(i)->setEnabled(enabled);
22465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
22565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
22665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
22765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t AudioPolicyService::onTransact(
22865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
22965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
23065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return BnAudioPolicyService::onTransact(code, data, reply, flags);
23165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
23265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
23365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
23465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// -----------  AudioPolicyService::AudioCommandThread implementation ----------
23565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
23665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianAudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
23765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                           const wp<AudioPolicyService>& service)
23865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    : Thread(false), mName(name), mService(service)
23965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
240d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    mpToneGenerator = NULL;
24165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
242d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
243d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park
244d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young ParkAudioPolicyService::AudioCommandThread::~AudioCommandThread()
245d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park{
246d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    if (!mAudioCommands.isEmpty()) {
247d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park        release_wake_lock(mName.string());
24865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
24965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mAudioCommands.clear();
25065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    delete mpToneGenerator;
25165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
25265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
25365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioPolicyService::AudioCommandThread::onFirstRef()
25465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
25565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    run(mName.string(), ANDROID_PRIORITY_AUDIO);
25665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
25765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
25865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianbool AudioPolicyService::AudioCommandThread::threadLoop()
25965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
26065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    nsecs_t waitTime = INT64_MAX;
26165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
26229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    mLock.lock();
26365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    while (!exitPending())
26465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    {
26565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        while (!mAudioCommands.isEmpty()) {
26665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            nsecs_t curTime = systemTime();
26765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            // commands are sorted by increasing time stamp: execute them from index 0 and up
26865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian            if (mAudioCommands[0]->mTime <= curTime) {
26965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                AudioCommand *command = mAudioCommands[0];
27065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                mAudioCommands.removeAt(0);
27165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                mLastCommand = *command;
27265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
27365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                switch (command->mCommand) {
27465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case START_TONE: {
27565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.unlock();
27665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ToneData *data = (ToneData *)command->mParam;
27765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing start tone %d on stream %d",
27865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            data->mType, data->mStream);
27965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete mpToneGenerator;
28065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
28165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mpToneGenerator->startTone(data->mType);
28265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete data;
28365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.lock();
28465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
28565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case STOP_TONE: {
28665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.unlock();
28765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing stop tone");
28865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    if (mpToneGenerator != NULL) {
28965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        mpToneGenerator->stopTone();
29065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        delete mpToneGenerator;
291ff4f55c8d77e276dbcceedb4e560ca1d91ba38baChih-Chung Chang                        mpToneGenerator = NULL;
29265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
29365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.lock();
29460a78ac9535878984b0777788760b9ee7465c5e6Eino-Ville Talvala                    }break;
29565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case SET_VOLUME: {
29665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    VolumeData *data = (VolumeData *)command->mParam;
29729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGV("AudioCommandThread() processing set volume stream %d, \
29865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
29965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
30065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                                    data->mVolume,
30165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                                    data->mIO);
30265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    if (command->mWaitStatus) {
30365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.signal();
30465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
30565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
30665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete data;
30765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
30865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case SET_PARAMETERS: {
30965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ParametersData *data = (ParametersData *)command->mParam;
31065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
31165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            data->mKeyValuePairs.string(), data->mIO);
31265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
31365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    if (command->mWaitStatus) {
31465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.signal();
31565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
31665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
31765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete data;
31865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
31965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case SET_VOICE_VOLUME: {
32065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
32165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing set voice volume volume %f",
32265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            data->mVolume);
32365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
32465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    if (command->mWaitStatus) {
32565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.signal();
32665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        command->mCond.waitRelative(mLock, kAudioCommandTimeout);
32765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
32865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete data;
32965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
3308888a75f01d904541e409e858d23e4150ace34b6Chih-Chung Chang                case STOP_OUTPUT: {
3318888a75f01d904541e409e858d23e4150ace34b6Chih-Chung Chang                    StopOutputData *data = (StopOutputData *)command->mParam;
33265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing stop output %d",
33365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                            data->mIO);
33465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    sp<AudioPolicyService> svc = mService.promote();
33565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    if (svc == 0) {
33665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                        break;
33765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
338b7a67942823e8339eb298238f117aaa6d7b63111Wu-cheng Li                    mLock.unlock();
33908ad5efcef90e24db2863c0f85972ed05fe848a2Wu-cheng Li                    svc->doStopOutput(data->mIO, data->mStream, data->mSession);
34065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.lock();
3412fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    delete data;
34265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
34365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                case RELEASE_OUTPUT: {
34465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ReleaseOutputData *data = (ReleaseOutputData *)command->mParam;
34565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGV("AudioCommandThread() processing release output %d",
346e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li                            data->mIO);
34765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    sp<AudioPolicyService> svc = mService.promote();
348d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park                    if (svc == 0) {
3495e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala                        break;
35065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }
35165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.unlock();
3522fd2440d0175ca3e196b01b7541a9e0d4ed9a694Wu-cheng Li                    svc->doReleaseOutput(data->mIO);
35365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    mLock.lock();
35465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    delete data;
35565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    }break;
35665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                default:
35765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
35865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                }
35965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                delete command;
36065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                waitTime = INT64_MAX;
361d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park            } else {
362d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park                waitTime = mAudioCommands[0]->mTime - curTime;
363d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park                break;
364d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park            }
365d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park        }
366d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park        // release delayed commands wake lock
367d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park        if (mAudioCommands.isEmpty()) {
368d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park            release_wake_lock(mName.string());
36965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        }
37065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        ALOGV("AudioCommandThread() going to sleep");
37165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mWaitWorkCV.waitRelative(mLock, waitTime);
37265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        ALOGV("AudioCommandThread() waking up");
373d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    }
374d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    mLock.unlock();
375d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park    return false;
376d8973a71a3d1dd670e5dcdf6e94ec0cd45444eecKeun young Park}
37765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
37865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t AudioPolicyService::AudioCommandThread::dump(int fd)
37965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
38065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    const size_t SIZE = 256;
3815e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala    char buffer[SIZE];
3825e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala    String8 result;
3835e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala
384e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
385e09591eff55fdff1868b32c3e046c62f800330fcWu-cheng Li    result.append(buffer);
38665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    write(fd, result.string(), result.size());
38765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
38865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    bool locked = tryLock(mLock);
38965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (!locked) {
39065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        String8 result2(kCmdDeadlockedString);
39165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        write(fd, result2.string(), result2.size());
39265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
39365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
39465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    snprintf(buffer, SIZE, "- Commands:\n");
39565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result = String8(buffer);
39665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result.append("   Command Time        Wait pParam\n");
39765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    for (size_t i = 0; i < mAudioCommands.size(); i++) {
39865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        mAudioCommands[i]->dump(buffer, SIZE);
39965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        result.append(buffer);
40065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    }
40165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result.append("  Last Command\n");
40265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mLastCommand.dump(buffer, SIZE);
40365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    result.append(buffer);
40465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
40565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    write(fd, result.string(), result.size());
40665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
40765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    if (locked) mLock.unlock();
40865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
40965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    return NO_ERROR;
41065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
41165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
41265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
41365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian        audio_stream_type_t stream)
41465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
41565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    AudioCommand *command = new AudioCommand();
41665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    command->mCommand = START_TONE;
41765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ToneData *data = new ToneData();
41865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    data->mType = type;
41965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    data->mStream = stream;
42065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    command->mParam = (void *)data;
42165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock _l(mLock);
42265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    insertCommand_l(command);
42365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
42465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mWaitWorkCV.signal();
42565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
42665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
42765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioPolicyService::AudioCommandThread::stopToneCommand()
42865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
42965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    AudioCommand *command = new AudioCommand();
4305e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala    command->mCommand = STOP_TONE;
43165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    command->mParam = NULL;
43265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock _l(mLock);
43365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    insertCommand_l(command);
43465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    ALOGV("AudioCommandThread() adding tone stop");
43565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    mWaitWorkCV.signal();
43665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian}
43765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
43865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
43965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                               float volume,
44065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                               audio_io_handle_t output,
44165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian                                                               int delayMs)
44265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian{
44365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    status_t status = NO_ERROR;
44465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian
44565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    AudioCommand *command = new AudioCommand();
44665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    command->mCommand = SET_VOLUME;
44765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    VolumeData *data = new VolumeData();
44865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    data->mStream = stream;
44965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    data->mVolume = volume;
45065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    data->mIO = output;
45165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    command->mParam = data;
45265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    Mutex::Autolock _l(mLock);
45365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    insertCommand_l(command, delayMs);
45465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian    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