AudioPolicyService.cpp revision de070137f11d346fba77605bd76a44c040a618fc
1f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project/*
2f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
3a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt *
4f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * you may not use this file except in compliance with the License.
6f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * You may obtain a copy of the License at
7f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *
8f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project *
10f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * See the License for the specific language governing permissions and
14f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project * limitations under the License.
15f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project */
16f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
17f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define LOG_TAG "AudioPolicyService"
18f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project//#define LOG_NDEBUG 0
19f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
20f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#undef __STRICT_ANSI__
21f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define __STDINT_LIMITS
22f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#define __STDC_LIMIT_MACROS
23f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <stdint.h>
24f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
25f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <sys/time.h>
26f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <binder/IServiceManager.h>
27f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <utils/Log.h>
28f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <cutils/properties.h>
29f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <binder/IPCThreadState.h>
30f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <utils/String16.h>
31f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <utils/threads.h>
32f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include "AudioPolicyService.h"
33f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <hardware_legacy/AudioPolicyManagerBase.h>
34f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <cutils/properties.h>
35f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <dlfcn.h>
36f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#include <hardware_legacy/power.h>
37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt// ----------------------------------------------------------------------------
39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt// the sim build doesn't have gettid
40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#ifndef HAVE_GETTID
42f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project# define gettid getpid
43a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt#endif
44a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
45a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtnamespace android {
46a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
47a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
48a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
49a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
50f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic const int kDumpLockRetries = 50;
52f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic const int kDumpLockSleep = 20000;
53f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
54f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatic bool checkPermission() {
55f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#ifndef HAVE_ANDROID_OS
56f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return true;
57f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project#endif
58f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
59f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
61f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return ok;
62f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
63f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt// ----------------------------------------------------------------------------
65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
66e86eee143ed21592f88a46623a81f71002430459Dmitry ShmidtAudioPolicyService::AudioPolicyService()
67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    : BnAudioPolicyService() , mpPolicyManager(NULL)
68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    char value[PROPERTY_VALUE_MAX];
70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    // start tone playback thread
72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mTonePlaybackThread = new AudioCommandThread(String8(""));
73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    // start audio commands thread
74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager = new AudioPolicyManagerBase(this);
78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    LOGV("build for GENERIC_AUDIO - using generic audio policy");
79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#else
80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    // if running in emulation - use the emulator driver
81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (property_get("ro.kernel.qemu", value, 0)) {
82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        LOGV("Running in emulation - using generic audio policy");
83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        mpPolicyManager = new AudioPolicyManagerBase(this);
84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    else {
86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        LOGV("Using hardware specific audio policy");
87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        mpPolicyManager = createAudioPolicyManager(this);
88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#endif
90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    // load properties
92f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    property_get("ro.camera.sound.forced", value, "0");
93f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
96e86eee143ed21592f88a46623a81f71002430459Dmitry ShmidtAudioPolicyService::~AudioPolicyService()
97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mTonePlaybackThread->exit();
99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mTonePlaybackThread.clear();
100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mAudioCommandThread->exit();
101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mAudioCommandThread.clear();
102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager) {
104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        delete mpPolicyManager;
105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                                  AudioSystem::device_connection_state state,
111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                                  const char *device_address)
112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
115f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
116f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (!checkPermission()) {
117f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return PERMISSION_DENIED;
118f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
119f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
122f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (state != AudioSystem::DEVICE_STATE_AVAILABLE &&
123f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    LOGV("setDeviceConnectionState() tid %d", gettid());
128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
132e86eee143ed21592f88a46623a81f71002430459Dmitry ShmidtAudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(
133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                                              AudioSystem::audio_devices device,
134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                                              const char *device_address)
135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->getDeviceConnectionState(device, device_address);
143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::setPhoneState(int state)
146f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
147f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (mpPolicyManager == NULL) {
148f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return NO_INIT;
149f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
151f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return PERMISSION_DENIED;
152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (state < 0 || state >= AudioSystem::NUM_MODES) {
154f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return BAD_VALUE;
155f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
156f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
157f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    LOGV("setPhoneState() tid %d", gettid());
158e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
159e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    // TODO: check if it is more appropriate to do it in platform specific policy manager
160f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    AudioSystem::setMode(state);
161f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
162f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    Mutex::Autolock _l(mLock);
163f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    mpPolicyManager->setPhoneState(state);
164f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return NO_ERROR;
165f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
166f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
167f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
168e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
169e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
170e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
171e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
172e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
173e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return PERMISSION_DENIED;
174f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
175e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
176e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager->setRingerMode(mode, mask);
177e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return NO_ERROR;
178e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
179e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
180e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::setForceUse(AudioSystem::force_use usage,
181e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                         AudioSystem::forced_config config)
182e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
183e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
184e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
185e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
186e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
187e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return PERMISSION_DENIED;
188e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
189e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
190e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
191e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
192e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
193e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
194f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
195f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    LOGV("setForceUse() tid %d", gettid());
196f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    Mutex::Autolock _l(mLock);
197e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager->setForceUse(usage, config);
198f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return NO_ERROR;
199f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
200f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
201f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source ProjectAudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
202f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
203f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (mpPolicyManager == NULL) {
204e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return AudioSystem::FORCE_NONE;
205f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
206f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (!checkPermission()) {
207f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return AudioSystem::FORCE_NONE;
208f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
209e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
210f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return AudioSystem::FORCE_NONE;
211f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
212f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mpPolicyManager->getForceUse(usage);
213f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
214f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
215f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectaudio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
216f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                    uint32_t samplingRate,
217f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                    uint32_t format,
218f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                    uint32_t channels,
219f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                    AudioSystem::output_flags flags)
220f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
221f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (mpPolicyManager == NULL) {
222f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return 0;
223f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
224f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    LOGV("getOutput() tid %d", gettid());
225f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    Mutex::Autolock _l(mLock);
226f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
227f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
228f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
229e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::startOutput(audio_io_handle_t output,
230e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                         AudioSystem::stream_type stream,
231e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                         int session)
232e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
233e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
234e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
235e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
236e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    LOGV("startOutput() tid %d", gettid());
237e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
238e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->startOutput(output, stream, session);
239e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
240e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
241e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::stopOutput(audio_io_handle_t output,
242e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                        AudioSystem::stream_type stream,
243e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                        int session)
244e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
245e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
246e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
247e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
248e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    LOGV("stopOutput() tid %d", gettid());
249e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
250e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->stopOutput(output, stream, session);
251e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
252e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
253e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid AudioPolicyService::releaseOutput(audio_io_handle_t output)
254e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
255e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
256e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return;
257e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
258e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    LOGV("releaseOutput() tid %d", gettid());
259e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
260e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager->releaseOutput(output);
261e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
262e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
263e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtaudio_io_handle_t AudioPolicyService::getInput(int inputSource,
264e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                    uint32_t samplingRate,
265e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                    uint32_t format,
266e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                    uint32_t channels,
267e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                    AudioSystem::audio_in_acoustics acoustics)
268e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
269e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
270e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return 0;
271e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
272e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
273e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
274e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
275e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
276e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::startInput(audio_io_handle_t input)
277e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
278e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
279e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
280e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
281e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
282e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->startInput(input);
283e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
284e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
285e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::stopInput(audio_io_handle_t input)
286e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
287e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
288e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
289e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
290e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
291e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->stopInput(input);
292e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
293e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
294e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid AudioPolicyService::releaseInput(audio_io_handle_t input)
295e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
296e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
297e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return;
298e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
299e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    Mutex::Autolock _l(mLock);
300e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager->releaseInput(input);
301e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
302e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
303e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
304e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                            int indexMin,
305e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt                                            int indexMax)
306e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
307e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
308e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
309e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
310e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
311e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return PERMISSION_DENIED;
312e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
313e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
314e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
315e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
316e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
317e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return NO_ERROR;
318e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
319e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
320e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
321e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
322e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
323e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
324e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
325e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
326e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return PERMISSION_DENIED;
327e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
328e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
329e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return BAD_VALUE;
330e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
331e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
332e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->setStreamVolumeIndex(stream, index);
333e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
334e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
335e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
336e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
337e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
338e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
339e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
340e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (!checkPermission()) {
341f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return PERMISSION_DENIED;
342f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
343f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
344f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return BAD_VALUE;
345f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
346f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mpPolicyManager->getStreamVolumeIndex(stream, index);
347e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
348e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
349e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtuint32_t AudioPolicyService::getStrategyForStream(AudioSystem::stream_type stream)
350e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{
351e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
352e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return 0;
353e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
354f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mpPolicyManager->getStrategyForStream(stream);
355f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
356f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
357f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectaudio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
358f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
359f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (mpPolicyManager == NULL) {
360f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return NO_INIT;
361f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
362f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    Mutex::Autolock _l(mLock);
363e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return mpPolicyManager->getOutputForEffect(desc);
364f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
365f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
366f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
367f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                audio_io_handle_t output,
368f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t strategy,
369f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                int session,
370f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                int id)
371f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
372e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (mpPolicyManager == NULL) {
373e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        return NO_INIT;
374f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
375f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mpPolicyManager->registerEffect(desc, output, strategy, session, id);
376f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
377f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
378f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::unregisterEffect(int id)
379f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
380f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (mpPolicyManager == NULL) {
381a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt        return NO_INIT;
382a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    }
383a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    return mpPolicyManager->unregisterEffect(id);
384a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt}
385a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
386a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtvoid AudioPolicyService::binderDied(const wp<IBinder>& who) {
387a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
388a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt            IPCThreadState::self()->getCallingPid());
389a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt}
390a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
391a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatic bool tryLock(Mutex& mutex)
392a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{
393a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    bool locked = false;
394a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    for (int i = 0; i < kDumpLockRetries; ++i) {
395a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt        if (mutex.tryLock() == NO_ERROR) {
396a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt            locked = true;
397a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt            break;
398e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        }
399f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        usleep(kDumpLockSleep);
400f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
401f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return locked;
402e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
403f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
404e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatus_t AudioPolicyService::dumpInternals(int fd)
405f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
406f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    const size_t SIZE = 256;
407f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    char buffer[SIZE];
408f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    String8 result;
409f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
410e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
411f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    result.append(buffer);
412f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
413f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    result.append(buffer);
414f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
415f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    result.append(buffer);
416f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
417f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    write(fd, result.string(), result.size());
418f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return NO_ERROR;
419e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
420e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
421f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
422f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
423f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
424f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        dumpPermissionDenial(fd);
425f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    } else {
426f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        bool locked = tryLock(mLock);
427e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        if (!locked) {
428e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt            String8 result(kDeadlockedString);
429f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            write(fd, result.string(), result.size());
430f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        }
431f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
432f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        dumpInternals(fd);
433f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        if (mAudioCommandThread != NULL) {
434e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt            mAudioCommandThread->dump(fd);
435f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        }
436f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        if (mTonePlaybackThread != NULL) {
437f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            mTonePlaybackThread->dump(fd);
438f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        }
439e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
440f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        if (mpPolicyManager) {
441f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            mpPolicyManager->dump(fd);
442f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        }
443f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
444f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        if (locked) mLock.unlock();
445f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
446f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return NO_ERROR;
447f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
448f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
449f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::dumpPermissionDenial(int fd)
450f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
451f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    const size_t SIZE = 256;
452f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    char buffer[SIZE];
453f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    String8 result;
454f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    snprintf(buffer, SIZE, "Permission Denial: "
455f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
456f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            IPCThreadState::self()->getCallingPid(),
457f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            IPCThreadState::self()->getCallingUid());
458f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    result.append(buffer);
459f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    write(fd, result.string(), result.size());
460f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return NO_ERROR;
461f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
462f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
463f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::onTransact(
464f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
465f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
466f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return BnAudioPolicyService::onTransact(code, data, reply, flags);
467f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
468f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
469f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
470f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project// ----------------------------------------------------------------------------
471f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid AudioPolicyService::instantiate() {
472f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    defaultServiceManager()->addService(
473f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project            String16("media.audio_policy"), new AudioPolicyService());
474f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
475f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
476f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
477f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project// ----------------------------------------------------------------------------
478f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project// AudioPolicyClientInterface implementation
479f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project// ----------------------------------------------------------------------------
480f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
481f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
482f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectaudio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
483f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t *pSamplingRate,
484f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t *pFormat,
485f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t *pChannels,
486f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t *pLatencyMs,
487f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                AudioSystem::output_flags flags)
488f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
489f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
490f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (af == 0) {
491f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        LOGW("openOutput() could not get AudioFlinger");
492f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return 0;
493e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    }
494e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
495e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return af->openOutput(pDevices,
496f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                          pSamplingRate,
497f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                          (uint32_t *)pFormat,
498f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                          pChannels,
499f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                          pLatencyMs,
500f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                          flags);
501f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
502f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
503f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectaudio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1,
504f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                                          audio_io_handle_t output2)
505f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
506f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
507f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (af == 0) {
508e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt        LOGW("openDuplicateOutput() could not get AudioFlinger");
509f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return 0;
510f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
511f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return af->openDuplicateOutput(output1, output2);
512f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
513f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
514f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::closeOutput(audio_io_handle_t output)
515f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
516f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
517e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    if (af == 0) return PERMISSION_DENIED;
518f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
519e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt    return af->closeOutput(output);
520e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt}
521f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
522e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt
523f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
524f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
525f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
526f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (af == 0) {
527f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        LOGW("suspendOutput() could not get AudioFlinger");
528f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return PERMISSION_DENIED;
529f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
530f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
531a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    return af->suspendOutput(output);
532f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
533f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
534f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
535f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
536f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
537a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    if (af == 0) {
538f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        LOGW("restoreOutput() could not get AudioFlinger");
539f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return PERMISSION_DENIED;
540f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    }
541f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
542f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return af->restoreOutput(output);
543f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
544f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
545f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectaudio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
546938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt                                uint32_t *pSamplingRate,
547938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt                                uint32_t *pFormat,
5480545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt                                uint32_t *pChannels,
549f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                uint32_t acoustics)
550f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
551f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
552f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    if (af == 0) {
553f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        LOGW("openInput() could not get AudioFlinger");
554f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project        return 0;
555938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    }
556f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
557f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
5580545fad98723550607287a86bfee3807c7d26e91Dmitry Shmidt}
559938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt
560a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatus_t AudioPolicyService::closeInput(audio_io_handle_t input)
561a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt{
562a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
563938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    if (af == 0) return PERMISSION_DENIED;
564938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt
565938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    return af->closeInput(input);
566a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt}
567a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
568a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidtstatus_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream,
569f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                             float volume,
570f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                             audio_io_handle_t output,
571f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                             int delayMs)
572f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
573f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
574f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
575a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
576f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectstatus_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream,
577a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt                                             audio_io_handle_t output)
578938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt{
579938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
580a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    if (af == 0) return PERMISSION_DENIED;
581938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt
582938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidt    return af->setStreamOutput(stream, output);
583a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt}
584a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt
585938bc384f44031877543765a9ae18c764f5da9c8Dmitry Shmidtstatus_t AudioPolicyService::moveEffects(int session, audio_io_handle_t srcOutput,
586a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt                                               audio_io_handle_t dstOutput)
587f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project{
588f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
589a3a2260384a906e1674c7498c2f479e9f37bc503Dmitry Shmidt    if (af == 0) return PERMISSION_DENIED;
590f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
591f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project    return af->moveEffects(session, (int)srcOutput, (int)dstOutput);
592f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project}
593f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project
594f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Projectvoid AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
595f7c5421560640d23fc10803b9d59a9ff1d83e467The Android Open Source Project                                       const String8& keyValuePairs,
596                                       int delayMs)
597{
598    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
599}
600
601String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
602{
603    String8 result = AudioSystem::getParameters(ioHandle, keys);
604    return result;
605}
606
607status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone,
608                                       AudioSystem::stream_type stream)
609{
610    mTonePlaybackThread->startToneCommand(tone, stream);
611    return NO_ERROR;
612}
613
614status_t AudioPolicyService::stopTone()
615{
616    mTonePlaybackThread->stopToneCommand();
617    return NO_ERROR;
618}
619
620status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
621{
622    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
623}
624
625// -----------  AudioPolicyService::AudioCommandThread implementation ----------
626
627AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
628    : Thread(false), mName(name)
629{
630    mpToneGenerator = NULL;
631}
632
633
634AudioPolicyService::AudioCommandThread::~AudioCommandThread()
635{
636    if (mName != "" && !mAudioCommands.isEmpty()) {
637        release_wake_lock(mName.string());
638    }
639    mAudioCommands.clear();
640    if (mpToneGenerator != NULL) delete mpToneGenerator;
641}
642
643void AudioPolicyService::AudioCommandThread::onFirstRef()
644{
645    if (mName != "") {
646        run(mName.string(), ANDROID_PRIORITY_AUDIO);
647    } else {
648        run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
649    }
650}
651
652bool AudioPolicyService::AudioCommandThread::threadLoop()
653{
654    nsecs_t waitTime = INT64_MAX;
655
656    mLock.lock();
657    while (!exitPending())
658    {
659        while(!mAudioCommands.isEmpty()) {
660            nsecs_t curTime = systemTime();
661            // commands are sorted by increasing time stamp: execute them from index 0 and up
662            if (mAudioCommands[0]->mTime <= curTime) {
663                AudioCommand *command = mAudioCommands[0];
664                mAudioCommands.removeAt(0);
665                mLastCommand = *command;
666
667                switch (command->mCommand) {
668                case START_TONE: {
669                    mLock.unlock();
670                    ToneData *data = (ToneData *)command->mParam;
671                    LOGV("AudioCommandThread() processing start tone %d on stream %d",
672                            data->mType, data->mStream);
673                    if (mpToneGenerator != NULL)
674                        delete mpToneGenerator;
675                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
676                    mpToneGenerator->startTone(data->mType);
677                    delete data;
678                    mLock.lock();
679                    }break;
680                case STOP_TONE: {
681                    mLock.unlock();
682                    LOGV("AudioCommandThread() processing stop tone");
683                    if (mpToneGenerator != NULL) {
684                        mpToneGenerator->stopTone();
685                        delete mpToneGenerator;
686                        mpToneGenerator = NULL;
687                    }
688                    mLock.lock();
689                    }break;
690                case SET_VOLUME: {
691                    VolumeData *data = (VolumeData *)command->mParam;
692                    LOGV("AudioCommandThread() processing set volume stream %d, \
693                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
694                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
695                                                                    data->mVolume,
696                                                                    data->mIO);
697                    if (command->mWaitStatus) {
698                        command->mCond.signal();
699                        mWaitWorkCV.wait(mLock);
700                    }
701                    delete data;
702                    }break;
703                case SET_PARAMETERS: {
704                     ParametersData *data = (ParametersData *)command->mParam;
705                     LOGV("AudioCommandThread() processing set parameters string %s, io %d",
706                             data->mKeyValuePairs.string(), data->mIO);
707                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
708                     if (command->mWaitStatus) {
709                         command->mCond.signal();
710                         mWaitWorkCV.wait(mLock);
711                     }
712                     delete data;
713                     }break;
714                case SET_VOICE_VOLUME: {
715                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
716                    LOGV("AudioCommandThread() processing set voice volume volume %f",
717                            data->mVolume);
718                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
719                    if (command->mWaitStatus) {
720                        command->mCond.signal();
721                        mWaitWorkCV.wait(mLock);
722                    }
723                    delete data;
724                    }break;
725                default:
726                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
727                }
728                delete command;
729                waitTime = INT64_MAX;
730            } else {
731                waitTime = mAudioCommands[0]->mTime - curTime;
732                break;
733            }
734        }
735        // release delayed commands wake lock
736        if (mName != "" && mAudioCommands.isEmpty()) {
737            release_wake_lock(mName.string());
738        }
739        LOGV("AudioCommandThread() going to sleep");
740        mWaitWorkCV.waitRelative(mLock, waitTime);
741        LOGV("AudioCommandThread() waking up");
742    }
743    mLock.unlock();
744    return false;
745}
746
747status_t AudioPolicyService::AudioCommandThread::dump(int fd)
748{
749    const size_t SIZE = 256;
750    char buffer[SIZE];
751    String8 result;
752
753    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
754    result.append(buffer);
755    write(fd, result.string(), result.size());
756
757    bool locked = tryLock(mLock);
758    if (!locked) {
759        String8 result2(kCmdDeadlockedString);
760        write(fd, result2.string(), result2.size());
761    }
762
763    snprintf(buffer, SIZE, "- Commands:\n");
764    result = String8(buffer);
765    result.append("   Command Time        Wait pParam\n");
766    for (int i = 0; i < (int)mAudioCommands.size(); i++) {
767        mAudioCommands[i]->dump(buffer, SIZE);
768        result.append(buffer);
769    }
770    result.append("  Last Command\n");
771    mLastCommand.dump(buffer, SIZE);
772    result.append(buffer);
773
774    write(fd, result.string(), result.size());
775
776    if (locked) mLock.unlock();
777
778    return NO_ERROR;
779}
780
781void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
782{
783    AudioCommand *command = new AudioCommand();
784    command->mCommand = START_TONE;
785    ToneData *data = new ToneData();
786    data->mType = type;
787    data->mStream = stream;
788    command->mParam = (void *)data;
789    command->mWaitStatus = false;
790    Mutex::Autolock _l(mLock);
791    insertCommand_l(command);
792    LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
793    mWaitWorkCV.signal();
794}
795
796void AudioPolicyService::AudioCommandThread::stopToneCommand()
797{
798    AudioCommand *command = new AudioCommand();
799    command->mCommand = STOP_TONE;
800    command->mParam = NULL;
801    command->mWaitStatus = false;
802    Mutex::Autolock _l(mLock);
803    insertCommand_l(command);
804    LOGV("AudioCommandThread() adding tone stop");
805    mWaitWorkCV.signal();
806}
807
808status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
809                                                               float volume,
810                                                               int output,
811                                                               int delayMs)
812{
813    status_t status = NO_ERROR;
814
815    AudioCommand *command = new AudioCommand();
816    command->mCommand = SET_VOLUME;
817    VolumeData *data = new VolumeData();
818    data->mStream = stream;
819    data->mVolume = volume;
820    data->mIO = output;
821    command->mParam = data;
822    if (delayMs == 0) {
823        command->mWaitStatus = true;
824    } else {
825        command->mWaitStatus = false;
826    }
827    Mutex::Autolock _l(mLock);
828    insertCommand_l(command, delayMs);
829    LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
830            stream, volume, output);
831    mWaitWorkCV.signal();
832    if (command->mWaitStatus) {
833        command->mCond.wait(mLock);
834        status =  command->mStatus;
835        mWaitWorkCV.signal();
836    }
837    return status;
838}
839
840status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
841                                                                   const String8& keyValuePairs,
842                                                                   int delayMs)
843{
844    status_t status = NO_ERROR;
845
846    AudioCommand *command = new AudioCommand();
847    command->mCommand = SET_PARAMETERS;
848    ParametersData *data = new ParametersData();
849    data->mIO = ioHandle;
850    data->mKeyValuePairs = keyValuePairs;
851    command->mParam = data;
852    if (delayMs == 0) {
853        command->mWaitStatus = true;
854    } else {
855        command->mWaitStatus = false;
856    }
857    Mutex::Autolock _l(mLock);
858    insertCommand_l(command, delayMs);
859    LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
860            keyValuePairs.string(), ioHandle, delayMs);
861    mWaitWorkCV.signal();
862    if (command->mWaitStatus) {
863        command->mCond.wait(mLock);
864        status =  command->mStatus;
865        mWaitWorkCV.signal();
866    }
867    return status;
868}
869
870status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
871{
872    status_t status = NO_ERROR;
873
874    AudioCommand *command = new AudioCommand();
875    command->mCommand = SET_VOICE_VOLUME;
876    VoiceVolumeData *data = new VoiceVolumeData();
877    data->mVolume = volume;
878    command->mParam = data;
879    if (delayMs == 0) {
880        command->mWaitStatus = true;
881    } else {
882        command->mWaitStatus = false;
883    }
884    Mutex::Autolock _l(mLock);
885    insertCommand_l(command, delayMs);
886    LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
887    mWaitWorkCV.signal();
888    if (command->mWaitStatus) {
889        command->mCond.wait(mLock);
890        status =  command->mStatus;
891        mWaitWorkCV.signal();
892    }
893    return status;
894}
895
896// insertCommand_l() must be called with mLock held
897void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
898{
899    ssize_t i;
900    Vector <AudioCommand *> removedCommands;
901
902    command->mTime = systemTime() + milliseconds(delayMs);
903
904    // acquire wake lock to make sure delayed commands are processed
905    if (mName != "" && mAudioCommands.isEmpty()) {
906        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
907    }
908
909    // check same pending commands with later time stamps and eliminate them
910    for (i = mAudioCommands.size()-1; i >= 0; i--) {
911        AudioCommand *command2 = mAudioCommands[i];
912        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
913        if (command2->mTime <= command->mTime) break;
914        if (command2->mCommand != command->mCommand) continue;
915
916        switch (command->mCommand) {
917        case SET_PARAMETERS: {
918            ParametersData *data = (ParametersData *)command->mParam;
919            ParametersData *data2 = (ParametersData *)command2->mParam;
920            if (data->mIO != data2->mIO) break;
921            LOGV("Comparing parameter command %s to new command %s",
922                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
923            AudioParameter param = AudioParameter(data->mKeyValuePairs);
924            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
925            for (size_t j = 0; j < param.size(); j++) {
926               String8 key;
927               String8 value;
928               param.getAt(j, key, value);
929               for (size_t k = 0; k < param2.size(); k++) {
930                  String8 key2;
931                  String8 value2;
932                  param2.getAt(k, key2, value2);
933                  if (key2 == key) {
934                      param2.remove(key2);
935                      LOGV("Filtering out parameter %s", key2.string());
936                      break;
937                  }
938               }
939            }
940            // if all keys have been filtered out, remove the command.
941            // otherwise, update the key value pairs
942            if (param2.size() == 0) {
943                removedCommands.add(command2);
944            } else {
945                data2->mKeyValuePairs = param2.toString();
946            }
947        } break;
948
949        case SET_VOLUME: {
950            VolumeData *data = (VolumeData *)command->mParam;
951            VolumeData *data2 = (VolumeData *)command2->mParam;
952            if (data->mIO != data2->mIO) break;
953            if (data->mStream != data2->mStream) break;
954            LOGV("Filtering out volume command on output %d for stream %d",
955                    data->mIO, data->mStream);
956            removedCommands.add(command2);
957        } break;
958        case START_TONE:
959        case STOP_TONE:
960        default:
961            break;
962        }
963    }
964
965    // remove filtered commands
966    for (size_t j = 0; j < removedCommands.size(); j++) {
967        // removed commands always have time stamps greater than current command
968        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
969            if (mAudioCommands[k] == removedCommands[j]) {
970                LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
971                mAudioCommands.removeAt(k);
972                break;
973            }
974        }
975    }
976    removedCommands.clear();
977
978    // insert command at the right place according to its time stamp
979    LOGV("inserting command: %d at index %d, num commands %d",
980            command->mCommand, (int)i+1, mAudioCommands.size());
981    mAudioCommands.insertAt(command, i + 1);
982}
983
984void AudioPolicyService::AudioCommandThread::exit()
985{
986    LOGV("AudioCommandThread::exit");
987    {
988        AutoMutex _l(mLock);
989        requestExit();
990        mWaitWorkCV.signal();
991    }
992    requestExitAndWait();
993}
994
995void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
996{
997    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
998            mCommand,
999            (int)ns2s(mTime),
1000            (int)ns2ms(mTime)%1000,
1001            mWaitStatus,
1002            mParam);
1003}
1004
1005}; // namespace android
1006