AudioPolicyInterfaceImpl.cpp revision baac183f3808d7b68f184647a97bd381620415fe
1e3365aa452673f7ea3244bb6638551f13ab7570dNick Lewycky/*
23ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * Copyright (C) 2009 The Android Open Source Project
33ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar *
43ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * Licensed under the Apache License, Version 2.0 (the "License");
53ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * you may not use this file except in compliance with the License.
63ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * You may obtain a copy of the License at
73ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar *
83ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar *      http://www.apache.org/licenses/LICENSE-2.0
93ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar *
103ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * Unless required by applicable law or agreed to in writing, software
113ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar * distributed under the License is distributed on an "AS IS" BASIS,
1253ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar * See the License for the specific language governing permissions and
141b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar * limitations under the License.
151b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar */
164ad4b3ebbe5769143389dccfcfadb666a4ba5940Daniel Dunbar
17f353c8cc2ee1cc16ff194b399a8d951f707fb129Daniel Dunbar#define LOG_TAG "AudioPolicyIntefaceImpl"
1827e738d0d3f781672a5999d2a9e2827b00a97d0cDaniel Dunbar//#define LOG_NDEBUG 0
190648262df75d97b464c2be0ed867da3615659785Daniel Dunbar
201b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar#include <utils/Log.h>
21f353c8cc2ee1cc16ff194b399a8d951f707fb129Daniel Dunbar#include "AudioPolicyService.h"
22f353c8cc2ee1cc16ff194b399a8d951f707fb129Daniel Dunbar#include "ServiceUtilities.h"
230648262df75d97b464c2be0ed867da3615659785Daniel Dunbar
24ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregornamespace android {
25ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor
267f9fc3f7ce076645cb6aefc99c64d9446caf13d6Chris Lattner
271368954db9ce2989ed8f03f5c65e8ee775a5229aDaniel Dunbar// ----------------------------------------------------------------------------
284d7b14734f2285695dcec347f8718b512093390aTed Kremenek
29548f6c8e8010b181cb151df92f0a989363cb993eDavid Blaikiestatus_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
308f25c79e59d88df41c5a3cabba1c58035d384a6eDaniel Dunbar                                                  audio_policy_dev_state_t state,
310648262df75d97b464c2be0ed867da3615659785Daniel Dunbar                                                  const char *device_address)
32256053b31e697fdf0cc48f17d621c82fc3b8dff0Michael J. Spencer{
3303013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer    if (mAudioPolicyManager == NULL) {
3403013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer        return NO_INIT;
35ba1021388e6839b76c8968b931189361c7286674Daniel Dunbar    }
36f353c8cc2ee1cc16ff194b399a8d951f707fb129Daniel Dunbar    if (!settingsAllowed()) {
3718d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth        return PERMISSION_DENIED;
38f353c8cc2ee1cc16ff194b399a8d951f707fb129Daniel Dunbar    }
39f2462be34a49e2108c9b4151f8e6d3fe1b916179Dylan Noblesmith    if (!audio_is_output_device(device) && !audio_is_input_device(device)) {
4069d3b4f7c9fa818d2536b4f1b220b942ae392128Dylan Noblesmith        return BAD_VALUE;
41cc8a94565ec2ff459dcee9ef34237fdcdfc69b3fDylan Noblesmith    }
42cc8a94565ec2ff459dcee9ef34237fdcdfc69b3fDylan Noblesmith    if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
431b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar            state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
4492b369928b8e9ad156fb6eec2bf9f21d657bd69bChris Lattner        return BAD_VALUE;
451b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar    }
465f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
479606a57b6f2c43bf438a958fdffea1de60f6b2b7Sebastian Pop    ALOGV("setDeviceConnectionState()");
485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    Mutex::Autolock _l(mLock);
4910a82cde7c317c5dd41dc3faf17f503c52ce2a3dBob Wilson    return mAudioPolicyManager->setDeviceConnectionState(device,
50d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie                                                      state, device_address);
517e46d0b8436d844d77f3ff580b6e1204e0407044Nick Lewycky}
524762a2da74875d2ae94e0d77d38ed964816cce36Sebastian Pop
534762a2da74875d2ae94e0d77d38ed964816cce36Sebastian Popaudio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState(
54abac441b7d114d5980864093ee0643bf68f1a8f2Chad Rosier                                                              audio_devices_t device,
556f85b1e7906f7a03cbede1f730ba19b28a5f85e8Bob Wilson                                                              const char *device_address)
56c8a22b091677c02003880166e5d5767ca8d74b70Daniel Dunbar{
57c8a22b091677c02003880166e5d5767ca8d74b70Daniel Dunbar    if (mAudioPolicyManager == NULL) {
58951c5705771a57eca0bca07aae5d4738619dd6c6Joerg Sonnenberger        return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
59c8a22b091677c02003880166e5d5767ca8d74b70Daniel Dunbar    }
602b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    return mAudioPolicyManager->getDeviceConnectionState(device,
612b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier                                                      device_address);
62d6277fb9e0353edffc0d6c8655a65542c08cf6f1Argyrios Kyrtzidis}
63225c41706dc0f3682236e351820d339e14390e00Daniel Dunbar
64d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencerstatus_t AudioPolicyService::setPhoneState(audio_mode_t state)
65d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer{
660bbad519aa068206f1e158d5073f72a39fbe83c5Daniel Dunbar    if (mAudioPolicyManager == NULL) {
67225c41706dc0f3682236e351820d339e14390e00Daniel Dunbar        return NO_INIT;
685f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    }
69f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith    if (!settingsAllowed()) {
70d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer        return PERMISSION_DENIED;
71d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer    }
72d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer    if (uint32_t(state) >= AUDIO_MODE_CNT) {
73d5b08bee799d4f77f1a25fa5977ca77b983ab031Michael J. Spencer        return BAD_VALUE;
74225c41706dc0f3682236e351820d339e14390e00Daniel Dunbar    }
753ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar
763ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar    ALOGV("setPhoneState()");
773ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar
781b3bb6efc59a21f794b534078f9ae7e95393f510Daniel Dunbar    // TODO: check if it is more appropriate to do it in platform specific policy manager
7918d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth    AudioSystem::setMode(state);
8018d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth
8118d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth    Mutex::Autolock _l(mLock);
8218d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth    mAudioPolicyManager->setPhoneState(state);
8318d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth    mPhoneState = state;
843ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar    return NO_ERROR;
853ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar}
862d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner
878f25c79e59d88df41c5a3cabba1c58035d384a6eDaniel Dunbaraudio_mode_t AudioPolicyService::getPhoneState()
88847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar{
897f9fc3f7ce076645cb6aefc99c64d9446caf13d6Chris Lattner    Mutex::Autolock _l(mLock);
90847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar    return mPhoneState;
91847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar}
92847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar
93847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbarstatus_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage,
94847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar                                         audio_policy_forced_cfg_t config)
95847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar{
96847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar    if (mAudioPolicyManager == NULL) {
97847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar        return NO_INIT;
98847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar    }
99847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar    if (!settingsAllowed()) {
100847abaa62883b6c20005bdd3346ebbd44e46dbacDaniel Dunbar        return PERMISSION_DENIED;
10191e06dab9335ed6b4474a74353549c708cf3d936Michael J. Spencer    }
102b0c4df5c4df69a003f26b378eb95961bc7c486e5Daniel Dunbar    if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
103b0c4df5c4df69a003f26b378eb95961bc7c486e5Daniel Dunbar        return BAD_VALUE;
104b0c4df5c4df69a003f26b378eb95961bc7c486e5Daniel Dunbar    }
1052dd17a15ddc0184790d790b6128d79ffddae4964Chad Rosier    if (config < 0 || config >= AUDIO_POLICY_FORCE_CFG_CNT) {
1062dd17a15ddc0184790d790b6128d79ffddae4964Chad Rosier        return BAD_VALUE;
1076467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosier    }
1082dd17a15ddc0184790d790b6128d79ffddae4964Chad Rosier    ALOGV("setForceUse()");
1096467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosier    Mutex::Autolock _l(mLock);
1106467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosier    mAudioPolicyManager->setForceUse(usage, config);
1112dd17a15ddc0184790d790b6128d79ffddae4964Chad Rosier    return NO_ERROR;
1120648262df75d97b464c2be0ed867da3615659785Daniel Dunbar}
1130648262df75d97b464c2be0ed867da3615659785Daniel Dunbar
1140648262df75d97b464c2be0ed867da3615659785Daniel Dunbaraudio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use_t usage)
1150648262df75d97b464c2be0ed867da3615659785Daniel Dunbar{
1160648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    if (mAudioPolicyManager == NULL) {
1171fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier        return AUDIO_POLICY_FORCE_NONE;
1181fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    }
1191fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
1201fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier        return AUDIO_POLICY_FORCE_NONE;
1211fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    }
1221fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    return mAudioPolicyManager->getForceUse(usage);
1231fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier}
12459f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher
1251fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosieraudio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream,
1261fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                    uint32_t samplingRate,
1271fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                    audio_format_t format,
1281fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                    audio_channel_mask_t channelMask,
1291fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                    audio_output_flags_t flags,
13059f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher                                    const audio_offload_info_t *offloadInfo)
1311fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier{
1321fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
1331fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier        return AUDIO_IO_HANDLE_NONE;
134582b395ea4d5dfe353e2132a470d39efe2f84a54Fariborz Jahanian    }
13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (mAudioPolicyManager == NULL) {
1361fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier        return AUDIO_IO_HANDLE_NONE;
13753cb2b47596b0ca893a449fa81e0912ded658759Chad Rosier    }
1381fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    ALOGV("getOutput()");
1391fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    Mutex::Autolock _l(mLock);
1401fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    return mAudioPolicyManager->getOutput(stream, samplingRate,
1411fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                    format, channelMask, flags, offloadInfo);
1421fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier}
1431fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier
1441fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosierstatus_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
1451fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_io_handle_t *output,
1461fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_session_t session,
1471fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_stream_type_t *stream,
1481fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              uint32_t samplingRate,
1491fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_format_t format,
1501fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_channel_mask_t channelMask,
1511fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              audio_output_flags_t flags,
1521fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier                                              const audio_offload_info_t *offloadInfo)
1531fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier{
1541fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier    if (mAudioPolicyManager == NULL) {
1551fc1de48cdf9a2f241e0f2c7b9e9db2322f1b794Chad Rosier        return NO_INIT;
156279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    }
157279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    ALOGV("getOutput()");
158279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    Mutex::Autolock _l(mLock);
159e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar    return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, samplingRate,
160279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar                                    format, channelMask, flags, offloadInfo);
161f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar}
162f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar
163f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbarstatus_t AudioPolicyService::startOutput(audio_io_handle_t output,
164f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar                                         audio_stream_type_t stream,
165f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar                                         audio_session_t session)
166f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar{
167eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
168eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar        return BAD_VALUE;
169eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    }
170eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    if (mAudioPolicyManager == NULL) {
171eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar        return NO_INIT;
172eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    }
173f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar    ALOGV("startOutput()");
174f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar    sp<AudioPolicyEffects>audioPolicyEffects;
175f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar    {
176f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        Mutex::Autolock _l(mLock);
177f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        audioPolicyEffects = mAudioPolicyEffects;
1785f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    }
179f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar    if (audioPolicyEffects != 0) {
180f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        // create audio processors according to stream
181f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        status_t status = audioPolicyEffects->addOutputSessionEffects(output, stream, session);
182f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        if (status != NO_ERROR && status != ALREADY_EXISTS) {
183f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar            ALOGW("Failed to add effects on session %d", session);
184f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar        }
185eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    }
186eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    Mutex::Autolock _l(mLock);
187eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    return mAudioPolicyManager->startOutput(output, stream, session);
188eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar}
189eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar
1905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatus_t AudioPolicyService::stopOutput(audio_io_handle_t output,
1915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                        audio_stream_type_t stream,
192212df32d955c34dbb8b976bc0316e8eb83ac579eDaniel Dunbar                                        audio_session_t session)
1935f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner{
194212df32d955c34dbb8b976bc0316e8eb83ac579eDaniel Dunbar    if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
195212df32d955c34dbb8b976bc0316e8eb83ac579eDaniel Dunbar        return BAD_VALUE;
196212df32d955c34dbb8b976bc0316e8eb83ac579eDaniel Dunbar    }
197eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    if (mAudioPolicyManager == NULL) {
198eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar        return NO_INIT;
199eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    }
200eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    ALOGV("stopOutput()");
201eda3f707fd53f90f4232b0e694d3f5514237aba5Daniel Dunbar    mOutputCommandThread->stopOutputCommand(output, stream, session);
2027433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen    return NO_ERROR;
2037433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen}
2045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner
205e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbarstatus_t  AudioPolicyService::doStopOutput(audio_io_handle_t output,
2067433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen                                      audio_stream_type_t stream,
2077433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen                                      audio_session_t session)
208e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar{
209e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar    ALOGV("doStopOutput from tid %d", gettid());
210e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar    sp<AudioPolicyEffects>audioPolicyEffects;
211e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar    {
2127433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen        Mutex::Autolock _l(mLock);
2137433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen        audioPolicyEffects = mAudioPolicyEffects;
2147433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen    }
2157433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen    if (audioPolicyEffects != 0) {
2167433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen        // release audio processors from the stream
2177433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen        status_t status = audioPolicyEffects->releaseOutputSessionEffects(output, stream, session);
2187433fedce98a58341d0f30c2e12e8d53f3bba575Shantonu Sen        if (status != NO_ERROR && status != ALREADY_EXISTS) {
219e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar            ALOGW("Failed to release effects on session %d", session);
220e5a37f48388c7e4cc081f44d13a4910bfa56cd35Daniel Dunbar        }
221279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    }
222f78925f633e949f06521d9ffd937019e59f35efcDaniel Dunbar    Mutex::Autolock _l(mLock);
223279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    return mAudioPolicyManager->stopOutput(output, stream, session);
224a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar}
225a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar
226a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbarvoid AudioPolicyService::releaseOutput(audio_io_handle_t output,
227a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar                                       audio_stream_type_t stream,
228a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar                                       audio_session_t session)
229a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar{
230c326b64a4d14ad89d6a5d227d2460050149d5461Daniel Dunbar    if (mAudioPolicyManager == NULL) {
231a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar        return;
232a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar    }
233a77a723489b0cff63bf90f23416e10b8b6fc1f55Daniel Dunbar    ALOGV("releaseOutput()");
234279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    mOutputCommandThread->releaseOutputCommand(output, stream, session);
235279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar}
236279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar
2372d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattnervoid AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
2388f25c79e59d88df41c5a3cabba1c58035d384a6eDaniel Dunbar                                         audio_stream_type_t stream,
2398f25c79e59d88df41c5a3cabba1c58035d384a6eDaniel Dunbar                                         audio_session_t session)
24059f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher{
241e8cb554c36c94e31e80ea893d9ad528afb491bdfBill Wendling    ALOGV("doReleaseOutput from tid %d", gettid());
242815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier    Mutex::Autolock _l(mLock);
243815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier    mAudioPolicyManager->releaseOutput(output, stream, session);
244815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier}
245815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier
2466467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosierstatus_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
247815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier                                             audio_io_handle_t *input,
248815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier                                             audio_session_t session,
249815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier                                             uint32_t samplingRate,
250815eb6b80739ffca9879b9833208932dee55d0cbChad Rosier                                             audio_format_t format,
251cb881672c2c46142ec1bdfa401c9818ae805db0fDaniel Dunbar                                             audio_channel_mask_t channelMask,
252cb881672c2c46142ec1bdfa401c9818ae805db0fDaniel Dunbar                                             audio_input_flags_t flags)
253cb881672c2c46142ec1bdfa401c9818ae805db0fDaniel Dunbar{
254a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar    if (mAudioPolicyManager == NULL) {
25553ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar        return NO_INIT;
2560648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    }
2577f9fc3f7ce076645cb6aefc99c64d9446caf13d6Chris Lattner    // already checked by client, but double-check in case the client wrapper is bypassed
2588477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar    if (attr->source >= AUDIO_SOURCE_CNT && attr->source != AUDIO_SOURCE_HOTWORD &&
2597ca7987669fcd14d91b4227a9ddcf7fdd8b1f8c2Rafael Espindola        attr->source != AUDIO_SOURCE_FM_TUNER) {
2607ca7987669fcd14d91b4227a9ddcf7fdd8b1f8c2Rafael Espindola        return BAD_VALUE;
2617ca7987669fcd14d91b4227a9ddcf7fdd8b1f8c2Rafael Espindola    }
262c19a12dc3d441bec62eed55e312b76c12d6d9022Daniel Dunbar
263c19a12dc3d441bec62eed55e312b76c12d6d9022Daniel Dunbar    if (((attr->source == AUDIO_SOURCE_HOTWORD) && !captureHotwordAllowed()) ||
264c19a12dc3d441bec62eed55e312b76c12d6d9022Daniel Dunbar        ((attr->source == AUDIO_SOURCE_FM_TUNER) && !captureFmTunerAllowed())) {
2658477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        return BAD_VALUE;
266365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbar    }
267a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar    sp<AudioPolicyEffects>audioPolicyEffects;
268a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar    status_t status;
269a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar    {
270a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar        Mutex::Autolock _l(mLock);
2718477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        // the audio_in_acoustics_t parameter is ignored by get_input()
2728477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        status = mAudioPolicyManager->getInputForAttr(attr, input, session,
2738477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar                                                     samplingRate, format, channelMask,
274f5431e3563a64758584906cb9e0d10719a0756ecDaniel Dunbar                                                     flags);
2758477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        audioPolicyEffects = mAudioPolicyEffects;
2768477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar    }
2778477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar    if (status != NO_ERROR) {
2788477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        return status;
279f5431e3563a64758584906cb9e0d10719a0756ecDaniel Dunbar    }
280f5431e3563a64758584906cb9e0d10719a0756ecDaniel Dunbar    if (audioPolicyEffects != 0) {
2818477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        // create audio pre processors according to input source
2828477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        status_t status = audioPolicyEffects->addInputEffects(*input, attr->source, session);
2838477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar        if (status != NO_ERROR && status != ALREADY_EXISTS) {
2848477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar            ALOGW("Failed to add effects on input %d", *input);
2858a988c32b8ac18eb252ef4a58ed56f898255524dJoerg Sonnenberger        }
2868a988c32b8ac18eb252ef4a58ed56f898255524dJoerg Sonnenberger    }
2878a988c32b8ac18eb252ef4a58ed56f898255524dJoerg Sonnenberger    return NO_ERROR;
2888a988c32b8ac18eb252ef4a58ed56f898255524dJoerg Sonnenberger}
2898477ee93c9d81d1b5fe321706ff95bcd219c744bDaniel Dunbar
290c4ab3493bb3048014895cf577a8f27505a83603dDaniel Dunbarstatus_t AudioPolicyService::startInput(audio_io_handle_t input,
29109982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer                                        audio_session_t session)
29209982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer{
29309982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer    if (mAudioPolicyManager == NULL) {
29409982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer        return NO_INIT;
29509982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer    }
29609982cec0029bc495591067fa89967b6b4d1fa19Benjamin Kramer    Mutex::Autolock _l(mLock);
2978ab2bdcc4f397e100c684ede8e8ca6e226e1380aJoerg Sonnenberger
2988ab2bdcc4f397e100c684ede8e8ca6e226e1380aJoerg Sonnenberger    return mAudioPolicyManager->startInput(input, session);
29905e5930166333e382522b942f00d08abc6c0a28eJoerg Sonnenberger}
30005e5930166333e382522b942f00d08abc6c0a28eJoerg Sonnenberger
301365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbarstatus_t AudioPolicyService::stopInput(audio_io_handle_t input,
302279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar                                       audio_session_t session)
303279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar{
304279c1dbebf37cd128f3c73c70741a6b8c35ad025Daniel Dunbar    if (mAudioPolicyManager == NULL) {
30508386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth        return NO_INIT;
30618d7f3af752c41a197552a1ff25ddd639224b4bbChandler Carruth    }
30708386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth    Mutex::Autolock _l(mLock);
30821549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar
30908386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth    return mAudioPolicyManager->stopInput(input, session);
31021549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar}
311365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbar
312365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbarvoid AudioPolicyService::releaseInput(audio_io_handle_t input,
313be21cd0f07726045367861d3882d18ef30f6a30cDaniel Dunbar                                      audio_session_t session)
31421549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar{
315365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbar    if (mAudioPolicyManager == NULL) {
31653ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar        return;
31721549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar    }
31821549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar    sp<AudioPolicyEffects>audioPolicyEffects;
319cb881672c2c46142ec1bdfa401c9818ae805db0fDaniel Dunbar    {
320be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier        Mutex::Autolock _l(mLock);
321be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier        mAudioPolicyManager->releaseInput(input, session);
322be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier        audioPolicyEffects = mAudioPolicyEffects;
323be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier    }
3244a04d0b4aa33e98ea9e7b3e787f0490585ce9b6fChandler Carruth    if (audioPolicyEffects != 0) {
3254a04d0b4aa33e98ea9e7b3e787f0490585ce9b6fChandler Carruth        // release audio processors from the input
32608386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth        status_t status = audioPolicyEffects->releaseInputEffects(input);
32765f7165676854bf75494f5b73a620d7237db5d41Joerg Sonnenberger        if(status != NO_ERROR) {
328be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier            ALOGW("Failed to release effects on input %d", input);
32953ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar        }
330be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier    }
331be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier}
33253ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar
33353ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbarstatus_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream,
33410ffa9a4887d9376e3eb3598e40523d1b58773c9Daniel Dunbar                                            int indexMin,
33521549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar                                            int indexMax)
33653ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar{
337ab835430b4f758dd49903251c7c7f21b95933c89Daniel Dunbar    if (mAudioPolicyManager == NULL) {
33821549237f14505cfc2a18a06416372a36229d0ceDaniel Dunbar        return NO_INIT;
3398d2554a2c3201aa664cbf2108cf9d57aa0aa4b0aDaniel Dunbar    }
3408d2554a2c3201aa664cbf2108cf9d57aa0aa4b0aDaniel Dunbar    if (!settingsAllowed()) {
341365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbar        return PERMISSION_DENIED;
342365c02f65be026f90e67a8e00e7b827cee60e228Daniel Dunbar    }
34359f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
34459f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher        return BAD_VALUE;
3452b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
3462b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    Mutex::Autolock _l(mLock);
3472b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax);
3482639ac628cff5dedb4fa60169082b2a1a9dd8694Chad Rosier    return NO_ERROR;
3496467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosier}
3508ba9a6244c56b19bc2a24de5d0c32ff37d50177bChad Rosier
3518ba9a6244c56b19bc2a24de5d0c32ff37d50177bChad Rosierstatus_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream,
35280ec127fc9af8b83eea326fbd65265a1adc307d8Chad Rosier                                                  int index,
3532639ac628cff5dedb4fa60169082b2a1a9dd8694Chad Rosier                                                  audio_devices_t device)
3542639ac628cff5dedb4fa60169082b2a1a9dd8694Chad Rosier{
3554f6a4b47675a30e621251fcda1d192a2c17c6eeaChad Rosier    if (mAudioPolicyManager == NULL) {
3564f6a4b47675a30e621251fcda1d192a2c17c6eeaChad Rosier        return NO_INIT;
3574f6a4b47675a30e621251fcda1d192a2c17c6eeaChad Rosier    }
3582b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (!settingsAllowed()) {
35913223073a94f8df6527193827192a326d50877fbChad Rosier        return PERMISSION_DENIED;
36013223073a94f8df6527193827192a326d50877fbChad Rosier    }
3612b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
3622b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return BAD_VALUE;
3632b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
3642b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    Mutex::Autolock _l(mLock);
365e75d9cfbf41a0ee9e456a665776f91fdd9773b36David Blaikie    return mAudioPolicyManager->setStreamVolumeIndex(stream,
3662b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier                                                    index,
367ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier                                                    device);
368ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier}
369ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier
37053d2409a223a14d063faf06e4360ede09c41ed80Chad Rosierstatus_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream,
37153d2409a223a14d063faf06e4360ede09c41ed80Chad Rosier                                                  int *index,
37253d2409a223a14d063faf06e4360ede09c41ed80Chad Rosier                                                  audio_devices_t device)
3736467c9bf4f07f54789d3ed902f04048f4d80ad47Chad Rosier{
37453d2409a223a14d063faf06e4360ede09c41ed80Chad Rosier    if (mAudioPolicyManager == NULL) {
37553d2409a223a14d063faf06e4360ede09c41ed80Chad Rosier        return NO_INIT;
376ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    }
377ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
3782b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return BAD_VALUE;
3792b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
380be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier    Mutex::Autolock _l(mLock);
381be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier    return mAudioPolicyManager->getStreamVolumeIndex(stream,
382be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier                                                    index,
383be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier                                                    device);
384be69f6092668b0586c8729855c01ca2eea22e6feChad Rosier}
3852b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier
386137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosieruint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
38790c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier{
38890c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
38990c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier        return 0;
39090c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    }
39190c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    if (mAudioPolicyManager == NULL) {
39290c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier        return 0;
39390c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    }
39490c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    return mAudioPolicyManager->getStrategyForStream(stream);
39590c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier}
39690c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier
39790c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier//audio policy: use audio_device_t appropriately
39890c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier
39990c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosieraudio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
400137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier{
401137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
4023060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier        return AUDIO_DEVICE_NONE;
403137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier    }
4043060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier    if (mAudioPolicyManager == NULL) {
405137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier        return AUDIO_DEVICE_NONE;
40690c88023fd4cb709c8645aa24e9eac420f733b5dChad Rosier    }
40746e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier    return mAudioPolicyManager->getDevicesForStream(stream);
408c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier}
409c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier
41046e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosieraudio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor_t *desc)
41146e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier{
41246e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier    // FIXME change return type to status_t, and return NO_INIT here
41346e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier    if (mAudioPolicyManager == NULL) {
414c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier        return 0;
415c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier    }
41646e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier    Mutex::Autolock _l(mLock);
41746e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier    return mAudioPolicyManager->getOutputForEffect(desc);
418c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier}
419c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier
420c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosierstatus_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc,
421c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier                                audio_io_handle_t io,
422c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier                                uint32_t strategy,
423c56389189e7a8b99d7db3a6f60c896adb2b092bfChad Rosier                                int session,
42446e3908af1ba2af6d7497e8e501f5c9a01acde7eChad Rosier                                int id)
425137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier{
426137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier    if (mAudioPolicyManager == NULL) {
427137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier        return NO_INIT;
428137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier    }
429137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier    return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
430137a20b5f9360311dd0b6d2500e3365ab2cdf40eChad Rosier}
4314a04d0b4aa33e98ea9e7b3e787f0490585ce9b6fChandler Carruth
4324a04d0b4aa33e98ea9e7b3e787f0490585ce9b6fChandler Carruthstatus_t AudioPolicyService::unregisterEffect(int id)
43308386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth{
43408386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth    if (mAudioPolicyManager == NULL) {
43508386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth        return NO_INIT;
4362b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
43708386a9769575bd8290024aaaecb2dbad5bfd59dChandler Carruth    return mAudioPolicyManager->unregisterEffect(id);
4382b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier}
4392b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier
4402b81910618f63e4ce2373c926a26e76b4b91373fChad Rosierstatus_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
4412b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier{
4422b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (mAudioPolicyManager == NULL) {
4432b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return NO_INIT;
4442b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
4452b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    return mAudioPolicyManager->setEffectEnabled(id, enabled);
4462b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier}
4472b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier
4482b81910618f63e4ce2373c926a26e76b4b91373fChad Rosierbool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
4492b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier{
4502b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
4512b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return false;
4522b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
4532b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (mAudioPolicyManager == NULL) {
4542b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return false;
45513223073a94f8df6527193827192a326d50877fbChad Rosier    }
45613223073a94f8df6527193827192a326d50877fbChad Rosier    Mutex::Autolock _l(mLock);
45713223073a94f8df6527193827192a326d50877fbChad Rosier    return mAudioPolicyManager->isStreamActive(stream, inPastMs);
4582b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier}
45959f9b26bcb59bfb4d66c6ea129172795dcd1cb6bEric Christopher
460ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosierbool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs) const
4612b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier{
462ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
463ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier        return false;
464ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    }
465ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    if (mAudioPolicyManager == NULL) {
466ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier        return false;
467ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    }
468ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    Mutex::Autolock _l(mLock);
469ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs);
470ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier}
471ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier
472ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosierbool AudioPolicyService::isSourceActive(audio_source_t source) const
473d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier{
474cc66b08945099b734b05d06179ea85413c69753dChad Rosier    if (mAudioPolicyManager == NULL) {
475d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        return false;
47637302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    }
477d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    Mutex::Autolock _l(mLock);
478d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    return mAudioPolicyManager->isSourceActive(source);
47937302ead1c067ec984a75e847cd83c6881637e72Chad Rosier}
48037302ead1c067ec984a75e847cd83c6881637e72Chad Rosier
48137302ead1c067ec984a75e847cd83c6881637e72Chad Rosierstatus_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
48237302ead1c067ec984a75e847cd83c6881637e72Chad Rosier                                                       effect_descriptor_t *descriptors,
48337302ead1c067ec984a75e847cd83c6881637e72Chad Rosier                                                       uint32_t *count)
48437302ead1c067ec984a75e847cd83c6881637e72Chad Rosier{
48537302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    if (mAudioPolicyManager == NULL) {
48637302ead1c067ec984a75e847cd83c6881637e72Chad Rosier        *count = 0;
48737302ead1c067ec984a75e847cd83c6881637e72Chad Rosier        return NO_INIT;
488d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    }
489d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    sp<AudioPolicyEffects>audioPolicyEffects;
490d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    {
491d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        Mutex::Autolock _l(mLock);
492d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        audioPolicyEffects = mAudioPolicyEffects;
493a4ba28f3215b4ea70d0cf15026edbfb535e2f0d3Chad Rosier    }
494d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    if (audioPolicyEffects == 0) {
495d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        *count = 0;
496699c6cd0b99f715b6638c8d49f1dfee22f30aabeChad Rosier        return NO_INIT;
497699c6cd0b99f715b6638c8d49f1dfee22f30aabeChad Rosier    }
498a4ba28f3215b4ea70d0cf15026edbfb535e2f0d3Chad Rosier    return audioPolicyEffects->queryDefaultInputEffects(audioSession, descriptors, count);
499a4ba28f3215b4ea70d0cf15026edbfb535e2f0d3Chad Rosier}
500a4ba28f3215b4ea70d0cf15026edbfb535e2f0d3Chad Rosier
501d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosierbool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
502a4ba28f3215b4ea70d0cf15026edbfb535e2f0d3Chad Rosier{
50337302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    if (mAudioPolicyManager == NULL) {
504d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        ALOGV("mAudioPolicyManager == NULL");
505d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier        return false;
506d83217cbfcfcde7b21a829483347e593e2f2a4a3Chad Rosier    }
507cc66b08945099b734b05d06179ea85413c69753dChad Rosier
508cc66b08945099b734b05d06179ea85413c69753dChad Rosier    return mAudioPolicyManager->isOffloadSupported(info);
509cc66b08945099b734b05d06179ea85413c69753dChad Rosier}
510cc66b08945099b734b05d06179ea85413c69753dChad Rosier
51113223073a94f8df6527193827192a326d50877fbChad Rosierstatus_t AudioPolicyService::listAudioPorts(audio_port_role_t role,
512cc66b08945099b734b05d06179ea85413c69753dChad Rosier                                            audio_port_type_t type,
513cc66b08945099b734b05d06179ea85413c69753dChad Rosier                                            unsigned int *num_ports,
51437302ead1c067ec984a75e847cd83c6881637e72Chad Rosier                                            struct audio_port *ports,
51537302ead1c067ec984a75e847cd83c6881637e72Chad Rosier                                            unsigned int *generation)
51637302ead1c067ec984a75e847cd83c6881637e72Chad Rosier{
51737302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    Mutex::Autolock _l(mLock);
51837302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    if(!modifyAudioRoutingAllowed()) {
51937302ead1c067ec984a75e847cd83c6881637e72Chad Rosier        return PERMISSION_DENIED;
52037302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    }
52137302ead1c067ec984a75e847cd83c6881637e72Chad Rosier    if (mAudioPolicyManager == NULL) {
522cc66b08945099b734b05d06179ea85413c69753dChad Rosier        return NO_INIT;
523cc66b08945099b734b05d06179ea85413c69753dChad Rosier    }
52444727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier
52544727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier    return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
52644727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier}
52744727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier
52844727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosierstatus_t AudioPolicyService::getAudioPort(struct audio_port *port)
52944727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier{
53044727629b766bf34bc2299c40f5ee8e4c7a71391Chad Rosier    Mutex::Autolock _l(mLock);
5318775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier    if(!modifyAudioRoutingAllowed()) {
5328775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier        return PERMISSION_DENIED;
5338775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier    }
5348775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier    if (mAudioPolicyManager == NULL) {
5358775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier        return NO_INIT;
5368775485350b2419cb9953518ace61cf68b1c9c18Chad Rosier    }
537ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier
538ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier    return mAudioPolicyManager->getAudioPort(port);
539ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier}
540ce50c55f8cb569cc1b71770fd62327a883fdb7baChad Rosier
54113223073a94f8df6527193827192a326d50877fbChad Rosierstatus_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch,
54213223073a94f8df6527193827192a326d50877fbChad Rosier        audio_patch_handle_t *handle)
5432b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier{
5442b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    Mutex::Autolock _l(mLock);
5452b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if(!modifyAudioRoutingAllowed()) {
5462b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return PERMISSION_DENIED;
5472b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
5482b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    if (mAudioPolicyManager == NULL) {
5492b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return NO_INIT;
5502b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    }
5512b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier    return mAudioPolicyManager->createAudioPatch(patch, handle,
5522b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier                                                  IPCThreadState::self()->getCallingUid());
5532b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier}
5542b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier
555c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbarstatus_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle)
556c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar{
557c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    Mutex::Autolock _l(mLock);
558c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    if(!modifyAudioRoutingAllowed()) {
559c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar        return PERMISSION_DENIED;
560c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    }
561c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    if (mAudioPolicyManager == NULL) {
5622b81910618f63e4ce2373c926a26e76b4b91373fChad Rosier        return NO_INIT;
563c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    }
564c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar
565c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    return mAudioPolicyManager->releaseAudioPatch(handle,
566a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar                                                     IPCThreadState::self()->getCallingUid());
567c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar}
568c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar
569c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbarstatus_t AudioPolicyService::listAudioPatches(unsigned int *num_patches,
5709fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar        struct audio_patch *patches,
5719fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar        unsigned int *generation)
5729fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar{
5739fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    Mutex::Autolock _l(mLock);
5749fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    if(!modifyAudioRoutingAllowed()) {
5755d4d9807a65291cbe6ab88d4a4f74cb7fff01bdePeter Collingbourne        return PERMISSION_DENIED;
576c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    }
577c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    if (mAudioPolicyManager == NULL) {
5785d4d9807a65291cbe6ab88d4a4f74cb7fff01bdePeter Collingbourne        return NO_INIT;
579df9b933aa354b8108cee028cc4726cfa9f2df62cNAKAMURA Takumi    }
5805d4d9807a65291cbe6ab88d4a4f74cb7fff01bdePeter Collingbourne
5815d4d9807a65291cbe6ab88d4a4f74cb7fff01bdePeter Collingbourne    return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation);
5825d4d9807a65291cbe6ab88d4a4f74cb7fff01bdePeter Collingbourne}
583c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar
5849fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbarstatus_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *config)
5859fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar{
5869fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    Mutex::Autolock _l(mLock);
5879fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    if(!modifyAudioRoutingAllowed()) {
5889fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar        return PERMISSION_DENIED;
5899fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    }
5909fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    if (mAudioPolicyManager == NULL) {
5919fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar        return NO_INIT;
5929fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    }
5939fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar
5949fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar    return mAudioPolicyManager->setAudioPortConfig(config);
5959fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar}
596ecff7c80e5ce4ccb1d2765c234c88efafdc1a378Benjamin Kramer
5979fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbarstatus_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
5989fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar                                       audio_io_handle_t *ioHandle,
5999fcbc050a704cc5bb46e1c493940aca7c79aebf9Daniel Dunbar                                       audio_devices_t *device)
600c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar{
601c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    if (mAudioPolicyManager == NULL) {
602c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar        return NO_INIT;
603c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar    }
604c88a88f6f7672b6bb831dce9da4acfa0c846975fDaniel Dunbar
605d65bddcbe1385a4de212ecbbdc8919c54b3efeb0Daniel Dunbar    return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
6060648262df75d97b464c2be0ed867da3615659785Daniel Dunbar}
607a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar
6080648262df75d97b464c2be0ed867da3615659785Daniel Dunbarstatus_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
6090648262df75d97b464c2be0ed867da3615659785Daniel Dunbar{
6100648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    if (mAudioPolicyManager == NULL) {
6110648262df75d97b464c2be0ed867da3615659785Daniel Dunbar        return NO_INIT;
6120648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    }
6130648262df75d97b464c2be0ed867da3615659785Daniel Dunbar
6140648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    return mAudioPolicyManager->releaseSoundTriggerSession(session);
6150648262df75d97b464c2be0ed867da3615659785Daniel Dunbar}
61653ec55215075c8f4ddd47ca6ed7d382f16beb670Daniel Dunbar
6170648262df75d97b464c2be0ed867da3615659785Daniel Dunbarstatus_t AudioPolicyService::registerPolicyMixes(Vector<AudioMix> mixes, bool registration)
6180648262df75d97b464c2be0ed867da3615659785Daniel Dunbar{
6190648262df75d97b464c2be0ed867da3615659785Daniel Dunbar    Mutex::Autolock _l(mLock);
6203ede8d0a7d1813f678ccc6011a99a0834b1b6116Daniel Dunbar    if(!modifyAudioRoutingAllowed()) {
621dd98e2cad165ca73c769e4f105a4e47c2216387aDaniel Dunbar        return PERMISSION_DENIED;
622c35d71f1e0a0c72fd43a73ddecd408bf43d501deDaniel Dunbar    }
62343302d4144b5291961aa160d2fe191c09a9d8ad1Daniel Dunbar    if (mAudioPolicyManager == NULL) {
62443302d4144b5291961aa160d2fe191c09a9d8ad1Daniel Dunbar        return NO_INIT;
62591e28afe3503893c69afd71877f11e3bf03fa4ceDaniel Dunbar    }
62691e28afe3503893c69afd71877f11e3bf03fa4ceDaniel Dunbar    if (registration) {
6275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner        return mAudioPolicyManager->registerPolicyMixes(mixes);
628a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar    } else {
629a82318332c9e9b61d3d17371e675ca2859877ee5Daniel Dunbar        return mAudioPolicyManager->unregisterPolicyMixes(mixes);
630a18f1b88a7ef3d2c944bb1d3b6586a2860ce2baaTed Kremenek    }
63170c8db1003af49d3627aeef41fcdd7c6c6a7df79Daniel Dunbar}
632793007242ba209b68ce14ec7547ac70ee981303aDaniel Dunbar
6333ee96baa3fff269e145855a6f7526c36e59a7f4bDaniel Dunbar}; // namespace android
6343ee96baa3fff269e145855a6f7526c36e59a7f4bDaniel Dunbar