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;
}
示例#2
0
/* 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;
}
示例#3
0
/* 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!
  }
}
示例#4
0
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;
}
示例#5
0
/**
 * 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;
}
示例#8
0
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;
}