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::AudioPatch" 18//#define LOG_NDEBUG 0 19 20#include "AudioPatch.h" 21#include "AudioGain.h" 22#include "TypeConverter.h" 23 24#include <log/log.h> 25#include <utils/String8.h> 26 27namespace android { 28 29AudioPatch::AudioPatch(const struct audio_patch *patch, uid_t uid) : 30 mHandle(HandleGenerator<audio_patch_handle_t>::getNextHandle()), 31 mPatch(*patch), 32 mUid(uid), 33 mAfPatchHandle(AUDIO_PATCH_HANDLE_NONE) 34{ 35} 36 37status_t AudioPatch::dump(int fd, int spaces, int index) const 38{ 39 const size_t SIZE = 256; 40 char buffer[SIZE]; 41 String8 result; 42 43 snprintf(buffer, SIZE, "%*sAudio patch %d:\n", spaces, "", index+1); 44 result.append(buffer); 45 snprintf(buffer, SIZE, "%*s- handle: %2d\n", spaces, "", mHandle); 46 result.append(buffer); 47 snprintf(buffer, SIZE, "%*s- audio flinger handle: %2d\n", spaces, "", mAfPatchHandle); 48 result.append(buffer); 49 snprintf(buffer, SIZE, "%*s- owner uid: %2d\n", spaces, "", mUid); 50 result.append(buffer); 51 snprintf(buffer, SIZE, "%*s- %d sources:\n", spaces, "", mPatch.num_sources); 52 result.append(buffer); 53 for (size_t i = 0; i < mPatch.num_sources; i++) { 54 if (mPatch.sources[i].type == AUDIO_PORT_TYPE_DEVICE) { 55 std::string device; 56 deviceToString(mPatch.sources[i].ext.device.type, device); 57 snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "", 58 mPatch.sources[i].id, 59 device.c_str()); 60 } else { 61 snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "", 62 mPatch.sources[i].id, mPatch.sources[i].ext.mix.handle); 63 } 64 result.append(buffer); 65 } 66 snprintf(buffer, SIZE, "%*s- %d sinks:\n", spaces, "", mPatch.num_sinks); 67 result.append(buffer); 68 for (size_t i = 0; i < mPatch.num_sinks; i++) { 69 if (mPatch.sinks[i].type == AUDIO_PORT_TYPE_DEVICE) { 70 std::string device; 71 deviceToString(mPatch.sinks[i].ext.device.type, device); 72 snprintf(buffer, SIZE, "%*s- Device ID %d %s\n", spaces + 2, "", 73 mPatch.sinks[i].id, 74 device.c_str()); 75 } else { 76 snprintf(buffer, SIZE, "%*s- Mix ID %d I/O handle %d\n", spaces + 2, "", 77 mPatch.sinks[i].id, mPatch.sinks[i].ext.mix.handle); 78 } 79 result.append(buffer); 80 } 81 82 write(fd, result.string(), result.size()); 83 return NO_ERROR; 84} 85 86status_t AudioPatchCollection::addAudioPatch(audio_patch_handle_t handle, 87 const sp<AudioPatch>& patch) 88{ 89 ssize_t index = indexOfKey(handle); 90 91 if (index >= 0) { 92 ALOGW("addAudioPatch() patch %d already in", handle); 93 return ALREADY_EXISTS; 94 } 95 add(handle, patch); 96 ALOGV("addAudioPatch() handle %d af handle %d num_sources %d num_sinks %d source handle %d" 97 "sink handle %d", 98 handle, patch->mAfPatchHandle, patch->mPatch.num_sources, patch->mPatch.num_sinks, 99 patch->mPatch.sources[0].id, patch->mPatch.sinks[0].id); 100 return NO_ERROR; 101} 102 103status_t AudioPatchCollection::removeAudioPatch(audio_patch_handle_t handle) 104{ 105 ssize_t index = indexOfKey(handle); 106 107 if (index < 0) { 108 ALOGW("removeAudioPatch() patch %d not in", handle); 109 return ALREADY_EXISTS; 110 } 111 ALOGV("removeAudioPatch() handle %d af handle %d", handle, valueAt(index)->mAfPatchHandle); 112 removeItemsAt(index); 113 return NO_ERROR; 114} 115 116status_t AudioPatchCollection::listAudioPatches(unsigned int *num_patches, 117 struct audio_patch *patches) const 118{ 119 if (num_patches == NULL || (*num_patches != 0 && patches == NULL)) { 120 return BAD_VALUE; 121 } 122 ALOGV("listAudioPatches() num_patches %d patches %p available patches %zu", 123 *num_patches, patches, size()); 124 if (patches == NULL) { 125 *num_patches = 0; 126 } 127 128 size_t patchesWritten = 0; 129 size_t patchesMax = *num_patches; 130 *num_patches = 0; 131 for (size_t patchIndex = 0; patchIndex < size(); patchIndex++) { 132 // do not report patches with AUDIO_DEVICE_IN_STUB as source or 133 // AUDIO_DEVICE_OUT_STUB as sink as those devices are used by stub HALs by convention 134 const sp<AudioPatch> patch = valueAt(patchIndex); 135 bool skip = false; 136 for (size_t srcIndex = 0; srcIndex < patch->mPatch.num_sources && !skip; srcIndex++) { 137 if (patch->mPatch.sources[srcIndex].type == AUDIO_PORT_TYPE_DEVICE && 138 patch->mPatch.sources[srcIndex].ext.device.type == AUDIO_DEVICE_IN_STUB) { 139 skip = true; 140 } 141 } 142 for (size_t sinkIndex = 0; sinkIndex < patch->mPatch.num_sinks && !skip; sinkIndex++) { 143 if (patch->mPatch.sinks[sinkIndex].type == AUDIO_PORT_TYPE_DEVICE && 144 patch->mPatch.sinks[sinkIndex].ext.device.type == AUDIO_DEVICE_OUT_STUB) { 145 skip = true; 146 } 147 } 148 if (skip) { 149 continue; // to next audio patch 150 } 151 if (patchesWritten < patchesMax) { 152 patches[patchesWritten] = patch->mPatch; 153 patches[patchesWritten++].id = patch->mHandle; 154 } 155 (*num_patches)++; 156 ALOGV("listAudioPatches() patch %zu num_sources %d num_sinks %d", 157 patchIndex, patch->mPatch.num_sources, patch->mPatch.num_sinks); 158 } 159 160 ALOGV("listAudioPatches() got %zu patches needed %d", patchesWritten, *num_patches); 161 return NO_ERROR; 162} 163 164status_t AudioPatchCollection::dump(int fd) const 165{ 166 const size_t SIZE = 256; 167 char buffer[SIZE]; 168 snprintf(buffer, SIZE, "\nAudio Patches:\n"); 169 write(fd, buffer, strlen(buffer)); 170 for (size_t i = 0; i < size(); i++) { 171 valueAt(i)->dump(fd, 2, i); 172 } 173 return NO_ERROR; 174} 175 176} // namespace android 177