static int _out_a2dp_suspend(struct astream_out *out, bool suspend)
{
    pthread_mutex_lock(&out->lock);
    out->suspended = suspend;
    out_standby_stream_locked(out);
    pthread_mutex_unlock(&out->lock);

    return 0;
}
static int out_standby(struct audio_stream *stream)
{
    struct astream_out *out = (struct astream_out *)stream;

    pthread_mutex_lock(&out->lock);
    out_standby_stream_locked(out);
    pthread_mutex_unlock(&out->lock);

    return 0;
}
static int out_close_stream_locked(struct astream_out *out)
{
    out_standby_stream_locked(out);

    if (out->data) {
        LOGV("%s: calling a2dp_cleanup()", __func__);
        a2dp_cleanup(out->data);
        out->data = NULL;
    }

    return 0;
}
static int out_standby(struct audio_stream *stream)
{
    struct astream_out *out = (struct astream_out *)stream;

    pthread_mutex_lock(&out->lock);

#ifdef GLOBALCONFIG_BLUETOOTH_A2DP_NOT_STANDBY        // for T map with a2dp 
    char checkTmap[PROPERTY_VALUE_MAX];
    property_get("sys.sktgps", checkTmap, "0");
    if (atoi(checkTmap) == 1) {
        LOGV("======================================================");
        LOGV("T-Map is operating, a2dp doesn't enter standby state");
        LOGV("======================================================");
        pthread_mutex_unlock(&out->lock);
        return 0;
    }
#endif
    
    out_standby_stream_locked(out);
    pthread_mutex_unlock(&out->lock);

    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;
}