1/* 2 * Copyright (C) 2017 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 18#define LOG_TAG "AAudio" 19//#define LOG_NDEBUG 0 20#include <utils/Log.h> 21 22#include <binder/IServiceManager.h> 23#include <utils/Mutex.h> 24#include <utils/RefBase.h> 25#include <utils/Singleton.h> 26 27#include <aaudio/AAudio.h> 28 29#include "AudioEndpointParcelable.h" 30#include "binding/AAudioStreamRequest.h" 31#include "binding/AAudioStreamConfiguration.h" 32#include "binding/IAAudioService.h" 33#include "binding/AAudioServiceMessage.h" 34 35#include "AAudioBinderClient.h" 36#include "AAudioServiceInterface.h" 37 38using android::String16; 39using android::IServiceManager; 40using android::defaultServiceManager; 41using android::interface_cast; 42using android::IAAudioService; 43using android::Mutex; 44using android::sp; 45 46using namespace aaudio; 47 48static android::Mutex gServiceLock; 49static sp<IAAudioService> gAAudioService; 50 51ANDROID_SINGLETON_STATIC_INSTANCE(AAudioBinderClient); 52 53// TODO Share code with other service clients. 54// Helper function to get access to the "AAudioService" service. 55// This code was modeled after frameworks/av/media/libaudioclient/AudioSystem.cpp 56static const sp<IAAudioService> getAAudioService() { 57 sp<IBinder> binder; 58 Mutex::Autolock _l(gServiceLock); 59 if (gAAudioService == 0) { 60 sp<IServiceManager> sm = defaultServiceManager(); 61 // Try several times to get the service. 62 int retries = 4; 63 do { 64 binder = sm->getService(String16(AAUDIO_SERVICE_NAME)); // This will wait a while. 65 if (binder != 0) { 66 break; 67 } 68 } while (retries-- > 0); 69 70 if (binder != 0) { 71 // TODO Add linkToDeath() like in frameworks/av/media/libaudioclient/AudioSystem.cpp 72 // TODO Create a DeathRecipient that disconnects all active streams. 73 gAAudioService = interface_cast<IAAudioService>(binder); 74 } else { 75 ALOGE("AudioStreamInternal could not get %s", AAUDIO_SERVICE_NAME); 76 } 77 } 78 return gAAudioService; 79} 80 81static void dropAAudioService() { 82 Mutex::Autolock _l(gServiceLock); 83 gAAudioService.clear(); // force a reconnect 84} 85 86AAudioBinderClient::AAudioBinderClient() 87 : AAudioServiceInterface() 88 , Singleton<AAudioBinderClient>() {} 89 90AAudioBinderClient::~AAudioBinderClient() {} 91 92/** 93* @param request info needed to create the stream 94* @param configuration contains information about the created stream 95* @return handle to the stream or a negative error 96*/ 97aaudio_handle_t AAudioBinderClient::openStream(const AAudioStreamRequest &request, 98 AAudioStreamConfiguration &configurationOutput) { 99 aaudio_handle_t stream; 100 for (int i = 0; i < 2; i++) { 101 const sp<IAAudioService> &service = getAAudioService(); 102 if (service == 0) { 103 return AAUDIO_ERROR_NO_SERVICE; 104 } 105 106 stream = service->openStream(request, configurationOutput); 107 108 if (stream == AAUDIO_ERROR_NO_SERVICE) { 109 ALOGE("AAudioBinderClient: lost connection to AAudioService."); 110 dropAAudioService(); // force a reconnect 111 } else { 112 break; 113 } 114 } 115 return stream; 116} 117 118aaudio_result_t AAudioBinderClient::closeStream(aaudio_handle_t streamHandle) { 119 const sp<IAAudioService> &service = getAAudioService(); 120 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 121 return service->closeStream(streamHandle); 122} 123 124/* Get an immutable description of the in-memory queues 125* used to communicate with the underlying HAL or Service. 126*/ 127aaudio_result_t AAudioBinderClient::getStreamDescription(aaudio_handle_t streamHandle, 128 AudioEndpointParcelable &parcelable) { 129 const sp<IAAudioService> &service = getAAudioService(); 130 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 131 return service->getStreamDescription(streamHandle, parcelable); 132} 133 134aaudio_result_t AAudioBinderClient::startStream(aaudio_handle_t streamHandle) { 135 const sp<IAAudioService> &service = getAAudioService(); 136 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 137 return service->startStream(streamHandle); 138} 139 140aaudio_result_t AAudioBinderClient::pauseStream(aaudio_handle_t streamHandle) { 141 const sp<IAAudioService> &service = getAAudioService(); 142 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 143 return service->pauseStream(streamHandle); 144} 145 146aaudio_result_t AAudioBinderClient::stopStream(aaudio_handle_t streamHandle) { 147 const sp<IAAudioService> &service = getAAudioService(); 148 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 149 return service->stopStream(streamHandle); 150} 151 152aaudio_result_t AAudioBinderClient::flushStream(aaudio_handle_t streamHandle) { 153 const sp<IAAudioService> &service = getAAudioService(); 154 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 155 return service->flushStream(streamHandle); 156} 157 158/** 159* Manage the specified thread as a low latency audio thread. 160*/ 161aaudio_result_t AAudioBinderClient::registerAudioThread(aaudio_handle_t streamHandle, 162 pid_t clientProcessId, 163 pid_t clientThreadId, 164 int64_t periodNanoseconds) { 165 const sp<IAAudioService> &service = getAAudioService(); 166 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 167 return service->registerAudioThread(streamHandle, 168 clientProcessId, 169 clientThreadId, 170 periodNanoseconds); 171} 172 173aaudio_result_t AAudioBinderClient::unregisterAudioThread(aaudio_handle_t streamHandle, 174 pid_t clientProcessId, 175 pid_t clientThreadId) { 176 const sp<IAAudioService> &service = getAAudioService(); 177 if (service == 0) return AAUDIO_ERROR_NO_SERVICE; 178 return service->unregisterAudioThread(streamHandle, 179 clientProcessId, 180 clientThreadId); 181} 182