diff options
author | Igor Murashkin <iam@google.com> | 2013-03-01 16:22:28 -0800 |
---|---|---|
committer | Igor Murashkin <iam@google.com> | 2013-03-11 16:32:24 -0700 |
commit | a2e203bdb911bd5595723651d06ad91c330a7873 (patch) | |
tree | e227cb82c2473d654fd9429d71733fc5a241b604 /services | |
parent | 954a8902f7a6521e110005b4f9490a2fd5be9fe9 (diff) | |
download | frameworks_av-a2e203bdb911bd5595723651d06ad91c330a7873.zip frameworks_av-a2e203bdb911bd5595723651d06ad91c330a7873.tar.gz frameworks_av-a2e203bdb911bd5595723651d06ad91c330a7873.tar.bz2 |
CameraService: Refactor Camera2Client to share a base with ProCameraClient
Change-Id: I249e2a0fc47ae84f29c9d9c4a223fba13da3ee66
Diffstat (limited to 'services')
15 files changed, 583 insertions, 470 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index d6ad889..8600735 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -11,6 +11,7 @@ LOCAL_SRC_FILES:= \ CameraClient.cpp \ Camera2Client.cpp \ ProCamera2Client.cpp \ + Camera2ClientBase.cpp \ CameraDeviceBase.cpp \ Camera2Device.cpp \ Camera3Device.cpp \ diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index 8295905..eb7a8d8 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -49,9 +49,8 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService, uid_t clientUid, int servicePid, int deviceVersion): - Client(cameraService, cameraClient, clientPackageName, + Camera2ClientBase(cameraService, cameraClient, clientPackageName, cameraId, cameraFacing, clientPid, clientUid, servicePid), - mSharedCameraClient(cameraClient), mParameters(cameraId, cameraFacing) { ATRACE_CALL(); @@ -76,15 +75,6 @@ Camera2Client::Camera2Client(const sp<CameraService>& cameraService, l.mParameters.state = Parameters::DISCONNECTED; } -status_t Camera2Client::checkPid(const char* checkLocation) const { - int callingPid = getCallingPid(); - if (callingPid == mClientPid) return NO_ERROR; - - ALOGE("%s: attempt to use a locked camera from a different process" - " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid); - return PERMISSION_DENIED; -} - status_t Camera2Client::initialize(camera_module_t *module) { ATRACE_CALL(); @@ -173,7 +163,7 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) { String8 result; result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n", mCameraId, - getCameraClient()->asBinder().get(), + getRemoteCallback()->asBinder().get(), mClientPid); result.append(" State: "); #define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break; @@ -376,25 +366,15 @@ status_t Camera2Client::dump(int fd, const Vector<String16>& args) { mZslProcessor->dump(fd, args); - result = " Device dump:\n"; - write(fd, result.string(), result.size()); - - status_t res = mDevice->dump(fd, args); - if (res != OK) { - result = String8::format(" Error dumping device: %s (%d)", - strerror(-res), res); - write(fd, result.string(), result.size()); - } - + return dumpDevice(fd, args); #undef CASE_APPEND_ENUM - return NO_ERROR; } // ICamera interface void Camera2Client::disconnect() { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); // Allow both client and the media server to disconnect at all times int callingPid = getCallingPid(); @@ -444,7 +424,7 @@ void Camera2Client::disconnect() { status_t Camera2Client::connect(const sp<ICameraClient>& client) { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); if (mClientPid != 0 && getCallingPid() != mClientPid) { ALOGE("%s: Camera %d: Connection attempt from pid %d; " @@ -455,8 +435,8 @@ status_t Camera2Client::connect(const sp<ICameraClient>& client) { mClientPid = getCallingPid(); - mCameraClient = client; - mSharedCameraClient = client; + mRemoteCallback = client; + mSharedCameraCallbacks = client; return OK; } @@ -464,7 +444,7 @@ status_t Camera2Client::connect(const sp<ICameraClient>& client) { status_t Camera2Client::lock() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); ALOGV("%s: Camera %d: Lock call from pid %d; current client pid %d", __FUNCTION__, mCameraId, getCallingPid(), mClientPid); @@ -485,7 +465,7 @@ status_t Camera2Client::lock() { status_t Camera2Client::unlock() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); ALOGV("%s: Camera %d: Unlock call from pid %d; current client pid %d", __FUNCTION__, mCameraId, getCallingPid(), mClientPid); @@ -497,8 +477,8 @@ status_t Camera2Client::unlock() { return INVALID_OPERATION; } mClientPid = 0; - mCameraClient.clear(); - mSharedCameraClient.clear(); + mRemoteCallback.clear(); + mSharedCameraCallbacks.clear(); return OK; } @@ -511,7 +491,7 @@ status_t Camera2Client::setPreviewDisplay( const sp<Surface>& surface) { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -529,7 +509,7 @@ status_t Camera2Client::setPreviewTexture( const sp<IGraphicBufferProducer>& bufferProducer) { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -598,7 +578,7 @@ status_t Camera2Client::setPreviewWindowL(const sp<IBinder>& binder, void Camera2Client::setPreviewCallbackFlag(int flag) { ATRACE_CALL(); ALOGV("%s: Camera %d: Flag 0x%x", __FUNCTION__, mCameraId, flag); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); if ( checkPid(__FUNCTION__) != OK) return; @@ -637,7 +617,7 @@ void Camera2Client::setPreviewCallbackFlagL(Parameters ¶ms, int flag) { status_t Camera2Client::startPreview() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; SharedParameters::Lock l(mParameters); @@ -753,7 +733,7 @@ status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) { void Camera2Client::stopPreview() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return; stopPreviewL(); @@ -801,7 +781,7 @@ void Camera2Client::stopPreviewL() { bool Camera2Client::previewEnabled() { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return false; @@ -811,7 +791,7 @@ bool Camera2Client::previewEnabled() { status_t Camera2Client::storeMetaDataInBuffers(bool enabled) { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -836,7 +816,7 @@ status_t Camera2Client::storeMetaDataInBuffers(bool enabled) { status_t Camera2Client::startRecording() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; SharedParameters::Lock l(mParameters); @@ -927,7 +907,7 @@ status_t Camera2Client::startRecordingL(Parameters ¶ms, bool restart) { void Camera2Client::stopRecording() { ATRACE_CALL(); ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedParameters::Lock l(mParameters); status_t res; @@ -959,7 +939,7 @@ void Camera2Client::stopRecording() { bool Camera2Client::recordingEnabled() { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); if ( checkPid(__FUNCTION__) != OK) return false; @@ -976,7 +956,7 @@ bool Camera2Client::recordingEnabledL() { void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); if ( checkPid(__FUNCTION__) != OK) return; mStreamingProcessor->releaseRecordingFrame(mem); @@ -984,7 +964,7 @@ void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) { status_t Camera2Client::autoFocus() { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); ALOGV("%s: Camera %d", __FUNCTION__, mCameraId); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -1022,9 +1002,9 @@ status_t Camera2Client::autoFocus() { * Send immediate notification back to client */ if (notifyImmediately) { - SharedCameraClient::Lock l(mSharedCameraClient); - if (l.mCameraClient != 0) { - l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, + SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, notifySuccess ? 1 : 0, 0); } return OK; @@ -1055,7 +1035,7 @@ status_t Camera2Client::autoFocus() { status_t Camera2Client::cancelAutoFocus() { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); ALOGV("%s: Camera %d", __FUNCTION__, mCameraId); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -1087,7 +1067,7 @@ status_t Camera2Client::cancelAutoFocus() { status_t Camera2Client::takePicture(int msgType) { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -1146,7 +1126,7 @@ status_t Camera2Client::takePicture(int msgType) { status_t Camera2Client::setParameters(const String8& params) { ATRACE_CALL(); ALOGV("%s: Camera %d", __FUNCTION__, mCameraId); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -1163,7 +1143,7 @@ status_t Camera2Client::setParameters(const String8& params) { String8 Camera2Client::getParameters() const { ATRACE_CALL(); ALOGV("%s: Camera %d", __FUNCTION__, mCameraId); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); if ( checkPid(__FUNCTION__) != OK) return String8(); SharedParameters::ReadLock l(mParameters); @@ -1173,7 +1153,7 @@ String8 Camera2Client::getParameters() const { status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { ATRACE_CALL(); - Mutex::Autolock icl(mICameraLock); + Mutex::Autolock icl(mBinderSerializationLock); status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; @@ -1348,18 +1328,6 @@ status_t Camera2Client::commandSetVideoBufferCountL(size_t count) { } /** Device-related methods */ - -void Camera2Client::notifyError(int errorCode, int arg1, int arg2) { - ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode, arg1, arg2); -} - -void Camera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) { - (void)frameNumber; - (void)timestamp; - ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__, - frameNumber, timestamp); -} - void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) { ALOGV("%s: Autofocus state now %d, last trigger %d", __FUNCTION__, newState, triggerId); @@ -1455,16 +1423,16 @@ void Camera2Client::notifyAutoFocus(uint8_t newState, int triggerId) { } } if (sendMovingMessage) { - SharedCameraClient::Lock l(mSharedCameraClient); - if (l.mCameraClient != 0) { - l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS_MOVE, + SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, afInMotion ? 1 : 0, 0); } } if (sendCompletedMessage) { - SharedCameraClient::Lock l(mSharedCameraClient); - if (l.mCameraClient != 0) { - l.mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, + SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, success ? 1 : 0, 0); } } @@ -1476,25 +1444,6 @@ void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) { mCaptureSequencer->notifyAutoExposure(newState, triggerId); } -void Camera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) { - (void)newState; - (void)triggerId; - ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", - __FUNCTION__, newState, triggerId); -} - -int Camera2Client::getCameraId() const { - return mCameraId; -} - -const sp<CameraDeviceBase>& Camera2Client::getCameraDevice() { - return mDevice; -} - -const sp<CameraService>& Camera2Client::getCameraService() { - return mCameraService; -} - camera2::SharedParameters& Camera2Client::getParameters() { return mParameters; } @@ -1533,32 +1482,6 @@ status_t Camera2Client::stopStream() { return mStreamingProcessor->stopStream(); } -Camera2Client::SharedCameraClient::Lock::Lock(SharedCameraClient &client): - mCameraClient(client.mCameraClient), - mSharedClient(client) { - mSharedClient.mCameraClientLock.lock(); -} - -Camera2Client::SharedCameraClient::Lock::~Lock() { - mSharedClient.mCameraClientLock.unlock(); -} - -Camera2Client::SharedCameraClient::SharedCameraClient(const sp<ICameraClient>&client): - mCameraClient(client) { -} - -Camera2Client::SharedCameraClient& Camera2Client::SharedCameraClient::operator=( - const sp<ICameraClient>&client) { - Mutex::Autolock l(mCameraClientLock); - mCameraClient = client; - return *this; -} - -void Camera2Client::SharedCameraClient::clear() { - Mutex::Autolock l(mCameraClientLock); - mCameraClient.clear(); -} - const int32_t Camera2Client::kPreviewRequestIdStart; const int32_t Camera2Client::kPreviewRequestIdEnd; const int32_t Camera2Client::kRecordingRequestIdStart; @@ -1660,4 +1583,5 @@ status_t Camera2Client::syncWithDevice() { return res; } + } // namespace android diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index 80b88f4..713fab3 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -26,6 +26,7 @@ #include "camera2/ZslProcessor.h" #include "camera2/CaptureSequencer.h" #include "camera2/CallbackProcessor.h" +#include "Camera2ClientBase.h" namespace android { @@ -35,8 +36,7 @@ class IMemory; * CAMERA_DEVICE_API_VERSION_2_0 and 3_0. */ class Camera2Client : - public CameraService::Client, - public CameraDeviceBase::NotificationListener + public Camera2ClientBase<CameraService::Client> { public: /** @@ -90,19 +90,13 @@ public: * Interface used by CameraDeviceBase */ - virtual void notifyError(int errorCode, int arg1, int arg2); - virtual void notifyShutter(int frameNumber, nsecs_t timestamp); virtual void notifyAutoFocus(uint8_t newState, int triggerId); virtual void notifyAutoExposure(uint8_t newState, int triggerId); - virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId); /** * Interface used by independent components of Camera2Client. */ - int getCameraId() const; - const sp<CameraDeviceBase>& getCameraDevice(); - const sp<CameraService>& getCameraService(); camera2::SharedParameters& getParameters(); int getPreviewStreamId() const; @@ -118,27 +112,6 @@ public: status_t stopStream(); - // Simple class to ensure that access to ICameraClient is serialized by - // requiring mCameraClientLock to be locked before access to mCameraClient - // is possible. - class SharedCameraClient { - public: - class Lock { - public: - Lock(SharedCameraClient &client); - ~Lock(); - sp<ICameraClient> &mCameraClient; - private: - SharedCameraClient &mSharedClient; - }; - SharedCameraClient(const sp<ICameraClient>& client); - SharedCameraClient& operator=(const sp<ICameraClient>& client); - void clear(); - private: - sp<ICameraClient> mCameraClient; - mutable Mutex mCameraClientLock; - } mSharedCameraClient; - static size_t calculateBufferSize(int width, int height, int format, int stride); @@ -153,13 +126,6 @@ public: private: /** ICamera interface-related private members */ - - // Mutex that must be locked by methods implementing the ICamera interface. - // Ensures serialization between incoming ICamera calls. All methods below - // that append 'L' to the name assume that mICameraLock is locked when - // they're called - mutable Mutex mICameraLock; - typedef camera2::Parameters Parameters; status_t setPreviewWindowL(const sp<IBinder>& binder, @@ -213,17 +179,10 @@ private: bool mAfInMotion; - /** CameraDevice instance, wraps HAL camera device */ - - sp<CameraDeviceBase> mDevice; - /** Utility members */ // Wait until the camera device has received the latest control settings status_t syncWithDevice(); - - // Verify that caller is the owner of the camera - status_t checkPid(const char *checkLocation) const; }; }; // namespace android diff --git a/services/camera/libcameraservice/Camera2ClientBase.cpp b/services/camera/libcameraservice/Camera2ClientBase.cpp new file mode 100644 index 0000000..e92ad1c --- /dev/null +++ b/services/camera/libcameraservice/Camera2ClientBase.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (C) 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_TAG "Camera2ClientBase" +#define ATRACE_TAG ATRACE_TAG_CAMERA +//#define LOG_NDEBUG 0 + +#include <utils/Log.h> +#include <utils/Trace.h> + +#include <cutils/properties.h> +#include <gui/Surface.h> +#include <gui/Surface.h> +#include "camera2/Parameters.h" +#include "Camera2ClientBase.h" +#include "camera2/ProFrameProcessor.h" + +#include "Camera2Device.h" + +namespace android { +using namespace camera2; + +static int getCallingPid() { + return IPCThreadState::self()->getCallingPid(); +} + +// Interface used by CameraService + +template <typename TClientBase> +Camera2ClientBase<TClientBase>::Camera2ClientBase( + const sp<CameraService>& cameraService, + const sp<TCamCallbacks>& remoteCallback, + const String16& clientPackageName, + int cameraId, + int cameraFacing, + int clientPid, + uid_t clientUid, + int servicePid): + TClientBase(cameraService, remoteCallback, clientPackageName, + cameraId, cameraFacing, clientPid, clientUid, servicePid), + mSharedCameraCallbacks(remoteCallback) +{ + ALOGI("Camera %d: Opened", cameraId); + mDevice = new Camera2Device(cameraId); +} + +template <typename TClientBase> +status_t Camera2ClientBase<TClientBase>::checkPid(const char* checkLocation) + const { + + int callingPid = getCallingPid(); + if (callingPid == TClientBase::mClientPid) return NO_ERROR; + + ALOGE("%s: attempt to use a locked camera from a different process" + " (old pid %d, new pid %d)", checkLocation, TClientBase::mClientPid, callingPid); + return PERMISSION_DENIED; +} + +template <typename TClientBase> +status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) { + ATRACE_CALL(); + ALOGV("%s: Initializing client for camera %d", __FUNCTION__, + TClientBase::mCameraId); + status_t res; + + res = mDevice->initialize(module); + if (res != OK) { + ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", + __FUNCTION__, TClientBase::mCameraId, strerror(-res), res); + return NO_INIT; + } + + res = mDevice->setNotifyCallback(this); + + return OK; +} + +template <typename TClientBase> +Camera2ClientBase<TClientBase>::~Camera2ClientBase() { + ATRACE_CALL(); + + TClientBase::mDestructionStarted = true; + + disconnect(); + + ALOGI("Closed Camera %d", TClientBase::mCameraId); +} + +template <typename TClientBase> +status_t Camera2ClientBase<TClientBase>::dump(int fd, + const Vector<String16>& args) { + String8 result; + result.appendFormat("Camera2ClientBase[%d] (%p) PID: %d, dump:\n", + TClientBase::mCameraId, + TClientBase::getRemoteCallback()->asBinder().get(), + TClientBase::mClientPid); + result.append(" State: "); + + write(fd, result.string(), result.size()); + // TODO: print dynamic/request section from most recent requests + + return dumpDevice(fd, args); +} + +template <typename TClientBase> +status_t Camera2ClientBase<TClientBase>::dumpDevice( + int fd, + const Vector<String16>& args) { + String8 result; + + result = " Device dump:\n"; + write(fd, result.string(), result.size()); + + if (!mDevice.get()) { + result = " *** Device is detached\n"; + write(fd, result.string(), result.size()); + return NO_ERROR; + } + + status_t res = mDevice->dump(fd, args); + if (res != OK) { + result = String8::format(" Error dumping device: %s (%d)", + strerror(-res), res); + write(fd, result.string(), result.size()); + } + + return NO_ERROR; +} + +// ICameraClient2BaseUser interface + + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::disconnect() { + ATRACE_CALL(); + Mutex::Autolock icl(mBinderSerializationLock); + + // Allow both client and the media server to disconnect at all times + int callingPid = getCallingPid(); + if (callingPid != TClientBase::mClientPid && + callingPid != TClientBase::mServicePid) return; + + ALOGV("Camera %d: Shutting down", TClientBase::mCameraId); + + detachDevice(); + + TClientBase::disconnect(); + + ALOGV("Camera %d: Shut down complete complete", TClientBase::mCameraId); +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::detachDevice() { + if (mDevice == 0) return; + mDevice->disconnect(); + + mDevice.clear(); + + ALOGV("Camera %d: Detach complete", TClientBase::mCameraId); +} + +template <typename TClientBase> +status_t Camera2ClientBase<TClientBase>::connect( + const sp<TCamCallbacks>& client) { + ATRACE_CALL(); + ALOGV("%s: E", __FUNCTION__); + Mutex::Autolock icl(mBinderSerializationLock); + + if (TClientBase::mClientPid != 0 && + getCallingPid() != TClientBase::mClientPid) { + + ALOGE("%s: Camera %d: Connection attempt from pid %d; " + "current locked to pid %d", + __FUNCTION__, + TClientBase::mCameraId, + getCallingPid(), + TClientBase::mClientPid); + return BAD_VALUE; + } + + TClientBase::mClientPid = getCallingPid(); + + TClientBase::mRemoteCallback = client; + mSharedCameraCallbacks = client; + + return OK; +} + +/** Device-related methods */ + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::notifyError(int errorCode, int arg1, + int arg2) { + ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode, + arg1, arg2); +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::notifyShutter(int frameNumber, + nsecs_t timestamp) { + (void)frameNumber; + (void)timestamp; + + ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__, + frameNumber, timestamp); +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::notifyAutoFocus(uint8_t newState, + int triggerId) { + (void)newState; + (void)triggerId; + + ALOGV("%s: Autofocus state now %d, last trigger %d", + __FUNCTION__, newState, triggerId); + + typename SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, 1, 0); + } + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, 1, 0); + } +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::notifyAutoExposure(uint8_t newState, + int triggerId) { + (void)newState; + (void)triggerId; + + ALOGV("%s: Autoexposure state now %d, last trigger %d", + __FUNCTION__, newState, triggerId); +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::notifyAutoWhitebalance(uint8_t newState, + int triggerId) { + (void)newState; + (void)triggerId; + + ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", + __FUNCTION__, newState, triggerId); +} + +template <typename TClientBase> +int Camera2ClientBase<TClientBase>::getCameraId() const { + return TClientBase::mCameraId; +} + +template <typename TClientBase> +const sp<CameraDeviceBase>& Camera2ClientBase<TClientBase>::getCameraDevice() { + return mDevice; +} + +template <typename TClientBase> +const sp<CameraService>& Camera2ClientBase<TClientBase>::getCameraService() { + return TClientBase::mCameraService; +} + +template <typename TClientBase> +Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::Lock( + SharedCameraCallbacks &client) : + + mRemoteCallback(client.mRemoteCallback), + mSharedClient(client) { + + mSharedClient.mRemoteCallbackLock.lock(); +} + +template <typename TClientBase> +Camera2ClientBase<TClientBase>::SharedCameraCallbacks::Lock::~Lock() { + mSharedClient.mRemoteCallbackLock.unlock(); +} + +template <typename TClientBase> +Camera2ClientBase<TClientBase>::SharedCameraCallbacks::SharedCameraCallbacks( + const sp<TCamCallbacks>&client) : + + mRemoteCallback(client) { +} + +template <typename TClientBase> +typename Camera2ClientBase<TClientBase>::SharedCameraCallbacks& +Camera2ClientBase<TClientBase>::SharedCameraCallbacks::operator=( + const sp<TCamCallbacks>&client) { + + Mutex::Autolock l(mRemoteCallbackLock); + mRemoteCallback = client; + return *this; +} + +template <typename TClientBase> +void Camera2ClientBase<TClientBase>::SharedCameraCallbacks::clear() { + Mutex::Autolock l(mRemoteCallbackLock); + mRemoteCallback.clear(); +} + +template class Camera2ClientBase<CameraService::ProClient>; +template class Camera2ClientBase<CameraService::Client>; + +} // namespace android diff --git a/services/camera/libcameraservice/Camera2ClientBase.h b/services/camera/libcameraservice/Camera2ClientBase.h new file mode 100644 index 0000000..9001efb --- /dev/null +++ b/services/camera/libcameraservice/Camera2ClientBase.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H +#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_BASE_H + +#include "CameraDeviceBase.h" +#include "CameraService.h" + +namespace android { + +class IMemory; + +template <typename TClientBase> +class Camera2ClientBase : + public TClientBase, + public CameraDeviceBase::NotificationListener +{ +public: + typedef typename TClientBase::TCamCallbacks TCamCallbacks; + + /** + * Base binder interface (see ICamera/IProCameraUser for details) + */ + virtual status_t connect(const sp<TCamCallbacks>& callbacks); + virtual void disconnect(); + + /** + * Interface used by CameraService + */ + + // TODO: too many params, move into a ClientArgs<T> + Camera2ClientBase(const sp<CameraService>& cameraService, + const sp<TCamCallbacks>& remoteCallback, + const String16& clientPackageName, + int cameraId, + int cameraFacing, + int clientPid, + uid_t clientUid, + int servicePid); + virtual ~Camera2ClientBase(); + + virtual status_t initialize(camera_module_t *module); + virtual status_t dump(int fd, const Vector<String16>& args); + + /** + * CameraDeviceBase::NotificationListener implementation + */ + + virtual void notifyError(int errorCode, int arg1, int arg2); + virtual void notifyShutter(int frameNumber, nsecs_t timestamp); + virtual void notifyAutoFocus(uint8_t newState, int triggerId); + virtual void notifyAutoExposure(uint8_t newState, int triggerId); + virtual void notifyAutoWhitebalance(uint8_t newState, + int triggerId); + + + int getCameraId() const; + const sp<CameraDeviceBase>& + getCameraDevice(); + const sp<CameraService>& + getCameraService(); + + /** + * Interface used by independent components of CameraClient2Base. + */ + + // Simple class to ensure that access to TCamCallbacks is serialized + // by requiring mRemoteCallbackLock to be locked before access to + // mRemoteCallback is possible. + class SharedCameraCallbacks { + public: + class Lock { + public: + Lock(SharedCameraCallbacks &client); + ~Lock(); + sp<TCamCallbacks> &mRemoteCallback; + private: + SharedCameraCallbacks &mSharedClient; + }; + SharedCameraCallbacks(const sp<TCamCallbacks>& client); + SharedCameraCallbacks& operator=(const sp<TCamCallbacks>& client); + void clear(); + private: + sp<TCamCallbacks> mRemoteCallback; + mutable Mutex mRemoteCallbackLock; + } mSharedCameraCallbacks; + +protected: + + virtual status_t dumpDevice(int fd, const Vector<String16>& args); + + /** Binder client interface-related private members */ + + // Mutex that must be locked by methods implementing the binder client + // interface. Ensures serialization between incoming client calls. + // All methods in this class hierarchy that append 'L' to the name assume + // that mBinderSerializationLock is locked when they're called + mutable Mutex mBinderSerializationLock; + + /** CameraDeviceBase instance wrapping HAL2+ entry */ + + sp<CameraDeviceBase> mDevice; + + /** Utility members */ + + // Verify that caller is the owner of the camera + status_t checkPid(const char *checkLocation) const; + + virtual void detachDevice(); +}; + +}; // namespace android + +#endif diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index 90f8f40..e577fa3 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -117,7 +117,7 @@ status_t CameraClient::dump(int fd, const Vector<String16>& args) { size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) PID: %d\n", mCameraId, - getCameraClient()->asBinder().get(), + getRemoteCallback()->asBinder().get(), mClientPid); len = (len > SIZE - 1) ? SIZE - 1 : len; write(fd, buffer, len); @@ -173,10 +173,10 @@ status_t CameraClient::unlock() { return INVALID_OPERATION; } mClientPid = 0; - LOG1("clear mCameraClient (pid %d)", callingPid); + LOG1("clear mRemoteCallback (pid %d)", callingPid); // we need to remove the reference to ICameraClient so that when the app // goes away, the reference count goes to 0. - mCameraClient.clear(); + mRemoteCallback.clear(); } return result; } @@ -193,14 +193,15 @@ status_t CameraClient::connect(const sp<ICameraClient>& client) { return EBUSY; } - if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) { + if (mRemoteCallback != 0 && + (client->asBinder() == mRemoteCallback->asBinder())) { LOG1("Connect to the same client"); return NO_ERROR; } mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP; mClientPid = callingPid; - mCameraClient = client; + mRemoteCallback = client; LOG1("connect X (pid %d)", callingPid); return NO_ERROR; @@ -780,7 +781,7 @@ void CameraClient::handleShutter(void) { mCameraService->playSound(CameraService::SOUND_SHUTTER); } - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; if (c != 0) { mLock.unlock(); c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); @@ -811,7 +812,7 @@ void CameraClient::handlePreviewData(int32_t msgType, } // hold a strong pointer to the client - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; // clear callback flags if no client or one-shot mode if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) { @@ -841,7 +842,7 @@ void CameraClient::handlePreviewData(int32_t msgType, void CameraClient::handlePostview(const sp<IMemory>& mem) { disableMsgType(CAMERA_MSG_POSTVIEW_FRAME); - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL); @@ -856,7 +857,7 @@ void CameraClient::handleRawPicture(const sp<IMemory>& mem) { size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL); @@ -867,7 +868,7 @@ void CameraClient::handleRawPicture(const sp<IMemory>& mem) { void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL); @@ -877,7 +878,7 @@ void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { void CameraClient::handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2) { - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->notifyCallback(msgType, ext1, ext2); @@ -886,7 +887,7 @@ void CameraClient::handleGenericNotify(int32_t msgType, void CameraClient::handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallback(msgType, dataPtr, metadata); @@ -895,7 +896,7 @@ void CameraClient::handleGenericData(int32_t msgType, void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) { - sp<ICameraClient> c = mCameraClient; + sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); if (c != 0) { c->dataCallbackTimestamp(timestamp, msgType, dataPtr); diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 8c4f619..d46ca88 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -223,7 +223,9 @@ sp<ICamera> CameraService::connect( if (mClient[cameraId] != 0) { client = mClient[cameraId].promote(); if (client != 0) { - if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) { + if (cameraClient->asBinder() == + client->getRemoteCallback()->asBinder()) { + LOG1("CameraService::connect X (pid %d) (the same client)", callingPid); return client; @@ -496,7 +498,7 @@ sp<CameraService::Client> CameraService::findClientUnsafe( continue; } - if (cameraClient == client->getCameraClient()->asBinder()) { + if (cameraClient == client->getRemoteCallback()->asBinder()) { // Found our camera outIndex = i; return client; @@ -639,7 +641,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, int callingPid = getCallingPid(); LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId); - mCameraClient = cameraClient; + mRemoteCallback = cameraClient; cameraService->setCameraBusy(cameraId); cameraService->loadSound(); @@ -666,7 +668,7 @@ CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService, mClientPackageName(clientPackageName) { mCameraService = cameraService; - mRemoteCallback = remoteCallback; + mRemoteBinder = remoteCallback; mCameraId = cameraId; mCameraFacing = cameraFacing; mClientPid = clientPid; @@ -681,7 +683,7 @@ CameraService::BasicClient::~BasicClient() { } void CameraService::BasicClient::disconnect() { - mCameraService->removeClientByRemote(mRemoteCallback); + mCameraService->removeClientByRemote(mRemoteBinder); } status_t CameraService::BasicClient::startCameraOps() { @@ -767,7 +769,7 @@ CameraService::Client* CameraService::Client::getClientFromCookie(void* user) { } void CameraService::Client::notifyError() { - mCameraClient->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); + mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); } // NOTE: function is idempotent diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 8acc63f..d7a336c 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -109,7 +109,7 @@ public: virtual void disconnect() = 0; wp<IBinder> getRemote() { - return mRemoteCallback; + return mRemoteBinder; } protected: @@ -140,7 +140,7 @@ public: pid_t mServicePid; // immutable after constructor // - The app-side Binder interface to receive callbacks from us - wp<IBinder> mRemoteCallback; // immutable after constructor + wp<IBinder> mRemoteBinder; // immutable after constructor // permissions management status_t startCameraOps(); @@ -173,6 +173,8 @@ public: class Client : public BnCamera, public BasicClient { public: + typedef ICameraClient TCamCallbacks; + // ICamera interface (see ICamera for details) virtual void disconnect(); virtual status_t connect(const sp<ICameraClient>& client) = 0; @@ -208,8 +210,8 @@ public: ~Client(); // return our camera client - const sp<ICameraClient>& getCameraClient() { - return mCameraClient; + const sp<ICameraClient>& getRemoteCallback() { + return mRemoteCallback; } protected: @@ -222,12 +224,14 @@ public: // Initialized in constructor // - The app-side Binder interface to receive callbacks from us - sp<ICameraClient> mCameraClient; + sp<ICameraClient> mRemoteCallback; }; // class Client class ProClient : public BnProCameraUser, public BasicClient { public: + typedef IProCameraCallbacks TCamCallbacks; + ProClient(const sp<CameraService>& cameraService, const sp<IProCameraCallbacks>& remoteCallback, const String16& clientPackageName, diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp index 6fed8b4..4a5a3d5 100644 --- a/services/camera/libcameraservice/ProCamera2Client.cpp +++ b/services/camera/libcameraservice/ProCamera2Client.cpp @@ -31,64 +31,38 @@ namespace android { using namespace camera2; -static int getCallingPid() { - return IPCThreadState::self()->getCallingPid(); -} - -static int getCallingUid() { - return IPCThreadState::self()->getCallingUid(); -} - // Interface used by CameraService ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService, - const sp<IProCameraCallbacks>& remoteCallback, - const String16& clientPackageName, - int cameraId, - int cameraFacing, - int clientPid, - uid_t clientUid, - int servicePid): - ProClient(cameraService, remoteCallback, clientPackageName, - cameraId, cameraFacing, clientPid, clientUid, servicePid), - mSharedCameraCallbacks(remoteCallback) + const sp<IProCameraCallbacks>& remoteCallback, + const String16& clientPackageName, + int cameraId, + int cameraFacing, + int clientPid, + uid_t clientUid, + int servicePid) : + Camera2ClientBase(cameraService, remoteCallback, clientPackageName, + cameraId, cameraFacing, clientPid, clientUid, servicePid) { ATRACE_CALL(); ALOGI("ProCamera %d: Opened", cameraId); - mDevice = new Camera2Device(cameraId); - mExclusiveLock = false; } -status_t ProCamera2Client::checkPid(const char* checkLocation) const { - int callingPid = getCallingPid(); - if (callingPid == mClientPid) return NO_ERROR; - - ALOGE("%s: attempt to use a locked camera from a different process" - " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid); - return PERMISSION_DENIED; -} - status_t ProCamera2Client::initialize(camera_module_t *module) { ATRACE_CALL(); - ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId); status_t res; - res = mDevice->initialize(module); + res = Camera2ClientBase::initialize(module); if (res != OK) { - ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", - __FUNCTION__, mCameraId, strerror(-res), res); - return NO_INIT; + return res; } - res = mDevice->setNotifyCallback(this); - String8 threadName; mFrameProcessor = new ProFrameProcessor(this); - threadName = String8::format("PC2-%d-FrameProc", - mCameraId); + threadName = String8::format("PC2-%d-FrameProc", mCameraId); mFrameProcessor->run(threadName.string()); mFrameProcessor->registerListener(FRAME_PROCESSOR_LISTENER_MIN_ID, @@ -99,20 +73,13 @@ status_t ProCamera2Client::initialize(camera_module_t *module) } ProCamera2Client::~ProCamera2Client() { - ATRACE_CALL(); - - mDestructionStarted = true; - - disconnect(); - - ALOGI("ProCamera %d: Closed", mCameraId); } status_t ProCamera2Client::exclusiveTryLock() { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); if (!mDevice.get()) return PERMISSION_DENIED; @@ -143,7 +110,7 @@ status_t ProCamera2Client::exclusiveLock() { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); if (!mDevice.get()) return PERMISSION_DENIED; @@ -177,7 +144,7 @@ status_t ProCamera2Client::exclusiveUnlock() { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); // don't allow unlocking if we have no lock @@ -198,6 +165,7 @@ status_t ProCamera2Client::exclusiveUnlock() { } bool ProCamera2Client::hasExclusiveLock() { + Mutex::Autolock icl(mBinderSerializationLock); return mExclusiveLock; } @@ -205,7 +173,7 @@ void ProCamera2Client::onExclusiveLockStolen() { ALOGV("%s: ProClient lost exclusivity (id %d)", __FUNCTION__, mCameraId); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); if (mExclusiveLock && mRemoteCallback.get() != NULL) { @@ -224,7 +192,7 @@ status_t ProCamera2Client::submitRequest(camera_metadata_t* request, ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; @@ -248,7 +216,7 @@ status_t ProCamera2Client::cancelRequest(int requestId) { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; @@ -256,10 +224,12 @@ status_t ProCamera2Client::cancelRequest(int requestId) { return PERMISSION_DENIED; } + // TODO: implement ALOGE("%s: not fully implemented yet", __FUNCTION__); return INVALID_OPERATION; } +//TODO: Remove status_t ProCamera2Client::requestStream(int streamId) { ALOGE("%s: not implemented yet", __FUNCTION__); @@ -273,7 +243,7 @@ status_t ProCamera2Client::cancelStream(int streamId) { status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; mDevice->clearStreamingRequest(); @@ -301,7 +271,7 @@ status_t ProCamera2Client::createStream(int width, int height, int format, status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; @@ -332,7 +302,7 @@ status_t ProCamera2Client::createDefaultRequest(int templateId, status_t res; if ( (res = checkPid(__FUNCTION__) ) != OK) return res; - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; @@ -352,7 +322,7 @@ status_t ProCamera2Client::getCameraInfo(int cameraId, return INVALID_OPERATION; } - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); if (!mDevice.get()) return DEAD_OBJECT; @@ -373,47 +343,11 @@ status_t ProCamera2Client::dump(int fd, const Vector<String16>& args) { // TODO: print dynamic/request section from most recent requests mFrameProcessor->dump(fd, args); -#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break; - - result = " Device dump:\n"; - write(fd, result.string(), result.size()); - - if (!mDevice.get()) { - result = " *** Device is detached\n"; - write(fd, result.string(), result.size()); - return NO_ERROR; - } - - status_t res = mDevice->dump(fd, args); - if (res != OK) { - result = String8::format(" Error dumping device: %s (%d)", - strerror(-res), res); - write(fd, result.string(), result.size()); - } - -#undef CASE_APPEND_ENUM - return NO_ERROR; + return dumpDevice(fd, args); } // IProCameraUser interface -void ProCamera2Client::disconnect() { - ATRACE_CALL(); - Mutex::Autolock icl(mIProCameraUserLock); - status_t res; - - // Allow both client and the media server to disconnect at all times - int callingPid = getCallingPid(); - if (callingPid != mClientPid && callingPid != mServicePid) return; - - ALOGV("Camera %d: Shutting down", mCameraId); - - detachDevice(); - ProClient::disconnect(); - - ALOGV("Camera %d: Shut down complete complete", mCameraId); -} - void ProCamera2Client::detachDevice() { if (mDevice == 0) return; @@ -438,117 +372,16 @@ void ProCamera2Client::detachDevice() { } } - mDevice->disconnect(); - - mDevice.clear(); - - ALOGV("Camera %d: Detach complete", mCameraId); -} - -status_t ProCamera2Client::connect(const sp<IProCameraCallbacks>& client) { - ATRACE_CALL(); - ALOGV("%s: E", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); - - if (mClientPid != 0 && getCallingPid() != mClientPid) { - ALOGE("%s: Camera %d: Connection attempt from pid %d; " - "current locked to pid %d", __FUNCTION__, - mCameraId, getCallingPid(), mClientPid); - return BAD_VALUE; - } - - mClientPid = getCallingPid(); - - mRemoteCallback = client; - mSharedCameraCallbacks = client; - - return OK; + Camera2ClientBase::detachDevice(); } /** Device-related methods */ - -void ProCamera2Client::notifyError(int errorCode, int arg1, int arg2) { - ALOGE("Error condition %d reported by HAL, arguments %d, %d", errorCode, - arg1, arg2); -} - -void ProCamera2Client::notifyShutter(int frameNumber, nsecs_t timestamp) { - ALOGV("%s: Shutter notification for frame %d at time %lld", __FUNCTION__, - frameNumber, timestamp); -} - -void ProCamera2Client::notifyAutoFocus(uint8_t newState, int triggerId) { - ALOGV("%s: Autofocus state now %d, last trigger %d", - __FUNCTION__, newState, triggerId); - - SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); - if (l.mRemoteCallback != 0) { - l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS_MOVE, - 1, 0); - } - if (l.mRemoteCallback != 0) { - l.mRemoteCallback->notifyCallback(CAMERA_MSG_FOCUS, - 1, 0); - } -} - -void ProCamera2Client::notifyAutoExposure(uint8_t newState, int triggerId) { - ALOGV("%s: Autoexposure state now %d, last trigger %d", - __FUNCTION__, newState, triggerId); -} - -void ProCamera2Client::notifyAutoWhitebalance(uint8_t newState, int triggerId) { - ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", - __FUNCTION__, newState, triggerId); -} - -int ProCamera2Client::getCameraId() const { - return mCameraId; -} - -const sp<Camera2Device>& ProCamera2Client::getCameraDevice() { - return mDevice; -} - -const sp<CameraService>& ProCamera2Client::getCameraService() { - return mCameraService; -} - -ProCamera2Client::SharedCameraCallbacks::Lock::Lock( - SharedCameraCallbacks &client): - mRemoteCallback(client.mRemoteCallback), - mSharedClient(client) { - mSharedClient.mRemoteCallbackLock.lock(); -} - -ProCamera2Client::SharedCameraCallbacks::Lock::~Lock() { - mSharedClient.mRemoteCallbackLock.unlock(); -} - -ProCamera2Client::SharedCameraCallbacks::SharedCameraCallbacks - (const sp<IProCameraCallbacks>&client): - mRemoteCallback(client) { -} - -ProCamera2Client::SharedCameraCallbacks& - ProCamera2Client::SharedCameraCallbacks::operator=( - const sp<IProCameraCallbacks>&client) { - Mutex::Autolock l(mRemoteCallbackLock); - mRemoteCallback = client; - return *this; -} - -void ProCamera2Client::SharedCameraCallbacks::clear() { - Mutex::Autolock l(mRemoteCallbackLock); - mRemoteCallback.clear(); -} - void ProCamera2Client::onFrameAvailable(int32_t frameId, const CameraMetadata& frame) { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); - Mutex::Autolock icl(mIProCameraUserLock); + Mutex::Autolock icl(mBinderSerializationLock); SharedCameraCallbacks::Lock l(mSharedCameraCallbacks); if (mRemoteCallback != NULL) { diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h index ff6f4e2..f69021e 100644 --- a/services/camera/libcameraservice/ProCamera2Client.h +++ b/services/camera/libcameraservice/ProCamera2Client.h @@ -20,6 +20,7 @@ #include "Camera2Device.h" #include "CameraService.h" #include "camera2/ProFrameProcessor.h" +#include "Camera2ClientBase.h" namespace android { @@ -29,17 +30,13 @@ class IMemory; * meant for HAL2-level private API access. */ class ProCamera2Client : - public CameraService::ProClient, - public Camera2Device::NotificationListener, + public Camera2ClientBase<CameraService::ProClient>, public camera2::ProFrameProcessor::FilteredListener { public: /** * IProCameraUser interface (see IProCameraUser for details) */ - virtual status_t connect(const sp<IProCameraCallbacks>& callbacks); - virtual void disconnect(); - virtual status_t exclusiveTryLock(); virtual status_t exclusiveLock(); virtual status_t exclusiveUnlock(); @@ -54,10 +51,13 @@ public: virtual status_t requestStream(int streamId); virtual status_t cancelStream(int streamId); - virtual status_t createStream(int width, int height, int format, - const sp<IGraphicBufferProducer>& bufferProducer, - /*out*/ - int* streamId); + virtual status_t createStream( + int width, + int height, + int format, + const sp<IGraphicBufferProducer>& bufferProducer, + /*out*/ + int* streamId); // Create a request object from a template. // -- Caller owns the newly allocated metadata @@ -85,24 +85,9 @@ public: int servicePid); virtual ~ProCamera2Client(); - status_t initialize(camera_module_t *module); - - virtual status_t dump(int fd, const Vector<String16>& args); - - /** - * Interface used by Camera2Device - */ - - virtual void notifyError(int errorCode, int arg1, int arg2); - virtual void notifyShutter(int frameNumber, nsecs_t timestamp); - virtual void notifyAutoFocus(uint8_t newState, int triggerId); - virtual void notifyAutoExposure(uint8_t newState, int triggerId); - virtual void notifyAutoWhitebalance(uint8_t newState, int triggerId); + virtual status_t initialize(camera_module_t *module); - - int getCameraId() const; - const sp<Camera2Device>& getCameraDevice(); - const sp<CameraService>& getCameraService(); + virtual status_t dump(int fd, const Vector<String16>& args); // Callbacks from camera service virtual void onExclusiveLockStolen(); @@ -111,67 +96,26 @@ public: * Interface used by independent components of ProCamera2Client. */ - // Simple class to ensure that access to IProCameraCallbacks is serialized - // by requiring mRemoteCallbackLock to be locked before access to - // mCameraClient is possible. - class SharedCameraCallbacks { - public: - class Lock { - public: - Lock(SharedCameraCallbacks &client); - ~Lock(); - sp<IProCameraCallbacks> &mRemoteCallback; - private: - SharedCameraCallbacks &mSharedClient; - }; - SharedCameraCallbacks(const sp<IProCameraCallbacks>& client); - SharedCameraCallbacks& operator=(const sp<IProCameraCallbacks>& client); - void clear(); - private: - sp<IProCameraCallbacks> mRemoteCallback; - mutable Mutex mRemoteCallbackLock; - } mSharedCameraCallbacks; - protected: /** FilteredListener implementation **/ - virtual void onFrameAvailable(int32_t frameId, const CameraMetadata& frame); + virtual void onFrameAvailable(int32_t frameId, + const CameraMetadata& frame); + virtual void detachDevice(); private: /** IProCameraUser interface-related private members */ - // Mutex that must be locked by methods implementing the IProCameraUser - // interface. Ensures serialization between incoming IProCameraUser calls. - // All methods below that append 'L' to the name assume that - // mIProCameraUserLock is locked when they're called - mutable Mutex mIProCameraUserLock; - - // Used with stream IDs - static const int NO_STREAM = -1; - - /* Preview/Recording related members */ - - sp<IBinder> mPreviewSurface; - /** Preview callback related members */ sp<camera2::ProFrameProcessor> mFrameProcessor; static const int32_t FRAME_PROCESSOR_LISTENER_MIN_ID = 0; static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL; - /** Camera2Device instance wrapping HAL2 entry */ - - sp<Camera2Device> mDevice; - /** Utility members */ - // Verify that caller is the owner of the camera - status_t checkPid(const char *checkLocation) const; - // Whether or not we have an exclusive lock on the device // - if no we can't modify the request queue. // note that creating/deleting streams we own is still OK bool mExclusiveLock; - - void detachDevice(); }; }; // namespace android diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp index 9a14758..30c14ef 100644 --- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp +++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp @@ -278,11 +278,12 @@ status_t CallbackProcessor::processNewCallback(sp<Camera2Client> &client) { // Call outside parameter lock to allow re-entrancy from notification { - Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); - if (l.mCameraClient != 0) { + Camera2Client::SharedCameraCallbacks::Lock + l(client->mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { ALOGV("%s: Camera %d: Invoking client data callback", __FUNCTION__, client->getCameraId()); - l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, + l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mCallbackHeap->mBuffers[heapIdx], NULL); } } diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp index 513a47e..1880912 100644 --- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp +++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp @@ -271,10 +271,11 @@ CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &c } if (mCaptureBuffer != 0 && res == OK) { - Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); + Camera2Client::SharedCameraCallbacks::Lock + l(client->mSharedCameraCallbacks); ALOGV("%s: Sending still image to client", __FUNCTION__); - if (l.mCameraClient != 0) { - l.mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mCaptureBuffer, NULL); } else { ALOGV("%s: No client!", __FUNCTION__); @@ -344,7 +345,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageZslStart( } SharedParameters::Lock l(client->getParameters()); - /* warning: this also locks a SharedCameraClient */ + /* warning: this also locks a SharedCameraCallbacks */ shutterNotifyLocked(l.mParameters, client, mMsgType); mShutterNotified = true; mTimeoutCount = kMaxTimeoutsForCaptureEnd; @@ -496,7 +497,7 @@ CaptureSequencer::CaptureState CaptureSequencer::manageStandardCaptureWait( } if (mNewFrameReceived && !mShutterNotified) { SharedParameters::Lock l(client->getParameters()); - /* warning: this also locks a SharedCameraClient */ + /* warning: this also locks a SharedCameraCallbacks */ shutterNotifyLocked(l.mParameters, client, mMsgType); mShutterNotified = true; } @@ -651,16 +652,17 @@ status_t CaptureSequencer::updateCaptureRequest(const Parameters ¶ms, } { - Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); + Camera2Client::SharedCameraCallbacks::Lock + l(client->mSharedCameraCallbacks); ALOGV("%s: Notifying of shutter close to client", __FUNCTION__); - if (l.mCameraClient != 0) { + if (l.mRemoteCallback != 0) { // ShutterCallback - l.mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, + l.mRemoteCallback->notifyCallback(CAMERA_MSG_SHUTTER, /*ext1*/0, /*ext2*/0); // RawCallback with null buffer - l.mCameraClient->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY, + l.mRemoteCallback->notifyCallback(CAMERA_MSG_RAW_IMAGE_NOTIFY, /*ext1*/0, /*ext2*/0); } else { ALOGV("%s: No client!", __FUNCTION__); diff --git a/services/camera/libcameraservice/camera2/FrameProcessor.cpp b/services/camera/libcameraservice/camera2/FrameProcessor.cpp index 1f2659c..09b4b27 100644 --- a/services/camera/libcameraservice/camera2/FrameProcessor.cpp +++ b/services/camera/libcameraservice/camera2/FrameProcessor.cpp @@ -195,7 +195,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, entry = frame.find(ANDROID_STATISTICS_FACE_RECTANGLES); if (entry.count == 0) { // No faces this frame - /* warning: locks SharedCameraClient */ + /* warning: locks SharedCameraCallbacks */ callbackFaceDetection(client, metadata); return OK; } @@ -286,7 +286,7 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, metadata.faces = faces.editArray(); } - /* warning: locks SharedCameraClient */ + /* warning: locks SharedCameraCallbacks */ callbackFaceDetection(client, metadata); return OK; @@ -297,9 +297,9 @@ void FrameProcessor::callbackFaceDetection(sp<Camera2Client> client, /* Filter out repeated 0-face callbacks, but not when the last frame was >0 */ if (metadata.number_of_faces != 0 || mLastFrameNumberOfFaces != metadata.number_of_faces) { - Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); - if (l.mCameraClient != NULL) { - l.mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_METADATA, + Camera2Client::SharedCameraCallbacks::Lock l(client->mSharedCameraCallbacks); + if (l.mRemoteCallback != NULL) { + l.mRemoteCallback->dataCallback(CAMERA_MSG_PREVIEW_METADATA, NULL, &metadata); } } diff --git a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp index 8d4933c..742577a 100644 --- a/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp +++ b/services/camera/libcameraservice/camera2/ProFrameProcessor.cpp @@ -22,7 +22,7 @@ #include <utils/Trace.h> #include "ProFrameProcessor.h" -#include "../Camera2Device.h" +#include "../CameraDeviceBase.h" #include "../ProCamera2Client.h" namespace android { @@ -62,7 +62,7 @@ status_t ProFrameProcessor::removeListener(int32_t minId, return OK; } -void ProFrameProcessor::dump(int fd, const Vector<String16>& args) { +void ProFrameProcessor::dump(int fd, const Vector<String16>& /*args*/) { String8 result(" Latest received frame:\n"); write(fd, result.string(), result.size()); mLastFrame.dump(fd, 2, 6); @@ -71,7 +71,7 @@ void ProFrameProcessor::dump(int fd, const Vector<String16>& args) { bool ProFrameProcessor::threadLoop() { status_t res; - sp<Camera2Device> device; + sp<CameraDeviceBase> device; { sp<ProCamera2Client> client = mClient.promote(); if (client == 0) return false; @@ -125,7 +125,6 @@ void ProFrameProcessor::processNewFrames(sp<ProCamera2Client> &client) { status_t ProFrameProcessor::processListeners(const CameraMetadata &frame, sp<ProCamera2Client> &client) { - status_t res; ATRACE_CALL(); camera_metadata_ro_entry_t entry; diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp index 6a4b95d..fbc5b93 100644 --- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp +++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp @@ -556,9 +556,9 @@ void StreamingProcessor::onFrameAvailable() { } // Call outside locked parameters to allow re-entrancy from notification - Camera2Client::SharedCameraClient::Lock l(client->mSharedCameraClient); - if (l.mCameraClient != 0) { - l.mCameraClient->dataCallbackTimestamp(timestamp, + Camera2Client::SharedCameraCallbacks::Lock l(client->mSharedCameraCallbacks); + if (l.mRemoteCallback != 0) { + l.mRemoteCallback->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, recordingHeap->mBuffers[heapIdx]); } |