AudioPolicyService.cpp revision ba2b43990a7b4f0f2c425cf6cdfc63376a45772c
127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/* 227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Copyright (C) 2009 The Android Open Source Project 327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * 427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Licensed under the Apache License, Version 2.0 (the "License"); 527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * you may not use this file except in compliance with the License. 627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * You may obtain a copy of the License at 727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * 827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * http://www.apache.org/licenses/LICENSE-2.0 927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * 1027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Unless required by applicable law or agreed to in writing, software 1127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * distributed under the License is distributed on an "AS IS" BASIS, 1227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * See the License for the specific language governing permissions and 1427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * limitations under the License. 1527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi */ 1627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 1727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#define LOG_TAG "AudioPolicyService" 1827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi//#define LOG_NDEBUG 0 1927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 2027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "Configuration.h" 2127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#undef __STRICT_ANSI__ 2227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#define __STDINT_LIMITS 2327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#define __STDC_LIMIT_MACROS 2427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <stdint.h> 2527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 2627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <sys/time.h> 2727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <binder/IServiceManager.h> 2827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/Log.h> 2927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <cutils/properties.h> 3027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <binder/IPCThreadState.h> 3127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/String16.h> 3227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/threads.h> 3327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include "AudioPolicyService.h" 343473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi#include "ServiceUtilities.h" 353473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi#include <hardware_legacy/power.h> 363473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi#include <media/AudioEffect.h> 373473846f64f5b28e1cbeb70ef5867073fc93159eTakeshi Aimi#include <media/EffectsFactoryApi.h> 3827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 3927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <hardware/hardware.h> 4027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <system/audio.h> 4127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <system/audio_policy.h> 4227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <hardware/audio_policy.h> 4327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 4427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshinamespace android { 4527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 4627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n"; 4727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n"; 4827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 4927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const int kDumpLockRetries = 50; 5027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const int kDumpLockSleepUs = 20000; 5127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 5227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshistatic const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds 5327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 5427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshinamespace { 5527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi extern struct audio_policy_service_ops aps_ops; 5627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi}; 5727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 5827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi// ---------------------------------------------------------------------------- 592272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi 6027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiAudioPolicyService::AudioPolicyService() 6127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL), 6227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioPolicyManager(NULL), mAudioPolicyClient(NULL) 6327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{ 6427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi char value[PROPERTY_VALUE_MAX]; 6527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi const struct hw_module_t *module; 6627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi int forced_val; 6727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi int rc; 6827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 6927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi Mutex::Autolock _l(mLock); 7027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 7127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi // start tone playback thread 7227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this); 7327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi // start audio commands thread 7427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this); 7527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi // start output activity command thread 7627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this); 7727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 7827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#ifdef USE_LEGACY_AUDIO_POLICY 7927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi ALOGI("AudioPolicyService CSTOR in legacy mode"); 8027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 812272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi /* instantiate the audio policy manager */ 8227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module); 832272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi if (rc) { 8427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi return; 8527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi } 862272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi rc = audio_policy_dev_open(module, &mpAudioPolicyDev); 87a2cd44cb5067b4fe98794860690394254d3ac73cGloria Wang ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc)); 882272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi if (rc) { 8927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi return; 9027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi } 9127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 9227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this, 9327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi &mpAudioPolicy); 9427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc)); 9527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi if (rc) { 9627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi return; 972272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi } 982272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi 9927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi rc = mpAudioPolicy->init_check(mpAudioPolicy); 10027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc)); 1012272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi if (rc) { 1022272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi return; 10327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi } 10427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi ALOGI("Loaded audio policy from %s (%s)", module->name, module->id); 1052272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi#else 1062272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi ALOGI("AudioPolicyService CSTOR in new mode"); 10727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 10827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioPolicyClient = new AudioPolicyClient(this); 10927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient); 11027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#endif 11127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 11227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi // load audio processing modules 11327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioPolicyEffects = new AudioPolicyEffects(); 11427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi} 11527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 11627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiAudioPolicyService::~AudioPolicyService() 11727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{ 11827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mTonePlaybackThread->exit(); 11927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mAudioCommandThread->exit(); 12027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mOutputCommandThread->exit(); 12127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 12227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#ifdef USE_LEGACY_AUDIO_POLICY 1239d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) { 1249d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy); 1259d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong } 1269d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong if (mpAudioPolicyDev != NULL) { 1279d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong audio_policy_dev_close(mpAudioPolicyDev); 1289d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong } 1299d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong#else 1309d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong destroyAudioPolicyManager(mAudioPolicyManager); 13127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi delete mAudioPolicyClient; 13227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#endif 133e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi 1349d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong mNotificationClients.clear(); 1359d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong mAudioPolicyEffects.clear(); 1369d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong} 1379d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong 1389d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong// A notification client is always registered by AudioSystem when the client process 1399d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong// connects to AudioPolicyService. 140e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimivoid AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client) 141e943f84129326ab885cc7a69dcfa17f766b72b89Takeshi Aimi{ 142cba7b32d8f2c47632313f54118ed3733b4b02cc8Kei Takahashi 143cba7b32d8f2c47632313f54118ed3733b4b02cc8Kei Takahashi Mutex::Autolock _l(mLock); 144cba7b32d8f2c47632313f54118ed3733b4b02cc8Kei Takahashi 145cba7b32d8f2c47632313f54118ed3733b4b02cc8Kei Takahashi uid_t uid = IPCThreadState::self()->getCallingUid(); 146cba7b32d8f2c47632313f54118ed3733b4b02cc8Kei Takahashi if (mNotificationClients.indexOfKey(uid) < 0) { 1472272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi sp<NotificationClient> notificationClient = new NotificationClient(this, 1482272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi client, 14927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi uid); 15027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi ALOGV("registerClient() client %p, uid %d", client.get(), uid); 1512272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi 15227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi mNotificationClients.add(uid, notificationClient); 1532272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi 15427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi sp<IBinder> binder = client->asBinder(); 15527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi binder->linkToDeath(notificationClient); 15627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi } 15727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi} 1582272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi 1592272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi// removeNotificationClient() is called when the client process dies. 16027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshivoid AudioPolicyService::removeNotificationClient(uid_t uid) 16127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi{ 1622272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi Mutex::Autolock _l(mLock); 16327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 1642272ee27d9022d173b6eab45c409b3c3f57f30ecTakeshi Aimi mNotificationClients.removeItem(uid); 16527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi 16627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#ifndef USE_LEGACY_AUDIO_POLICY 16727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi if (mAudioPolicyManager) { 168a2cd44cb5067b4fe98794860690394254d3ac73cGloria Wang mAudioPolicyManager->clearAudioPatches(uid); 16927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi } 17027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#endif 17127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi} 172 173void AudioPolicyService::onAudioPortListUpdate() 174{ 175 mOutputCommandThread->updateAudioPortListCommand(); 176} 177 178void AudioPolicyService::doOnAudioPortListUpdate() 179{ 180 Mutex::Autolock _l(mLock); 181 for (size_t i = 0; i < mNotificationClients.size(); i++) { 182 mNotificationClients.valueAt(i)->onAudioPortListUpdate(); 183 } 184} 185 186void AudioPolicyService::onAudioPatchListUpdate() 187{ 188 mOutputCommandThread->updateAudioPatchListCommand(); 189} 190 191status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch, 192 audio_patch_handle_t *handle, 193 int delayMs) 194{ 195 return mAudioCommandThread->createAudioPatchCommand(patch, handle, delayMs); 196} 197 198status_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle, 199 int delayMs) 200{ 201 return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs); 202} 203 204void AudioPolicyService::doOnAudioPatchListUpdate() 205{ 206 Mutex::Autolock _l(mLock); 207 for (size_t i = 0; i < mNotificationClients.size(); i++) { 208 mNotificationClients.valueAt(i)->onAudioPatchListUpdate(); 209 } 210} 211 212status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config, 213 int delayMs) 214{ 215 return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs); 216} 217 218AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service, 219 const sp<IAudioPolicyServiceClient>& client, 220 uid_t uid) 221 : mService(service), mUid(uid), mAudioPolicyServiceClient(client) 222{ 223} 224 225AudioPolicyService::NotificationClient::~NotificationClient() 226{ 227} 228 229void AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused) 230{ 231 sp<NotificationClient> keep(this); 232 sp<AudioPolicyService> service = mService.promote(); 233 if (service != 0) { 234 service->removeNotificationClient(mUid); 235 } 236} 237 238void AudioPolicyService::NotificationClient::onAudioPortListUpdate() 239{ 240 if (mAudioPolicyServiceClient != 0) { 241 mAudioPolicyServiceClient->onAudioPortListUpdate(); 242 } 243} 244 245void AudioPolicyService::NotificationClient::onAudioPatchListUpdate() 246{ 247 if (mAudioPolicyServiceClient != 0) { 248 mAudioPolicyServiceClient->onAudioPatchListUpdate(); 249 } 250} 251 252void AudioPolicyService::binderDied(const wp<IBinder>& who) { 253 ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(), 254 IPCThreadState::self()->getCallingPid()); 255} 256 257static bool tryLock(Mutex& mutex) 258{ 259 bool locked = false; 260 for (int i = 0; i < kDumpLockRetries; ++i) { 261 if (mutex.tryLock() == NO_ERROR) { 262 locked = true; 263 break; 264 } 265 usleep(kDumpLockSleepUs); 266 } 267 return locked; 268} 269 270status_t AudioPolicyService::dumpInternals(int fd) 271{ 272 const size_t SIZE = 256; 273 char buffer[SIZE]; 274 String8 result; 275 276#ifdef USE_LEGACY_AUDIO_POLICY 277 snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy); 278#else 279 snprintf(buffer, SIZE, "AudioPolicyManager: %p\n", mAudioPolicyManager); 280#endif 281 result.append(buffer); 282 snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get()); 283 result.append(buffer); 284 snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get()); 285 result.append(buffer); 286 287 write(fd, result.string(), result.size()); 288 return NO_ERROR; 289} 290 291status_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused) 292{ 293 if (!dumpAllowed()) { 294 dumpPermissionDenial(fd); 295 } else { 296 bool locked = tryLock(mLock); 297 if (!locked) { 298 String8 result(kDeadlockedString); 299 write(fd, result.string(), result.size()); 300 } 301 302 dumpInternals(fd); 303 if (mAudioCommandThread != 0) { 304 mAudioCommandThread->dump(fd); 305 } 306 if (mTonePlaybackThread != 0) { 307 mTonePlaybackThread->dump(fd); 308 } 309 310#ifdef USE_LEGACY_AUDIO_POLICY 311 if (mpAudioPolicy) { 312 mpAudioPolicy->dump(mpAudioPolicy, fd); 313 } 314#else 315 if (mAudioPolicyManager) { 316 mAudioPolicyManager->dump(fd); 317 } 318#endif 319 320 if (locked) mLock.unlock(); 321 } 322 return NO_ERROR; 323} 324 325status_t AudioPolicyService::dumpPermissionDenial(int fd) 326{ 327 const size_t SIZE = 256; 328 char buffer[SIZE]; 329 String8 result; 330 snprintf(buffer, SIZE, "Permission Denial: " 331 "can't dump AudioPolicyService from pid=%d, uid=%d\n", 332 IPCThreadState::self()->getCallingPid(), 333 IPCThreadState::self()->getCallingUid()); 334 result.append(buffer); 335 write(fd, result.string(), result.size()); 336 return NO_ERROR; 337} 338 339status_t AudioPolicyService::onTransact( 340 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 341{ 342 return BnAudioPolicyService::onTransact(code, data, reply, flags); 343} 344 345 346// ----------- AudioPolicyService::AudioCommandThread implementation ---------- 347 348AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name, 349 const wp<AudioPolicyService>& service) 350 : Thread(false), mName(name), mService(service) 351{ 352 mpToneGenerator = NULL; 353} 354 355 356AudioPolicyService::AudioCommandThread::~AudioCommandThread() 357{ 358 if (!mAudioCommands.isEmpty()) { 359 release_wake_lock(mName.string()); 360 } 361 mAudioCommands.clear(); 362 delete mpToneGenerator; 363} 364 365void AudioPolicyService::AudioCommandThread::onFirstRef() 366{ 367 run(mName.string(), ANDROID_PRIORITY_AUDIO); 368} 369 370bool AudioPolicyService::AudioCommandThread::threadLoop() 371{ 372 nsecs_t waitTime = INT64_MAX; 373 374 mLock.lock(); 375 while (!exitPending()) 376 { 377 sp<AudioPolicyService> svc; 378 while (!mAudioCommands.isEmpty() && !exitPending()) { 379 nsecs_t curTime = systemTime(); 380 // commands are sorted by increasing time stamp: execute them from index 0 and up 381 if (mAudioCommands[0]->mTime <= curTime) { 382 sp<AudioCommand> command = mAudioCommands[0]; 383 mAudioCommands.removeAt(0); 384 mLastCommand = command; 385 386 switch (command->mCommand) { 387 case START_TONE: { 388 mLock.unlock(); 389 ToneData *data = (ToneData *)command->mParam.get(); 390 ALOGV("AudioCommandThread() processing start tone %d on stream %d", 391 data->mType, data->mStream); 392 delete mpToneGenerator; 393 mpToneGenerator = new ToneGenerator(data->mStream, 1.0); 394 mpToneGenerator->startTone(data->mType); 395 mLock.lock(); 396 }break; 397 case STOP_TONE: { 398 mLock.unlock(); 399 ALOGV("AudioCommandThread() processing stop tone"); 400 if (mpToneGenerator != NULL) { 401 mpToneGenerator->stopTone(); 402 delete mpToneGenerator; 403 mpToneGenerator = NULL; 404 } 405 mLock.lock(); 406 }break; 407 case SET_VOLUME: { 408 VolumeData *data = (VolumeData *)command->mParam.get(); 409 ALOGV("AudioCommandThread() processing set volume stream %d, \ 410 volume %f, output %d", data->mStream, data->mVolume, data->mIO); 411 command->mStatus = AudioSystem::setStreamVolume(data->mStream, 412 data->mVolume, 413 data->mIO); 414 }break; 415 case SET_PARAMETERS: { 416 ParametersData *data = (ParametersData *)command->mParam.get(); 417 ALOGV("AudioCommandThread() processing set parameters string %s, io %d", 418 data->mKeyValuePairs.string(), data->mIO); 419 command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs); 420 }break; 421 case SET_VOICE_VOLUME: { 422 VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get(); 423 ALOGV("AudioCommandThread() processing set voice volume volume %f", 424 data->mVolume); 425 command->mStatus = AudioSystem::setVoiceVolume(data->mVolume); 426 }break; 427 case STOP_OUTPUT: { 428 StopOutputData *data = (StopOutputData *)command->mParam.get(); 429 ALOGV("AudioCommandThread() processing stop output %d", 430 data->mIO); 431 svc = mService.promote(); 432 if (svc == 0) { 433 break; 434 } 435 mLock.unlock(); 436 svc->doStopOutput(data->mIO, data->mStream, data->mSession); 437 mLock.lock(); 438 }break; 439 case RELEASE_OUTPUT: { 440 ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get(); 441 ALOGV("AudioCommandThread() processing release output %d", 442 data->mIO); 443 svc = mService.promote(); 444 if (svc == 0) { 445 break; 446 } 447 mLock.unlock(); 448 svc->doReleaseOutput(data->mIO); 449 mLock.lock(); 450 }break; 451 case CREATE_AUDIO_PATCH: { 452 CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get(); 453 ALOGV("AudioCommandThread() processing create audio patch"); 454 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 455 if (af == 0) { 456 command->mStatus = PERMISSION_DENIED; 457 } else { 458 command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle); 459 } 460 } break; 461 case RELEASE_AUDIO_PATCH: { 462 ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mParam.get(); 463 ALOGV("AudioCommandThread() processing release audio patch"); 464 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 465 if (af == 0) { 466 command->mStatus = PERMISSION_DENIED; 467 } else { 468 command->mStatus = af->releaseAudioPatch(data->mHandle); 469 } 470 } break; 471 case UPDATE_AUDIOPORT_LIST: { 472 ALOGV("AudioCommandThread() processing update audio port list"); 473 svc = mService.promote(); 474 if (svc == 0) { 475 break; 476 } 477 mLock.unlock(); 478 svc->doOnAudioPortListUpdate(); 479 mLock.lock(); 480 }break; 481 case UPDATE_AUDIOPATCH_LIST: { 482 ALOGV("AudioCommandThread() processing update audio patch list"); 483 svc = mService.promote(); 484 if (svc == 0) { 485 break; 486 } 487 mLock.unlock(); 488 svc->doOnAudioPatchListUpdate(); 489 mLock.lock(); 490 }break; 491 case SET_AUDIOPORT_CONFIG: { 492 SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get(); 493 ALOGV("AudioCommandThread() processing set port config"); 494 sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); 495 if (af == 0) { 496 command->mStatus = PERMISSION_DENIED; 497 } else { 498 command->mStatus = af->setAudioPortConfig(&data->mConfig); 499 } 500 } break; 501 default: 502 ALOGW("AudioCommandThread() unknown command %d", command->mCommand); 503 } 504 { 505 Mutex::Autolock _l(command->mLock); 506 if (command->mWaitStatus) { 507 command->mWaitStatus = false; 508 command->mCond.signal(); 509 } 510 } 511 waitTime = INT64_MAX; 512 } else { 513 waitTime = mAudioCommands[0]->mTime - curTime; 514 break; 515 } 516 } 517 // release delayed commands wake lock 518 if (mAudioCommands.isEmpty()) { 519 release_wake_lock(mName.string()); 520 } 521 // release mLock before releasing strong reference on the service as 522 // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock. 523 mLock.unlock(); 524 svc.clear(); 525 mLock.lock(); 526 if (!exitPending()) { 527 ALOGV("AudioCommandThread() going to sleep"); 528 mWaitWorkCV.waitRelative(mLock, waitTime); 529 ALOGV("AudioCommandThread() waking up"); 530 } 531 } 532 mLock.unlock(); 533 return false; 534} 535 536status_t AudioPolicyService::AudioCommandThread::dump(int fd) 537{ 538 const size_t SIZE = 256; 539 char buffer[SIZE]; 540 String8 result; 541 542 snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this); 543 result.append(buffer); 544 write(fd, result.string(), result.size()); 545 546 bool locked = tryLock(mLock); 547 if (!locked) { 548 String8 result2(kCmdDeadlockedString); 549 write(fd, result2.string(), result2.size()); 550 } 551 552 snprintf(buffer, SIZE, "- Commands:\n"); 553 result = String8(buffer); 554 result.append(" Command Time Wait pParam\n"); 555 for (size_t i = 0; i < mAudioCommands.size(); i++) { 556 mAudioCommands[i]->dump(buffer, SIZE); 557 result.append(buffer); 558 } 559 result.append(" Last Command\n"); 560 if (mLastCommand != 0) { 561 mLastCommand->dump(buffer, SIZE); 562 result.append(buffer); 563 } else { 564 result.append(" none\n"); 565 } 566 567 write(fd, result.string(), result.size()); 568 569 if (locked) mLock.unlock(); 570 571 return NO_ERROR; 572} 573 574void AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type, 575 audio_stream_type_t stream) 576{ 577 sp<AudioCommand> command = new AudioCommand(); 578 command->mCommand = START_TONE; 579 sp<ToneData> data = new ToneData(); 580 data->mType = type; 581 data->mStream = stream; 582 command->mParam = data; 583 ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream); 584 sendCommand(command); 585} 586 587void AudioPolicyService::AudioCommandThread::stopToneCommand() 588{ 589 sp<AudioCommand> command = new AudioCommand(); 590 command->mCommand = STOP_TONE; 591 ALOGV("AudioCommandThread() adding tone stop"); 592 sendCommand(command); 593} 594 595status_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream, 596 float volume, 597 audio_io_handle_t output, 598 int delayMs) 599{ 600 sp<AudioCommand> command = new AudioCommand(); 601 command->mCommand = SET_VOLUME; 602 sp<VolumeData> data = new VolumeData(); 603 data->mStream = stream; 604 data->mVolume = volume; 605 data->mIO = output; 606 command->mParam = data; 607 command->mWaitStatus = true; 608 ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d", 609 stream, volume, output); 610 return sendCommand(command, delayMs); 611} 612 613status_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle, 614 const char *keyValuePairs, 615 int delayMs) 616{ 617 sp<AudioCommand> command = new AudioCommand(); 618 command->mCommand = SET_PARAMETERS; 619 sp<ParametersData> data = new ParametersData(); 620 data->mIO = ioHandle; 621 data->mKeyValuePairs = String8(keyValuePairs); 622 command->mParam = data; 623 command->mWaitStatus = true; 624 ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d", 625 keyValuePairs, ioHandle, delayMs); 626 return sendCommand(command, delayMs); 627} 628 629status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs) 630{ 631 sp<AudioCommand> command = new AudioCommand(); 632 command->mCommand = SET_VOICE_VOLUME; 633 sp<VoiceVolumeData> data = new VoiceVolumeData(); 634 data->mVolume = volume; 635 command->mParam = data; 636 command->mWaitStatus = true; 637 ALOGV("AudioCommandThread() adding set voice volume volume %f", volume); 638 return sendCommand(command, delayMs); 639} 640 641void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output, 642 audio_stream_type_t stream, 643 int session) 644{ 645 sp<AudioCommand> command = new AudioCommand(); 646 command->mCommand = STOP_OUTPUT; 647 sp<StopOutputData> data = new StopOutputData(); 648 data->mIO = output; 649 data->mStream = stream; 650 data->mSession = session; 651 command->mParam = data; 652 ALOGV("AudioCommandThread() adding stop output %d", output); 653 sendCommand(command); 654} 655 656void AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output) 657{ 658 sp<AudioCommand> command = new AudioCommand(); 659 command->mCommand = RELEASE_OUTPUT; 660 sp<ReleaseOutputData> data = new ReleaseOutputData(); 661 data->mIO = output; 662 command->mParam = data; 663 ALOGV("AudioCommandThread() adding release output %d", output); 664 sendCommand(command); 665} 666 667status_t AudioPolicyService::AudioCommandThread::createAudioPatchCommand( 668 const struct audio_patch *patch, 669 audio_patch_handle_t *handle, 670 int delayMs) 671{ 672 status_t status = NO_ERROR; 673 674 sp<AudioCommand> command = new AudioCommand(); 675 command->mCommand = CREATE_AUDIO_PATCH; 676 CreateAudioPatchData *data = new CreateAudioPatchData(); 677 data->mPatch = *patch; 678 data->mHandle = *handle; 679 command->mParam = data; 680 command->mWaitStatus = true; 681 ALOGV("AudioCommandThread() adding create patch delay %d", delayMs); 682 status = sendCommand(command, delayMs); 683 if (status == NO_ERROR) { 684 *handle = data->mHandle; 685 } 686 return status; 687} 688 689status_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle, 690 int delayMs) 691{ 692 sp<AudioCommand> command = new AudioCommand(); 693 command->mCommand = RELEASE_AUDIO_PATCH; 694 ReleaseAudioPatchData *data = new ReleaseAudioPatchData(); 695 data->mHandle = handle; 696 command->mParam = data; 697 command->mWaitStatus = true; 698 ALOGV("AudioCommandThread() adding release patch delay %d", delayMs); 699 return sendCommand(command, delayMs); 700} 701 702void AudioPolicyService::AudioCommandThread::updateAudioPortListCommand() 703{ 704 sp<AudioCommand> command = new AudioCommand(); 705 command->mCommand = UPDATE_AUDIOPORT_LIST; 706 ALOGV("AudioCommandThread() adding update audio port list"); 707 sendCommand(command); 708} 709 710void AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand() 711{ 712 sp<AudioCommand>command = new AudioCommand(); 713 command->mCommand = UPDATE_AUDIOPATCH_LIST; 714 ALOGV("AudioCommandThread() adding update audio patch list"); 715 sendCommand(command); 716} 717 718status_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand( 719 const struct audio_port_config *config, int delayMs) 720{ 721 sp<AudioCommand> command = new AudioCommand(); 722 command->mCommand = SET_AUDIOPORT_CONFIG; 723 SetAudioPortConfigData *data = new SetAudioPortConfigData(); 724 data->mConfig = *config; 725 command->mParam = data; 726 command->mWaitStatus = true; 727 ALOGV("AudioCommandThread() adding set port config delay %d", delayMs); 728 return sendCommand(command, delayMs); 729} 730 731status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs) 732{ 733 { 734 Mutex::Autolock _l(mLock); 735 insertCommand_l(command, delayMs); 736 mWaitWorkCV.signal(); 737 } 738 Mutex::Autolock _l(command->mLock); 739 while (command->mWaitStatus) { 740 nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs); 741 if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) { 742 command->mStatus = TIMED_OUT; 743 command->mWaitStatus = false; 744 } 745 } 746 return command->mStatus; 747} 748 749// insertCommand_l() must be called with mLock held 750void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs) 751{ 752 ssize_t i; // not size_t because i will count down to -1 753 Vector < sp<AudioCommand> > removedCommands; 754 command->mTime = systemTime() + milliseconds(delayMs); 755 756 // acquire wake lock to make sure delayed commands are processed 757 if (mAudioCommands.isEmpty()) { 758 acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string()); 759 } 760 761 // check same pending commands with later time stamps and eliminate them 762 for (i = mAudioCommands.size()-1; i >= 0; i--) { 763 sp<AudioCommand> command2 = mAudioCommands[i]; 764 // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands 765 if (command2->mTime <= command->mTime) break; 766 if (command2->mCommand != command->mCommand) continue; 767 768 switch (command->mCommand) { 769 case SET_PARAMETERS: { 770 ParametersData *data = (ParametersData *)command->mParam.get(); 771 ParametersData *data2 = (ParametersData *)command2->mParam.get(); 772 if (data->mIO != data2->mIO) break; 773 ALOGV("Comparing parameter command %s to new command %s", 774 data2->mKeyValuePairs.string(), data->mKeyValuePairs.string()); 775 AudioParameter param = AudioParameter(data->mKeyValuePairs); 776 AudioParameter param2 = AudioParameter(data2->mKeyValuePairs); 777 for (size_t j = 0; j < param.size(); j++) { 778 String8 key; 779 String8 value; 780 param.getAt(j, key, value); 781 for (size_t k = 0; k < param2.size(); k++) { 782 String8 key2; 783 String8 value2; 784 param2.getAt(k, key2, value2); 785 if (key2 == key) { 786 param2.remove(key2); 787 ALOGV("Filtering out parameter %s", key2.string()); 788 break; 789 } 790 } 791 } 792 // if all keys have been filtered out, remove the command. 793 // otherwise, update the key value pairs 794 if (param2.size() == 0) { 795 removedCommands.add(command2); 796 } else { 797 data2->mKeyValuePairs = param2.toString(); 798 } 799 command->mTime = command2->mTime; 800 // force delayMs to non 0 so that code below does not request to wait for 801 // command status as the command is now delayed 802 delayMs = 1; 803 } break; 804 805 case SET_VOLUME: { 806 VolumeData *data = (VolumeData *)command->mParam.get(); 807 VolumeData *data2 = (VolumeData *)command2->mParam.get(); 808 if (data->mIO != data2->mIO) break; 809 if (data->mStream != data2->mStream) break; 810 ALOGV("Filtering out volume command on output %d for stream %d", 811 data->mIO, data->mStream); 812 removedCommands.add(command2); 813 command->mTime = command2->mTime; 814 // force delayMs to non 0 so that code below does not request to wait for 815 // command status as the command is now delayed 816 delayMs = 1; 817 } break; 818 case START_TONE: 819 case STOP_TONE: 820 default: 821 break; 822 } 823 } 824 825 // remove filtered commands 826 for (size_t j = 0; j < removedCommands.size(); j++) { 827 // removed commands always have time stamps greater than current command 828 for (size_t k = i + 1; k < mAudioCommands.size(); k++) { 829 if (mAudioCommands[k].get() == removedCommands[j].get()) { 830 ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand); 831 mAudioCommands.removeAt(k); 832 break; 833 } 834 } 835 } 836 removedCommands.clear(); 837 838 // Disable wait for status if delay is not 0 839 if (delayMs != 0) { 840 command->mWaitStatus = false; 841 } 842 843 // insert command at the right place according to its time stamp 844 ALOGV("inserting command: %d at index %d, num commands %d", 845 command->mCommand, (int)i+1, mAudioCommands.size()); 846 mAudioCommands.insertAt(command, i + 1); 847} 848 849void AudioPolicyService::AudioCommandThread::exit() 850{ 851 ALOGV("AudioCommandThread::exit"); 852 { 853 AutoMutex _l(mLock); 854 requestExit(); 855 mWaitWorkCV.signal(); 856 } 857 requestExitAndWait(); 858} 859 860void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size) 861{ 862 snprintf(buffer, size, " %02d %06d.%03d %01u %p\n", 863 mCommand, 864 (int)ns2s(mTime), 865 (int)ns2ms(mTime)%1000, 866 mWaitStatus, 867 mParam.get()); 868} 869 870/******* helpers for the service_ops callbacks defined below *********/ 871void AudioPolicyService::setParameters(audio_io_handle_t ioHandle, 872 const char *keyValuePairs, 873 int delayMs) 874{ 875 mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs, 876 delayMs); 877} 878 879int AudioPolicyService::setStreamVolume(audio_stream_type_t stream, 880 float volume, 881 audio_io_handle_t output, 882 int delayMs) 883{ 884 return (int)mAudioCommandThread->volumeCommand(stream, volume, 885 output, delayMs); 886} 887 888int AudioPolicyService::startTone(audio_policy_tone_t tone, 889 audio_stream_type_t stream) 890{ 891 if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) { 892 ALOGE("startTone: illegal tone requested (%d)", tone); 893 } 894 if (stream != AUDIO_STREAM_VOICE_CALL) { 895 ALOGE("startTone: illegal stream (%d) requested for tone %d", stream, 896 tone); 897 } 898 mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING, 899 AUDIO_STREAM_VOICE_CALL); 900 return 0; 901} 902 903int AudioPolicyService::stopTone() 904{ 905 mTonePlaybackThread->stopToneCommand(); 906 return 0; 907} 908 909int AudioPolicyService::setVoiceVolume(float volume, int delayMs) 910{ 911 return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs); 912} 913 914extern "C" { 915audio_module_handle_t aps_load_hw_module(void *service __unused, 916 const char *name); 917audio_io_handle_t aps_open_output(void *service __unused, 918 audio_devices_t *pDevices, 919 uint32_t *pSamplingRate, 920 audio_format_t *pFormat, 921 audio_channel_mask_t *pChannelMask, 922 uint32_t *pLatencyMs, 923 audio_output_flags_t flags); 924 925audio_io_handle_t aps_open_output_on_module(void *service __unused, 926 audio_module_handle_t module, 927 audio_devices_t *pDevices, 928 uint32_t *pSamplingRate, 929 audio_format_t *pFormat, 930 audio_channel_mask_t *pChannelMask, 931 uint32_t *pLatencyMs, 932 audio_output_flags_t flags, 933 const audio_offload_info_t *offloadInfo); 934audio_io_handle_t aps_open_dup_output(void *service __unused, 935 audio_io_handle_t output1, 936 audio_io_handle_t output2); 937int aps_close_output(void *service __unused, audio_io_handle_t output); 938int aps_suspend_output(void *service __unused, audio_io_handle_t output); 939int aps_restore_output(void *service __unused, audio_io_handle_t output); 940audio_io_handle_t aps_open_input(void *service __unused, 941 audio_devices_t *pDevices, 942 uint32_t *pSamplingRate, 943 audio_format_t *pFormat, 944 audio_channel_mask_t *pChannelMask, 945 audio_in_acoustics_t acoustics __unused); 946audio_io_handle_t aps_open_input_on_module(void *service __unused, 947 audio_module_handle_t module, 948 audio_devices_t *pDevices, 949 uint32_t *pSamplingRate, 950 audio_format_t *pFormat, 951 audio_channel_mask_t *pChannelMask); 952int aps_close_input(void *service __unused, audio_io_handle_t input); 953int aps_invalidate_stream(void *service __unused, audio_stream_type_t stream); 954int aps_move_effects(void *service __unused, int session, 955 audio_io_handle_t src_output, 956 audio_io_handle_t dst_output); 957char * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle, 958 const char *keys); 959void aps_set_parameters(void *service, audio_io_handle_t io_handle, 960 const char *kv_pairs, int delay_ms); 961int aps_set_stream_volume(void *service, audio_stream_type_t stream, 962 float volume, audio_io_handle_t output, 963 int delay_ms); 964int aps_start_tone(void *service, audio_policy_tone_t tone, 965 audio_stream_type_t stream); 966int aps_stop_tone(void *service); 967int aps_set_voice_volume(void *service, float volume, int delay_ms); 968}; 969 970namespace { 971 struct audio_policy_service_ops aps_ops = { 972 .open_output = aps_open_output, 973 .open_duplicate_output = aps_open_dup_output, 974 .close_output = aps_close_output, 975 .suspend_output = aps_suspend_output, 976 .restore_output = aps_restore_output, 977 .open_input = aps_open_input, 978 .close_input = aps_close_input, 979 .set_stream_volume = aps_set_stream_volume, 980 .invalidate_stream = aps_invalidate_stream, 981 .set_parameters = aps_set_parameters, 982 .get_parameters = aps_get_parameters, 983 .start_tone = aps_start_tone, 984 .stop_tone = aps_stop_tone, 985 .set_voice_volume = aps_set_voice_volume, 986 .move_effects = aps_move_effects, 987 .load_hw_module = aps_load_hw_module, 988 .open_output_on_module = aps_open_output_on_module, 989 .open_input_on_module = aps_open_input_on_module, 990 }; 991}; // namespace <unnamed> 992 993}; // namespace android 994