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