static int out_standby_stream_locked(struct astream_out *out) { int ret = 0; int attempts = MAX_WRITE_COMPLETION_ATTEMPTS; if (out->standby || !out->data) return 0; out->standby = true; /* wait for write completion if needed */ while (out->write_busy && attempts--) { ret = pthread_cond_timeout_np(&out->write_cond, &out->lock, BUF_WRITE_COMPLETION_TIMEOUT_MS); LOGE_IF(ret != 0, "out_standby_stream_locked() wait cond error %d", ret); } LOGE_IF(attempts == 0, "out_standby_stream_locked() a2dp_write() would not stop!!!"); LOGV_IF(!out->bt_enabled, "Standby skip stop: enabled %d", out->bt_enabled); if (out->bt_enabled) { ret = a2dp_stop(out->data); } release_wake_lock(A2DP_WAKE_LOCK_NAME); return ret; }
/* you must be inside a m_mutex lock to invoke this! */ static int32_t wait(NVEventSem* sem, pthread_mutex_t* mutex, int waitMS) { if(sem->m_block) { if( waitMS < 0 ) { return pthread_cond_wait(&sem->m_cond, mutex); } else { return pthread_cond_timeout_np(&sem->m_cond, mutex, (unsigned)waitMS); } } return 1; }
/* you must be inside mutex lock to invoke this! */ static int32_t wait(NVEventSync * sem, pthread_mutex_t * mutex, int waitMS) { // TBD - spec is dodgy; do we definitely release the mutex even if // wait fails? if(sem->m_block) { if( waitMS < 0 ) return pthread_cond_wait(&sem->m_cond, mutex); else return pthread_cond_timeout_np(&sem->m_cond, mutex, (unsigned)waitMS); } else { // must release this, as failure assumes no lock pthread_mutex_unlock(mutex); return 1; // do not return 0 - we do not own the lock! } }
static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) { int err = 0; #ifndef USE_NP struct timespec ts; #endif /*USE_NP*/ if(sp_response != NULL) { err = AT_ERROR_COMMAND_PENDING; goto error; } err = writeline (command); if (err < 0) { goto error; } s_type = type; s_responsePrefix = responsePrefix; s_smsPDU = smspdu; sp_response = at_response_new(); #ifndef USE_NP if (timeoutMsec != 0) { setTimespecRelative(&ts, timeoutMsec); } #endif /*USE_NP*/ while (sp_response->finalResponse == NULL && s_readerClosed == 0) { if (timeoutMsec != 0) { #ifdef USE_NP err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); #else err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts); #endif /*USE_NP*/ } else { err = pthread_cond_wait(&s_commandcond, &s_commandmutex); } if (err == ETIMEDOUT) { err = AT_ERROR_TIMEOUT; goto error; } } if (pp_outResponse == NULL) { at_response_free(sp_response); } else { /* line reader stores intermediate responses in reverse order */ reverseIntermediates(sp_response); *pp_outResponse = sp_response; } sp_response = NULL; if(s_readerClosed > 0) { err = AT_ERROR_CHANNEL_CLOSED; goto error; } err = 0; error: clearPendingCommand(); return err; }
/** * Internal send_command implementation. * Doesn't lock or call the timeout callback. * * timeoutMsec == 0 means infinite timeout. */ static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) { int err = AT_NOERROR; struct atcontext *ac = getAtContext(); /* Default to NULL, to allow caller to free securely even if * no response will be set below */ if (pp_outResponse != NULL) *pp_outResponse = NULL; /* FIXME This is to prevent future problems due to calls from other threads; should be revised. */ while (pthread_mutex_trylock(&ac->requestmutex) == EBUSY) pthread_cond_wait(&ac->requestcond, &ac->commandmutex); if(ac->response != NULL) { err = AT_ERROR_COMMAND_PENDING; goto finally; } ac->type = type; ac->responsePrefix = responsePrefix; ac->smsPDU = smspdu; ac->response = at_response_new(); if (ac->response == NULL) { err = AT_ERROR_MEMORY_ALLOCATION; goto finally; } err = writeline (command); if (err != AT_NOERROR) goto finally; while (ac->response->finalResponse == NULL && ac->readerClosed == 0) { if (timeoutMsec != 0) err = pthread_cond_timeout_np(&ac->commandcond, &ac->commandmutex, timeoutMsec); else err = pthread_cond_wait(&ac->commandcond, &ac->commandmutex); if (err == ETIMEDOUT) { err = AT_ERROR_TIMEOUT; goto finally; } } if (ac->response->success == 0) { err = at_get_error(ac->response); } if (pp_outResponse == NULL) at_response_free(ac->response); else { /* Line reader stores intermediate responses in reverse order. */ reverseIntermediates(ac->response); *pp_outResponse = ac->response; } ac->response = NULL; if(ac->readerClosed > 0) { err = AT_ERROR_CHANNEL_CLOSED; goto finally; } finally: clearPendingCommand(); pthread_cond_broadcast(&ac->requestcond); pthread_mutex_unlock(&ac->requestmutex); return err; }
void *SpeechVMRecorder::DumpVMRecordDataThread(void *arg) { // Adjust thread priority prctl(PR_SET_NAME, (unsigned long)__FUNCTION__, 0, 0, 0); setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO); ALOGD("%s(), pid: %d, tid: %d", __FUNCTION__, getpid(), gettid()); SpeechVMRecorder *pSpeechVMRecorder = (SpeechVMRecorder *)arg; RingBuf &ring_buf = pSpeechVMRecorder->mRingBuf; // open modem record function SpeechDriverInterface *pSpeechDriver = SpeechDriverFactory::GetInstance()->GetSpeechDriver(); status_t retval = pSpeechDriver->VoiceMemoRecordOn(); if (retval != NO_ERROR) { ALOGE("%s(), VoiceMemoRecordOn() fail!! Return.", __FUNCTION__); pSpeechDriver->VoiceMemoRecordOff(); pthread_exit(NULL); return 0; } // open file if (pSpeechVMRecorder->OpenFile() != NO_ERROR) { pSpeechDriver->VoiceMemoRecordOff(); pthread_exit(NULL); return 0; } // Internal Input Buffer Initialization pSpeechVMRecorder->mRingBuf.pBufBase = new char[kReadBufferSize]; pSpeechVMRecorder->mRingBuf.bufLen = kReadBufferSize; pSpeechVMRecorder->mRingBuf.pRead = pSpeechVMRecorder->mRingBuf.pBufBase; pSpeechVMRecorder->mRingBuf.pWrite = pSpeechVMRecorder->mRingBuf.pBufBase; ASSERT(pSpeechVMRecorder->mRingBuf.pBufBase != NULL); memset(pSpeechVMRecorder->mRingBuf.pBufBase, 0, pSpeechVMRecorder->mRingBuf.bufLen); pSpeechVMRecorder->mStarting = true; while (1) { // lock & wait data pthread_mutex_lock(&pSpeechVMRecorder->mMutex); int ret = pthread_cond_timeout_np(&pSpeechVMRecorder->mExitCond, &pSpeechVMRecorder->mMutex, kCondWaitTimeoutMsec); if (ret != 0) { ALOGW("%s(), pthread_cond_timeout_np return %d. ", __FUNCTION__, ret); } // make sure VM is still recording after conditional wait if (pSpeechVMRecorder->mStarting == false) { // close file if (pSpeechVMRecorder->mDumpFile != NULL) { fflush(pSpeechVMRecorder->mDumpFile); fclose(pSpeechVMRecorder->mDumpFile); pSpeechVMRecorder->mDumpFile = NULL; } // release local ring buffer if (pSpeechVMRecorder->mRingBuf.pBufBase != NULL) { delete []pSpeechVMRecorder->mRingBuf.pBufBase; pSpeechVMRecorder->mRingBuf.pBufBase = NULL; pSpeechVMRecorder->mRingBuf.pRead = NULL; pSpeechVMRecorder->mRingBuf.pWrite = NULL; pSpeechVMRecorder->mRingBuf.bufLen = 0; } ALOGD("%s(), pid: %d, tid: %d, mStarting == false, break", __FUNCTION__, getpid(), gettid()); pthread_mutex_unlock(&pSpeechVMRecorder->mMutex); break; } // write data to sd card const uint16_t data_count = RingBuf_getDataCount(&ring_buf); uint16_t write_bytes = 0; if (data_count > 0) { const char *end = ring_buf.pBufBase + ring_buf.bufLen; if (ring_buf.pRead <= ring_buf.pWrite) { write_bytes += fwrite((void *)ring_buf.pRead, sizeof(char), data_count, pSpeechVMRecorder->mDumpFile); } else { int r2e = end - ring_buf.pRead; write_bytes += fwrite((void *)ring_buf.pRead, sizeof(char), r2e, pSpeechVMRecorder->mDumpFile); write_bytes += fwrite((void *)ring_buf.pBufBase, sizeof(char), data_count - r2e, pSpeechVMRecorder->mDumpFile); } ring_buf.pRead += write_bytes; if (ring_buf.pRead >= end) { ring_buf.pRead -= ring_buf.bufLen; } SLOGV("data_count: %u, write_bytes: %u", data_count, write_bytes); } if (write_bytes != data_count) { ALOGE("%s(), write_bytes(%d) != data_count(%d), SD Card might be full!!", __FUNCTION__, write_bytes, data_count); } // unlock pthread_mutex_unlock(&pSpeechVMRecorder->mMutex); } pthread_exit(NULL); return 0; }
static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { struct astream_out *out = (struct astream_out *)stream; int ret; size_t frames_total = bytes / sizeof(uint32_t); // always stereo 16 bit uint32_t *buf = (uint32_t *)buffer; size_t frames_written = 0; pthread_mutex_lock(&out->buf_lock); pthread_mutex_lock(&out->lock); if (!out->bt_enabled || out->suspended) { LOGV("a2dp write: bluetooth disabled bt_en %d, suspended %d", out->bt_enabled, out->suspended); ret = -1; goto err_bt_disabled; } if (out->standby) { acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME); out->standby = false; out->last_write_time = system_time(); out->buf_rd_idx = 0; out->buf_wr_idx = 0; out->buf_frames_ready = 0; } ret = _out_init_locked(out, NULL); if (ret < 0) { goto err_init; } pthread_mutex_unlock(&out->lock); if(isToMono){ int16_t mono; int16_t *stereoData = (int16_t *)buffer; uint16_t i; for(i = 0; i<bytes/4; i++) { // to Mono mono = (int16_t)(((int32_t)*(stereoData+2*i) + (int32_t)*(stereoData+2*i+1)) >> 1); // to Stereo again *(stereoData+2*i) = *(stereoData+2*i+1) = mono; } } while (frames_written < frames_total) { size_t frames = _out_frames_available_locked(out); if (frames == 0) { int ret = pthread_cond_timeout_np(&out->buf_cond, &out->buf_lock, BUF_WRITE_AVAILABILITY_TIMEOUT_MS); if (ret != 0) { pthread_mutex_lock(&out->lock); goto err_write; } frames = _out_frames_available_locked(out); } if (frames > frames_total - frames_written) { frames = frames_total - frames_written; } memcpy(out->buf + out->buf_wr_idx, buf + frames_written, frames * sizeof(uint32_t)); frames_written += frames; _out_inc_wr_idx_locked(out, frames); pthread_mutex_lock(&out->lock); if (out->standby) { goto err_write; } pthread_mutex_unlock(&out->lock); } pthread_mutex_unlock(&out->buf_lock); return bytes; /* out->lock must be locked and out->buf_lock unlocked when jumping here */ err_write: err_init: err_bt_disabled: pthread_mutex_unlock(&out->buf_lock); LOGV("!!!! write error"); out_standby_stream_locked(out); pthread_mutex_unlock(&out->lock); /* XXX: simulate audio output timing in case of error?!?! */ usleep(out->buffer_duration_us); return ret; }
static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) { int err = 0; #ifndef USE_NP struct timespec ts; #endif /*USE_NP*/ if(sp_response != NULL) { err = AT_ERROR_COMMAND_PENDING; goto error; } if (!strncmp(command, "ATD", 3)) s_last_cme_error = CME_NO_ERROR; err = writeline (command); if (err < 0) { goto error; } s_type = type; s_responsePrefix = responsePrefix; s_smsPDU = smspdu; sp_response = at_response_new(); #ifndef USE_NP if (timeoutMsec != 0) { setTimespecRelative(&ts, timeoutMsec); } #endif /*USE_NP*/ while (sp_response->finalResponse == NULL && s_readerClosed == 0) { if (timeoutMsec != 0) { #ifdef USE_NP err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); #else err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts); #endif /*USE_NP*/ } else { err = pthread_cond_wait(&s_commandcond, &s_commandmutex); } if (err == ETIMEDOUT) { err = AT_ERROR_TIMEOUT; goto error; } } if (pp_outResponse == NULL) { at_response_free(sp_response); } else { /* line reader stores intermediate responses in reverse order */ reverseIntermediates(sp_response); *pp_outResponse = sp_response; } sp_response = NULL; if(s_readerClosed > 0) { err = AT_ERROR_CHANNEL_CLOSED; goto error; } err = 0; error: clearPendingCommand(); /* Have to save the error message right away */ if (pp_outResponse && !(*pp_outResponse)->success && !err && !strncmp(command, "ATD", 3)) { ATResponse *err_resp; err = at_send_command_full_nolock("AT+CEER", SINGLELINE, "+CEER:", NULL, timeoutMsec, &err_resp); if (!err) { if (err_resp->p_intermediates != NULL) { free(s_last_errmsg); s_last_errmsg = strdup(err_resp->p_intermediates->line); } at_response_free(err_resp); } } return err; }