93b94584ed
This is the second half of bug 1837832. Modifies the camera client and camera service to use the new binder interface. Removes the old binder interface. There will be one more part to this change to surface the undefined callbacks to the Java layer so that partners can implement new features without having to touch the stack.
418 lines
9.8 KiB
C++
418 lines
9.8 KiB
C++
/*
|
|
**
|
|
** 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 <utils/IServiceManager.h>
|
|
#include <utils/threads.h>
|
|
#include <utils/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
|
|
|