Home | History | Annotate | Download | only in binding
      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 
     38 using android::String16;
     39 using android::IServiceManager;
     40 using android::defaultServiceManager;
     41 using android::interface_cast;
     42 using android::IAAudioService;
     43 using android::Mutex;
     44 using android::sp;
     45 
     46 using namespace aaudio;
     47 
     48 static android::Mutex gServiceLock;
     49 static sp<IAAudioService>  gAAudioService;
     50 
     51 ANDROID_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
     56 static 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 
     81 static void dropAAudioService() {
     82     Mutex::Autolock _l(gServiceLock);
     83     gAAudioService.clear(); // force a reconnect
     84 }
     85 
     86 AAudioBinderClient::AAudioBinderClient()
     87         : AAudioServiceInterface()
     88         , Singleton<AAudioBinderClient>() {}
     89 
     90 AAudioBinderClient::~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 */
     97 aaudio_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 
    118 aaudio_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 */
    127 aaudio_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 
    134 aaudio_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 
    140 aaudio_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 
    146 aaudio_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 
    152 aaudio_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 */
    161 aaudio_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 
    173 aaudio_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