void onResultReceived(int32_t requestId, const CameraMetadata& result) {
     Parcel data, reply;
     data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
     data.writeInt32(requestId);
     data.writeInt32(1); // to mark presence of metadata object
     result.writeToParcel(&data);
     remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
     data.writeNoException();
 }
 void onResultReceived(const CameraMetadata& metadata,
         const CaptureResultExtras& resultExtras) {
     ALOGV("onResultReceived");
     Parcel data, reply;
     data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor());
     data.writeInt32(1); // to mark presence of metadata object
     metadata.writeToParcel(&data);
     data.writeInt32(1); // to mark presence of CaptureResult object
     resultExtras.writeToParcel(&data);
     remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY);
     data.writeNoException();
 }
static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
    ALOGV("%s", __FUNCTION__);
    CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
    if (metadata == NULL) {
        return;
    }

    Parcel* parcelNative = parcelForJavaObject(env, parcel);
    if (parcelNative == NULL) {
        jniThrowNullPointerException(env, "parcel");
        return;
    }

    status_t err;
    if ((err = metadata->writeToParcel(parcelNative)) != OK) {
        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                                  "Failed to write to parcel (error code %d)", err);
        return;
    }
}
status_t BnCameraDeviceUser::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case DISCONNECT: {
            ALOGV("DISCONNECT");
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            disconnect();
            reply->writeNoException();
            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            // arg0 = request
            sp<CaptureRequest> request;
            if (data.readInt32() != 0) {
                request = new CaptureRequest();
                request->readFromParcel(const_cast<Parcel*>(&data));
            }

            // arg1 = streaming (bool)
            bool repeating = data.readInt32();

            // return code: requestId (int32)
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST_LIST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            List<sp<CaptureRequest> > requestList;
            int requestListSize = data.readInt32();
            for (int i = 0; i < requestListSize; i++) {
                if (data.readInt32() != 0) {
                    sp<CaptureRequest> request = new CaptureRequest();
                    if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
                        return BAD_VALUE;
                    }
                    requestList.push_back(request);
                } else {
                    sp<CaptureRequest> request = 0;
                    requestList.push_back(request);
                    ALOGE("A request is missing. Sending in null request.");
                }
            }

            bool repeating = data.readInt32();

            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
        case CANCEL_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int requestId = data.readInt32();
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        } break;
        case DELETE_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int streamId = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(deleteStream(streamId));
            return NO_ERROR;
        } break;
        case CREATE_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int width, height, format;

            width = data.readInt32();
            ALOGV("%s: CREATE_STREAM: width = %d", __FUNCTION__, width);
            height = data.readInt32();
            ALOGV("%s: CREATE_STREAM: height = %d", __FUNCTION__, height);
            format = data.readInt32();
            ALOGV("%s: CREATE_STREAM: format = %d", __FUNCTION__, format);

            sp<IGraphicBufferProducer> bp;
            if (data.readInt32() != 0) {
                String16 name = readMaybeEmptyString16(data);
                bp = interface_cast<IGraphicBufferProducer>(
                        data.readStrongBinder());

                ALOGV("%s: CREATE_STREAM: bp = %p, name = %s", __FUNCTION__,
                      bp.get(), String8(name).string());
            } else {
                ALOGV("%s: CREATE_STREAM: bp = unset, name = unset",
                      __FUNCTION__);
            }

            status_t ret;
            ret = createStream(width, height, format, bp);

            reply->writeNoException();
            ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
            reply->writeInt32(ret);
            ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);

            return NO_ERROR;
        } break;

        case CREATE_DEFAULT_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            int templateId = data.readInt32();

            CameraMetadata request;
            status_t ret;
            ret = createDefaultRequest(templateId, &request);

            reply->writeNoException();
            reply->writeInt32(ret);

            // out-variables are after exception and return value
            reply->writeInt32(1); // to mark presence of metadata object
            request.writeToParcel(const_cast<Parcel*>(reply));

            return NO_ERROR;
        } break;
        case GET_CAMERA_INFO: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            CameraMetadata info;
            status_t ret;
            ret = getCameraInfo(&info);

            reply->writeNoException();
            reply->writeInt32(ret);

            // out-variables are after exception and return value
            reply->writeInt32(1); // to mark presence of metadata object
            info.writeToParcel(reply);

            return NO_ERROR;
        } break;
        case WAIT_UNTIL_IDLE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(waitUntilIdle());
            return NO_ERROR;
        } break;
        case FLUSH: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(flush(&lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        }
        case BEGIN_CONFIGURE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(beginConfigure());
            return NO_ERROR;
        } break;
        case END_CONFIGURE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(endConfigure());
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
status_t BnCameraDeviceUser::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case DISCONNECT: {
            ALOGV("DISCONNECT");
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            disconnect();
            reply->writeNoException();
            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            // arg0 = request
            sp<CaptureRequest> request;
            if (data.readInt32() != 0) {
                request = new CaptureRequest();
                request->readFromParcel(const_cast<Parcel*>(&data));
            }

            // arg1 = streaming (bool)
            bool repeating = data.readInt32();

            // return code: requestId (int32)
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequest(request, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
        case SUBMIT_REQUEST_LIST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            List<sp<CaptureRequest> > requestList;
            int requestListSize = data.readInt32();
            for (int i = 0; i < requestListSize; i++) {
                if (data.readInt32() != 0) {
                    sp<CaptureRequest> request = new CaptureRequest();
                    if (request->readFromParcel(const_cast<Parcel*>(&data)) != OK) {
                        return BAD_VALUE;
                    }
                    requestList.push_back(request);
                } else {
                    sp<CaptureRequest> request = 0;
                    requestList.push_back(request);
                    ALOGE("A request is missing. Sending in null request.");
                }
            }

            bool repeating = data.readInt32();

            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(submitRequestList(requestList, repeating, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);

            return NO_ERROR;
        } break;
        case CANCEL_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int requestId = data.readInt32();
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(cancelRequest(requestId, &lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        } break;
        case DELETE_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int streamId = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(deleteStream(streamId));
            return NO_ERROR;
        } break;
        case CREATE_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            status_t ret = BAD_VALUE;
            if (data.readInt32() != 0) {
                OutputConfiguration outputConfiguration(data);
                ret = createStream(outputConfiguration);
            } else {
                ALOGE("%s: cannot take an empty OutputConfiguration", __FUNCTION__);
            }

            reply->writeNoException();
            ALOGV("%s: CREATE_STREAM: write noException", __FUNCTION__);
            reply->writeInt32(ret);
            ALOGV("%s: CREATE_STREAM: write ret = %d", __FUNCTION__, ret);

            return NO_ERROR;
        } break;
        case CREATE_INPUT_STREAM: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int width, height, format;

            width = data.readInt32();
            height = data.readInt32();
            format = data.readInt32();
            status_t ret = createInputStream(width, height, format);

            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;

        } break;
        case GET_INPUT_SURFACE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            sp<IGraphicBufferProducer> bp;
            status_t ret = getInputBufferProducer(&bp);
            sp<IBinder> b(IInterface::asBinder(ret == OK ? bp : NULL));

            reply->writeNoException();
            reply->writeInt32(ret);
            reply->writeInt32(1);
            reply->writeString16(String16("camera input")); // name of surface
            reply->writeStrongBinder(b);

            return NO_ERROR;
        } break;
        case CREATE_DEFAULT_REQUEST: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            int templateId = data.readInt32();

            CameraMetadata request;
            status_t ret;
            ret = createDefaultRequest(templateId, &request);

            reply->writeNoException();
            reply->writeInt32(ret);

            // out-variables are after exception and return value
            reply->writeInt32(1); // to mark presence of metadata object
            request.writeToParcel(const_cast<Parcel*>(reply));

            return NO_ERROR;
        } break;
        case GET_CAMERA_INFO: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);

            CameraMetadata info;
            status_t ret;
            ret = getCameraInfo(&info);

            reply->writeNoException();
            reply->writeInt32(ret);

            // out-variables are after exception and return value
            reply->writeInt32(1); // to mark presence of metadata object
            info.writeToParcel(reply);

            return NO_ERROR;
        } break;
        case WAIT_UNTIL_IDLE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(waitUntilIdle());
            return NO_ERROR;
        } break;
        case FLUSH: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            int64_t lastFrameNumber = -1;
            reply->writeInt32(flush(&lastFrameNumber));
            reply->writeInt32(1);
            reply->writeInt64(lastFrameNumber);
            return NO_ERROR;
        }
        case BEGIN_CONFIGURE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            reply->writeNoException();
            reply->writeInt32(beginConfigure());
            return NO_ERROR;
        } break;
        case END_CONFIGURE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            bool isConstrainedHighSpeed = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(endConfigure(isConstrainedHighSpeed));
            return NO_ERROR;
        } break;
        case PREPARE: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int streamId = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(prepare(streamId));
            return NO_ERROR;
        } break;
        case TEAR_DOWN: {
            CHECK_INTERFACE(ICameraDeviceUser, data, reply);
            int streamId = data.readInt32();
            reply->writeNoException();
            reply->writeInt32(tearDown(streamId));
            return NO_ERROR;
        } break;

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case GET_NUMBER_OF_CAMERAS: {
            CHECK_INTERFACE(ICameraService, data, reply);
            reply->writeNoException();
            reply->writeInt32(getNumberOfCameras());
            return NO_ERROR;
        } break;
        case GET_CAMERA_INFO: {
            CHECK_INTERFACE(ICameraService, data, reply);
            CameraInfo cameraInfo = CameraInfo();
            memset(&cameraInfo, 0, sizeof(cameraInfo));
            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
            reply->writeNoException();
            reply->writeInt32(result);

            // Fake a parcelable object here
            reply->writeInt32(1); // means the parcelable is included
            reply->writeInt32(cameraInfo.facing);
            reply->writeInt32(cameraInfo.orientation);
            return NO_ERROR;
        } break;
        case GET_CAMERA_CHARACTERISTICS: {
            CHECK_INTERFACE(ICameraService, data, reply);
            CameraMetadata info;
            status_t result = getCameraCharacteristics(data.readInt32(), &info);
            reply->writeNoException();
            reply->writeInt32(result);

            // out-variables are after exception and return value
            reply->writeInt32(1); // means the parcelable is included
            info.writeToParcel(reply);
            return NO_ERROR;
        } break;
        case CONNECT: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraClient> cameraClient =
                    interface_cast<ICameraClient>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICamera> camera;
            status_t status = connect(cameraClient, cameraId,
                    clientName, clientUid, /*out*/ camera);
            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(camera->asBinder());
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
        case CONNECT_PRO: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<IProCameraCallbacks> cameraClient =
                interface_cast<IProCameraCallbacks>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<IProCameraUser> camera;
            status_t status = connectPro(cameraClient, cameraId,
                    clientName, clientUid, /*out*/ camera);
            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(camera->asBinder());
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
        case CONNECT_DEVICE: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraDeviceCallbacks> cameraClient =
                interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICameraDeviceUser> camera;
            status_t status = connectDevice(cameraClient, cameraId,
                    clientName, clientUid, /*out*/ camera);
            reply->writeNoException();
            reply->writeInt32(status);
            if (camera != NULL) {
                reply->writeInt32(1);
                reply->writeStrongBinder(camera->asBinder());
            } else {
                reply->writeInt32(0);
            }
            return NO_ERROR;
        } break;
        case ADD_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeNoException();
            reply->writeInt32(addListener(listener));
            return NO_ERROR;
        } break;
        case REMOVE_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeNoException();
            reply->writeInt32(removeListener(listener));
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}