Home | History | Annotate | Download | only in soundtrigger
      1 /*
      2 **
      3 ** Copyright (C) 2014, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "SoundTrigger"
     19 //#define LOG_NDEBUG 0
     20 
     21 #include <utils/Log.h>
     22 #include <utils/threads.h>
     23 #include <binder/IPCThreadState.h>
     24 #include <binder/IServiceManager.h>
     25 #include <binder/IMemory.h>
     26 
     27 #include <soundtrigger/SoundTrigger.h>
     28 #include <soundtrigger/ISoundTrigger.h>
     29 #include <soundtrigger/ISoundTriggerHwService.h>
     30 #include <soundtrigger/ISoundTriggerClient.h>
     31 #include <soundtrigger/SoundTriggerCallback.h>
     32 
     33 namespace android {
     34 
     35 namespace {
     36     sp<ISoundTriggerHwService> gSoundTriggerHwService;
     37     const int                  kSoundTriggerHwServicePollDelay = 500000; // 0.5s
     38     const char*                kSoundTriggerHwServiceName      = "media.sound_trigger_hw";
     39     Mutex                      gLock;
     40 
     41     class DeathNotifier : public IBinder::DeathRecipient
     42     {
     43     public:
     44         DeathNotifier() {
     45         }
     46 
     47         virtual void binderDied(const wp<IBinder>& who __unused) {
     48             ALOGV("binderDied");
     49             Mutex::Autolock _l(gLock);
     50             gSoundTriggerHwService.clear();
     51             ALOGW("Sound trigger service died!");
     52         }
     53     };
     54 
     55     sp<DeathNotifier>         gDeathNotifier;
     56 }; // namespace anonymous
     57 
     58 const sp<ISoundTriggerHwService> SoundTrigger::getSoundTriggerHwService()
     59 {
     60     Mutex::Autolock _l(gLock);
     61     if (gSoundTriggerHwService.get() == 0) {
     62         sp<IServiceManager> sm = defaultServiceManager();
     63         sp<IBinder> binder;
     64         do {
     65             binder = sm->getService(String16(kSoundTriggerHwServiceName));
     66             if (binder != 0) {
     67                 break;
     68             }
     69             ALOGW("SoundTriggerHwService not published, waiting...");
     70             usleep(kSoundTriggerHwServicePollDelay);
     71         } while(true);
     72         if (gDeathNotifier == NULL) {
     73             gDeathNotifier = new DeathNotifier();
     74         }
     75         binder->linkToDeath(gDeathNotifier);
     76         gSoundTriggerHwService = interface_cast<ISoundTriggerHwService>(binder);
     77     }
     78     ALOGE_IF(gSoundTriggerHwService == 0, "no SoundTriggerHwService!?");
     79     return gSoundTriggerHwService;
     80 }
     81 
     82 // Static methods
     83 status_t SoundTrigger::listModules(struct sound_trigger_module_descriptor *modules,
     84                                  uint32_t *numModules)
     85 {
     86     ALOGV("listModules()");
     87     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
     88     if (service == 0) {
     89         return NO_INIT;
     90     }
     91     return service->listModules(modules, numModules);
     92 }
     93 
     94 sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module,
     95                                             const sp<SoundTriggerCallback>& callback)
     96 {
     97     ALOGV("attach()");
     98     sp<SoundTrigger> soundTrigger;
     99     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
    100     if (service == 0) {
    101         return soundTrigger;
    102     }
    103     soundTrigger = new SoundTrigger(module, callback);
    104     status_t status = service->attach(module, soundTrigger, soundTrigger->mISoundTrigger);
    105 
    106     if (status == NO_ERROR && soundTrigger->mISoundTrigger != 0) {
    107         IInterface::asBinder(soundTrigger->mISoundTrigger)->linkToDeath(soundTrigger);
    108     } else {
    109         ALOGW("Error %d connecting to sound trigger service", status);
    110         soundTrigger.clear();
    111     }
    112     return soundTrigger;
    113 }
    114 
    115 
    116 status_t SoundTrigger::setCaptureState(bool active)
    117 {
    118     ALOGV("setCaptureState(%d)", active);
    119     const sp<ISoundTriggerHwService> service = getSoundTriggerHwService();
    120     if (service == 0) {
    121         return NO_INIT;
    122     }
    123     return service->setCaptureState(active);
    124 }
    125 
    126 // SoundTrigger
    127 SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module,
    128                                  const sp<SoundTriggerCallback>& callback)
    129     : mModule(module), mCallback(callback)
    130 {
    131 }
    132 
    133 SoundTrigger::~SoundTrigger()
    134 {
    135     if (mISoundTrigger != 0) {
    136         mISoundTrigger->detach();
    137     }
    138 }
    139 
    140 
    141 void SoundTrigger::detach() {
    142     ALOGV("detach()");
    143     Mutex::Autolock _l(mLock);
    144     mCallback.clear();
    145     if (mISoundTrigger != 0) {
    146         mISoundTrigger->detach();
    147         IInterface::asBinder(mISoundTrigger)->unlinkToDeath(this);
    148         mISoundTrigger = 0;
    149     }
    150 }
    151 
    152 status_t SoundTrigger::loadSoundModel(const sp<IMemory>& modelMemory,
    153                                 sound_model_handle_t *handle)
    154 {
    155     Mutex::Autolock _l(mLock);
    156     if (mISoundTrigger == 0) {
    157         return NO_INIT;
    158     }
    159 
    160     return mISoundTrigger->loadSoundModel(modelMemory, handle);
    161 }
    162 
    163 status_t SoundTrigger::unloadSoundModel(sound_model_handle_t handle)
    164 {
    165     Mutex::Autolock _l(mLock);
    166     if (mISoundTrigger == 0) {
    167         return NO_INIT;
    168     }
    169     return mISoundTrigger->unloadSoundModel(handle);
    170 }
    171 
    172 status_t SoundTrigger::startRecognition(sound_model_handle_t handle,
    173                                         const sp<IMemory>& dataMemory)
    174 {
    175     Mutex::Autolock _l(mLock);
    176     if (mISoundTrigger == 0) {
    177         return NO_INIT;
    178     }
    179     return mISoundTrigger->startRecognition(handle, dataMemory);
    180 }
    181 
    182 status_t SoundTrigger::stopRecognition(sound_model_handle_t handle)
    183 {
    184     Mutex::Autolock _l(mLock);
    185     if (mISoundTrigger == 0) {
    186         return NO_INIT;
    187     }
    188     return mISoundTrigger->stopRecognition(handle);
    189 }
    190 
    191 // BpSoundTriggerClient
    192 void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
    193 {
    194     Mutex::Autolock _l(mLock);
    195     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    196         return;
    197     }
    198 
    199     if (mCallback != 0) {
    200         mCallback->onRecognitionEvent(
    201                 (struct sound_trigger_recognition_event *)eventMemory->pointer());
    202     }
    203 }
    204 
    205 void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
    206 {
    207     Mutex::Autolock _l(mLock);
    208     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    209         return;
    210     }
    211 
    212     if (mCallback != 0) {
    213         mCallback->onSoundModelEvent(
    214                 (struct sound_trigger_model_event *)eventMemory->pointer());
    215     }
    216 }
    217 
    218 void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
    219 {
    220     Mutex::Autolock _l(mLock);
    221     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    222         return;
    223     }
    224 
    225     if (mCallback != 0) {
    226         mCallback->onServiceStateChange(
    227                 *((sound_trigger_service_state_t *)eventMemory->pointer()));
    228     }
    229 }
    230 
    231 //IBinder::DeathRecipient
    232 void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {
    233     Mutex::Autolock _l(mLock);
    234     ALOGW("SoundTrigger server binder Died ");
    235     mISoundTrigger = 0;
    236     if (mCallback != 0) {
    237         mCallback->onServiceDied();
    238     }
    239 }
    240 
    241 status_t SoundTrigger::stringToGuid(const char *str, sound_trigger_uuid_t *guid)
    242 {
    243     if (str == NULL || guid == NULL) {
    244         return BAD_VALUE;
    245     }
    246 
    247     int tmp[10];
    248 
    249     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    250             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
    251         return BAD_VALUE;
    252     }
    253     guid->timeLow = (uint32_t)tmp[0];
    254     guid->timeMid = (uint16_t)tmp[1];
    255     guid->timeHiAndVersion = (uint16_t)tmp[2];
    256     guid->clockSeq = (uint16_t)tmp[3];
    257     guid->node[0] = (uint8_t)tmp[4];
    258     guid->node[1] = (uint8_t)tmp[5];
    259     guid->node[2] = (uint8_t)tmp[6];
    260     guid->node[3] = (uint8_t)tmp[7];
    261     guid->node[4] = (uint8_t)tmp[8];
    262     guid->node[5] = (uint8_t)tmp[9];
    263 
    264     return NO_ERROR;
    265 }
    266 
    267 status_t SoundTrigger::guidToString(const sound_trigger_uuid_t *guid, char *str, size_t maxLen)
    268 {
    269     if (guid == NULL || str == NULL) {
    270         return BAD_VALUE;
    271     }
    272 
    273     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
    274             guid->timeLow,
    275             guid->timeMid,
    276             guid->timeHiAndVersion,
    277             guid->clockSeq,
    278             guid->node[0],
    279             guid->node[1],
    280             guid->node[2],
    281             guid->node[3],
    282             guid->node[4],
    283             guid->node[5]);
    284 
    285     return NO_ERROR;
    286 }
    287 
    288 }; // namespace android
    289