156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi/*
256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Copyright (C) 2015 The Android Open Source Project
356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * you may not use this file except in compliance with the License.
656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * You may obtain a copy of the License at
756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi *
1056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * See the License for the specific language governing permissions and
1456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi * limitations under the License.
1556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi */
1656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#define LOG_TAG "APM::HwModule"
1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define LOG_NDEBUG 0
1956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
20ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "HwModule.h"
21ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "IOProfile.h"
2298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioGain.h"
2356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi#include <hardware/audio.h>
2453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie#include <policy.h>
2556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
2756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
28a8ecc2c72ca26389bd6b0162181d60aaeaca8149François GaffieHwModule::HwModule(const char *name, uint32_t halVersion)
29a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    : mName(String8(name)),
30a13cde98a880341f0a56d91da6364b093fb5d24eGlenn Kasten      mHandle(AUDIO_MODULE_HANDLE_NONE),
31a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie      mHalVersion(halVersion)
3256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
3356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
3456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
3556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel TriviHwModule::~HwModule()
3656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
3756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
38a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        mOutputProfiles[i]->clearSupportedDevices();
3956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
4056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mInputProfiles.size(); i++) {
41a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        mInputProfiles[i]->clearSupportedDevices();
4256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
4356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
4456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
4556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t HwModule::addOutputProfile(String8 name, const audio_config_t *config,
46112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                    audio_devices_t device, String8 address)
4756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
48a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    sp<IOProfile> profile = new OutputProfile(name);
4956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
50112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
51112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                              config->sample_rate));
5256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
537288ab87a7aa730ffe97d7dc7e118123107bfceaEric Laurent    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
5456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    devDesc->mAddress = address;
55a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    profile->addSupportedDevice(devDesc);
5656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
57a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return addOutputProfile(profile);
58a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
59a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
60a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t HwModule::addOutputProfile(const sp<IOProfile> &profile)
61a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
62322b4d25387a04c9afebe998326d005bbdf17edeEric Laurent    profile->attach(this);
6356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    mOutputProfiles.add(profile);
64cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    mPorts.add(profile);
65a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return NO_ERROR;
66a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
6756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
68a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t HwModule::addInputProfile(const sp<IOProfile> &profile)
69a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
70a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    profile->attach(this);
71a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    mInputProfiles.add(profile);
72cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    mPorts.add(profile);
7356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return NO_ERROR;
7456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
7556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
76a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffiestatus_t HwModule::addProfile(const sp<IOProfile> &profile)
77a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
78a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    switch (profile->getRole()) {
79a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    case AUDIO_PORT_ROLE_SOURCE:
80a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return addOutputProfile(profile);
81a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    case AUDIO_PORT_ROLE_SINK:
82a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return addInputProfile(profile);
83a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    case AUDIO_PORT_ROLE_NONE:
84a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        return BAD_VALUE;
85a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
86a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return BAD_VALUE;
87a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
88a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
89a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffievoid HwModule::setProfiles(const IOProfileCollection &profiles)
90a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie{
91a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    for (size_t i = 0; i < profiles.size(); i++) {
92a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        addProfile(profiles[i]);
93a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    }
94a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie}
95a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie
9656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t HwModule::removeOutputProfile(String8 name)
9756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
9856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
99a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (mOutputProfiles[i]->getName() == name) {
10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mOutputProfiles.removeAt(i);
10156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            break;
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
10356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
10456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return NO_ERROR;
10656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
10756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t HwModule::addInputProfile(String8 name, const audio_config_t *config,
109112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                   audio_devices_t device, String8 address)
11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
111a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    sp<IOProfile> profile = new InputProfile(name);
112112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    profile->addAudioProfile(new AudioProfile(config->format, config->channel_mask,
113112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                                              config->sample_rate));
11456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1157288ab87a7aa730ffe97d7dc7e118123107bfceaEric Laurent    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
11656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    devDesc->mAddress = address;
117a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    profile->addSupportedDevice(devDesc);
11856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1197b279bbc24139ee1e01b58055ca94926ec18e2e9Eric Laurent    ALOGV("addInputProfile() name %s rate %d mask 0x%08x",
1207b279bbc24139ee1e01b58055ca94926ec18e2e9Eric Laurent          name.string(), config->sample_rate, config->channel_mask);
12156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
122a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    return addInputProfile(profile);
12356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
12456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
12556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivistatus_t HwModule::removeInputProfile(String8 name)
12656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
12756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    for (size_t i = 0; i < mInputProfiles.size(); i++) {
128a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (mInputProfiles[i]->getName() == name) {
12956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mInputProfiles.removeAt(i);
13056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            break;
13156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
13256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
13356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
13456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return NO_ERROR;
13556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
13656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
137cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffievoid HwModule::setDeclaredDevices(const DeviceVector &devices)
138cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie{
139cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    mDeclaredDevices = devices;
140cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    for (size_t i = 0; i < devices.size(); i++) {
141cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        mPorts.add(devices[i]);
142cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    }
143cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}
144cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie
145cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffiesp<DeviceDescriptor> HwModule::getRouteSinkDevice(const sp<AudioRoute> &route) const
146cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie{
147cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    sp<DeviceDescriptor> sinkDevice = 0;
148cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    if (route->getSink()->getType() == AUDIO_PORT_TYPE_DEVICE) {
149cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        sinkDevice = mDeclaredDevices.getDeviceFromTagName(route->getSink()->getTagName());
150cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    }
151cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    return sinkDevice;
152cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}
153cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie
154cbb3044d6bfa9ab30c83b67874f40344e29805e1François GaffieDeviceVector HwModule::getRouteSourceDevices(const sp<AudioRoute> &route) const
155cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie{
156cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    DeviceVector sourceDevices;
157cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    Vector <sp<AudioPort> > sources = route->getSources();
158cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    for (size_t i = 0; i < sources.size(); i++) {
159cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        if (sources[i]->getType() == AUDIO_PORT_TYPE_DEVICE) {
160cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sourceDevices.add(mDeclaredDevices.getDeviceFromTagName(sources[i]->getTagName()));
161cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        }
162cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    }
163cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    return sourceDevices;
164cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}
165cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie
166cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffievoid HwModule::setRoutes(const AudioRouteVector &routes)
167cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie{
168cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    mRoutes = routes;
169cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    // Now updating the streams (aka IOProfile until now) supported devices
170cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    refreshSupportedDevices();
171cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}
172cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie
173cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffievoid HwModule::refreshSupportedDevices()
174cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie{
175cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    // Now updating the streams (aka IOProfile until now) supported devices
176cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    for (size_t i = 0; i < mInputProfiles.size(); i++) {
177cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        sp<IOProfile> stream = mInputProfiles[i];
178cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        DeviceVector sourceDevices;
179cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        const AudioRouteVector &routes = stream->getRoutes();
180cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        for (size_t j = 0; j < routes.size(); j++) {
181cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sp<AudioPort> sink = routes[j]->getSink();
182cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            if (sink == 0 || stream != sink) {
183cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                ALOGE("%s: Invalid route attached to input stream", __FUNCTION__);
184cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                continue;
185cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            }
186cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            DeviceVector sourceDevicesForRoute = getRouteSourceDevices(routes[j]);
187cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            if (sourceDevicesForRoute.isEmpty()) {
188cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
189cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                continue;
190cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            }
191cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sourceDevices.add(sourceDevicesForRoute);
192cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        }
193cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        if (sourceDevices.isEmpty()) {
194cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            ALOGE("%s: invalid source devices for %s", __FUNCTION__, stream->getName().string());
195cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            continue;
196cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        }
197cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        stream->setSupportedDevices(sourceDevices);
198cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    }
199cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    for (size_t i = 0; i < mOutputProfiles.size(); i++) {
200cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        sp<IOProfile> stream = mOutputProfiles[i];
201cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        DeviceVector sinkDevices;
202cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        const AudioRouteVector &routes = stream->getRoutes();
203cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        for (size_t j = 0; j < routes.size(); j++) {
204cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sp<AudioPort> source = routes[j]->getSources().findByTagName(stream->getTagName());
205cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            if (source == 0 || stream != source) {
206cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                ALOGE("%s: Invalid route attached to output stream", __FUNCTION__);
207cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                continue;
208cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            }
209cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sp<DeviceDescriptor> sinkDevice = getRouteSinkDevice(routes[j]);
210cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            if (sinkDevice == 0) {
211cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                ALOGE("%s: invalid sink device for %s", __FUNCTION__, stream->getName().string());
212cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie                continue;
213cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            }
214cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie            sinkDevices.add(sinkDevice);
215cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        }
216cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie        stream->setSupportedDevices(sinkDevices);
217cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie    }
218cbb3044d6bfa9ab30c83b67874f40344e29805e1François Gaffie}
21956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
22056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid HwModule::dump(int fd)
22156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
22256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const size_t SIZE = 256;
22356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char buffer[SIZE];
22456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    String8 result;
22556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
226a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    snprintf(buffer, SIZE, "  - name: %s\n", getName());
22756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
22856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "  - handle: %d\n", mHandle);
22956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
23056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    snprintf(buffer, SIZE, "  - version: %u.%u\n", mHalVersion >> 8, mHalVersion & 0xFF);
23156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
23256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    write(fd, result.string(), result.size());
23356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mOutputProfiles.size()) {
23456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        write(fd, "  - outputs:\n", strlen("  - outputs:\n"));
23556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mOutputProfiles.size(); i++) {
23656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            snprintf(buffer, SIZE, "    output %zu:\n", i);
23756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            write(fd, buffer, strlen(buffer));
23856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mOutputProfiles[i]->dump(fd);
23956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
24056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
24156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (mInputProfiles.size()) {
24256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        write(fd, "  - inputs:\n", strlen("  - inputs:\n"));
24356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        for (size_t i = 0; i < mInputProfiles.size(); i++) {
24456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            snprintf(buffer, SIZE, "    input %zu:\n", i);
24556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            write(fd, buffer, strlen(buffer));
24656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            mInputProfiles[i]->dump(fd);
24756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        }
24856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
249112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    mDeclaredDevices.dump(fd, String8("Declared"),  2, true);
250f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mRoutes.dump(fd, 2);
25156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
25256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
25353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffiesp <HwModule> HwModuleCollection::getModuleFromName(const char *name) const
25453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
25553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    sp <HwModule> module;
25653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
25753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    for (size_t i = 0; i < size(); i++)
25853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    {
259a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (strcmp(itemAt(i)->getName(), name) == 0) {
26053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            return itemAt(i);
26153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
26253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
26353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return module;
26453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
26553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
26653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
26753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffiesp <HwModule> HwModuleCollection::getModuleForDevice(audio_devices_t device) const
26853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
26953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    sp <HwModule> module;
27053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
27153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    for (size_t i = 0; i < size(); i++) {
272a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie        if (itemAt(i)->getHandle() == 0) {
27353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            continue;
27453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
27553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        if (audio_is_output_device(device)) {
27653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            for (size_t j = 0; j < itemAt(i)->mOutputProfiles.size(); j++)
27753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            {
278a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                if (itemAt(i)->mOutputProfiles[j]->supportDevice(device)) {
27953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                    return itemAt(i);
28053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                }
28153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
28253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        } else {
28353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            for (size_t j = 0; j < itemAt(i)->mInputProfiles.size(); j++) {
284a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie                if (itemAt(i)->mInputProfiles[j]->supportDevice(device)) {
28553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                    return itemAt(i);
28653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                }
28753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            }
28853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
28953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
29053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return module;
29153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
29253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
29353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffiesp<DeviceDescriptor>  HwModuleCollection::getDeviceDescriptor(const audio_devices_t device,
29453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                                              const char *device_address,
295634b71478742310960f3fdb4241e70a0735712c4Eric Laurent                                                              const char *device_name,
296634b71478742310960f3fdb4241e70a0735712c4Eric Laurent                                                              bool matchAdress) const
29753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
29853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    String8 address = (device_address == NULL) ? String8("") : String8(device_address);
29953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    // handle legacy remote submix case where the address was not always specified
30053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    if (device_distinguishes_on_address(device) && (address.length() == 0)) {
30153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        address = String8("0");
30253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
30353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
30453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    for (size_t i = 0; i < size(); i++) {
30553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        const sp<HwModule> hwModule = itemAt(i);
30653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        if (hwModule->mHandle == 0) {
30753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            continue;
30853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
309634b71478742310960f3fdb4241e70a0735712c4Eric Laurent        DeviceVector declaredDevices = hwModule->getDeclaredDevices();
310634b71478742310960f3fdb4241e70a0735712c4Eric Laurent        DeviceVector deviceList = declaredDevices.getDevicesFromTypeAddr(device, address);
31153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        if (!deviceList.isEmpty()) {
31253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie            return deviceList.itemAt(0);
31353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        }
314634b71478742310960f3fdb4241e70a0735712c4Eric Laurent        if (!matchAdress) {
315634b71478742310960f3fdb4241e70a0735712c4Eric Laurent            deviceList = declaredDevices.getDevicesFromType(device);
316634b71478742310960f3fdb4241e70a0735712c4Eric Laurent            if (!deviceList.isEmpty()) {
317634b71478742310960f3fdb4241e70a0735712c4Eric Laurent                return deviceList.itemAt(0);
318634b71478742310960f3fdb4241e70a0735712c4Eric Laurent            }
319634b71478742310960f3fdb4241e70a0735712c4Eric Laurent        }
32053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
32153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
3221d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie    sp<DeviceDescriptor> devDesc = new DeviceDescriptor(device);
3231d4481fb9cb1ea149f79f2a5d22110af84fbc90bFrançois Gaffie    devDesc->setName(String8(device_name));
32453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    devDesc->mAddress = address;
32553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return devDesc;
32653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
32753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
32853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffiestatus_t HwModuleCollection::dump(int fd) const
32953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie{
33053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    const size_t SIZE = 256;
33153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    char buffer[SIZE];
33253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
33353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    snprintf(buffer, SIZE, "\nHW Modules dump:\n");
33453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    write(fd, buffer, strlen(buffer));
33553615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    for (size_t i = 0; i < size(); i++) {
33653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        snprintf(buffer, SIZE, "- HW Module %zu:\n", i + 1);
33753615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        write(fd, buffer, strlen(buffer));
33853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie        itemAt(i)->dump(fd);
33953615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    }
34053615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie    return NO_ERROR;
34153615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie}
34253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie
34356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi} //namespace android
344