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