| /* | 
 | ** | 
 | ** Copyright (C) 2008, The Android Open Source Project | 
 | ** Copyright (C) 2008 HTC Inc. | 
 | ** | 
 | ** 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 "Camera" | 
 | #include <utils/Log.h> | 
 | #include <binder/IServiceManager.h> | 
 | #include <utils/threads.h> | 
 | #include <binder/IMemory.h> | 
 | #include <ui/Surface.h> | 
 | #include <ui/Camera.h> | 
 | #include <ui/ICameraService.h> | 
 |  | 
 | namespace android { | 
 |  | 
 | // client singleton for camera service binder interface | 
 | Mutex Camera::mLock; | 
 | sp<ICameraService> Camera::mCameraService; | 
 | sp<Camera::DeathNotifier> Camera::mDeathNotifier; | 
 |  | 
 | // establish binder interface to camera service | 
 | const sp<ICameraService>& Camera::getCameraService() | 
 | { | 
 |     Mutex::Autolock _l(mLock); | 
 |     if (mCameraService.get() == 0) { | 
 |         sp<IServiceManager> sm = defaultServiceManager(); | 
 |         sp<IBinder> binder; | 
 |         do { | 
 |             binder = sm->getService(String16("media.camera")); | 
 |             if (binder != 0) | 
 |                 break; | 
 |             LOGW("CameraService not published, waiting..."); | 
 |             usleep(500000); // 0.5 s | 
 |         } while(true); | 
 |         if (mDeathNotifier == NULL) { | 
 |             mDeathNotifier = new DeathNotifier(); | 
 |         } | 
 |         binder->linkToDeath(mDeathNotifier); | 
 |         mCameraService = interface_cast<ICameraService>(binder); | 
 |     } | 
 |     LOGE_IF(mCameraService==0, "no CameraService!?"); | 
 |     return mCameraService; | 
 | } | 
 |  | 
 | // --------------------------------------------------------------------------- | 
 |  | 
 | Camera::Camera() | 
 | { | 
 |     init(); | 
 | } | 
 |  | 
 | // construct a camera client from an existing camera remote | 
 | sp<Camera> Camera::create(const sp<ICamera>& camera) | 
 | { | 
 |      LOGV("create"); | 
 |      if (camera == 0) { | 
 |          LOGE("camera remote is a NULL pointer"); | 
 |          return 0; | 
 |      } | 
 |  | 
 |     sp<Camera> c = new Camera(); | 
 |     if (camera->connect(c) == NO_ERROR) { | 
 |         c->mStatus = NO_ERROR; | 
 |         c->mCamera = camera; | 
 |         camera->asBinder()->linkToDeath(c); | 
 |     } | 
 |     return c; | 
 | } | 
 |  | 
 | void Camera::init() | 
 | { | 
 |     mStatus = UNKNOWN_ERROR; | 
 |     mShutterCallback = 0; | 
 |     mShutterCallbackCookie = 0; | 
 |     mRawCallback = 0; | 
 |     mRawCallbackCookie = 0; | 
 |     mJpegCallback = 0; | 
 |     mJpegCallbackCookie = 0; | 
 |     mPreviewCallback = 0; | 
 |     mPreviewCallbackCookie = 0; | 
 |     mRecordingCallback = 0; | 
 |     mRecordingCallbackCookie = 0; | 
 |     mErrorCallback = 0; | 
 |     mErrorCallbackCookie = 0; | 
 |     mAutoFocusCallback = 0; | 
 |     mAutoFocusCallbackCookie = 0; | 
 | } | 
 |  | 
 | Camera::~Camera() | 
 | { | 
 |     disconnect(); | 
 | } | 
 |  | 
 | sp<Camera> Camera::connect() | 
 | { | 
 |     LOGV("connect"); | 
 |     sp<Camera> c = new Camera(); | 
 |     const sp<ICameraService>& cs = getCameraService(); | 
 |     if (cs != 0) { | 
 |         c->mCamera = cs->connect(c); | 
 |     } | 
 |     if (c->mCamera != 0) { | 
 |         c->mCamera->asBinder()->linkToDeath(c); | 
 |         c->mStatus = NO_ERROR; | 
 |     } else { | 
 |         c.clear(); | 
 |     } | 
 |     return c; | 
 | } | 
 |  | 
 | void Camera::disconnect() | 
 | { | 
 |     LOGV("disconnect"); | 
 |     if (mCamera != 0) { | 
 |         mErrorCallback = 0; | 
 |         mCamera->disconnect(); | 
 |         mCamera = 0; | 
 |     } | 
 | } | 
 |  | 
 | status_t Camera::reconnect() | 
 | { | 
 |     LOGV("reconnect"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->connect(this); | 
 | } | 
 |  | 
 | sp<ICamera> Camera::remote() | 
 | { | 
 |     return mCamera; | 
 | } | 
 |  | 
 | status_t Camera::lock() | 
 | { | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->lock(); | 
 | } | 
 |  | 
 | status_t Camera::unlock() | 
 | { | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->unlock(); | 
 | } | 
 |  | 
 | // pass the buffered ISurface to the camera service | 
 | status_t Camera::setPreviewDisplay(const sp<Surface>& surface) | 
 | { | 
 |     LOGV("setPreviewDisplay"); | 
 |     if (surface == 0) { | 
 |         LOGE("app passed NULL surface"); | 
 |         return NO_INIT; | 
 |     } | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->setPreviewDisplay(surface->getISurface()); | 
 | } | 
 |  | 
 | status_t Camera::setPreviewDisplay(const sp<ISurface>& surface) | 
 | { | 
 |     LOGV("setPreviewDisplay"); | 
 |     if (surface == 0) { | 
 |         LOGE("app passed NULL surface"); | 
 |         return NO_INIT; | 
 |     } | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->setPreviewDisplay(surface); | 
 | } | 
 |  | 
 |  | 
 | // start preview mode, must call setPreviewDisplay first | 
 | status_t Camera::startPreview() | 
 | { | 
 |     LOGV("startPreview"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->startPreview(); | 
 | } | 
 |  | 
 | // start recording mode, must call setPreviewDisplay first | 
 | status_t Camera::startRecording() | 
 | { | 
 |     LOGV("startRecording"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->startRecording(); | 
 | } | 
 |  | 
 | // stop preview mode | 
 | void Camera::stopPreview() | 
 | { | 
 |     LOGV("stopPreview"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return; | 
 |     c->stopPreview(); | 
 | } | 
 |  | 
 | // stop recording mode | 
 | void Camera::stopRecording() | 
 | { | 
 |     LOGV("stopRecording"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return; | 
 |     c->stopRecording(); | 
 | } | 
 |  | 
 | // release a recording frame | 
 | void Camera::releaseRecordingFrame(const sp<IMemory>& mem) | 
 | { | 
 |     LOGV("releaseRecordingFrame"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return; | 
 |     c->releaseRecordingFrame(mem); | 
 | } | 
 |  | 
 | // get preview state | 
 | bool Camera::previewEnabled() | 
 | { | 
 |     LOGV("previewEnabled"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return false; | 
 |     return c->previewEnabled(); | 
 | } | 
 |  | 
 | // get recording state | 
 | bool Camera::recordingEnabled() | 
 | { | 
 |     LOGV("recordingEnabled"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return false; | 
 |     return c->recordingEnabled(); | 
 | } | 
 |  | 
 | status_t Camera::autoFocus() | 
 | { | 
 |     LOGV("autoFocus"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->autoFocus(); | 
 | } | 
 |  | 
 | // take a picture | 
 | status_t Camera::takePicture() | 
 | { | 
 |     LOGV("takePicture"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->takePicture(); | 
 | } | 
 |  | 
 | // set preview/capture parameters - key/value pairs | 
 | status_t Camera::setParameters(const String8& params) | 
 | { | 
 |     LOGV("setParameters"); | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return NO_INIT; | 
 |     return c->setParameters(params); | 
 | } | 
 |  | 
 | // get preview/capture parameters - key/value pairs | 
 | String8 Camera::getParameters() const | 
 | { | 
 |     LOGV("getParameters"); | 
 |     String8 params; | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c != 0) params = mCamera->getParameters(); | 
 |     return params; | 
 | } | 
 |  | 
 | void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setAutoFocusCallback"); | 
 |     mAutoFocusCallback = cb; | 
 |     mAutoFocusCallbackCookie = cookie; | 
 | } | 
 |  | 
 | void Camera::setShutterCallback(shutter_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setShutterCallback"); | 
 |     mShutterCallback = cb; | 
 |     mShutterCallbackCookie = cookie; | 
 | } | 
 |  | 
 | void Camera::setRawCallback(frame_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setRawCallback"); | 
 |     mRawCallback = cb; | 
 |     mRawCallbackCookie = cookie; | 
 | } | 
 |  | 
 | void Camera::setJpegCallback(frame_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setJpegCallback"); | 
 |     mJpegCallback = cb; | 
 |     mJpegCallbackCookie = cookie; | 
 | } | 
 |  | 
 | void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag) | 
 | { | 
 |     LOGV("setPreviewCallback"); | 
 |     mPreviewCallback = cb; | 
 |     mPreviewCallbackCookie = cookie; | 
 |     sp <ICamera> c = mCamera; | 
 |     if (c == 0) return; | 
 |     mCamera->setPreviewCallbackFlag(flag); | 
 | } | 
 |  | 
 | void Camera::setRecordingCallback(frame_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setRecordingCallback"); | 
 |     mRecordingCallback = cb; | 
 |     mRecordingCallbackCookie = cookie; | 
 | } | 
 |  | 
 | void Camera::setErrorCallback(error_callback cb, void *cookie) | 
 | { | 
 |     LOGV("setErrorCallback"); | 
 |     mErrorCallback = cb; | 
 |     mErrorCallbackCookie = cookie; | 
 | } | 
 |  | 
 | // callback from camera service | 
 | void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) | 
 | { | 
 |     switch(msgType) { | 
 |     case CAMERA_MSG_ERROR: | 
 |         LOGV("errorCallback"); | 
 |         if (mErrorCallback) { | 
 |             mErrorCallback((status_t)ext1, mErrorCallbackCookie); | 
 |         } | 
 |         break; | 
 |     case CAMERA_MSG_FOCUS: | 
 |         LOGV("autoFocusCallback"); | 
 |         if (mAutoFocusCallback) { | 
 |             mAutoFocusCallback((bool)ext1, mAutoFocusCallbackCookie); | 
 |         } | 
 |         break; | 
 |     case CAMERA_MSG_SHUTTER: | 
 |         LOGV("shutterCallback"); | 
 |         if (mShutterCallback) { | 
 |             mShutterCallback(mShutterCallbackCookie); | 
 |         } | 
 |         break; | 
 |     default: | 
 |         LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2); | 
 |         break; | 
 |     } | 
 | } | 
 |  | 
 | // callback from camera service when frame or image is ready | 
 | void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) | 
 | { | 
 |     switch(msgType) { | 
 |     case CAMERA_MSG_PREVIEW_FRAME: | 
 |         LOGV("previewCallback"); | 
 |         if (mPreviewCallback) { | 
 |             mPreviewCallback(dataPtr, mPreviewCallbackCookie); | 
 |         } | 
 |         break; | 
 |     case CAMERA_MSG_VIDEO_FRAME: | 
 |         LOGV("recordingCallback"); | 
 |         if (mRecordingCallback) { | 
 |             mRecordingCallback(dataPtr, mRecordingCallbackCookie); | 
 |         } | 
 |         break; | 
 |     case CAMERA_MSG_RAW_IMAGE: | 
 |         LOGV("rawCallback"); | 
 |         if (mRawCallback) { | 
 |             mRawCallback(dataPtr, mRawCallbackCookie); | 
 |         } | 
 |         break; | 
 |     case CAMERA_MSG_COMPRESSED_IMAGE: | 
 |         LOGV("jpegCallback"); | 
 |         if (mJpegCallback) { | 
 |             mJpegCallback(dataPtr, mJpegCallbackCookie); | 
 |         } | 
 |         break; | 
 |     default: | 
 |         LOGV("dataCallback(%d, %p)", msgType, dataPtr.get()); | 
 |         break; | 
 |     } | 
 | } | 
 |  | 
 | void Camera::binderDied(const wp<IBinder>& who) { | 
 |     LOGW("ICamera died"); | 
 |     if (mErrorCallback) { | 
 |         mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie); | 
 |     } | 
 | } | 
 |  | 
 | void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) { | 
 |     LOGV("binderDied"); | 
 |     Mutex::Autolock _l(Camera::mLock); | 
 |     Camera::mCameraService.clear(); | 
 |     LOGW("Camera server died!"); | 
 | } | 
 |  | 
 | }; // namespace android | 
 |  |