void Camera3StreamSplitter::onBufferReleasedByOutputLocked(
        const sp<IGraphicBufferProducer>& from) {
    ATRACE_CALL();
    sp<GraphicBuffer> buffer;
    sp<Fence> fence;
    status_t res = from->detachNextBuffer(&buffer, &fence);
    if (res == NO_INIT) {
        // If we just discovered that this output has been abandoned, note that,
        // but we can't do anything else, since buffer is invalid
        onAbandonedLocked();
        return;
    } else if (res == NO_MEMORY) {
        SP_LOGV("%s: No free buffers", __FUNCTION__);
        return;
    } else if (res != OK) {
        SP_LOGE("%s: detaching buffer from output failed (%d)", __FUNCTION__, res);
        return;
    }

    BufferTracker& tracker = *(mBuffers[buffer->getId()]);
    // Merge the release fence of the incoming buffer so that the fence we send
    // back to the input includes all of the outputs' fences
    if (fence != nullptr && fence->isValid()) {
        tracker.mergeFence(fence);
    }
    SP_LOGV("detached buffer %" PRId64 " %p from output %p",
            buffer->getId(), buffer.get(), from.get());

    // Check to see if this is the last outstanding reference to this buffer
    decrementBufRefCountLocked(buffer->getId(), from);
}
void JNIImageWriterContext::onBufferReleased() {
    ALOGV("%s: buffer released", __FUNCTION__);
    bool needsDetach = false;
    JNIEnv* env = getJNIEnv(&needsDetach);
    if (env != NULL) {
        // Detach the buffer every time when a buffer consumption is done,
        // need let this callback give a BufferItem, then only detach if it was attached to this
        // Writer. Do the detach unconditionally for opaque format now. see b/19977520
        if (mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
            sp<Fence> fence;
            sp<GraphicBuffer> buffer;
            ALOGV("%s: One buffer is detached", __FUNCTION__);
            mProducer->detachNextBuffer(&buffer, &fence);
        }

        env->CallStaticVoidMethod(mClazz, gImageWriterClassInfo.postEventFromNative, mWeakThiz);
    } else {
        ALOGW("onBufferReleased event will not posted");
    }

    if (needsDetach) {
        detachJNI();
    }
}