1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "APM::IOProfile" 18//#define LOG_NDEBUG 0 19 20#include "IOProfile.h" 21#include "HwModule.h" 22#include "AudioGain.h" 23#include "TypeConverter.h" 24 25namespace android { 26 27// checks if the IO profile is compatible with specified parameters. 28// Sampling rate, format and channel mask must be specified in order to 29// get a valid a match 30bool IOProfile::isCompatibleProfile(audio_devices_t device, 31 const String8& address, 32 uint32_t samplingRate, 33 uint32_t *updatedSamplingRate, 34 audio_format_t format, 35 audio_format_t *updatedFormat, 36 audio_channel_mask_t channelMask, 37 audio_channel_mask_t *updatedChannelMask, 38 // FIXME type punning here 39 uint32_t flags, 40 bool exactMatchRequiredForInputFlags) const 41{ 42 const bool isPlaybackThread = 43 getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SOURCE; 44 const bool isRecordThread = 45 getType() == AUDIO_PORT_TYPE_MIX && getRole() == AUDIO_PORT_ROLE_SINK; 46 ALOG_ASSERT(isPlaybackThread != isRecordThread); 47 48 49 if (device != AUDIO_DEVICE_NONE) { 50 // just check types if multiple devices are selected 51 if (popcount(device & ~AUDIO_DEVICE_BIT_IN) > 1) { 52 if ((mSupportedDevices.types() & device) != device) { 53 return false; 54 } 55 } else if (mSupportedDevices.getDevice(device, address) == 0) { 56 return false; 57 } 58 } 59 60 if (!audio_is_valid_format(format) || 61 (isPlaybackThread && (samplingRate == 0 || !audio_is_output_channel(channelMask))) || 62 (isRecordThread && (!audio_is_input_channel(channelMask)))) { 63 return false; 64 } 65 66 audio_format_t myUpdatedFormat = format; 67 audio_channel_mask_t myUpdatedChannelMask = channelMask; 68 uint32_t myUpdatedSamplingRate = samplingRate; 69 if (isRecordThread) 70 { 71 if (checkCompatibleAudioProfile( 72 myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) { 73 return false; 74 } 75 } else { 76 const struct audio_port_config config = { 77 .config_mask = AUDIO_PORT_CONFIG_ALL & ~AUDIO_PORT_CONFIG_GAIN, 78 .sample_rate = samplingRate, 79 .channel_mask = channelMask, 80 .format = format, 81 }; 82 if (checkExactAudioProfile(&config) != NO_ERROR) { 83 return false; 84 } 85 } 86 87 if (isPlaybackThread && (getFlags() & flags) != flags) { 88 return false; 89 } 90 // The only input flag that is allowed to be different is the fast flag. 91 // An existing fast stream is compatible with a normal track request. 92 // An existing normal stream is compatible with a fast track request, 93 // but the fast request will be denied by AudioFlinger and converted to normal track. 94 if (isRecordThread && ((getFlags() ^ flags) & 95 ~(exactMatchRequiredForInputFlags ? AUDIO_INPUT_FLAG_NONE : AUDIO_INPUT_FLAG_FAST))) { 96 return false; 97 } 98 99 if (updatedSamplingRate != NULL) { 100 *updatedSamplingRate = myUpdatedSamplingRate; 101 } 102 if (updatedFormat != NULL) { 103 *updatedFormat = myUpdatedFormat; 104 } 105 if (updatedChannelMask != NULL) { 106 *updatedChannelMask = myUpdatedChannelMask; 107 } 108 return true; 109} 110 111void IOProfile::dump(int fd) 112{ 113 const size_t SIZE = 256; 114 char buffer[SIZE]; 115 String8 result; 116 117 AudioPort::dump(fd, 4); 118 119 snprintf(buffer, SIZE, " - flags: 0x%04x", getFlags()); 120 result.append(buffer); 121 std::string flagsLiteral; 122 if (getRole() == AUDIO_PORT_ROLE_SINK) { 123 InputFlagConverter::maskToString(getFlags(), flagsLiteral); 124 } else if (getRole() == AUDIO_PORT_ROLE_SOURCE) { 125 OutputFlagConverter::maskToString(getFlags(), flagsLiteral); 126 } 127 if (!flagsLiteral.empty()) { 128 result.appendFormat(" (%s)", flagsLiteral.c_str()); 129 } 130 result.append("\n"); 131 write(fd, result.string(), result.size()); 132 mSupportedDevices.dump(fd, String8("Supported"), 4, false); 133 134 result.clear(); 135 snprintf(buffer, SIZE, "\n - maxOpenCount: %u - curOpenCount: %u\n", 136 maxOpenCount, curOpenCount); 137 result.append(buffer); 138 snprintf(buffer, SIZE, " - maxActiveCount: %u - curActiveCount: %u\n", 139 maxActiveCount, curActiveCount); 140 result.append(buffer); 141 142 write(fd, result.string(), result.size()); 143} 144 145void IOProfile::log() 146{ 147 // @TODO: forward log to AudioPort 148} 149 150} // namespace android 151