AudioPolicyService.cpp revision a7e04803ffa0d8d4cc51a122f68bf5038422aabb
19258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org/*
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * Copyright (C) 2009 The Android Open Source Project
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen *
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * Licensed under the Apache License, Version 2.0 (the "License");
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * you may not use this file except in compliance with the License.
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * You may obtain a copy of the License at
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen *
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen *      http://www.apache.org/licenses/LICENSE-2.0
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen *
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * Unless required by applicable law or agreed to in writing, software
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * distributed under the License is distributed on an "AS IS" BASIS,
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * See the License for the specific language governing permissions and
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen * limitations under the License.
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen */
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define LOG_TAG "AudioPolicyService"
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//#define LOG_NDEBUG 0
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "Configuration.h"
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#undef __STRICT_ANSI__
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define __STDINT_LIMITS
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#define __STDC_LIMIT_MACROS
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <stdint.h>
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <sys/time.h>
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <binder/IServiceManager.h>
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <utils/Log.h>
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <cutils/properties.h>
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <binder/IPCThreadState.h>
319d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com#include <utils/String16.h>
32ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org#include <utils/threads.h>
339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com#include "AudioPolicyService.h"
3471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include "ServiceUtilities.h"
3571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#include <hardware_legacy/power.h>
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <media/AudioEffect.h>
37a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <media/EffectsFactoryApi.h>
38a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
39a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <hardware/hardware.h>
40a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include <system/audio.h>
4143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <system/audio_policy.h>
4243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include <hardware/audio_policy.h>
4368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
4468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgnamespace android {
45c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
4668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgstatic const char kDeadlockedString[] = "AudioPolicyService may be deadlocked\n";
47c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.orgstatic const char kCmdDeadlockedString[] = "AudioPolicyService command thread may be deadlocked\n";
48c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org
49bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgstatic const int kDumpLockRetries = 50;
50bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgstatic const int kDumpLockSleepUs = 20000;
5168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org
5243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic const nsecs_t kAudioCommandTimeoutNs = seconds(3); // 3 seconds
5343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
549a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comnamespace {
559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    extern struct audio_policy_service_ops aps_ops;
5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
5743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
5943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
6043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenAudioPolicyService::AudioPolicyService()
6143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    : BnAudioPolicyService(), mpAudioPolicyDev(NULL), mpAudioPolicy(NULL),
6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      mAudioPolicyManager(NULL), mAudioPolicyClient(NULL)
6343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen{
648bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    char value[PROPERTY_VALUE_MAX];
658bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    const struct hw_module_t *module;
668bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    int forced_val;
677be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    int rc;
6841044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
6941044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    Mutex::Autolock _l(mLock);
7041044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
7143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // start tone playback thread
7243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    mTonePlaybackThread = new AudioCommandThread(String8("ApmTone"), this);
7343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // start audio commands thread
7441044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
7541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    // start output activity command thread
767be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
777be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
7843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#ifdef USE_LEGACY_AUDIO_POLICY
798bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    ALOGI("AudioPolicyService CSTOR in legacy mode");
80cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
81cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    /* instantiate the audio policy manager */
82cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    rc = hw_get_module(AUDIO_POLICY_HARDWARE_MODULE_ID, &module);
83cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    if (rc) {
84a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        return;
85a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
867be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    rc = audio_policy_dev_open(module, &mpAudioPolicyDev);
877be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    ALOGE_IF(rc, "couldn't open audio policy device (%s)", strerror(-rc));
887be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    if (rc) {
897be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        return;
907be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    }
9141044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org
9241044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    rc = mpAudioPolicyDev->create_audio_policy(mpAudioPolicyDev, &aps_ops, this,
937be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                                               &mpAudioPolicy);
947be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    ALOGE_IF(rc, "couldn't create audio policy (%s)", strerror(-rc));
9541044eb0969b0d7d5c041a077519a36efa6aff27kasperl@chromium.org    if (rc) {
96cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        return;
97cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    }
98cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
99cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    rc = mpAudioPolicy->init_check(mpAudioPolicy);
100cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    ALOGE_IF(rc, "couldn't init_check the audio policy (%s)", strerror(-rc));
101cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    if (rc) {
102cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        return;
103cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    }
104cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    ALOGI("Loaded audio policy from %s (%s)", module->name, module->id);
105cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#else
106cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    ALOGI("AudioPolicyService CSTOR in new mode");
107cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
108cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    mAudioPolicyClient = new AudioPolicyClient(this);
109cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    mAudioPolicyManager = createAudioPolicyManager(mAudioPolicyClient);
110cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org#endif
111cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
112cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    // load audio processing modules
113cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    mAudioPolicyEffects = new AudioPolicyEffects();
114cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org}
115cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
116cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.orgAudioPolicyService::~AudioPolicyService()
117cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org{
118cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    mTonePlaybackThread->exit();
119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mAudioCommandThread->exit();
12041826e77311db718135ef6517b846933dfd275f3ager@chromium.org    mOutputCommandThread->exit();
12141826e77311db718135ef6517b846933dfd275f3ager@chromium.org
12241826e77311db718135ef6517b846933dfd275f3ager@chromium.org#ifdef USE_LEGACY_AUDIO_POLICY
123a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (mpAudioPolicy != NULL && mpAudioPolicyDev != NULL) {
124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        mpAudioPolicyDev->destroy_audio_policy(mpAudioPolicyDev, mpAudioPolicy);
1257be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    }
1267be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    if (mpAudioPolicyDev != NULL) {
127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        audio_policy_dev_close(mpAudioPolicyDev);
1280c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
1297be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org#else
1307be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    destroyAudioPolicyManager(mAudioPolicyManager);
1317be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    delete mAudioPolicyClient;
132bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org#endif
1337be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1347be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    mNotificationClients.clear();
1350c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    mAudioPolicyEffects.clear();
1360c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
1370c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
1380c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// A notification client is always registered by AudioSystem when the client process
1390c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org// connects to AudioPolicyService.
1400c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::registerClient(const sp<IAudioPolicyServiceClient>& client)
1410c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
1420c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
1430c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    Mutex::Autolock _l(mLock);
1440c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
145bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    uid_t uid = IPCThreadState::self()->getCallingUid();
1467be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    if (mNotificationClients.indexOfKey(uid) < 0) {
1477be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        sp<NotificationClient> notificationClient = new NotificationClient(this,
1487be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                                                                           client,
1497be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org                                                                           uid);
1507be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        ALOGV("registerClient() client %p, uid %d", client.get(), uid);
1517be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1527be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        mNotificationClients.add(uid, notificationClient);
1537be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1547be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        sp<IBinder> binder = client->asBinder();
155bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org        binder->linkToDeath(notificationClient);
1567be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    }
1577be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
1587be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
159bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org// removeNotificationClient() is called when the client process dies.
1607be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgvoid AudioPolicyService::removeNotificationClient(uid_t uid)
1617be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org{
1627be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    Mutex::Autolock _l(mLock);
1637be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1647be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    mNotificationClients.removeItem(uid);
165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
166bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org#ifndef USE_LEGACY_AUDIO_POLICY
167bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org        if (mAudioPolicyManager) {
168bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org            mAudioPolicyManager->clearAudioPatches(uid);
1697be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org        }
170bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org#endif
1717be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
1727be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org
1737be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.orgvoid AudioPolicyService::onAudioPortListUpdate()
1747be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org{
1757be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org    mOutputCommandThread->updateAudioPortListCommand();
1767be3c996bea370e151c9fe4ecf7f779cdc5f87adkasperl@chromium.org}
17743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
178bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgvoid AudioPolicyService::doOnAudioPortListUpdate()
179bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org{
180bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    Mutex::Autolock _l(mLock);
181bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    for (size_t i = 0; i < mNotificationClients.size(); i++) {
18268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org        mNotificationClients.valueAt(i)->onAudioPortListUpdate();
18368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org    }
184bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
185bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
18643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid AudioPolicyService::onAudioPatchListUpdate()
18743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen{
188a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mOutputCommandThread->updateAudioPatchListCommand();
189a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
190a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
191a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                audio_patch_handle_t *handle,
19343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                int delayMs)
19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen{
19543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return mAudioCommandThread->createAudioPatchCommand(patch, handle, delayMs);
19643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
19743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
19843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatus_t AudioPolicyService::clientReleaseAudioPatch(audio_patch_handle_t handle,
19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                                                 int delayMs)
20043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen{
20143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return mAudioCommandThread->releaseAudioPatchCommand(handle, delayMs);
20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2040c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::doOnAudioPatchListUpdate()
2050c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2060c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    Mutex::Autolock _l(mLock);
2070c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    for (size_t i = 0; i < mNotificationClients.size(); i++) {
2080c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        mNotificationClients.valueAt(i)->onAudioPatchListUpdate();
2090c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2100c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2110c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2120c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgstatus_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_config *config,
2130c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                      int delayMs)
2140c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2150c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
2160c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2170c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2180c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgAudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
2190c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                     const sp<IAudioPolicyServiceClient>& client,
2200c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                     uid_t uid)
2210c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    : mService(service), mUid(uid), mAudioPolicyServiceClient(client)
2220c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2230c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2240c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2250c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgAudioPolicyService::NotificationClient::~NotificationClient()
2260c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2270c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2280c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2290c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::NotificationClient::binderDied(const wp<IBinder>& who __unused)
2300c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2310c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sp<NotificationClient> keep(this);
2320c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sp<AudioPolicyService> service = mService.promote();
2330c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (service != 0) {
2340c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        service->removeNotificationClient(mUid);
2350c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2360c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2370c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2380c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::NotificationClient::onAudioPortListUpdate()
2390c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2400c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (mAudioPolicyServiceClient != 0) {
2410c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        mAudioPolicyServiceClient->onAudioPortListUpdate();
2420c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2430c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2440c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2450c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
2460c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2470c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (mAudioPolicyServiceClient != 0) {
2480c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        mAudioPolicyServiceClient->onAudioPatchListUpdate();
2490c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    }
2500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2520c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::binderDied(const wp<IBinder>& who) {
2530c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
2540c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            IPCThreadState::self()->getCallingPid());
255a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
256a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
257a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatic bool tryLock(Mutex& mutex)
258a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
259a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    bool locked = false;
260a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    for (int i = 0; i < kDumpLockRetries; ++i) {
261a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (mutex.tryLock() == NO_ERROR) {
262a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            locked = true;
263a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            break;
264a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
265a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        usleep(kDumpLockSleepUs);
266a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
267a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return locked;
268a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
269a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
270a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::dumpInternals(int fd)
271a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
272a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const size_t SIZE = 256;
273a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    char buffer[SIZE];
274a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    String8 result;
275a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
276a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#ifdef USE_LEGACY_AUDIO_POLICY
277a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpAudioPolicy);
278a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#else
2798bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    snprintf(buffer, SIZE, "AudioPolicyManager: %p\n", mAudioPolicyManager);
280a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#endif
28138e4c715e3a3df4ef11ccd3b86525be8f686ecb5ager@chromium.org    result.append(buffer);
282a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
283a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    result.append(buffer);
284a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
285a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    result.append(buffer);
2860c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    write(fd, result.string(), result.size());
2880c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return NO_ERROR;
2890c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
2900c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
2910c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgstatus_t AudioPolicyService::dump(int fd, const Vector<String16>& args __unused)
2920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
2930c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (!dumpAllowed()) {
2940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        dumpPermissionDenial(fd);
2950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    } else {
2960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        bool locked = tryLock(mLock);
2970c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (!locked) {
2980c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            String8 result(kDeadlockedString);
2990c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            write(fd, result.string(), result.size());
3000c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        }
3010c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
3020c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        dumpInternals(fd);
3030c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (mAudioCommandThread != 0) {
3040c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            mAudioCommandThread->dump(fd);
3050c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        }
3060c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (mTonePlaybackThread != 0) {
3070c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            mTonePlaybackThread->dump(fd);
3080c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        }
3090c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
3100c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org#ifdef USE_LEGACY_AUDIO_POLICY
3110c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (mpAudioPolicy) {
3120c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            mpAudioPolicy->dump(mpAudioPolicy, fd);
3130c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        }
3140c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org#else
3150c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        if (mAudioPolicyManager) {
3160c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org            mAudioPolicyManager->dump(fd);
3170c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        }
3180c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org#endif
319a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
320a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (locked) mLock.unlock();
321a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
322a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return NO_ERROR;
323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
324a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
325a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::dumpPermissionDenial(int fd)
326a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
327a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    const size_t SIZE = 256;
328a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    char buffer[SIZE];
329a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    String8 result;
330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    snprintf(buffer, SIZE, "Permission Denial: "
331a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
332a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            IPCThreadState::self()->getCallingPid(),
333a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            IPCThreadState::self()->getCallingUid());
334a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    result.append(buffer);
335a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    write(fd, result.string(), result.size());
336a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return NO_ERROR;
337a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
338a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
339a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::onTransact(
340a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
341a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
342a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return BnAudioPolicyService::onTransact(code, data, reply, flags);
343a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
344a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
345a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
346a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// -----------  AudioPolicyService::AudioCommandThread implementation ----------
347a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
348a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgAudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
349a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                           const wp<AudioPolicyService>& service)
350a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    : Thread(false), mName(name), mService(service)
351a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
352a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mpToneGenerator = NULL;
3533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
354a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
355a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
356a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgAudioPolicyService::AudioCommandThread::~AudioCommandThread()
357a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
358a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (!mAudioCommands.isEmpty()) {
359a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        release_wake_lock(mName.string());
360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
361a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mAudioCommands.clear();
362a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    delete mpToneGenerator;
363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
364a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
365a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid AudioPolicyService::AudioCommandThread::onFirstRef()
366a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
367a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    run(mName.string(), ANDROID_PRIORITY_AUDIO);
368a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
369a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
370a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgbool AudioPolicyService::AudioCommandThread::threadLoop()
371a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    nsecs_t waitTime = INT64_MAX;
373a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
374a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mLock.lock();
375a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    while (!exitPending())
376a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    {
377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        sp<AudioPolicyService> svc;
378a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        while (!mAudioCommands.isEmpty() && !exitPending()) {
379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            nsecs_t curTime = systemTime();
380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            // commands are sorted by increasing time stamp: execute them from index 0 and up
381a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            if (mAudioCommands[0]->mTime <= curTime) {
382a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                sp<AudioCommand> command = mAudioCommands[0];
383a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                mAudioCommands.removeAt(0);
384a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                mLastCommand = command;
385a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
386a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                switch (command->mCommand) {
387a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case START_TONE: {
388a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.unlock();
389a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ToneData *data = (ToneData *)command->mParam.get();
390a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing start tone %d on stream %d",
391a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            data->mType, data->mStream);
392a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    delete mpToneGenerator;
393a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
394a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mpToneGenerator->startTone(data->mType);
395a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.lock();
396a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
397a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case STOP_TONE: {
398a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.unlock();
399a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing stop tone");
400a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (mpToneGenerator != NULL) {
401a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        mpToneGenerator->stopTone();
402a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        delete mpToneGenerator;
403a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        mpToneGenerator = NULL;
404a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
405a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.lock();
406a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
407a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case SET_VOLUME: {
408a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    VolumeData *data = (VolumeData *)command->mParam.get();
409a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing set volume stream %d, \
410a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                                    data->mVolume,
413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                                    data->mIO);
414ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                    }break;
415a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case SET_PARAMETERS: {
416a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ParametersData *data = (ParametersData *)command->mParam.get();
417a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing set parameters string %s, io %d",
418a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            data->mKeyValuePairs.string(), data->mIO);
419a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case SET_VOICE_VOLUME: {
422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam.get();
423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing set voice volume volume %f",
424a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            data->mVolume);
425a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case STOP_OUTPUT: {
428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    StopOutputData *data = (StopOutputData *)command->mParam.get();
429a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing stop output %d",
430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            data->mIO);
431a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc = mService.promote();
432a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (svc == 0) {
433a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        break;
434a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
435a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.unlock();
436a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc->doStopOutput(data->mIO, data->mStream, data->mSession);
437a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.lock();
438a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
439a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case RELEASE_OUTPUT: {
440a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ReleaseOutputData *data = (ReleaseOutputData *)command->mParam.get();
4418bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    ALOGV("AudioCommandThread() processing release output %d",
442a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                            data->mIO);
443a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc = mService.promote();
44437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                    if (svc == 0) {
445a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        break;
446a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
447a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.unlock();
448a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc->doReleaseOutput(data->mIO);
449a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.lock();
4508bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    }break;
451a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case CREATE_AUDIO_PATCH: {
452a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    CreateAudioPatchData *data = (CreateAudioPatchData *)command->mParam.get();
453a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing create audio patch");
4543291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
4558bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    if (af == 0) {
4568bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                        command->mStatus = PERMISSION_DENIED;
457a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } else {
458a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
459a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
460a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } break;
461a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case RELEASE_AUDIO_PATCH: {
462a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ReleaseAudioPatchData *data = (ReleaseAudioPatchData *)command->mParam.get();
463a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing release audio patch");
464a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
465a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (af == 0) {
466a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mStatus = PERMISSION_DENIED;
467a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } else {
468a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mStatus = af->releaseAudioPatch(data->mHandle);
469a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
470a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } break;
471a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case UPDATE_AUDIOPORT_LIST: {
472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing update audio port list");
47337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                    svc = mService.promote();
474a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (svc == 0) {
475a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        break;
476a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
477a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.unlock();
478a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc->doOnAudioPortListUpdate();
479a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    mLock.lock();
480a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }break;
481a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case UPDATE_AUDIOPATCH_LIST: {
482a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing update audio patch list");
483a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    svc = mService.promote();
484a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (svc == 0) {
4858bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                        break;
4868bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    }
4878bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    mLock.unlock();
4888bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    svc->doOnAudioPatchListUpdate();
4898bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    mLock.lock();
4908bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    }break;
491a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                case SET_AUDIOPORT_CONFIG: {
492a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    SetAudioPortConfigData *data = (SetAudioPortConfigData *)command->mParam.get();
493a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGV("AudioCommandThread() processing set port config");
494a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
495a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (af == 0) {
496a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mStatus = PERMISSION_DENIED;
497a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } else {
498a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mStatus = af->setAudioPortConfig(&data->mConfig);
499a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
500a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    } break;
501a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                default:
502a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
503a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                }
504a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                {
505a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    Mutex::Autolock _l(command->mLock);
506a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    if (command->mWaitStatus) {
507a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mWaitStatus = false;
508a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        command->mCond.signal();
509a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
510a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                }
511a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                waitTime = INT64_MAX;
512a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            } else {
513a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                waitTime = mAudioCommands[0]->mTime - curTime;
514a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                break;
515a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            }
516a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
517a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // release delayed commands wake lock
518a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (mAudioCommands.isEmpty()) {
519a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            release_wake_lock(mName.string());
520a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
521a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // release mLock before releasing strong reference on the service as
522a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // AudioPolicyService destructor calls AudioCommandThread::exit() which acquires mLock.
523a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        mLock.unlock();
524a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        svc.clear();
525a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        mLock.lock();
526a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (!exitPending()) {
527a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            ALOGV("AudioCommandThread() going to sleep");
528a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            mWaitWorkCV.waitRelative(mLock, waitTime);
529a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            ALOGV("AudioCommandThread() waking up");
530a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
531a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
532a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mLock.unlock();
533a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return false;
534a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
535a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
536a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::dump(int fd)
53737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com{
53837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    const size_t SIZE = 256;
53937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    char buffer[SIZE];
54037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    String8 result;
54137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
54237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
54337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result.append(buffer);
544245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    write(fd, result.string(), result.size());
545245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
54637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    bool locked = tryLock(mLock);
54737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (!locked) {
54837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        String8 result2(kCmdDeadlockedString);
549245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        write(fd, result2.string(), result2.size());
550245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    }
55137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
55237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    snprintf(buffer, SIZE, "- Commands:\n");
55337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result = String8(buffer);
55437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result.append("   Command Time        Wait pParam\n");
55537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    for (size_t i = 0; i < mAudioCommands.size(); i++) {
55637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        mAudioCommands[i]->dump(buffer, SIZE);
557245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org        result.append(buffer);
558245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    }
55937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    result.append("  Last Command\n");
56037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (mLastCommand != 0) {
56137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        mLastCommand->dump(buffer, SIZE);
56237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        result.append(buffer);
56337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    } else {
56437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        result.append("     none\n");
56537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
56637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
56737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    write(fd, result.string(), result.size());
56837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
56937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (locked) mLock.unlock();
57037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
57137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return NO_ERROR;
57237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
57337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
57437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid AudioPolicyService::AudioCommandThread::startToneCommand(ToneGenerator::tone_type type,
57537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        audio_stream_type_t stream)
57637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com{
57737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    sp<AudioCommand> command = new AudioCommand();
57837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    command->mCommand = START_TONE;
57937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    sp<ToneData> data = new ToneData();
58037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    data->mType = type;
58137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    data->mStream = stream;
58237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    command->mParam = data;
583245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    ALOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
584245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    sendCommand(command);
585245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org}
58637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
58737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid AudioPolicyService::AudioCommandThread::stopToneCommand()
58837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com{
589a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    sp<AudioCommand> command = new AudioCommand();
590a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mCommand = STOP_TONE;
5910c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ALOGV("AudioCommandThread() adding tone stop");
59237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    sendCommand(command);
593a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
594a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
595ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::volumeCommand(audio_stream_type_t stream,
59637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                               float volume,
597ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                                               audio_io_handle_t output,
598ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                                               int delayMs)
599a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org{
600a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    sp<AudioCommand> command = new AudioCommand();
601a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    command->mCommand = SET_VOLUME;
602a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    sp<VolumeData> data = new VolumeData();
603a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    data->mStream = stream;
604a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    data->mVolume = volume;
605a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    data->mIO = output;
60637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    command->mParam = data;
60737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    command->mWaitStatus = true;
60837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ALOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
60937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com            stream, volume, output);
6103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    return sendCommand(command, delayMs);
61137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
61237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
61337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comstatus_t AudioPolicyService::AudioCommandThread::parametersCommand(audio_io_handle_t ioHandle,
61437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                                   const char *keyValuePairs,
61537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                                   int delayMs)
61637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com{
61737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    sp<AudioCommand> command = new AudioCommand();
61837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    command->mCommand = SET_PARAMETERS;
61937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    sp<ParametersData> data = new ParametersData();
62037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    data->mIO = ioHandle;
621245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    data->mKeyValuePairs = String8(keyValuePairs);
622245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    command->mParam = data;
6238bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    command->mWaitStatus = true;
6248bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    ALOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
6258bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org            keyValuePairs, ioHandle, delayMs);
6263291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    return sendCommand(command, delayMs);
6273291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
6283291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
6303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org{
6313291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sp<AudioCommand> command = new AudioCommand();
632a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mCommand = SET_VOICE_VOLUME;
633a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    sp<VoiceVolumeData> data = new VoiceVolumeData();
634a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    data->mVolume = volume;
635a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mParam = data;
636a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mWaitStatus = true;
637a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ALOGV("AudioCommandThread() adding set voice volume volume %f", volume);
638a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return sendCommand(command, delayMs);
639a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
640a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
641a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
642a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                               audio_stream_type_t stream,
643a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                               int session)
644a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
645a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    sp<AudioCommand> command = new AudioCommand();
646a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mCommand = STOP_OUTPUT;
6470c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sp<StopOutputData> data = new StopOutputData();
6480c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    data->mIO = output;
6490c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    data->mStream = stream;
6500c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    data->mSession = session;
6510c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    command->mParam = data;
6520c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ALOGV("AudioCommandThread() adding stop output %d", output);
6530c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sendCommand(command);
6540c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
6550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
6560c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgvoid AudioPolicyService::AudioCommandThread::releaseOutputCommand(audio_io_handle_t output)
6570c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
6580c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sp<AudioCommand> command = new AudioCommand();
6590c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    command->mCommand = RELEASE_OUTPUT;
6600c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sp<ReleaseOutputData> data = new ReleaseOutputData();
6610c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    data->mIO = output;
6620c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    command->mParam = data;
6630c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ALOGV("AudioCommandThread() adding release output %d", output);
6640c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    sendCommand(command);
6650c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
666a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
667ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::createAudioPatchCommand(
6680c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                const struct audio_patch *patch,
6690c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                audio_patch_handle_t *handle,
6703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                                int delayMs)
671a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
672a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    status_t status = NO_ERROR;
673a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
674a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    sp<AudioCommand> command = new AudioCommand();
675a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mCommand = CREATE_AUDIO_PATCH;
676a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    CreateAudioPatchData *data = new CreateAudioPatchData();
677a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    data->mPatch = *patch;
678a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    data->mHandle = *handle;
679a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mParam = data;
680a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mWaitStatus = true;
681a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ALOGV("AudioCommandThread() adding create patch delay %d", delayMs);
682a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    status = sendCommand(command, delayMs);
683a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (status == NO_ERROR) {
684a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        *handle = data->mHandle;
685a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
6863291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    return status;
687a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
688a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
689a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle,
6900c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                 int delayMs)
691a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
692a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    sp<AudioCommand> command = new AudioCommand();
693a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mCommand = RELEASE_AUDIO_PATCH;
6940c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    ReleaseAudioPatchData *data = new ReleaseAudioPatchData();
6953291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    data->mHandle = handle;
6963291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mParam = data;
6973291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mWaitStatus = true;
6983291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    ALOGV("AudioCommandThread() adding release patch delay %d", delayMs);
6993291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    return sendCommand(command, delayMs);
7003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
7013291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid AudioPolicyService::AudioCommandThread::updateAudioPortListCommand()
7033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org{
7043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sp<AudioCommand> command = new AudioCommand();
7053291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mCommand = UPDATE_AUDIOPORT_LIST;
7063291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    ALOGV("AudioCommandThread() adding update audio port list");
7073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sendCommand(command);
7083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
7093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid AudioPolicyService::AudioCommandThread::updateAudioPatchListCommand()
7113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org{
7123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sp<AudioCommand>command = new AudioCommand();
7133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mCommand = UPDATE_AUDIOPATCH_LIST;
7143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    ALOGV("AudioCommandThread() adding update audio patch list");
7153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sendCommand(command);
7163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
7173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::setAudioPortConfigCommand(
7193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                            const struct audio_port_config *config, int delayMs)
7203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org{
7213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    sp<AudioCommand> command = new AudioCommand();
7223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mCommand = SET_AUDIOPORT_CONFIG;
7233291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    SetAudioPortConfigData *data = new SetAudioPortConfigData();
7243291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    data->mConfig = *config;
7253291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mParam = data;
7263291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    command->mWaitStatus = true;
7273291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    ALOGV("AudioCommandThread() adding set port config delay %d", delayMs);
728a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return sendCommand(command, delayMs);
729a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
730a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
731a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgstatus_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
732a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
733a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    {
734a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        Mutex::Autolock _l(mLock);
735a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        insertCommand_l(command, delayMs);
736a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        mWaitWorkCV.signal();
737a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
738a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Mutex::Autolock _l(command->mLock);
739a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    while (command->mWaitStatus) {
740a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        nsecs_t timeOutNs = kAudioCommandTimeoutNs + milliseconds(delayMs);
741a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        if (command->mCond.waitRelative(command->mLock, timeOutNs) != NO_ERROR) {
742a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            command->mStatus = TIMED_OUT;
743a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            command->mWaitStatus = false;
744a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
7458bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    }
746a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return command->mStatus;
747a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
748a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
7493291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org// insertCommand_l() must be called with mLock held
7503291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& command, int delayMs)
7513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org{
752a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    ssize_t i;  // not size_t because i will count down to -1
7538bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Vector < sp<AudioCommand> > removedCommands;
754a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    command->mTime = systemTime() + milliseconds(delayMs);
755ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
756ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // acquire wake lock to make sure delayed commands are processed
757ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    if (mAudioCommands.isEmpty()) {
7583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
7593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
7603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7613291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // check same pending commands with later time stamps and eliminate them
7623291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    for (i = mAudioCommands.size()-1; i >= 0; i--) {
7633291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        sp<AudioCommand> command2 = mAudioCommands[i];
764ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
765ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        if (command2->mTime <= command->mTime) break;
7663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        if (command2->mCommand != command->mCommand) continue;
7673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7683291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        switch (command->mCommand) {
7693291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        case SET_PARAMETERS: {
7703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            ParametersData *data = (ParametersData *)command->mParam.get();
771a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            ParametersData *data2 = (ParametersData *)command2->mParam.get();
772ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org            if (data->mIO != data2->mIO) break;
773a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            ALOGV("Comparing parameter command %s to new command %s",
774a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
775a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org            AudioParameter param = AudioParameter(data->mKeyValuePairs);
77637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
77737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com            for (size_t j = 0; j < param.size(); j++) {
778245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                String8 key;
779245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                String8 value;
780245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                param.getAt(j, key, value);
781245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                for (size_t k = 0; k < param2.size(); k++) {
78237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                    String8 key2;
7838bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    String8 value2;
7848bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    param2.getAt(k, key2, value2);
7858bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                    if (key2 == key) {
786a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        param2.remove(key2);
7870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                        ALOGV("Filtering out parameter %s", key2.string());
788a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                        break;
789a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                    }
790a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                }
791a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            }
792a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            // if all keys have been filtered out, remove the command.
793a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            // otherwise, update the key value pairs
794a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            if (param2.size() == 0) {
795a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                removedCommands.add(command2);
796a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            } else {
797a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                data2->mKeyValuePairs = param2.toString();
798a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            }
799ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org            command->mTime = command2->mTime;
800a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            // force delayMs to non 0 so that code below does not request to wait for
801a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            // command status as the command is now delayed
802a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            delayMs = 1;
803a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } break;
804ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
805ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        case SET_VOLUME: {
806a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            VolumeData *data = (VolumeData *)command->mParam.get();
8073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            VolumeData *data2 = (VolumeData *)command2->mParam.get();
8083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (data->mIO != data2->mIO) break;
8093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (data->mStream != data2->mStream) break;
8103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            ALOGV("Filtering out volume command on output %d for stream %d",
8113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    data->mIO, data->mStream);
8123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            removedCommands.add(command2);
8133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            command->mTime = command2->mTime;
8143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            // force delayMs to non 0 so that code below does not request to wait for
8153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            // command status as the command is now delayed
816a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            delayMs = 1;
817a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        } break;
818a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        case START_TONE:
819a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        case STOP_TONE:
820a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        default:
821a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            break;
822a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
823a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
824a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
825a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    // remove filtered commands
826a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    for (size_t j = 0; j < removedCommands.size(); j++) {
827a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        // removed commands always have time stamps greater than current command
8288bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
829a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            if (mAudioCommands[k].get() == removedCommands[j].get()) {
830a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                ALOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
831a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                mAudioCommands.removeAt(k);
8328bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                break;
833a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org            }
834a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        }
835a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
836a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    removedCommands.clear();
837a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
838ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Disable wait for status if delay is not 0
839a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    if (delayMs != 0) {
840a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org        command->mWaitStatus = false;
841a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    }
84237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
84337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // insert command at the right place according to its time stamp
844245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    ALOGV("inserting command: %d at index %zd, num commands %zu",
845245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org            command->mCommand, i+1, mAudioCommands.size());
846a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mAudioCommands.insertAt(command, i + 1);
84738e4c715e3a3df4ef11ccd3b86525be8f686ecb5ager@chromium.org}
8488bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
8498bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.orgvoid AudioPolicyService::AudioCommandThread::exit()
8508bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org{
8518bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    ALOGV("AudioCommandThread::exit");
8528bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    {
8538bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        AutoMutex _l(mLock);
8548bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        requestExit();
8550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org        mWaitWorkCV.signal();
85637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
85737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    requestExitAndWait();
858381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org}
859381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org
860381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.orgvoid AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
861381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org{
862381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
86337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com            mCommand,
864381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org            (int)ns2s(mTime),
865381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org            (int)ns2ms(mTime)%1000,
866381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org            mWaitStatus,
86737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com            mParam.get());
86837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
86937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
8703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org/******* helpers for the service_ops callbacks defined below *********/
87137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
87237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                       const char *keyValuePairs,
87337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                       int delayMs)
874a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org{
875a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    mAudioCommandThread->parametersCommand(ioHandle, keyValuePairs,
876a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                           delayMs);
877a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
878ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
879ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgint AudioPolicyService::setStreamVolume(audio_stream_type_t stream,
880ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                        float volume,
881ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                        audio_io_handle_t output,
882ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                        int delayMs)
883ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org{
884ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    return (int)mAudioCommandThread->volumeCommand(stream, volume,
8850c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                   output, delayMs);
8860c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org}
8870c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
8880c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.orgint AudioPolicyService::startTone(audio_policy_tone_t tone,
8890c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                  audio_stream_type_t stream)
8900c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org{
891ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    if (tone != AUDIO_POLICY_TONE_IN_CALL_NOTIFICATION) {
892ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        ALOGE("startTone: illegal tone requested (%d)", tone);
893ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    }
894ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    if (stream != AUDIO_STREAM_VOICE_CALL) {
895ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        ALOGE("startTone: illegal stream (%d) requested for tone %d", stream,
896ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org            tone);
897ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    }
898ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    mTonePlaybackThread->startToneCommand(ToneGenerator::TONE_SUP_CALL_WAITING,
899ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                          AUDIO_STREAM_VOICE_CALL);
900ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    return 0;
901ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org}
902ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
903ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgint AudioPolicyService::stopTone()
904ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org{
905ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    mTonePlaybackThread->stopToneCommand();
906ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    return 0;
907ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org}
908ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
909a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgint AudioPolicyService::setVoiceVolume(float volume, int delayMs)
910a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org{
911a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
912ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org}
913ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
914245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgextern "C" {
915245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgaudio_module_handle_t aps_load_hw_module(void *service __unused,
9160c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                             const char *name);
917ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgaudio_io_handle_t aps_open_output(void *service __unused,
918ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                         audio_devices_t *pDevices,
9190c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                         uint32_t *pSamplingRate,
920ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                         audio_format_t *pFormat,
921ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                         audio_channel_mask_t *pChannelMask,
922ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                         uint32_t *pLatencyMs,
923ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                         audio_output_flags_t flags);
924ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
925ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgaudio_io_handle_t aps_open_output_on_module(void *service __unused,
926ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                                                   audio_module_handle_t module,
927a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   audio_devices_t *pDevices,
928a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   uint32_t *pSamplingRate,
929a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   audio_format_t *pFormat,
930a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   audio_channel_mask_t *pChannelMask,
9318bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                                                   uint32_t *pLatencyMs,
932a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   audio_output_flags_t flags,
933a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                   const audio_offload_info_t *offloadInfo);
934a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgaudio_io_handle_t aps_open_dup_output(void *service __unused,
935a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                 audio_io_handle_t output1,
936a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                 audio_io_handle_t output2);
937a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgint aps_close_output(void *service __unused, audio_io_handle_t output);
938ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgint aps_suspend_output(void *service __unused, audio_io_handle_t output);
939a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgint aps_restore_output(void *service __unused, audio_io_handle_t output);
940a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgaudio_io_handle_t aps_open_input(void *service __unused,
941a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                        audio_devices_t *pDevices,
94237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                        uint32_t *pSamplingRate,
94337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                        audio_format_t *pFormat,
944245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                                        audio_channel_mask_t *pChannelMask,
945245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org                                        audio_in_acoustics_t acoustics __unused);
94637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comaudio_io_handle_t aps_open_input_on_module(void *service __unused,
94737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                  audio_module_handle_t module,
948a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                  audio_devices_t *pDevices,
9490c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org                                                  uint32_t *pSamplingRate,
950a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                  audio_format_t *pFormat,
951a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                                  audio_channel_mask_t *pChannelMask);
952a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgint aps_close_input(void *service __unused, audio_io_handle_t input);
953a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgint aps_invalidate_stream(void *service __unused, audio_stream_type_t stream);
954a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgint aps_move_effects(void *service __unused, int session,
955a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                audio_io_handle_t src_output,
956a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                audio_io_handle_t dst_output);
957a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgchar * aps_get_parameters(void *service __unused, audio_io_handle_t io_handle,
9588bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                                     const char *keys);
959a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid aps_set_parameters(void *service, audio_io_handle_t io_handle,
960a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                   const char *kv_pairs, int delay_ms);
961ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgint aps_set_stream_volume(void *service, audio_stream_type_t stream,
962a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                     float volume, audio_io_handle_t output,
963a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                     int delay_ms);
964a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgint aps_start_tone(void *service, audio_policy_tone_t tone,
96537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                              audio_stream_type_t stream);
96637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comint aps_stop_tone(void *service);
967245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgint aps_set_voice_volume(void *service, float volume, int delay_ms);
968245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org};
96937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
97037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comnamespace {
97137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    struct audio_policy_service_ops aps_ops = {
972a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .open_output           = aps_open_output,
973a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .open_duplicate_output = aps_open_dup_output,
974a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .close_output          = aps_close_output,
975a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .suspend_output        = aps_suspend_output,
976a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .restore_output        = aps_restore_output,
977a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org        .open_input            = aps_open_input,
9788bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        .close_input           = aps_close_input,
9798bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        .set_stream_volume     = aps_set_stream_volume,
980ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .invalidate_stream     = aps_invalidate_stream,
981ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .set_parameters        = aps_set_parameters,
982ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .get_parameters        = aps_get_parameters,
983ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .start_tone            = aps_start_tone,
9848bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        .stop_tone             = aps_stop_tone,
9858bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org        .set_voice_volume      = aps_set_voice_volume,
986ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .move_effects          = aps_move_effects,
987ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .load_hw_module        = aps_load_hw_module,
988ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .open_output_on_module = aps_open_output_on_module,
989ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        .open_input_on_module  = aps_open_input_on_module,
9908bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    };
9918bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org}; // namespace <unnamed>
9928bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
9938bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org}; // namespace android
994ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org