/* ** ** Copyright 2013, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ // #define LOG_NDEBUG 0 #define LOG_TAG "ICameraDeviceUser" #include #include #include #include #include #include #include #include #include namespace android { typedef Parcel::WritableBlob WritableBlob; typedef Parcel::ReadableBlob ReadableBlob; enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SUBMIT_REQUEST, SUBMIT_REQUEST_LIST, CANCEL_REQUEST, DELETE_STREAM, CREATE_STREAM, CREATE_DEFAULT_REQUEST, GET_CAMERA_INFO, WAIT_UNTIL_IDLE, FLUSH }; namespace { // Read empty strings without printing a false error message. String16 readMaybeEmptyString16(const Parcel& parcel) { size_t len; const char16_t* str = parcel.readString16Inplace(&len); if (str != NULL) { return String16(str, len); } else { return String16(); } } }; class BpCameraDeviceUser : public BpInterface { public: BpCameraDeviceUser(const sp& impl) : BpInterface(impl) { } // disconnect from camera service void disconnect() { ALOGV("disconnect"); Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); remote()->transact(DISCONNECT, data, &reply); reply.readExceptionCode(); } virtual status_t submitRequest(sp request, bool repeating, int64_t *lastFrameNumber) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); // arg0 = CaptureRequest if (request != 0) { data.writeInt32(1); request->writeToParcel(&data); } else { data.writeInt32(0); } // arg1 = streaming (bool) data.writeInt32(repeating); remote()->transact(SUBMIT_REQUEST, data, &reply); reply.readExceptionCode(); status_t res = reply.readInt32(); status_t resFrameNumber = BAD_VALUE; if (reply.readInt32() != 0) { if (lastFrameNumber != NULL) { resFrameNumber = reply.readInt64(lastFrameNumber); } } if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) { res = FAILED_TRANSACTION; } return res; } virtual status_t submitRequestList(List > requestList, bool repeating, int64_t *lastFrameNumber) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(requestList.size()); for (List >::iterator it = requestList.begin(); it != requestList.end(); ++it) { sp request = *it; if (request != 0) { data.writeInt32(1); if (request->writeToParcel(&data) != OK) { return BAD_VALUE; } } else { data.writeInt32(0); } } data.writeInt32(repeating); remote()->transact(SUBMIT_REQUEST_LIST, data, &reply); reply.readExceptionCode(); status_t res = reply.readInt32(); status_t resFrameNumber = BAD_VALUE; if (reply.readInt32() != 0) { if (lastFrameNumber != NULL) { resFrameNumber = reply.readInt64(lastFrameNumber); } } if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) { res = FAILED_TRANSACTION; } return res; } virtual status_t cancelRequest(int requestId, int64_t *lastFrameNumber) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(requestId); remote()->transact(CANCEL_REQUEST, data, &reply); reply.readExceptionCode(); status_t res = reply.readInt32(); status_t resFrameNumber = BAD_VALUE; if (reply.readInt32() != 0) { if (lastFrameNumber != NULL) { res = reply.readInt64(lastFrameNumber); } } if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) { res = FAILED_TRANSACTION; } return res; } virtual status_t deleteStream(int streamId) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(streamId); remote()->transact(DELETE_STREAM, data, &reply); reply.readExceptionCode(); return reply.readInt32(); } virtual status_t createStream(int width, int height, int format, const sp& bufferProducer) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(width); data.writeInt32(height); data.writeInt32(format); data.writeInt32(1); // marker that bufferProducer is not null data.writeString16(String16("unknown_name")); // name of surface sp b(bufferProducer->asBinder()); data.writeStrongBinder(b); remote()->transact(CREATE_STREAM, data, &reply); reply.readExceptionCode(); return reply.readInt32(); } // Create a request object from a template. virtual status_t createDefaultRequest(int templateId, /*out*/ CameraMetadata* request) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); data.writeInt32(templateId); remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply); reply.readExceptionCode(); status_t result = reply.readInt32(); CameraMetadata out; if (reply.readInt32() != 0) { out.readFromParcel(&reply); } if (request != NULL) { request->swap(out); } return result; } virtual status_t getCameraInfo(CameraMetadata* info) { Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); remote()->transact(GET_CAMERA_INFO, data, &reply); reply.readExceptionCode(); status_t result = reply.readInt32(); CameraMetadata out; if (reply.readInt32() != 0) { out.readFromParcel(&reply); } if (info != NULL) { info->swap(out); } return result; } virtual status_t waitUntilIdle() { ALOGV("waitUntilIdle"); Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); remote()->transact(WAIT_UNTIL_IDLE, data, &reply); reply.readExceptionCode(); return reply.readInt32(); } virtual status_t flush(int64_t *lastFrameNumber) { ALOGV("flush"); Parcel data, reply; data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); remote()->transact(FLUSH, data, &reply); reply.readExceptionCode(); status_t res = reply.readInt32(); status_t resFrameNumber = BAD_VALUE; if (reply.readInt32() != 0) { if (lastFrameNumber != NULL) { res = reply.readInt64(lastFrameNumber); } } if ((res != NO_ERROR) || (resFrameNumber != NO_ERROR)) { res = FAILED_TRANSACTION; } return res; } private: }; IMPLEMENT_META_INTERFACE(CameraDeviceUser, "android.hardware.camera2.ICameraDeviceUser"); // ---------------------------------------------------------------------- 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 request; if (data.readInt32() != 0) { request = new CaptureRequest(); request->readFromParcel(const_cast(&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 > requestList; int requestListSize = data.readInt32(); for (int i = 0; i < requestListSize; i++) { if (data.readInt32() != 0) { sp request = new CaptureRequest(); if (request->readFromParcel(const_cast(&data)) != OK) { return BAD_VALUE; } requestList.push_back(request); } else { sp 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 bp; if (data.readInt32() != 0) { String16 name = readMaybeEmptyString16(data); bp = interface_cast( 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(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; } default: return BBinder::onTransact(code, data, reply, flags); } } // ---------------------------------------------------------------------------- }; // namespace android