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::IOProfile"
1856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi//#define LOG_NDEBUG 0
1956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
20ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "IOProfile.h"
21ad3183e2d4cecd02f6261270a7ea1c68be0efa0fFrançois Gaffie#include "HwModule.h"
2298cc191247388132b6fd8a4ecd07abd6e4c5a0edFrançois Gaffie#include "AudioGain.h"
23112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie#include "TypeConverter.h"
2456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivinamespace android {
2656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
2756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// checks if the IO profile is compatible with specified parameters.
2856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// Sampling rate, format and channel mask must be specified in order to
2956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi// get a valid a match
3056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivibool IOProfile::isCompatibleProfile(audio_devices_t device,
31e964d4e421e2d1ca937227a580c0c837091a11e3Chih-Hung Hsieh                                    const String8& address,
3253615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                    uint32_t samplingRate,
3353615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                    uint32_t *updatedSamplingRate,
3453615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                    audio_format_t format,
35f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                                    audio_format_t *updatedFormat,
3653615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                    audio_channel_mask_t channelMask,
37f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung                                    audio_channel_mask_t *updatedChannelMask,
3853615e29c99c5e9d2ca77aaefd7bf5c770513120François Gaffie                                    uint32_t flags) const
3956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
40a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    const bool isPlaybackThread =
41a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE;
42a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    const bool isRecordThread =
43a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie            getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK;
4456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    ALOG_ASSERT(isPlaybackThread != isRecordThread);
4556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
46f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent
47f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent    if (device != AUDIO_DEVICE_NONE) {
48f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent        // just check types if multiple devices are selected
49f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent        if (popcount(device & ~AUDIO_DEVICE_BIT_IN) > 1) {
50f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent            if ((mSupportedDevices.types() & device) != device) {
51f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent                return false;
52f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent            }
53f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent        } else if (mSupportedDevices.getDevice(device, address) == 0) {
54f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent            return false;
55f5d144f7ca773750ea7be371f14f9fc975a15862Eric Laurent        }
5656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
5756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
5805ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten    if (!audio_is_valid_format(format) ||
5905ddca504ce8e0e61b41e5c1aebea72086eea57bGlenn Kasten            (isPlaybackThread && (samplingRate == 0 || !audio_is_output_channel(channelMask))) ||
60112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            (isRecordThread && (!audio_is_input_channel(channelMask)))) {
6156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi         return false;
6256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
6356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
64f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    audio_format_t myUpdatedFormat = format;
65f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    audio_channel_mask_t myUpdatedChannelMask = channelMask;
66112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    uint32_t myUpdatedSamplingRate = samplingRate;
67112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    if (isRecordThread)
68112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    {
69112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (checkCompatibleAudioProfile(
70112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie                myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
71112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return false;
72112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
73112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    } else {
74112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        if (checkExactAudioProfile(samplingRate, channelMask, format) != NO_ERROR) {
75112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie            return false;
76112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie        }
7756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
7856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
79a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (isPlaybackThread && (getFlags() & flags) != flags) {
8056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return false;
8156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
8256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // The only input flag that is allowed to be different is the fast flag.
8356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // An existing fast stream is compatible with a normal track request.
8456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // An existing normal stream is compatible with a fast track request,
8556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    // but the fast request will be denied by AudioFlinger and converted to normal track.
86a8ecc2c72ca26389bd6b0162181d60aaeaca8149François Gaffie    if (isRecordThread && ((getFlags() ^ flags) &
8756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi            ~AUDIO_INPUT_FLAG_FAST)) {
8856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        return false;
8956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
9056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
9156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    if (updatedSamplingRate != NULL) {
9256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi        *updatedSamplingRate = myUpdatedSamplingRate;
9356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    }
94f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    if (updatedFormat != NULL) {
95f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        *updatedFormat = myUpdatedFormat;
96f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    }
97f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    if (updatedChannelMask != NULL) {
98f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung        *updatedChannelMask = myUpdatedChannelMask;
99f129b03fa583d4cc26fd9c9171b8fb3b0ed8d4f4Andy Hung    }
10056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    return true;
10156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
10256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid IOProfile::dump(int fd)
10456ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
10556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    const size_t SIZE = 256;
10656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    char buffer[SIZE];
10756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    String8 result;
10856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
10956ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    AudioPort::dump(fd, 4);
11056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
1116163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    snprintf(buffer, SIZE, "    - flags: 0x%04x", getFlags());
11256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    result.append(buffer);
1136163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    std::string flagsLiteral;
1146163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    if (getRole() == AUDIO_PORT_ROLE_SINK) {
1156163904559247601e9a0834a3c09341862bcff95Mikhail Naganov        InputFlagConverter::maskToString(getFlags(), flagsLiteral);
1166163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    } else if (getRole() == AUDIO_PORT_ROLE_SOURCE) {
1176163904559247601e9a0834a3c09341862bcff95Mikhail Naganov        OutputFlagConverter::maskToString(getFlags(), flagsLiteral);
1186163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    }
1196163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    if (!flagsLiteral.empty()) {
1206163904559247601e9a0834a3c09341862bcff95Mikhail Naganov        result.appendFormat(" (%s)", flagsLiteral.c_str());
1216163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    }
1226163904559247601e9a0834a3c09341862bcff95Mikhail Naganov    result.append("\n");
12356ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi    write(fd, result.string(), result.size());
124f4ad6e5637b6deccdac4b60615383f290b3806cfFrançois Gaffie    mSupportedDevices.dump(fd, String8("Supported"), 4, false);
12556ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
12656ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
12756ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivivoid IOProfile::log()
12856ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi{
129112b0af826aeca45855690b9c105b2cdf9938bbeFrançois Gaffie    // @TODO: forward log to AudioPort
13056ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}
13156ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi
13256ec4ffcbae8aeac6c5245fc7b825d02e2e6cefdJean-Michel Trivi}; // namespace android
133