diff options
Diffstat (limited to 'camera')
-rw-r--r-- | camera/Android.mk | 3 | ||||
-rw-r--r-- | camera/CameraMetadata.cpp | 175 | ||||
-rw-r--r-- | camera/ICameraService.cpp | 36 | ||||
-rw-r--r-- | camera/IProCameraCallbacks.cpp | 9 | ||||
-rw-r--r-- | camera/IProCameraUser.cpp | 120 | ||||
-rw-r--r-- | camera/photography/CaptureRequest.cpp | 124 | ||||
-rw-r--r-- | camera/photography/ICameraDeviceCallbacks.cpp | 110 | ||||
-rw-r--r-- | camera/photography/ICameraDeviceUser.cpp | 307 |
8 files changed, 765 insertions, 119 deletions
diff --git a/camera/Android.mk b/camera/Android.mk index fa518fff61..8f58f8797c 100644 --- a/camera/Android.mk +++ b/camera/Android.mk @@ -16,6 +16,9 @@ LOCAL_SRC_FILES:= \ ICameraRecordingProxyListener.cpp \ IProCameraUser.cpp \ IProCameraCallbacks.cpp \ + photography/ICameraDeviceUser.cpp \ + photography/ICameraDeviceCallbacks.cpp \ + photography/CaptureRequest.cpp \ ProCamera.cpp \ CameraBase.cpp \ diff --git a/camera/CameraMetadata.cpp b/camera/CameraMetadata.cpp index a8f9eff10e..f447c5b3e2 100644 --- a/camera/CameraMetadata.cpp +++ b/camera/CameraMetadata.cpp @@ -21,9 +21,13 @@ #include <utils/Errors.h> #include <camera/CameraMetadata.h> +#include <binder/Parcel.h> namespace android { +typedef Parcel::WritableBlob WritableBlob; +typedef Parcel::ReadableBlob ReadableBlob; + CameraMetadata::CameraMetadata() : mBuffer(NULL), mLocked(false) { } @@ -408,4 +412,175 @@ status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) { return OK; } +status_t CameraMetadata::readFromParcel(const Parcel& data, + camera_metadata_t** out) { + + status_t err = OK; + + camera_metadata_t* metadata = NULL; + + if (out) { + *out = NULL; + } + + // arg0 = metadataSize (int32) + int32_t metadataSizeTmp = -1; + if ((err = data.readInt32(&metadataSizeTmp)) != OK) { + ALOGE("%s: Failed to read metadata size (error %d %s)", + __FUNCTION__, err, strerror(-err)); + return err; + } + const size_t metadataSize = static_cast<size_t>(metadataSizeTmp); + + if (metadataSize == 0) { + ALOGV("%s: Read 0-sized metadata", __FUNCTION__); + return OK; + } + + // NOTE: this doesn't make sense to me. shouldnt the blob + // know how big it is? why do we have to specify the size + // to Parcel::readBlob ? + + ReadableBlob blob; + // arg1 = metadata (blob) + do { + if ((err = data.readBlob(metadataSize, &blob)) != OK) { + ALOGE("%s: Failed to read metadata blob (sized %d). Possible " + " serialization bug. Error %d %s", + __FUNCTION__, metadataSize, err, strerror(-err)); + break; + } + const camera_metadata_t* tmp = + reinterpret_cast<const camera_metadata_t*>(blob.data()); + + metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); + if (metadata == NULL) { + // We consider that allocation only fails if the validation + // also failed, therefore the readFromParcel was a failure. + err = BAD_VALUE; + } + } while(0); + blob.release(); + + if (out) { + ALOGV("%s: Set out metadata to %p", __FUNCTION__, metadata); + *out = metadata; + } else if (metadata != NULL) { + ALOGV("%s: Freed camera metadata at %p", __FUNCTION__, metadata); + free_camera_metadata(metadata); + } + + return err; +} + +status_t CameraMetadata::writeToParcel(Parcel& data, + const camera_metadata_t* metadata) { + status_t res = OK; + + // arg0 = metadataSize (int32) + + if (metadata == NULL) { + return data.writeInt32(0); + } + + const size_t metadataSize = get_camera_metadata_compact_size(metadata); + res = data.writeInt32(static_cast<int32_t>(metadataSize)); + if (res != OK) { + return res; + } + + // arg1 = metadata (blob) + WritableBlob blob; + do { + res = data.writeBlob(metadataSize, &blob); + if (res != OK) { + break; + } + copy_camera_metadata(blob.data(), metadataSize, metadata); + + IF_ALOGV() { + if (validate_camera_metadata_structure( + (const camera_metadata_t*)blob.data(), + &metadataSize) != OK) { + ALOGV("%s: Failed to validate metadata %p after writing blob", + __FUNCTION__, blob.data()); + } else { + ALOGV("%s: Metadata written to blob. Validation success", + __FUNCTION__); + } + } + + // Not too big of a problem since receiving side does hard validation + // Don't check the size since the compact size could be larger + if (validate_camera_metadata_structure(metadata, /*size*/NULL) != OK) { + ALOGW("%s: Failed to validate metadata %p before writing blob", + __FUNCTION__, metadata); + } + + } while(false); + blob.release(); + + return res; +} + +status_t CameraMetadata::readFromParcel(Parcel *parcel) { + + ALOGV("%s: parcel = %p", __FUNCTION__, parcel); + + status_t res = OK; + + if (parcel == NULL) { + ALOGE("%s: parcel is null", __FUNCTION__); + return BAD_VALUE; + } + + if (mLocked) { + ALOGE("%s: CameraMetadata is locked", __FUNCTION__); + return INVALID_OPERATION; + } + + camera_metadata *buffer = NULL; + // TODO: reading should return a status code, in case validation fails + res = CameraMetadata::readFromParcel(*parcel, &buffer); + + if (res != NO_ERROR) { + ALOGE("%s: Failed to read from parcel. Metadata is unchanged.", + __FUNCTION__); + return res; + } + + clear(); + mBuffer = buffer; + + return OK; +} + +status_t CameraMetadata::writeToParcel(Parcel *parcel) const { + + ALOGV("%s: parcel = %p", __FUNCTION__, parcel); + + if (parcel == NULL) { + ALOGE("%s: parcel is null", __FUNCTION__); + return BAD_VALUE; + } + + return CameraMetadata::writeToParcel(*parcel, mBuffer); +} + +void CameraMetadata::swap(CameraMetadata& other) { + if (mLocked) { + ALOGE("%s: CameraMetadata is locked", __FUNCTION__); + return; + } else if (other.mLocked) { + ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__); + return; + } + + camera_metadata* thisBuf = mBuffer; + camera_metadata* otherBuf = other.mBuffer; + + other.mBuffer = thisBuf; + mBuffer = otherBuf; +} + }; // namespace android diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp index 819e410bf1..068fb0f4ae 100644 --- a/camera/ICameraService.cpp +++ b/camera/ICameraService.cpp @@ -31,6 +31,8 @@ #include <camera/IProCameraCallbacks.h> #include <camera/ICamera.h> #include <camera/ICameraClient.h> +#include <camera/photography/ICameraDeviceUser.h> +#include <camera/photography/ICameraDeviceCallbacks.h> namespace android { @@ -117,7 +119,7 @@ public: return result; } - // connect to camera service + // connect to camera service (android.hardware.Camera) virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId, const String16 &clientPackageName, int clientUid) { @@ -149,6 +151,25 @@ public: return interface_cast<IProCameraUser>(reply.readStrongBinder()); } + // connect to camera service (android.hardware.photography.CameraDevice) + virtual sp<ICameraDeviceUser> connect( + const sp<ICameraDeviceCallbacks>& cameraCb, + int cameraId, + const String16& clientPackageName, + int clientUid) + { + Parcel data, reply; + data.writeInterfaceToken(ICameraService::getInterfaceDescriptor()); + data.writeStrongBinder(cameraCb->asBinder()); + data.writeInt32(cameraId); + data.writeString16(clientPackageName); + data.writeInt32(clientUid); + remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply); + + if (readExceptionCode(reply)) return NULL; + return interface_cast<ICameraDeviceUser>(reply.readStrongBinder()); + } + virtual status_t addListener(const sp<ICameraServiceListener>& listener) { Parcel data, reply; @@ -226,6 +247,19 @@ status_t BnCameraService::onTransact( reply->writeStrongBinder(camera->asBinder()); 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 = connect(cameraClient, cameraId, + clientName, clientUid); + reply->writeNoException(); + reply->writeStrongBinder(camera->asBinder()); + return NO_ERROR; + } break; case ADD_LISTENER: { CHECK_INTERFACE(ICameraService, data, reply); sp<ICameraServiceListener> listener = diff --git a/camera/IProCameraCallbacks.cpp b/camera/IProCameraCallbacks.cpp index b9cd14d839..0fdb85a7a8 100644 --- a/camera/IProCameraCallbacks.cpp +++ b/camera/IProCameraCallbacks.cpp @@ -28,7 +28,7 @@ #include <camera/IProCameraCallbacks.h> -#include <system/camera_metadata.h> +#include "camera/CameraMetadata.h" namespace android { @@ -38,9 +38,6 @@ enum { RESULT_RECEIVED, }; -void readMetadata(const Parcel& data, camera_metadata_t** out); -void writeMetadata(Parcel& data, camera_metadata_t* metadata); - class BpProCameraCallbacks: public BpInterface<IProCameraCallbacks> { public: @@ -75,7 +72,7 @@ public: Parcel data, reply; data.writeInterfaceToken(IProCameraCallbacks::getInterfaceDescriptor()); data.writeInt32(frameId); - writeMetadata(data, result); + CameraMetadata::writeToParcel(data, result); remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY); } }; @@ -112,7 +109,7 @@ status_t BnProCameraCallbacks::onTransact( CHECK_INTERFACE(IProCameraCallbacks, data, reply); int32_t frameId = data.readInt32(); camera_metadata_t *result = NULL; - readMetadata(data, &result); + CameraMetadata::readFromParcel(data, &result); onResultReceived(frameId, result); return NO_ERROR; break; diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp index 015cb5c0d6..8f221241d1 100644 --- a/camera/IProCameraUser.cpp +++ b/camera/IProCameraUser.cpp @@ -15,7 +15,7 @@ ** limitations under the License. */ -//#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #define LOG_TAG "IProCameraUser" #include <utils/Log.h> #include <stdint.h> @@ -24,13 +24,10 @@ #include <camera/IProCameraUser.h> #include <gui/IGraphicBufferProducer.h> #include <gui/Surface.h> -#include <system/camera_metadata.h> +#include "camera/CameraMetadata.h" namespace android { -typedef Parcel::WritableBlob WritableBlob; -typedef Parcel::ReadableBlob ReadableBlob; - enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, CONNECT, @@ -46,107 +43,6 @@ enum { GET_CAMERA_INFO, }; -/** - * Caller becomes the owner of the new metadata - * 'const Parcel' doesnt prevent us from calling the read functions. - * which is interesting since it changes the internal state - * - * NULL can be returned when no metadata was sent, OR if there was an issue - * unpacking the serialized data (i.e. bad parcel or invalid structure). - */ -void readMetadata(const Parcel& data, camera_metadata_t** out) { - - status_t err = OK; - - camera_metadata_t* metadata = NULL; - - if (out) { - *out = NULL; - } - - // arg0 = metadataSize (int32) - int32_t metadataSizeTmp = -1; - if ((err = data.readInt32(&metadataSizeTmp)) != OK) { - ALOGE("%s: Failed to read metadata size (error %d %s)", - __FUNCTION__, err, strerror(-err)); - return; - } - const size_t metadataSize = static_cast<size_t>(metadataSizeTmp); - - if (metadataSize == 0) { - return; - } - - // NOTE: this doesn't make sense to me. shouldnt the blob - // know how big it is? why do we have to specify the size - // to Parcel::readBlob ? - - ReadableBlob blob; - // arg1 = metadata (blob) - do { - if ((err = data.readBlob(metadataSize, &blob)) != OK) { - ALOGE("%s: Failed to read metadata blob (sized %d). Possible " - " serialization bug. Error %d %s", - __FUNCTION__, metadataSize, err, strerror(-err)); - break; - } - const camera_metadata_t* tmp = - reinterpret_cast<const camera_metadata_t*>(blob.data()); - - metadata = allocate_copy_camera_metadata_checked(tmp, metadataSize); - } while(0); - blob.release(); - - if (out) { - *out = metadata; - } else if (metadata != NULL) { - free_camera_metadata(metadata); - } -} - -/** - * Caller retains ownership of metadata - * - Write 2 (int32 + blob) args in the current position - */ -void writeMetadata(Parcel& data, camera_metadata_t* metadata) { - // arg0 = metadataSize (int32) - - if (metadata == NULL) { - data.writeInt32(0); - return; - } - - const size_t metadataSize = get_camera_metadata_compact_size(metadata); - data.writeInt32(static_cast<int32_t>(metadataSize)); - - // arg1 = metadata (blob) - WritableBlob blob; - { - data.writeBlob(metadataSize, &blob); - copy_camera_metadata(blob.data(), metadataSize, metadata); - - IF_ALOGV() { - if (validate_camera_metadata_structure( - (const camera_metadata_t*)blob.data(), - &metadataSize) != OK) { - ALOGV("%s: Failed to validate metadata %p after writing blob", - __FUNCTION__, blob.data()); - } else { - ALOGV("%s: Metadata written to blob. Validation success", - __FUNCTION__); - } - } - - // Not too big of a problem since receiving side does hard validation - if (validate_camera_metadata_structure(metadata, &metadataSize) != OK) { - ALOGW("%s: Failed to validate metadata %p before writing blob", - __FUNCTION__, metadata); - } - - } - blob.release(); -} - class BpProCameraUser: public BpInterface<IProCameraUser> { public: @@ -214,7 +110,7 @@ public: data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); // arg0+arg1 - writeMetadata(data, metadata); + CameraMetadata::writeToParcel(data, metadata); // arg2 = streaming (bool) data.writeInt32(streaming); @@ -275,7 +171,7 @@ public: data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); data.writeInt32(templateId); remote()->transact(CREATE_DEFAULT_REQUEST, data, &reply); - readMetadata(reply, /*out*/request); + CameraMetadata::readFromParcel(reply, /*out*/request); return reply.readInt32(); } @@ -286,7 +182,7 @@ public: data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor()); data.writeInt32(cameraId); remote()->transact(GET_CAMERA_INFO, data, &reply); - readMetadata(reply, /*out*/info); + CameraMetadata::readFromParcel(reply, /*out*/info); return reply.readInt32(); } @@ -343,7 +239,7 @@ status_t BnProCameraUser::onTransact( case SUBMIT_REQUEST: { CHECK_INTERFACE(IProCameraUser, data, reply); camera_metadata_t* metadata; - readMetadata(data, /*out*/&metadata); + CameraMetadata::readFromParcel(data, /*out*/&metadata); // arg2 = streaming (bool) bool streaming = data.readInt32(); @@ -395,7 +291,7 @@ status_t BnProCameraUser::onTransact( status_t ret; ret = createDefaultRequest(templateId, &request); - writeMetadata(*reply, request); + CameraMetadata::writeToParcel(*reply, request); reply->writeInt32(ret); free_camera_metadata(request); @@ -411,7 +307,7 @@ status_t BnProCameraUser::onTransact( status_t ret; ret = getCameraInfo(cameraId, &info); - writeMetadata(*reply, info); + CameraMetadata::writeToParcel(*reply, info); reply->writeInt32(ret); free_camera_metadata(info); diff --git a/camera/photography/CaptureRequest.cpp b/camera/photography/CaptureRequest.cpp new file mode 100644 index 0000000000..b822fc9613 --- /dev/null +++ b/camera/photography/CaptureRequest.cpp @@ -0,0 +1,124 @@ +/* +** +** 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 "CameraRequest" +#include <utils/Log.h> + +#include <camera/photography/CaptureRequest.h> + +#include <binder/Parcel.h> +#include <gui/Surface.h> + +namespace android { + +status_t CaptureRequest::readFromParcel(Parcel* parcel) { + if (parcel == NULL) { + ALOGE("%s: Null parcel", __FUNCTION__); + return BAD_VALUE; + } + + mMetadata.clear(); + mSurfaceList.clear(); + + status_t err; + + if ((err = mMetadata.readFromParcel(parcel)) != OK) { + ALOGE("%s: Failed to read metadata from parcel", __FUNCTION__); + return err; + } + ALOGV("%s: Read metadata from parcel", __FUNCTION__); + + int32_t size; + if ((err = parcel->readInt32(&size)) != OK) { + ALOGE("%s: Failed to read surface list size from parcel", __FUNCTION__); + return err; + } + ALOGV("%s: Read surface list size = %d", __FUNCTION__, size); + + // Do not distinguish null arrays from 0-sized arrays. + for (int i = 0; i < size; ++i) { + // Parcel.writeParcelableArray + size_t len; + const char16_t* className = parcel->readString16Inplace(&len); + ALOGV("%s: Read surface class = %s", __FUNCTION__, + className != NULL ? String8(className).string() : "<null>"); + + if (className == NULL) { + continue; + } + + // Surface.writeToParcel + String16 name = parcel->readString16(); + ALOGV("%s: Read surface name = %s", + __FUNCTION__, String8(name).string()); + sp<IBinder> binder(parcel->readStrongBinder()); + ALOGV("%s: Read surface binder = %p", + __FUNCTION__, binder.get()); + + sp<Surface> surface; + + if (binder != NULL) { + sp<IGraphicBufferProducer> gbp = + interface_cast<IGraphicBufferProducer>(binder); + surface = new Surface(gbp); + } + + mSurfaceList.push_back(surface); + } + + return OK; +} + +status_t CaptureRequest::writeToParcel(Parcel* parcel) const { + if (parcel == NULL) { + ALOGE("%s: Null parcel", __FUNCTION__); + return BAD_VALUE; + } + + status_t err; + + if ((err = mMetadata.writeToParcel(parcel)) != OK) { + return err; + } + + int32_t size = static_cast<int32_t>(mSurfaceList.size()); + + // Send 0-sized arrays when it's empty. Do not send null arrays. + parcel->writeInt32(size); + + for (int32_t i = 0; i < size; ++i) { + sp<Surface> surface = mSurfaceList[i]; + + sp<IBinder> binder; + if (surface != 0) { + binder = surface->getIGraphicBufferProducer()->asBinder(); + } + + // not sure if readParcelableArray does this, hard to tell from source + parcel->writeString16(String16("android.view.Surface")); + + // Surface.writeToParcel + parcel->writeString16(String16("unknown_name")); + // Surface.nativeWriteToParcel + parcel->writeStrongBinder(binder); + } + + return OK; +} + +}; // namespace android diff --git a/camera/photography/ICameraDeviceCallbacks.cpp b/camera/photography/ICameraDeviceCallbacks.cpp new file mode 100644 index 0000000000..19763d7bbb --- /dev/null +++ b/camera/photography/ICameraDeviceCallbacks.cpp @@ -0,0 +1,110 @@ +/* +** +** 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 "ICameraDeviceCallbacks" +#include <utils/Log.h> +#include <stdint.h> +#include <sys/types.h> + +#include <binder/Parcel.h> +#include <gui/IGraphicBufferProducer.h> +#include <gui/Surface.h> +#include <utils/Mutex.h> + +#include <camera/photography/ICameraDeviceCallbacks.h> +#include "camera/CameraMetadata.h" + +namespace android { + +enum { + NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, + RESULT_RECEIVED, +}; + +class BpCameraDeviceCallbacks: public BpInterface<ICameraDeviceCallbacks> +{ +public: + BpCameraDeviceCallbacks(const sp<IBinder>& impl) + : BpInterface<ICameraDeviceCallbacks>(impl) + { + } + + // generic callback from camera service to app + void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) + { + ALOGV("notifyCallback"); + Parcel data, reply; + data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor()); + data.writeInt32(msgType); + data.writeInt32(ext1); + data.writeInt32(ext2); + remote()->transact(NOTIFY_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); + data.writeNoException(); + } + + void onResultReceived(int32_t frameId, const CameraMetadata& result) { + ALOGV("onResultReceived"); + Parcel data, reply; + data.writeInterfaceToken(ICameraDeviceCallbacks::getInterfaceDescriptor()); + data.writeInt32(frameId); + result.writeToParcel(&data); + remote()->transact(RESULT_RECEIVED, data, &reply, IBinder::FLAG_ONEWAY); + data.writeNoException(); + } +}; + +IMPLEMENT_META_INTERFACE(CameraDeviceCallbacks, + "android.hardware.photography.ICameraDeviceCallbacks"); + +// ---------------------------------------------------------------------- + +status_t BnCameraDeviceCallbacks::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + ALOGV("onTransact - code = %d", code); + switch(code) { + case NOTIFY_CALLBACK: { + ALOGV("NOTIFY_CALLBACK"); + CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply); + int32_t msgType = data.readInt32(); + int32_t ext1 = data.readInt32(); + int32_t ext2 = data.readInt32(); + notifyCallback(msgType, ext1, ext2); + data.readExceptionCode(); + return NO_ERROR; + } break; + case RESULT_RECEIVED: { + ALOGV("RESULT_RECEIVED"); + CHECK_INTERFACE(ICameraDeviceCallbacks, data, reply); + int32_t frameId = data.readInt32(); + CameraMetadata result; + result.readFromParcel(const_cast<Parcel*>(&data)); + onResultReceived(frameId, result); + data.readExceptionCode(); + return NO_ERROR; + break; + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android + diff --git a/camera/photography/ICameraDeviceUser.cpp b/camera/photography/ICameraDeviceUser.cpp new file mode 100644 index 0000000000..0515bd712f --- /dev/null +++ b/camera/photography/ICameraDeviceUser.cpp @@ -0,0 +1,307 @@ +/* +** +** 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 <utils/Log.h> +#include <stdint.h> +#include <sys/types.h> +#include <binder/Parcel.h> +#include <camera/photography/ICameraDeviceUser.h> +#include <gui/IGraphicBufferProducer.h> +#include <gui/Surface.h> +#include <camera/CameraMetadata.h> +#include <camera/photography/CaptureRequest.h> + +namespace android { + +typedef Parcel::WritableBlob WritableBlob; +typedef Parcel::ReadableBlob ReadableBlob; + +enum { + DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, + SUBMIT_REQUEST, + CANCEL_REQUEST, + DELETE_STREAM, + CREATE_STREAM, + CREATE_DEFAULT_REQUEST, + GET_CAMERA_INFO, +}; + +class BpCameraDeviceUser : public BpInterface<ICameraDeviceUser> +{ +public: + BpCameraDeviceUser(const sp<IBinder>& impl) + : BpInterface<ICameraDeviceUser>(impl) + { + } + + // disconnect from camera service + void disconnect() + { + ALOGV("disconnect"); + Parcel data, reply; + data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); + remote()->transact(DISCONNECT, data, &reply); + reply.readExceptionCode(); + } + + virtual int submitRequest(sp<CaptureRequest> request, bool streaming) + { + 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(streaming); + + remote()->transact(SUBMIT_REQUEST, data, &reply); + + reply.readExceptionCode(); + return reply.readInt32(); + } + + virtual status_t cancelRequest(int requestId) + { + Parcel data, reply; + data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); + data.writeInt32(requestId); + + remote()->transact(CANCEL_REQUEST, data, &reply); + + reply.readExceptionCode(); + return reply.readInt32(); + } + + 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<IGraphicBufferProducer>& 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<IBinder> 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(int cameraId, camera_metadata** info) + { + Parcel data, reply; + data.writeInterfaceToken(ICameraDeviceUser::getInterfaceDescriptor()); + data.writeInt32(cameraId); + remote()->transact(GET_CAMERA_INFO, data, &reply); + + + reply.readExceptionCode(); + status_t result = reply.readInt32(); + + if (reply.readInt32() != 0) { + CameraMetadata::readFromParcel(reply, /*out*/info); + } else if (info) { + *info = NULL; + } + + return result; + } + + +private: + + +}; + +IMPLEMENT_META_INTERFACE(CameraDeviceUser, + "android.hardware.photography.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<CaptureRequest> request; + if (data.readInt32() != 0) { + request = new CaptureRequest(); + request->readFromParcel(const_cast<Parcel*>(&data)); + } + + // arg1 = streaming (bool) + bool streaming = data.readInt32(); + + // return code: requestId (int32) + reply->writeNoException(); + reply->writeInt32(submitRequest(request, streaming)); + + return NO_ERROR; + } break; + case CANCEL_REQUEST: { + CHECK_INTERFACE(ICameraDeviceUser, data, reply); + int requestId = data.readInt32(); + reply->writeNoException(); + reply->writeInt32(cancelRequest(requestId)); + 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 = data.readString16(); + 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); + + 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); + + int cameraId = data.readInt32(); + + camera_metadata_t* info = NULL; + status_t ret; + ret = getCameraInfo(cameraId, &info); + + reply->writeInt32(1); // to mark presence of metadata object + CameraMetadata::writeToParcel(*reply, info); + + reply->writeNoException(); + reply->writeInt32(ret); + + free_camera_metadata(info); + + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android |