From e0c5a929875a3f858926d7fec7e236d6db1006a3 Mon Sep 17 00:00:00 2001 From: Ziyan Date: Sun, 3 Jan 2016 14:19:34 +0100 Subject: Add camera sources in-tree From hardware/ti/omap4 revision e57f2b6. Change-Id: I2e6164fdf6c0e2a2e75aee3bba3fe58a9c470add --- camera/CameraHal.cpp | 5012 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 5012 insertions(+) create mode 100644 camera/CameraHal.cpp (limited to 'camera/CameraHal.cpp') diff --git a/camera/CameraHal.cpp b/camera/CameraHal.cpp new file mode 100644 index 0000000..7e7cf9d --- /dev/null +++ b/camera/CameraHal.cpp @@ -0,0 +1,5012 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * 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. + */ + +/** +* @file CameraHal.cpp +* +* This file maps the Camera Hardware Interface to V4L2. +* +*/ + +#include "CameraHal.h" +#include "ANativeWindowDisplayAdapter.h" +#include "BufferSourceAdapter.h" +#include "TICameraParameters.h" +#include "CameraProperties.h" +#include + +#include +#include + +namespace Ti { +namespace Camera { + +extern "C" CameraAdapter* OMXCameraAdapter_Factory(size_t); +extern "C" CameraAdapter* V4LCameraAdapter_Factory(size_t, CameraHal*); + +/*****************************************************************************/ + +////Constant definitions and declarations +////@todo Have a CameraProperties class to store these parameters as constants for every camera +//// Currently, they are hard-coded + +const int CameraHal::NO_BUFFERS_PREVIEW = MAX_CAMERA_BUFFERS; +const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE = 5; +const int CameraHal::SW_SCALING_FPS_LIMIT = 15; + +const uint32_t MessageNotifier::EVENT_BIT_FIELD_POSITION = 16; + +const uint32_t MessageNotifier::FRAME_BIT_FIELD_POSITION = 0; + +// TODO(XXX): Temporarily increase number of buffers we can allocate from ANW +// until faux-NPA mode is implemented +const int CameraHal::NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP = 15; + +#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING +// HACK: Default path to directory where RAW images coming from video port will be saved to. +// If directory not exists the saving is skipped and video port frame is ignored. +// The directory name is choosed in so weird way to enable RAW images saving only when +// directory has been created explicitly by user. +extern const char * const kRawImagesOutputDirPath = "/data/misc/camera/RaW_PiCtUrEs"; +extern const char * const kYuvImagesOutputDirPath = "/data/misc/camera/YuV_PiCtUrEs"; +#endif + +/******************************************************************************/ + + +#ifdef OMAP_ENHANCEMENT_CPCAM +static int dummy_update_and_get_buffer(preview_stream_ops_t*, buffer_handle_t**, int*,int*) { + return INVALID_OPERATION; +} + +static int dummy_release_buffer(preview_stream_ops_t*, int slot) { + return INVALID_OPERATION; +} + +static int dummy_get_buffer_dimension(preview_stream_ops_t*, int*, int*) { + return INVALID_OPERATION; +} + +static int dummy_get_buffer_format(preview_stream_ops_t*, int*) { + return INVALID_OPERATION; +} + +static int dummy_set_metadata(preview_stream_ops_t*, const camera_memory_t*) { + return INVALID_OPERATION; +} + +static int dummy_get_id(preview_stream_ops_t*, char *data, unsigned int dataSize) { + return INVALID_OPERATION; +} + +static int dummy_get_buffer_count(preview_stream_ops_t*, int *count) { + return INVALID_OPERATION; +} + +static int dummy_get_crop(preview_stream_ops_t*, + int *, int *, int *, int *) { + return INVALID_OPERATION; +} + +static int dummy_get_current_size(preview_stream_ops_t*, + int *, int *) { + return INVALID_OPERATION; +} +#endif + + +CameraHal::SocFamily CameraHal::getSocFamily() { + static const struct { + const char *name; + const CameraHal::SocFamily value; + } socFamilyArray[] = { + {"OMAP4430", SocFamily_Omap4430}, + {"OMAP4460", SocFamily_Omap4460}, + {"OMAP4470", SocFamily_Omap4470} + }; + // lets get the soc family string from sysfs + static const char *sysfsNode = "/sys/board_properties/soc/family"; + FILE *sysfsFd = fopen(sysfsNode, "r"); + static const int bufSize = 128; + char buf[bufSize]; + if (sysfsFd == NULL) { + CAMHAL_LOGEA("'%s' Not Available", sysfsNode); + return SocFamily_Undefined; + } + const char *res = fgets(buf, bufSize, sysfsFd); + fclose(sysfsFd); + if (res == NULL) { + CAMHAL_LOGEA("Error reading '%s'", sysfsNode); + return SocFamily_Undefined; + } + // translate it to CameraHal::SocFamily enum + for (int i = 0; i < SocFamily_ElementCount; ++i) { + if (strncmp(socFamilyArray[i].name, buf, strlen(socFamilyArray[i].name)) == 0) { + return socFamilyArray[i].value; + } + } + return SocFamily_Undefined; +} + + +#ifdef OMAP_ENHANCEMENT_CPCAM +static preview_stream_extended_ops_t dummyPreviewStreamExtendedOps = { +#ifdef OMAP_ENHANCEMENT_CPCAM + dummy_update_and_get_buffer, + dummy_release_buffer, + dummy_get_buffer_dimension, + dummy_get_buffer_format, + dummy_set_metadata, + dummy_get_id, + dummy_get_buffer_count, + dummy_get_crop, + dummy_get_current_size, +#endif +}; +#endif + + +DisplayAdapter::DisplayAdapter() +{ +#ifdef OMAP_ENHANCEMENT_CPCAM + mExtendedOps = &dummyPreviewStreamExtendedOps; +#endif +} + +#ifdef OMAP_ENHANCEMENT_CPCAM +void DisplayAdapter::setExtendedOps(preview_stream_extended_ops_t * extendedOps) { + mExtendedOps = extendedOps ? extendedOps : &dummyPreviewStreamExtendedOps; +} +#endif + + + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + +struct timeval CameraHal::mStartPreview; +struct timeval CameraHal::mStartFocus; +struct timeval CameraHal::mStartCapture; + +#endif + +static void orientation_cb(uint32_t orientation, uint32_t tilt, void* cookie) { + CameraHal *camera = NULL; + + if (cookie) { + camera = (CameraHal*) cookie; + camera->onOrientationEvent(orientation, tilt); + } + +} + +/*-------------Camera Hal Interface Method definitions STARTS here--------------------*/ + +/** + Callback function to receive orientation events from SensorListener + */ +void CameraHal::onOrientationEvent(uint32_t orientation, uint32_t tilt) { + LOG_FUNCTION_NAME; + + if ( NULL != mCameraAdapter ) { + mCameraAdapter->onOrientationEvent(orientation, tilt); + } + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Set the notification and data callbacks + + @param[in] notify_cb Notify callback for notifying the app about events and errors + @param[in] data_cb Buffer callback for sending the preview/raw frames to the app + @param[in] data_cb_timestamp Buffer callback for sending the video frames w/ timestamp + @param[in] user Callback cookie + @return none + + */ +void CameraHal::setCallbacks(camera_notify_callback notify_cb, + camera_data_callback data_cb, + camera_data_timestamp_callback data_cb_timestamp, + camera_request_memory get_memory, + void *user) +{ + LOG_FUNCTION_NAME; + + if ( NULL != mAppCallbackNotifier.get() ) + { + mAppCallbackNotifier->setCallbacks(this, + notify_cb, + data_cb, + data_cb_timestamp, + get_memory, + user); + } + + if ( NULL != mCameraAdapter ) { + mCameraAdapter->setSharedAllocator(get_memory); + } + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Enable a message, or set of messages. + + @param[in] msgtype Bitmask of the messages to enable (defined in include/ui/Camera.h) + @return none + + */ +void CameraHal::enableMsgType(int32_t msgType) +{ + LOG_FUNCTION_NAME; + + if ( ( msgType & CAMERA_MSG_SHUTTER ) && ( !mShutterEnabled ) ) + { + msgType &= ~CAMERA_MSG_SHUTTER; + } + + // ignoring enable focus message from camera service + // we will enable internally in autoFocus call + msgType &= ~CAMERA_MSG_FOCUS; +#ifdef ANDROID_API_JB_OR_LATER + msgType &= ~CAMERA_MSG_FOCUS_MOVE; +#endif + + { + android::AutoMutex lock(mLock); + mMsgEnabled |= msgType; + } + + if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) + { + if(mDisplayPaused) + { + CAMHAL_LOGDA("Preview currently paused...will enable preview callback when restarted"); + msgType &= ~CAMERA_MSG_PREVIEW_FRAME; + }else + { + CAMHAL_LOGDA("Enabling Preview Callback"); + } + } + else + { + CAMHAL_LOGDB("Preview callback not enabled %x", msgType); + } + + + ///Configure app callback notifier with the message callback required + mAppCallbackNotifier->enableMsgType (msgType); + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Disable a message, or set of messages. + + @param[in] msgtype Bitmask of the messages to disable (defined in include/ui/Camera.h) + @return none + + */ +void CameraHal::disableMsgType(int32_t msgType) +{ + LOG_FUNCTION_NAME; + + { + android::AutoMutex lock(mLock); + mMsgEnabled &= ~msgType; + } + + if( msgType & CAMERA_MSG_PREVIEW_FRAME) + { + CAMHAL_LOGDA("Disabling Preview Callback"); + } + + ///Configure app callback notifier + mAppCallbackNotifier->disableMsgType (msgType); + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Query whether a message, or a set of messages, is enabled. + + Note that this is operates as an AND, if any of the messages queried are off, this will + return false. + + @param[in] msgtype Bitmask of the messages to query (defined in include/ui/Camera.h) + @return true If all message types are enabled + false If any message type + + */ +int CameraHal::msgTypeEnabled(int32_t msgType) +{ + int32_t msgEnabled = 0; + + LOG_FUNCTION_NAME; + android::AutoMutex lock(mLock); + + msgEnabled = mMsgEnabled; + if (!previewEnabled() && !mPreviewInitializationDone) { + msgEnabled &= ~(CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_PREVIEW_METADATA); + } + + LOG_FUNCTION_NAME_EXIT; + return (msgEnabled & msgType); +} + +/** + @brief Set the camera parameters. + + @param[in] params Camera parameters to configure the camera + @return NO_ERROR + @todo Define error codes + + */ +int CameraHal::setParameters(const char* parameters) +{ + + LOG_FUNCTION_NAME; + + android::CameraParameters params; + + android::String8 str_params(parameters); + params.unflatten(str_params); + + LOG_FUNCTION_NAME_EXIT; + + return setParameters(params); +} + +/** + @brief Set the camera parameters. + + @param[in] params Camera parameters to configure the camera + @return NO_ERROR + @todo Define error codes + + */ +int CameraHal::setParameters(const android::CameraParameters& params) +{ + + LOG_FUNCTION_NAME; + + int w, h; + int framerate; + const char *valstr = NULL; + int varint = 0; + status_t ret = NO_ERROR; + // Needed for KEY_RECORDING_HINT + bool restartPreviewRequired = false; + bool updateRequired = false; + android::CameraParameters oldParams = mParameters; +#ifdef MOTOROLA_CAMERA + char value[PROPERTY_VALUE_MAX]; +#endif + +#ifdef V4L_CAMERA_ADAPTER + if (strcmp (V4L_CAMERA_NAME_USB, mCameraProperties->get(CameraProperties::CAMERA_NAME)) == 0 ) { + updateRequired = true; + } +#endif + + { + android::AutoMutex lock(mLock); + + ///Ensure that preview is not enabled when the below parameters are changed. + if(!previewEnabled()) + { + if ((valstr = params.getPreviewFormat()) != NULL) { + if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS))) { + mParameters.setPreviewFormat(valstr); + CAMHAL_LOGDB("PreviewFormat set %s", valstr); + } else { + CAMHAL_LOGEB("Invalid preview format: %s. Supported: %s", valstr, + mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS)); + return BAD_VALUE; + } + } + + if ((valstr = params.get(TICameraParameters::KEY_VNF)) != NULL) { + if (strcmp(mCameraProperties->get(CameraProperties::VNF_SUPPORTED), + android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGDB("VNF %s", valstr); + mParameters.set(TICameraParameters::KEY_VNF, valstr); + } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGEB("ERROR: Invalid VNF: %s", valstr); + return BAD_VALUE; + } else { + mParameters.set(TICameraParameters::KEY_VNF, + android::CameraParameters::FALSE); + } + } + + if ((valstr = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL) { + // make sure we support vstab...if we don't and application is trying to set + // vstab then return an error + if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED), + android::CameraParameters::TRUE) != 0 && + strcmp(valstr, android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGEB("ERROR: Invalid VSTAB: %s", valstr); + return BAD_VALUE; + } + } + + if( (valstr = params.get(TICameraParameters::KEY_CAP_MODE)) != NULL) { + + if (strcmp(TICameraParameters::VIDEO_MODE, valstr)) { + mCapModeBackup = valstr; + } + + CAMHAL_LOGDB("Capture mode set %s", valstr); + + const char *currentMode = mParameters.get(TICameraParameters::KEY_CAP_MODE); + if ( NULL != currentMode ) { + if ( strcmp(currentMode, valstr) != 0 ) { + updateRequired = true; + } + } else { + updateRequired = true; + } + + mParameters.set(TICameraParameters::KEY_CAP_MODE, valstr); + } else if (!mCapModeBackup.isEmpty()) { + // Restore previous capture mode after stopPreview() + mParameters.set(TICameraParameters::KEY_CAP_MODE, + mCapModeBackup.string()); + updateRequired = true; + } + +#ifdef OMAP_ENHANCEMENT_VTC + if ((valstr = params.get(TICameraParameters::KEY_VTC_HINT)) != NULL ) { + mParameters.set(TICameraParameters::KEY_VTC_HINT, valstr); + if (strcmp(valstr, android::CameraParameters::TRUE) == 0) { + mVTCUseCase = true; + } else { + mVTCUseCase = false; + } + CAMHAL_LOGDB("VTC Hint = %d", mVTCUseCase); + } + + if (mVTCUseCase) { + if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL ) { + mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE, valstr); + } + + if ((valstr = params.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL ) { + mParameters.set(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT, valstr); + } + } +#endif + } + + if ((valstr = params.get(TICameraParameters::KEY_IPP)) != NULL) { + if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES))) { + if ((mParameters.get(TICameraParameters::KEY_IPP) == NULL) || + (strcmp(valstr, mParameters.get(TICameraParameters::KEY_IPP)))) { + CAMHAL_LOGDB("IPP mode set %s", params.get(TICameraParameters::KEY_IPP)); + mParameters.set(TICameraParameters::KEY_IPP, valstr); + restartPreviewRequired = true; + } + } else { + CAMHAL_LOGEB("ERROR: Invalid IPP mode: %s", valstr); + return BAD_VALUE; + } + } + + if ( (valstr = params.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL ) + { + if (strcmp(valstr, mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT))) + { + CAMHAL_LOGDB("Stereo 3D preview image layout is %s", valstr); + mParameters.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, valstr); + restartPreviewRequired = true; + } + } + +#ifdef OMAP_ENHANCEMENT + int orientation =0; + if((valstr = params.get(TICameraParameters::KEY_SENSOR_ORIENTATION)) != NULL) + { + doesSetParameterNeedUpdate(valstr, + mParameters.get(TICameraParameters::KEY_SENSOR_ORIENTATION), + updateRequired); + + orientation = params.getInt(TICameraParameters::KEY_SENSOR_ORIENTATION); + if ( orientation < 0 || orientation >= 360 || (orientation%90) != 0 ) { + CAMHAL_LOGE("Invalid sensor orientation: %s. Value must be one of: [0, 90, 180, 270]", valstr); + return BAD_VALUE; + } + + CAMHAL_LOGD("Sensor Orientation is set to %d", orientation); + mParameters.set(TICameraParameters::KEY_SENSOR_ORIENTATION, valstr); + } +#endif + + params.getPreviewSize(&w, &h); + if (w == -1 && h == -1) { + CAMHAL_LOGEA("Unable to get preview size"); + return BAD_VALUE; + } + + mVideoWidth = w; + mVideoHeight = h; + + // Handle RECORDING_HINT to Set/Reset Video Mode Parameters + valstr = params.get(android::CameraParameters::KEY_RECORDING_HINT); + if(valstr != NULL) + { + CAMHAL_LOGDB("Recording Hint is set to %s", valstr); + if(strcmp(valstr, android::CameraParameters::TRUE) == 0) + { + CAMHAL_LOGVB("Video Resolution: %d x %d", mVideoWidth, mVideoHeight); + mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr); + restartPreviewRequired |= setVideoModeParameters(params); + } + else if(strcmp(valstr, android::CameraParameters::FALSE) == 0) + { + mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, valstr); + restartPreviewRequired |= resetVideoModeParameters(); + } + else + { + CAMHAL_LOGEA("Invalid RECORDING_HINT"); + return BAD_VALUE; + } + } + else + { + // This check is required in following case. + // If VideoRecording activity sets KEY_RECORDING_HINT to TRUE and + // ImageCapture activity doesnot set KEY_RECORDING_HINT to FALSE (i.e. simply NULL), + // then Video Mode parameters may remain present in ImageCapture activity as well. + CAMHAL_LOGDA("Recording Hint is set to NULL"); + mParameters.set(android::CameraParameters::KEY_RECORDING_HINT, ""); + restartPreviewRequired |= resetVideoModeParameters(); + } + + if ( (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES))) + && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES))) + && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES))) + && (!isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES))) ) { + CAMHAL_LOGEB("Invalid preview resolution %d x %d", w, h); + return BAD_VALUE; + } + + int oldWidth, oldHeight; + mParameters.getPreviewSize(&oldWidth, &oldHeight); + if ( ( oldWidth != w ) || ( oldHeight != h ) ) + { + mParameters.setPreviewSize(w, h); + restartPreviewRequired = true; + } + + CAMHAL_LOGDB("Preview Resolution: %d x %d", w, h); + + if ((valstr = params.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES))) { + CAMHAL_LOGDB("Focus mode set %s", valstr); + + // we need to take a decision on the capture mode based on whether CAF picture or + // video is chosen so the behavior of each is consistent to the application + if(strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0){ + restartPreviewRequired |= resetVideoModeParameters(); + } else if (strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) == 0){ + restartPreviewRequired |= setVideoModeParameters(params); + } + + mParameters.set(android::CameraParameters::KEY_FOCUS_MODE, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid FOCUS mode = %s", valstr); + return BAD_VALUE; + } + } + + mRawCapture = false; + +#ifdef CAMERAHAL_USE_RAW_IMAGE_SAVING + valstr = params.get(TICameraParameters::KEY_CAP_MODE); + if ( (!valstr || strcmp(valstr, TICameraParameters::HIGH_QUALITY_MODE) == 0) && + access(kRawImagesOutputDirPath, F_OK) != -1 ) { + mRawCapture = true; + } +#endif + + if ( (valstr = params.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL ) + { + CAMHAL_LOGDB("Stereo 3D capture image layout is %s", valstr); + mParameters.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, valstr); + } + + params.getPictureSize(&w, &h); + if ( (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES))) + || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES))) + || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES))) + || (isResolutionValid(w, h, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES))) ) { + mParameters.setPictureSize(w, h); + } else { + CAMHAL_LOGEB("ERROR: Invalid picture resolution %d x %d", w, h); + return BAD_VALUE; + } + + CAMHAL_LOGDB("Picture Size by App %d x %d", w, h); + + if ( (valstr = params.getPictureFormat()) != NULL ) { + if (isParameterValid(valstr,mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS))) { + if ((strcmp(valstr, android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB) == 0) && + mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH) && + mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT)) { + unsigned int width = 0, height = 0; + // Set picture size to full frame for raw bayer capture + width = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_WIDTH)); + height = atoi(mCameraProperties->get(CameraProperties::MAX_PICTURE_HEIGHT)); + mParameters.setPictureSize(width,height); + } + mParameters.setPictureFormat(valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid picture format: %s",valstr); + ret = BAD_VALUE; + } + } + +#ifdef OMAP_ENHANCEMENT_BURST_CAPTURE + if ((valstr = params.get(TICameraParameters::KEY_BURST)) != NULL) { + if (params.getInt(TICameraParameters::KEY_BURST) >=0) { + CAMHAL_LOGDB("Burst set %s", valstr); + mParameters.set(TICameraParameters::KEY_BURST, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Burst value: %s",valstr); + return BAD_VALUE; + } + } +#endif + + // Variable framerate ranges have higher priority over + // deprecated constant FPS. + // There is possible 3 situations : + // 1) User change FPS range and HAL use it for fps port value (don't care about + // changed or not const FPS). + // 2) User change single FPS and not change FPS range - will be applyed single FPS value + // to port. + // 3) Both FPS range and const FPS are unchanged - FPS range will be applied to port. + + int curFramerate = 0; + bool frameRangeUpdated = false, fpsUpdated = false; + int curMaxFPS = 0, curMinFPS = 0, maxFPS = 0, minFPS = 0; + + mParameters.getPreviewFpsRange(&curMinFPS, &curMaxFPS); + params.getPreviewFpsRange(&minFPS, &maxFPS); + + curFramerate = mParameters.getPreviewFrameRate(); + framerate = params.getPreviewFrameRate(); + + valstr = params.get(android::CameraParameters::KEY_PREVIEW_FPS_RANGE); + if (valstr != NULL && strlen(valstr) && + ((curMaxFPS != maxFPS) || (curMinFPS != minFPS))) { + CAMHAL_LOGDB("## current minFPS = %d; maxFPS=%d", curMinFPS, curMaxFPS); + CAMHAL_LOGDB("## requested minFPS = %d; maxFPS=%d", minFPS, maxFPS); + if (!isFpsRangeValid(minFPS, maxFPS, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)) && + !isFpsRangeValid(minFPS, maxFPS, params.get(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED))) { + CAMHAL_LOGEA("Trying to set invalid FPS Range (%d,%d)", minFPS, maxFPS); + return BAD_VALUE; + } + mParameters.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, valstr); + CAMHAL_LOGDB("FPS Range = %s", valstr); + if ( curMaxFPS == (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) && + maxFPS < (FRAME_RATE_HIGH_HD * CameraHal::VFR_SCALE) ) { + restartPreviewRequired = true; + } + frameRangeUpdated = true; + } + + valstr = params.get(android::CameraParameters::KEY_PREVIEW_FRAME_RATE); + if (valstr != NULL && strlen(valstr) && (framerate != curFramerate)) { + CAMHAL_LOGD("current framerate = %d reqested framerate = %d", curFramerate, framerate); + if (!isParameterValid(framerate, params.get(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)) && + !isParameterValid(framerate, params.get(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED))) { + CAMHAL_LOGEA("Trying to set invalid frame rate %d", framerate); + return BAD_VALUE; + } + mParameters.setPreviewFrameRate(framerate); + CAMHAL_LOGDB("Set frame rate %d", framerate); + fpsUpdated = true; + } + + if (frameRangeUpdated) { + mParameters.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE, + mParameters.get(android::CameraParameters::KEY_PREVIEW_FPS_RANGE)); + } else if (fpsUpdated) { + char tmpBuffer[MAX_PROP_VALUE_LENGTH]; + sprintf(tmpBuffer, "%d,%d", framerate * CameraHal::VFR_SCALE, framerate * CameraHal::VFR_SCALE); + mParameters.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE, tmpBuffer); + } + + if ((valstr = params.get(TICameraParameters::KEY_GBCE)) != NULL) { + if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GBCE), + android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGDB("GBCE %s", valstr); + mParameters.set(TICameraParameters::KEY_GBCE, valstr); + } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGEB("ERROR: Invalid GBCE: %s", valstr); + return BAD_VALUE; + } else { + mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE); + } + } else { + mParameters.set(TICameraParameters::KEY_GBCE, android::CameraParameters::FALSE); + } + + if ((valstr = params.get(TICameraParameters::KEY_GLBCE)) != NULL) { + if (strcmp(mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE), + android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGDB("GLBCE %s", valstr); + mParameters.set(TICameraParameters::KEY_GLBCE, valstr); + } else if (strcmp(valstr, android::CameraParameters::TRUE) == 0) { + CAMHAL_LOGEB("ERROR: Invalid GLBCE: %s", valstr); + return BAD_VALUE; + } else { + mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE); + } + } else { + mParameters.set(TICameraParameters::KEY_GLBCE, android::CameraParameters::FALSE); + } + +#ifdef OMAP_ENHANCEMENT_S3D + ///Update the current parameter set + if ( (valstr = params.get(TICameraParameters::KEY_AUTOCONVERGENCE_MODE)) != NULL ) { + CAMHAL_LOGDB("AutoConvergence mode set = %s", valstr); + mParameters.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, valstr); + } + + if ( (valstr = params.get(TICameraParameters::KEY_MANUAL_CONVERGENCE)) != NULL ) { + int manualConvergence = (int)strtol(valstr, 0, 0); + + if ( ( manualConvergence < strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN), 0, 0) ) || + ( manualConvergence > strtol(mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX), 0, 0) ) ) { + CAMHAL_LOGEB("ERROR: Invalid Manual Convergence = %d", manualConvergence); + return BAD_VALUE; + } else { + CAMHAL_LOGDB("ManualConvergence Value = %d", manualConvergence); + mParameters.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, valstr); + } + } + + if((valstr = params.get(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION)) != NULL) { + if ( strcmp(mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED), + android::CameraParameters::TRUE) == 0 ) { + CAMHAL_LOGDB("Mechanical Mialignment Correction is %s", valstr); + mParameters.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, valstr); + } else { + mParameters.remove(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION); + } + } + + if ((valstr = params.get(TICameraParameters::KEY_EXPOSURE_MODE)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES))) { + CAMHAL_LOGDB("Exposure mode set = %s", valstr); + mParameters.set(TICameraParameters::KEY_EXPOSURE_MODE, valstr); + if (!strcmp(valstr, TICameraParameters::EXPOSURE_MODE_MANUAL)) { + int manualVal; + if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE)) != NULL) { + manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE); + if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) || + manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) { + CAMHAL_LOGEB("ERROR: Manual Exposure = %s is out of range - " + "setting minimum supported value", valstr); + valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN); + } + CAMHAL_LOGDB("Manual Exposure = %s", valstr); + mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE, valstr); + } + if ((valstr = params.get(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT)) != NULL) { + manualVal = params.getInt(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT); + if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN) || + manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX)) { + CAMHAL_LOGEB("ERROR: Manual Exposure right = %s is out of range - " + "setting minimum supported value", valstr); + valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN); + } + CAMHAL_LOGDB("Manual Exposure right = %s", valstr); + mParameters.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, valstr); + } + if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO)) != NULL) { + manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO); + if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) || + manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) { + CAMHAL_LOGEB("ERROR: Manual Gain = %s is out of range - " + "setting minimum supported value", valstr); + valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN); + } + CAMHAL_LOGDB("Manual Gain = %s", valstr); + mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, valstr); + } + if ((valstr = params.get(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT)) != NULL) { + manualVal = params.getInt(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT); + if (manualVal < mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN) || + manualVal > mParameters.getInt(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX)) { + CAMHAL_LOGEB("ERROR: Manual Gain right = %s is out of range - " + "setting minimum supported value", valstr); + valstr = mParameters.get(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN); + } + CAMHAL_LOGDB("Manual Gain right = %s", valstr); + mParameters.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, valstr); + } + } + } else { + CAMHAL_LOGEB("ERROR: Invalid Exposure mode = %s", valstr); + return BAD_VALUE; + } + } +#endif + + if ((valstr = params.get(android::CameraParameters::KEY_WHITE_BALANCE)) != NULL) { + if ( isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE))) { + CAMHAL_LOGDB("White balance set %s", valstr); + mParameters.set(android::CameraParameters::KEY_WHITE_BALANCE, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid white balance = %s", valstr); + return BAD_VALUE; + } + } + +#ifdef OMAP_ENHANCEMENT + if ((valstr = params.get(TICameraParameters::KEY_CONTRAST)) != NULL) { + if (params.getInt(TICameraParameters::KEY_CONTRAST) >= 0 ) { + CAMHAL_LOGDB("Contrast set %s", valstr); + mParameters.set(TICameraParameters::KEY_CONTRAST, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Contrast = %s", valstr); + return BAD_VALUE; + } + } + + if ((valstr =params.get(TICameraParameters::KEY_SHARPNESS)) != NULL) { + if (params.getInt(TICameraParameters::KEY_SHARPNESS) >= 0 ) { + CAMHAL_LOGDB("Sharpness set %s", valstr); + mParameters.set(TICameraParameters::KEY_SHARPNESS, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Sharpness = %s", valstr); + return BAD_VALUE; + } + } + + if ((valstr = params.get(TICameraParameters::KEY_SATURATION)) != NULL) { + if (params.getInt(TICameraParameters::KEY_SATURATION) >= 0 ) { + CAMHAL_LOGDB("Saturation set %s", valstr); + mParameters.set(TICameraParameters::KEY_SATURATION, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Saturation = %s", valstr); + return BAD_VALUE; + } + } + + if ((valstr = params.get(TICameraParameters::KEY_BRIGHTNESS)) != NULL) { + if (params.getInt(TICameraParameters::KEY_BRIGHTNESS) >= 0 ) { + CAMHAL_LOGDB("Brightness set %s", valstr); + mParameters.set(TICameraParameters::KEY_BRIGHTNESS, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Brightness = %s", valstr); + return BAD_VALUE; + } + } +#endif + + if ((valstr = params.get(android::CameraParameters::KEY_ANTIBANDING)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING))) { + CAMHAL_LOGDB("Antibanding set %s", valstr); + mParameters.set(android::CameraParameters::KEY_ANTIBANDING, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Antibanding = %s", valstr); + return BAD_VALUE; + } + } + +#ifdef OMAP_ENHANCEMENT + if ((valstr = params.get(TICameraParameters::KEY_ISO)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES))) { + CAMHAL_LOGDB("ISO set %s", valstr); + mParameters.set(TICameraParameters::KEY_ISO, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid ISO = %s", valstr); + return BAD_VALUE; + } + } +#endif + + if( (valstr = params.get(android::CameraParameters::KEY_FOCUS_AREAS)) != NULL ) + { + CAMHAL_LOGDB("Focus areas position set %s", params.get(android::CameraParameters::KEY_FOCUS_AREAS)); + mParameters.set(android::CameraParameters::KEY_FOCUS_AREAS, valstr); + } + +#ifdef OMAP_ENHANCEMENT + if( (valstr = params.get(TICameraParameters::KEY_MEASUREMENT_ENABLE)) != NULL ) + { + CAMHAL_LOGDB("Measurements set to %s", valstr); + mParameters.set(TICameraParameters::KEY_MEASUREMENT_ENABLE, valstr); + + if (strcmp(valstr, android::CameraParameters::TRUE) == 0) + { + mMeasurementEnabled = true; + } + else if (strcmp(valstr, android::CameraParameters::FALSE) == 0) + { + mMeasurementEnabled = false; + } + else + { + mMeasurementEnabled = false; + } + + } +#endif + + if( (valstr = params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION)) != NULL) + { + CAMHAL_LOGDB("Exposure compensation set %s", params.get(android::CameraParameters::KEY_EXPOSURE_COMPENSATION)); + mParameters.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, valstr); + } + + if ((valstr = params.get(android::CameraParameters::KEY_SCENE_MODE)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES))) { + CAMHAL_LOGDB("Scene mode set %s", valstr); + doesSetParameterNeedUpdate(valstr, + mParameters.get(android::CameraParameters::KEY_SCENE_MODE), + updateRequired); + mParameters.set(android::CameraParameters::KEY_SCENE_MODE, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Scene mode = %s", valstr); + return BAD_VALUE; + } + } + + if ((valstr = params.get(android::CameraParameters::KEY_FLASH_MODE)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES))) { + CAMHAL_LOGDB("Flash mode set %s", valstr); + mParameters.set(android::CameraParameters::KEY_FLASH_MODE, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Flash mode = %s", valstr); + return BAD_VALUE; + } + } + + if ((valstr = params.get(android::CameraParameters::KEY_EFFECT)) != NULL) { + if (isParameterValid(valstr, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS))) { + CAMHAL_LOGDB("Effect set %s", valstr); + mParameters.set(android::CameraParameters::KEY_EFFECT, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Effect = %s", valstr); + return BAD_VALUE; + } + } + + varint = params.getInt(android::CameraParameters::KEY_ROTATION); + if ( varint >= 0 ) { + CAMHAL_LOGDB("Rotation set %d", varint); + mParameters.set(android::CameraParameters::KEY_ROTATION, varint); + } + + varint = params.getInt(android::CameraParameters::KEY_JPEG_QUALITY); + if ( varint >= 0 ) { + CAMHAL_LOGDB("Jpeg quality set %d", varint); + mParameters.set(android::CameraParameters::KEY_JPEG_QUALITY, varint); + } + + varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH); + if ( varint >= 0 ) { + CAMHAL_LOGDB("Thumbnail width set %d", varint); + mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, varint); + } + + varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT); + if ( varint >= 0 ) { + CAMHAL_LOGDB("Thumbnail width set %d", varint); + mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, varint); + } + + varint = params.getInt(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY); + if ( varint >= 0 ) { + CAMHAL_LOGDB("Thumbnail quality set %d", varint); + mParameters.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, varint); + } + + if( (valstr = params.get(android::CameraParameters::KEY_GPS_LATITUDE)) != NULL ) + { + CAMHAL_LOGDB("GPS latitude set %s", params.get(android::CameraParameters::KEY_GPS_LATITUDE)); + mParameters.set(android::CameraParameters::KEY_GPS_LATITUDE, valstr); + }else{ + mParameters.remove(android::CameraParameters::KEY_GPS_LATITUDE); + } + + if( (valstr = params.get(android::CameraParameters::KEY_GPS_LONGITUDE)) != NULL ) + { + CAMHAL_LOGDB("GPS longitude set %s", params.get(android::CameraParameters::KEY_GPS_LONGITUDE)); + mParameters.set(android::CameraParameters::KEY_GPS_LONGITUDE, valstr); + }else{ + mParameters.remove(android::CameraParameters::KEY_GPS_LONGITUDE); + } + + if( (valstr = params.get(android::CameraParameters::KEY_GPS_ALTITUDE)) != NULL ) + { + CAMHAL_LOGDB("GPS altitude set %s", params.get(android::CameraParameters::KEY_GPS_ALTITUDE)); + mParameters.set(android::CameraParameters::KEY_GPS_ALTITUDE, valstr); + }else{ + mParameters.remove(android::CameraParameters::KEY_GPS_ALTITUDE); + } + + if( (valstr = params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)) != NULL ) + { + CAMHAL_LOGDB("GPS timestamp set %s", params.get(android::CameraParameters::KEY_GPS_TIMESTAMP)); + mParameters.set(android::CameraParameters::KEY_GPS_TIMESTAMP, valstr); + }else{ + mParameters.remove(android::CameraParameters::KEY_GPS_TIMESTAMP); + } + + if( (valstr = params.get(TICameraParameters::KEY_GPS_DATESTAMP)) != NULL ) + { + CAMHAL_LOGDB("GPS datestamp set %s", valstr); + mParameters.set(TICameraParameters::KEY_GPS_DATESTAMP, valstr); + }else{ + mParameters.remove(TICameraParameters::KEY_GPS_DATESTAMP); + } + + if( (valstr = params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD)) != NULL ) + { + CAMHAL_LOGDB("GPS processing method set %s", params.get(android::CameraParameters::KEY_GPS_PROCESSING_METHOD)); + mParameters.set(android::CameraParameters::KEY_GPS_PROCESSING_METHOD, valstr); + }else{ + mParameters.remove(android::CameraParameters::KEY_GPS_PROCESSING_METHOD); + } + + if( (valstr = params.get(TICameraParameters::KEY_GPS_MAPDATUM )) != NULL ) + { + CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr); + mParameters.set(TICameraParameters::KEY_GPS_MAPDATUM, valstr); + }else{ + mParameters.remove(TICameraParameters::KEY_GPS_MAPDATUM); + } + + if( (valstr = params.get(TICameraParameters::KEY_GPS_VERSION)) != NULL ) + { + CAMHAL_LOGDB("GPS MAPDATUM set %s", valstr); + mParameters.set(TICameraParameters::KEY_GPS_VERSION, valstr); + }else{ + mParameters.remove(TICameraParameters::KEY_GPS_VERSION); + } + +#ifndef MOTOROLA_CAMERA + if( (valstr = params.get(TICameraParameters::KEY_EXIF_MODEL)) != NULL ) + { + CAMHAL_LOGDB("EXIF Model set %s", valstr); + mParameters.set(TICameraParameters::KEY_EXIF_MODEL, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_EXIF_MAKE)) != NULL ) + { + CAMHAL_LOGDB("EXIF Make set %s", valstr); + mParameters.set(TICameraParameters::KEY_EXIF_MAKE, valstr); + } +#else + if( (property_get("ro.product.model",value,0) > 0)) + { + CAMHAL_LOGDB("EXIF Model set %s",value); + mParameters.set(TICameraParameters::KEY_EXIF_MODEL, value); + } + + if( (property_get("ro.product.manufacturer",value,0) > 0) ) + { + CAMHAL_LOGDB("EXIF Make set %s",value); + mParameters.set(TICameraParameters::KEY_EXIF_MAKE, value); + } + + // enabled/disabled similar parameters: + // KEY_MOT_LEDFLASH // int: 0..100 percent + if((params.get(TICameraParameters::KEY_MOT_LEDFLASH) != NULL) + && (params.getInt(TICameraParameters::KEY_MOT_LEDFLASH) >=0) + && (params.getInt(TICameraParameters::KEY_MOT_LEDFLASH) <=100)) + { + CAMHAL_LOGDB("Led Flash : %s",params.get(TICameraParameters::KEY_MOT_LEDFLASH)); + mParameters.set(TICameraParameters::KEY_MOT_LEDFLASH, + params.get(TICameraParameters::KEY_MOT_LEDFLASH)); + } + + // KEY_MOT_LEDTORCH // int: 0..100 percent + if((params.get(TICameraParameters::KEY_MOT_LEDTORCH) != NULL) + && (params.getInt(TICameraParameters::KEY_MOT_LEDTORCH) >=0) + && (params.getInt(TICameraParameters::KEY_MOT_LEDTORCH) <=100)) + { + CAMHAL_LOGDB("Led Torch : %s",params.get(TICameraParameters::KEY_MOT_LEDTORCH)); + mParameters.set(TICameraParameters::KEY_MOT_LEDTORCH, + params.get(TICameraParameters::KEY_MOT_LEDTORCH)); + } +#endif + +#ifdef OMAP_ENHANCEMENT + if( (valstr = params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)) != NULL ) + { + CAMHAL_LOGDB("Exposure Bracketing set %s", params.get(TICameraParameters::KEY_EXP_BRACKETING_RANGE)); + mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valstr); + mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE); + } + else if ((valstr = params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)) != NULL) { + CAMHAL_LOGDB("ABS Exposure+Gain Bracketing set %s", params.get(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE)); + mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valstr); + mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE); + } else + { + mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE); + } + + if( (valstr = params.get(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE)) != NULL ) { + CAMHAL_LOGDB("Zoom Bracketing range %s", valstr); + mParameters.set(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE, valstr); + } else { + mParameters.remove(TICameraParameters::KEY_ZOOM_BRACKETING_RANGE); + } +#endif + + if ((valstr = params.get(android::CameraParameters::KEY_ZOOM)) != NULL ) { + varint = atoi(valstr); + if ( varint >= 0 && varint <= mMaxZoomSupported ) { + CAMHAL_LOGDB("Zoom set %d", varint); + doesSetParameterNeedUpdate(valstr, + mParameters.get(android::CameraParameters::KEY_ZOOM), + updateRequired); + mParameters.set(android::CameraParameters::KEY_ZOOM, valstr); + } else { + CAMHAL_LOGEB("ERROR: Invalid Zoom: %s", valstr); + return BAD_VALUE; + } + } + + if( (valstr = params.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK)) != NULL ) + { + CAMHAL_LOGDB("Auto Exposure Lock set %s", valstr); + doesSetParameterNeedUpdate(valstr, + mParameters.get(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK), + updateRequired); + mParameters.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, valstr); + } + + if( (valstr = params.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK)) != NULL ) + { + CAMHAL_LOGDB("Auto WhiteBalance Lock set %s", valstr); + doesSetParameterNeedUpdate(valstr, + mParameters.get(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK), + updateRequired); + mParameters.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, valstr); + } + if( (valstr = params.get(android::CameraParameters::KEY_METERING_AREAS)) != NULL ) + { + CAMHAL_LOGDB("Metering areas position set %s", params.get(android::CameraParameters::KEY_METERING_AREAS)); + mParameters.set(android::CameraParameters::KEY_METERING_AREAS, valstr); + } + + if( (valstr = params.get(TICameraParameters::RAW_WIDTH)) != NULL ) { + CAMHAL_LOGDB("Raw image width set %s", params.get(TICameraParameters::RAW_WIDTH)); + mParameters.set(TICameraParameters::RAW_WIDTH, valstr); + } + + if( (valstr = params.get(TICameraParameters::RAW_HEIGHT)) != NULL ) { + CAMHAL_LOGDB("Raw image height set %s", params.get(TICameraParameters::RAW_HEIGHT)); + mParameters.set(TICameraParameters::RAW_HEIGHT, valstr); + } + + //TI extensions for enable/disable algos + if( (valstr = params.get(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA)) != NULL ) + { + CAMHAL_LOGDB("External Gamma set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF1)) != NULL ) + { + CAMHAL_LOGDB("NSF1 set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_NSF1, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_ALGO_NSF2)) != NULL ) + { + CAMHAL_LOGDB("NSF2 set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_NSF2, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_ALGO_SHARPENING)) != NULL ) + { + CAMHAL_LOGDB("Sharpening set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_SHARPENING, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_ALGO_THREELINCOLORMAP)) != NULL ) + { + CAMHAL_LOGDB("Color Conversion set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_ALGO_GIC)) != NULL ) + { + CAMHAL_LOGDB("Green Inballance Correction set %s", valstr); + mParameters.set(TICameraParameters::KEY_ALGO_GIC, valstr); + } + + if( (valstr = params.get(TICameraParameters::KEY_GAMMA_TABLE)) != NULL ) + { + CAMHAL_LOGDB("Manual gamma table set %s", valstr); + mParameters.set(TICameraParameters::KEY_GAMMA_TABLE, valstr); + } + + android::CameraParameters adapterParams = mParameters; + +#ifdef OMAP_ENHANCEMENT + if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS) ) + { + int posBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_POS); + if ( 0 < posBracketRange ) + { + mBracketRangePositive = posBracketRange; + } + } + CAMHAL_LOGDB("Positive bracketing range %d", mBracketRangePositive); + + + if( NULL != params.get(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG) ) + { + int negBracketRange = params.getInt(TICameraParameters::KEY_TEMP_BRACKETING_RANGE_NEG); + if ( 0 < negBracketRange ) + { + mBracketRangeNegative = negBracketRange; + } + } + CAMHAL_LOGDB("Negative bracketing range %d", mBracketRangeNegative); + + if( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL) && + ( strcmp(valstr, android::CameraParameters::TRUE) == 0 )) { + if ( !mBracketingEnabled ) { + CAMHAL_LOGDA("Enabling bracketing"); + mBracketingEnabled = true; + } else { + CAMHAL_LOGDA("Bracketing already enabled"); + } + adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr); + mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr); + } else if ( ( (valstr = params.get(TICameraParameters::KEY_TEMP_BRACKETING)) != NULL ) && + ( strcmp(valstr, android::CameraParameters::FALSE) == 0 )) { + CAMHAL_LOGDA("Disabling bracketing"); + + adapterParams.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr); + mParameters.set(TICameraParameters::KEY_TEMP_BRACKETING, valstr); + mBracketingEnabled = false; + if ( mBracketingRunning ) { + stopImageBracketing(); + } + + } else { + adapterParams.remove(TICameraParameters::KEY_TEMP_BRACKETING); + mParameters.remove(TICameraParameters::KEY_TEMP_BRACKETING); + } +#endif + +#ifdef OMAP_ENHANCEMENT_VTC + if (mVTCUseCase && !mTunnelSetup && (mCameraAdapter != NULL) && + ((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE)) != NULL )&& + ((mParameters.get(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT)) != NULL )) { + + uint32_t sliceHeight = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_SLICE_HEIGHT); + uint32_t encoderHandle = mParameters.getInt(TICameraParameters::KEY_VIDEO_ENCODER_HANDLE); + int w, h; + mParameters.getPreviewSize(&w, &h); + status_t done = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SETUP_TUNNEL, sliceHeight, encoderHandle, w, h); + if (done == NO_ERROR) mTunnelSetup = true; + ret |= done; + } +#endif + + // Only send parameters to adapter if preview is already + // enabled or doesSetParameterNeedUpdate says so. Initial setParameters to camera adapter, + // will be called in startPreview() + // TODO(XXX): Need to identify other parameters that need update from camera adapter + if ( (NULL != mCameraAdapter) && + (mPreviewEnabled || updateRequired) && + (!(mPreviewEnabled && restartPreviewRequired)) ) { + ret |= mCameraAdapter->setParameters(adapterParams); + } + +#ifdef OMAP_ENHANCEMENT + if( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) && + ( strcmp(valstr, android::CameraParameters::TRUE) == 0 )) + { + CAMHAL_LOGDA("Enabling shutter sound"); + + mShutterEnabled = true; + mMsgEnabled |= CAMERA_MSG_SHUTTER; + mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr); + } + else if ( ( (valstr = params.get(TICameraParameters::KEY_SHUTTER_ENABLE)) != NULL ) && + ( strcmp(valstr, android::CameraParameters::FALSE) == 0 )) + { + CAMHAL_LOGDA("Disabling shutter sound"); + + mShutterEnabled = false; + mMsgEnabled &= ~CAMERA_MSG_SHUTTER; + mParameters.set(TICameraParameters::KEY_SHUTTER_ENABLE, valstr); + } +#endif + } + + //On fail restore old parameters + if ( NO_ERROR != ret ) { + mParameters = oldParams; + } + + // Restart Preview if needed by KEY_RECODING_HINT only if preview is already running. + // If preview is not started yet, Video Mode parameters will take effect on next startPreview() + if (restartPreviewRequired && previewEnabled() && !mRecordingEnabled) { + CAMHAL_LOGDA("Restarting Preview"); + ret = restartPreview(); + } else if (restartPreviewRequired && !previewEnabled() && + mDisplayPaused && !mRecordingEnabled) { + CAMHAL_LOGDA("Restarting preview in paused mode"); + ret = restartPreview(); + + // TODO(XXX): If there is some delay between the restartPreview call and the code + // below, then the user could see some preview frames and callbacks. Let's find + // a better place to put this later... + if (ret == NO_ERROR) { + mDisplayPaused = true; + mPreviewEnabled = false; + ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); + } + } + + if ( !mBracketingRunning && mBracketingEnabled ) { + startImageBracketing(); + } + + if (ret != NO_ERROR) + { + CAMHAL_LOGEA("Failed to restart Preview"); + return ret; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::allocPreviewBufs(int width, int height, const char* previewFormat, + unsigned int buffercount, unsigned int &max_queueable) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if(mDisplayAdapter.get() == NULL) + { + // Memory allocation of preview buffers is now placed in gralloc + // CameraHal should not allocate preview buffers without DisplayAdapter + return NO_MEMORY; + } + + if(!mPreviewBuffers) + { + mPreviewLength = 0; + mPreviewBuffers = mDisplayAdapter->allocateBufferList(width, height, + previewFormat, + mPreviewLength, + buffercount); + if (NULL == mPreviewBuffers ) { + CAMHAL_LOGEA("Couldn't allocate preview buffers"); + return NO_MEMORY; + } + + mPreviewOffsets = (uint32_t *) mDisplayAdapter->getOffsets(); + if ( NULL == mPreviewOffsets ) { + CAMHAL_LOGEA("Buffer mapping failed"); + return BAD_VALUE; + } + + mBufProvider = (BufferProvider*) mDisplayAdapter.get(); + + ret = mDisplayAdapter->maxQueueableBuffers(max_queueable); + if (ret != NO_ERROR) { + return ret; + } + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::freePreviewBufs() +{ + status_t ret = NO_ERROR; + LOG_FUNCTION_NAME; + + CAMHAL_LOGDB("mPreviewBuffers = %p", mPreviewBuffers); + if(mPreviewBuffers) + { + ret = mBufProvider->freeBufferList(mPreviewBuffers); + mPreviewBuffers = NULL; + LOG_FUNCTION_NAME_EXIT; + return ret; + } + LOG_FUNCTION_NAME_EXIT; + return ret; +} + + +status_t CameraHal::allocPreviewDataBufs(size_t size, size_t bufferCount) +{ + status_t ret = NO_ERROR; + int bytes; + + LOG_FUNCTION_NAME; + + bytes = size; + + if ( NO_ERROR == ret ) + { + if( NULL != mPreviewDataBuffers ) + { + ret = freePreviewDataBufs(); + } + } + + if ( NO_ERROR == ret ) + { + bytes = ((bytes+4095)/4096)*4096; + mPreviewDataBuffers = mMemoryManager->allocateBufferList(0, 0, NULL, bytes, bufferCount); + + CAMHAL_LOGDB("Size of Preview data buffer = %d", bytes); + if( NULL == mPreviewDataBuffers ) + { + CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager"); + ret = -NO_MEMORY; + } + else + { + bytes = size; + } + } + + if ( NO_ERROR == ret ) + { + mPreviewDataFd = mMemoryManager->getFd(); + mPreviewDataLength = bytes; + mPreviewDataOffsets = mMemoryManager->getOffsets(); + } + else + { + mPreviewDataFd = -1; + mPreviewDataLength = 0; + mPreviewDataOffsets = NULL; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::freePreviewDataBufs() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if ( NO_ERROR == ret ) + { + + if( NULL != mPreviewDataBuffers ) + { + + ret = mMemoryManager->freeBufferList(mPreviewDataBuffers); + mPreviewDataBuffers = NULL; + + } + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::allocImageBufs(unsigned int width, unsigned int height, size_t size, + const char* previewFormat, unsigned int bufferCount) +{ + status_t ret = NO_ERROR; + int bytes = size; + + LOG_FUNCTION_NAME; + + // allocate image buffers only if not already allocated + if(NULL != mImageBuffers) { + return NO_ERROR; + } + + if ( NO_ERROR == ret ) { + bytes = ((bytes+4095)/4096)*4096; + mImageBuffers = mMemoryManager->allocateBufferList(0, 0, previewFormat, bytes, bufferCount); + CAMHAL_LOGDB("Size of Image cap buffer = %d", bytes); + if( NULL == mImageBuffers ) { + CAMHAL_LOGEA("Couldn't allocate image buffers using memory manager"); + ret = -NO_MEMORY; + } else { + bytes = size; + } + } + + if ( NO_ERROR == ret ) { + mImageFd = mMemoryManager->getFd(); + mImageLength = bytes; + mImageOffsets = mMemoryManager->getOffsets(); + mImageCount = bufferCount; + } else { + mImageFd = -1; + mImageLength = 0; + mImageOffsets = NULL; + mImageCount = 0; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::allocVideoBufs(uint32_t width, uint32_t height, uint32_t bufferCount) +{ + status_t ret = NO_ERROR; + LOG_FUNCTION_NAME; + + if( NULL != mVideoBuffers ){ + ret = freeVideoBufs(mVideoBuffers); + mVideoBuffers = NULL; + } + + if ( NO_ERROR == ret ){ + int32_t stride; + CameraBuffer *buffers = new CameraBuffer [bufferCount]; + + memset (buffers, 0, sizeof(CameraBuffer) * bufferCount); + + if (buffers != NULL){ + for (unsigned int i = 0; i< bufferCount; i++){ + android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get(); + buffer_handle_t handle; + ret = GrallocAlloc.alloc(width, height, HAL_PIXEL_FORMAT_NV12, CAMHAL_GRALLOC_USAGE, &handle, &stride); + if (ret != NO_ERROR){ + CAMHAL_LOGEA("Couldn't allocate video buffers using Gralloc"); + ret = -NO_MEMORY; + for (unsigned int j=0; j< i; j++){ + CAMHAL_LOGEB("Freeing Gralloc Buffer %p", buffers[i].opaque); + GrallocAlloc.free((buffer_handle_t)buffers[i].opaque); + } + delete [] buffers; + goto exit; + } + buffers[i].type = CAMERA_BUFFER_GRALLOC; + buffers[i].opaque = (void *)handle; + CAMHAL_LOGVB("*** Gralloc Handle =0x%x ***", handle); + } + + mVideoBuffers = buffers; + } + else{ + CAMHAL_LOGEA("Couldn't allocate video buffers "); + ret = -NO_MEMORY; + } + } + + exit: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::allocRawBufs(int width, int height, const char* previewFormat, int bufferCount) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME + + + ///@todo Enhance this method allocImageBufs() to take in a flag for burst capture + ///Always allocate the buffers for image capture using MemoryManager + if (NO_ERROR == ret) { + if(( NULL != mVideoBuffers )) { + // Re-use the buffer for raw capture. + return ret; + } + } + + if ( NO_ERROR == ret ) { + mVideoLength = 0; + mVideoLength = (((width * height * 2) + 4095)/4096)*4096; + mVideoBuffers = mMemoryManager->allocateBufferList(width, height, previewFormat, + mVideoLength, bufferCount); + + CAMHAL_LOGDB("Size of Video cap buffer (used for RAW capture) %d", mVideoLength); + if( NULL == mVideoBuffers ) { + CAMHAL_LOGEA("Couldn't allocate Video buffers using memory manager"); + ret = -NO_MEMORY; + } + } + + if ( NO_ERROR == ret ) { + mVideoFd = mMemoryManager->getFd(); + mVideoOffsets = mMemoryManager->getOffsets(); + } else { + mVideoFd = -1; + mVideoOffsets = NULL; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +void endImageCapture( void *userData) +{ + LOG_FUNCTION_NAME; + + if ( NULL != userData ) + { + CameraHal *c = reinterpret_cast(userData); + c->signalEndImageCapture(); + } + + LOG_FUNCTION_NAME_EXIT; +} + +void releaseImageBuffers(void *userData) +{ + LOG_FUNCTION_NAME; + + if (NULL != userData) { + CameraHal *c = reinterpret_cast(userData); + c->freeImageBufs(); + } + + LOG_FUNCTION_NAME_EXIT; +} + +status_t CameraHal::signalEndImageCapture() +{ + status_t ret = NO_ERROR; + int w,h; + android::AutoMutex lock(mLock); + + LOG_FUNCTION_NAME; + + if (mBufferSourceAdapter_Out.get()) { + mBufferSourceAdapter_Out->disableDisplay(); + } + + if (mBufferSourceAdapter_In.get()) { + mBufferSourceAdapter_In->disableDisplay(); + } + + if ( mBracketingRunning ) { + stopImageBracketing(); + } else { + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE); + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::freeImageBufs() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if (NULL == mImageBuffers) { + return -EINVAL; + } + + if (mBufferSourceAdapter_Out.get()) { + mBufferSourceAdapter_Out = 0; + } else { + ret = mMemoryManager->freeBufferList(mImageBuffers); + } + + mImageBuffers = NULL; + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::freeVideoBufs(CameraBuffer *bufs) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)); + if(bufs == NULL) + { + CAMHAL_LOGEA("NULL pointer passed to freeVideoBuffer"); + LOG_FUNCTION_NAME_EXIT; + return BAD_VALUE; + } + + android::GraphicBufferAllocator &GrallocAlloc = android::GraphicBufferAllocator::get(); + + for(int i = 0; i < count; i++){ + CAMHAL_LOGVB("Free Video Gralloc Handle 0x%x", bufs[i].opaque); + GrallocAlloc.free((buffer_handle_t)bufs[i].opaque); + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::freeRawBufs() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME + + if ( NO_ERROR == ret ) { + if( NULL != mVideoBuffers ) { + ///@todo Pluralise the name of this method to freeBuffers + ret = mMemoryManager->freeBufferList(mVideoBuffers); + mVideoBuffers = NULL; + } else { + ret = -EINVAL; + } + } + + LOG_FUNCTION_NAME_EXIT + + return ret; +} + +/** + @brief Start preview mode. + + @param none + @return NO_ERROR Camera switched to VF mode + @todo Update function header with the different errors that are possible + + */ +status_t CameraHal::startPreview() { + LOG_FUNCTION_NAME; + + // When tunneling is enabled during VTC, startPreview happens in 2 steps: + // When the application sends the command CAMERA_CMD_PREVIEW_INITIALIZATION, + // cameraPreviewInitialization() is called, which in turn causes the CameraAdapter + // to move from loaded to idle state. And when the application calls startPreview, + // the CameraAdapter moves from idle to executing state. + // + // If the application calls startPreview() without sending the command + // CAMERA_CMD_PREVIEW_INITIALIZATION, then the function cameraPreviewInitialization() + // AND startPreview() are executed. In other words, if the application calls + // startPreview() without sending the command CAMERA_CMD_PREVIEW_INITIALIZATION, + // then the CameraAdapter moves from loaded to idle to executing state in one shot. + status_t ret = cameraPreviewInitialization(); + + // The flag mPreviewInitializationDone is set to true at the end of the function + // cameraPreviewInitialization(). Therefore, if everything goes alright, then the + // flag will be set. Sometimes, the function cameraPreviewInitialization() may + // return prematurely if all the resources are not available for starting preview. + // For example, if the preview window is not set, then it would return NO_ERROR. + // Under such circumstances, one should return from startPreview as well and should + // not continue execution. That is why, we check the flag and not the return value. + if (!mPreviewInitializationDone) return ret; + + // Once startPreview is called, there is no need to continue to remember whether + // the function cameraPreviewInitialization() was called earlier or not. And so + // the flag mPreviewInitializationDone is reset here. Plus, this preserves the + // current behavior of startPreview under the circumstances where the application + // calls startPreview twice or more. + mPreviewInitializationDone = false; + + ///Enable the display adapter if present, actual overlay enable happens when we post the buffer + if(mDisplayAdapter.get() != NULL) { + CAMHAL_LOGDA("Enabling display"); + int width, height; + mParameters.getPreviewSize(&width, &height); + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview); +#else + ret = mDisplayAdapter->enableDisplay(width, height, NULL); +#endif + + if ( ret != NO_ERROR ) { + CAMHAL_LOGEA("Couldn't enable display"); + + // FIXME: At this stage mStateSwitchLock is locked and unlock is supposed to be called + // only from mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW) + // below. But this will never happen because of goto error. Thus at next + // startPreview() call CameraHAL will be deadlocked. + // Need to revisit mStateSwitch lock, for now just abort the process. + CAMHAL_ASSERT_X(false, + "At this stage mCameraAdapter->mStateSwitchLock is still locked, " + "deadlock is guaranteed"); + + goto error; + } + + } + + ///Send START_PREVIEW command to adapter + CAMHAL_LOGDA("Starting CameraAdapter preview mode"); + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW); + + if(ret!=NO_ERROR) { + CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter"); + goto error; + } + CAMHAL_LOGDA("Started preview"); + + mPreviewEnabled = true; + mPreviewStartInProgress = false; + return ret; + + error: + + CAMHAL_LOGEA("Performing cleanup after error"); + + //Do all the cleanup + freePreviewBufs(); + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); + if(mDisplayAdapter.get() != NULL) { + mDisplayAdapter->disableDisplay(false); + } + mAppCallbackNotifier->stop(); + mPreviewStartInProgress = false; + mPreviewEnabled = false; + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +//////////// +/** + @brief Set preview mode related initialization + -> Camera Adapter set params + -> Allocate buffers + -> Set use buffers for preview + @param none + @return NO_ERROR + @todo Update function header with the different errors that are possible + + */ +status_t CameraHal::cameraPreviewInitialization() +{ + + status_t ret = NO_ERROR; + CameraAdapter::BuffersDescriptor desc; + CameraFrame frame; + unsigned int required_buffer_count; + unsigned int max_queueble_buffers; + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + gettimeofday(&mStartPreview, NULL); +#endif + + LOG_FUNCTION_NAME; + + if (mPreviewInitializationDone) { + return NO_ERROR; + } + + if ( mPreviewEnabled ){ + CAMHAL_LOGDA("Preview already running"); + LOG_FUNCTION_NAME_EXIT; + return ALREADY_EXISTS; + } + + if ( NULL != mCameraAdapter ) { + ret = mCameraAdapter->setParameters(mParameters); + } + + if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){ + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame); + if ( NO_ERROR != ret ){ + CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret); + return ret; + } + + ///Update the current preview width and height + mPreviewWidth = frame.mWidth; + mPreviewHeight = frame.mHeight; + } + + ///If we don't have the preview callback enabled and display adapter, + if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){ + CAMHAL_LOGD("Preview not started. Preview in progress flag set"); + mPreviewStartInProgress = true; + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING); + if ( NO_ERROR != ret ){ + CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret); + return ret; + } + return NO_ERROR; + } + + if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) ) + { + CAMHAL_LOGDA("Preview is in paused state"); + + mDisplayPaused = false; + mPreviewEnabled = true; + if ( NO_ERROR == ret ) + { + ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); + + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("Display adapter resume failed %x", ret); + } + } + //restart preview callbacks + if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) + { + mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME); + } + + signalEndImageCapture(); + return ret; + } + + required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)); + + ///Allocate the preview buffers + ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers); + + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEA("Couldn't allocate buffers for Preview"); + goto error; + } + + if ( mMeasurementEnabled ) + { + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA, + ( int ) &frame, + required_buffer_count); + if ( NO_ERROR != ret ) + { + return ret; + } + + ///Allocate the preview data buffers + ret = allocPreviewDataBufs(frame.mLength, required_buffer_count); + if ( NO_ERROR != ret ) { + CAMHAL_LOGEA("Couldn't allocate preview data buffers"); + goto error; + } + + if ( NO_ERROR == ret ) + { + desc.mBuffers = mPreviewDataBuffers; + desc.mOffsets = mPreviewDataOffsets; + desc.mFd = mPreviewDataFd; + desc.mLength = mPreviewDataLength; + desc.mCount = ( size_t ) required_buffer_count; + desc.mMaxQueueable = (size_t) required_buffer_count; + + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA, + ( int ) &desc); + } + + } + + ///Pass the buffers to Camera Adapter + desc.mBuffers = mPreviewBuffers; + desc.mOffsets = mPreviewOffsets; + desc.mFd = mPreviewFd; + desc.mLength = mPreviewLength; + desc.mCount = ( size_t ) required_buffer_count; + desc.mMaxQueueable = (size_t) max_queueble_buffers; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW, + ( int ) &desc); + + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret); + freePreviewBufs(); + return ret; + } + + ///Start the callback notifier + ret = mAppCallbackNotifier->start(); + + if( ALREADY_EXISTS == ret ) + { + //Already running, do nothing + CAMHAL_LOGDA("AppCallbackNotifier already running"); + ret = NO_ERROR; + } + else if ( NO_ERROR == ret ) { + CAMHAL_LOGDA("Started AppCallbackNotifier.."); + mAppCallbackNotifier->setMeasurements(mMeasurementEnabled); + } + else + { + CAMHAL_LOGDA("Couldn't start AppCallbackNotifier"); + goto error; + } + + if (ret == NO_ERROR) mPreviewInitializationDone = true; + + mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count); + + return ret; + + error: + + CAMHAL_LOGEA("Performing cleanup after error"); + + //Do all the cleanup + freePreviewBufs(); + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); + if(mDisplayAdapter.get() != NULL) + { + mDisplayAdapter->disableDisplay(false); + } + mAppCallbackNotifier->stop(); + mPreviewStartInProgress = false; + mPreviewEnabled = false; + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Sets ANativeWindow object. + + Preview buffers provided to CameraHal via this object. DisplayAdapter will be interfacing with it + to render buffers to display. + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::setPreviewWindow(struct preview_stream_ops *window) +{ + status_t ret = NO_ERROR; + CameraAdapter::BuffersDescriptor desc; + + LOG_FUNCTION_NAME; + mSetPreviewWindowCalled = true; + + ///If the Camera service passes a null window, we destroy existing window and free the DisplayAdapter + if(!window) + { + if(mDisplayAdapter.get() != NULL) + { + ///NULL window passed, destroy the display adapter if present + CAMHAL_LOGD("NULL window passed, destroying display adapter"); + mDisplayAdapter.clear(); + ///@remarks If there was a window previously existing, we usually expect another valid window to be passed by the client + ///@remarks so, we will wait until it passes a valid window to begin the preview again + mSetPreviewWindowCalled = false; + } + CAMHAL_LOGD("NULL ANativeWindow passed to setPreviewWindow"); + return NO_ERROR; + }else if(mDisplayAdapter.get() == NULL) + { + // Need to create the display adapter since it has not been created + // Create display adapter + ANativeWindowDisplayAdapter* displayAdapter = new ANativeWindowDisplayAdapter(); + displayAdapter->setExternalLocking(mExternalLocking); + if (NULL != mAppCallbackNotifier.get()) { + mAppCallbackNotifier->setExternalLocking(mExternalLocking); + } else { + CAMHAL_LOGE("Can't apply locking policy on AppCallbackNotifier"); + CAMHAL_ASSERT(0); + } + mDisplayAdapter = displayAdapter; +#ifdef OMAP_ENHANCEMENT_CPCAM + mDisplayAdapter->setExtendedOps(mExtendedPreviewStreamOps); +#endif + ret = NO_ERROR; + if(!mDisplayAdapter.get() || ((ret=mDisplayAdapter->initialize())!=NO_ERROR)) + { + if(ret!=NO_ERROR) + { + mDisplayAdapter.clear(); + CAMHAL_LOGEA("DisplayAdapter initialize failed"); + LOG_FUNCTION_NAME_EXIT; + return ret; + } + else + { + CAMHAL_LOGEA("Couldn't create DisplayAdapter"); + LOG_FUNCTION_NAME_EXIT; + return NO_MEMORY; + } + } + + // DisplayAdapter needs to know where to get the CameraFrames from inorder to display + // Since CameraAdapter is the one that provides the frames, set it as the frame provider for DisplayAdapter + mDisplayAdapter->setFrameProvider(mCameraAdapter); + + // Any dynamic errors that happen during the camera use case has to be propagated back to the application + // via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application + // Set it as the error handler for the DisplayAdapter + mDisplayAdapter->setErrorHandler(mAppCallbackNotifier.get()); + + // Update the display adapter with the new window that is passed from CameraService + ret = mDisplayAdapter->setPreviewWindow(window); + if(ret!=NO_ERROR) + { + CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret); + } + + if(mPreviewStartInProgress) + { + CAMHAL_LOGDA("setPreviewWindow called when preview running"); + // Start the preview since the window is now available + ret = startPreview(); + } + } else { + // Update the display adapter with the new window that is passed from CameraService + ret = mDisplayAdapter->setPreviewWindow(window); + if ( (NO_ERROR == ret) && previewEnabled() ) { + restartPreview(); + } else if (ret == ALREADY_EXISTS) { + // ALREADY_EXISTS should be treated as a noop in this case + ret = NO_ERROR; + } + } + LOG_FUNCTION_NAME_EXIT; + + return ret; + +} + + +#ifdef OMAP_ENHANCEMENT_CPCAM +void CameraHal::setExtendedPreviewStreamOps(preview_stream_extended_ops_t *ops) +{ + mExtendedPreviewStreamOps = ops; +} + +/** + @brief Sets Tapout Surfaces. + + Buffers provided to CameraHal via this object for tap-out + functionality. + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::setTapoutLocked(struct preview_stream_ops *tapout) +{ + status_t ret = NO_ERROR; + int index = -1; + + LOG_FUNCTION_NAME; + + if (!tapout) { + CAMHAL_LOGD("Missing argument"); + LOG_FUNCTION_NAME_EXIT; + return NO_ERROR; + } + + // Set tapout point + // 1. Check name of tap-out + // 2. If not already set, then create a new one + // 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate + // in case dimensions have changed + + for (unsigned int i = 0; i < mOutAdapters.size(); i++) { + android::sp out; + out = mOutAdapters.itemAt(i); + ret = out->setPreviewWindow(tapout); + if (ret == ALREADY_EXISTS) { + CAMHAL_LOGD("Tap Out already set at index = %d", i); + index = i; + ret = NO_ERROR; + } + } + + if (index < 0) { + android::sp out = new BufferSourceAdapter(); + + ret = out->initialize(); + if (ret != NO_ERROR) { + out.clear(); + CAMHAL_LOGEA("DisplayAdapter initialize failed"); + goto exit; + } + + // BufferSourceAdapter will be handler of the extended OPS + out->setExtendedOps(mExtendedPreviewStreamOps); + + // CameraAdapter will be the frame provider for BufferSourceAdapter + out->setFrameProvider(mCameraAdapter); + + // BufferSourceAdapter will use ErrorHandler to send errors back to + // the application + out->setErrorHandler(mAppCallbackNotifier.get()); + + // Update the display adapter with the new window that is passed from CameraService + ret = out->setPreviewWindow(tapout); + if(ret != NO_ERROR) { + CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret); + goto exit; + } + + if (NULL != mCameraAdapter) { + unsigned int bufferCount, max_queueable; + CameraFrame frame; + + bufferCount = out->getBufferCount(); + if (bufferCount < 1) bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE, + ( int ) &frame, + bufferCount); + if (NO_ERROR != ret) { + CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret); + } + if (NO_ERROR == ret) { + CameraBuffer *bufs = NULL; + unsigned int stride; + unsigned int height = frame.mHeight; + int size = frame.mLength; + + stride = frame.mAlignment / getBPP(mParameters.getPictureFormat()); + bufs = out->allocateBufferList(stride, + height, + mParameters.getPictureFormat(), + size, + bufferCount); + if (bufs == NULL){ + CAMHAL_LOGEB("error allocating buffer list"); + goto exit; + } + } + } + mOutAdapters.add(out); + } + +exit: + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Releases Tapout Surfaces. + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::releaseTapoutLocked(struct preview_stream_ops *tapout) +{ + status_t ret = NO_ERROR; + char id[OP_STR_SIZE]; + + LOG_FUNCTION_NAME; + + if (!tapout) { + CAMHAL_LOGD("Missing argument"); + LOG_FUNCTION_NAME_EXIT; + return NO_ERROR; + } + + // Get the name of tapout + ret = mExtendedPreviewStreamOps->get_id(tapout, id, sizeof(id)); + if (NO_ERROR != ret) { + CAMHAL_LOGEB("get_id OPS returned error %d", ret); + return ret; + } + + // 1. Check name of tap-out + // 2. If exist, then free buffers and then remove it + if (mBufferSourceAdapter_Out.get() && mBufferSourceAdapter_Out->match(id)) { + CAMHAL_LOGD("REMOVE tap out %p previously set as current", tapout); + mBufferSourceAdapter_Out.clear(); + } + for (unsigned int i = 0; i < mOutAdapters.size(); i++) { + android::sp out; + out = mOutAdapters.itemAt(i); + if (out->match(id)) { + CAMHAL_LOGD("REMOVE tap out %p \"%s\" at position %d", tapout, id, i); + mOutAdapters.removeAt(i); + break; + } + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Sets Tapin Surfaces. + + Buffers provided to CameraHal via this object for tap-in + functionality. + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::setTapinLocked(struct preview_stream_ops *tapin) +{ + status_t ret = NO_ERROR; + int index = -1; + + LOG_FUNCTION_NAME; + + if (!tapin) { + CAMHAL_LOGD("Missing argument"); + LOG_FUNCTION_NAME_EXIT; + return NO_ERROR; + } + + // 1. Set tapin point + // 1. Check name of tap-in + // 2. If not already set, then create a new one + // 3. Allocate buffers. If user is re-setting the surface, free buffers first and re-allocate + // in case dimensions have changed + for (unsigned int i = 0; i < mInAdapters.size(); i++) { + android::sp in; + in = mInAdapters.itemAt(i); + ret = in->setPreviewWindow(tapin); + if (ret == ALREADY_EXISTS) { + CAMHAL_LOGD("Tap In already set at index = %d", i); + index = i; + ret = NO_ERROR; + } + } + + if (index < 0) { + android::sp in = new BufferSourceAdapter(); + + ret = in->initialize(); + if (ret != NO_ERROR) { + in.clear(); + CAMHAL_LOGEA("DisplayAdapter initialize failed"); + goto exit; + } + + // BufferSourceAdapter will be handler of the extended OPS + in->setExtendedOps(mExtendedPreviewStreamOps); + + // CameraAdapter will be the frame provider for BufferSourceAdapter + in->setFrameProvider(mCameraAdapter); + + // BufferSourceAdapter will use ErrorHandler to send errors back to + // the application + in->setErrorHandler(mAppCallbackNotifier.get()); + + // Update the display adapter with the new window that is passed from CameraService + ret = in->setPreviewWindow(tapin); + if(ret != NO_ERROR) { + CAMHAL_LOGEB("DisplayAdapter setPreviewWindow returned error %d", ret); + goto exit; + } + + mInAdapters.add(in); + } + +exit: + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + + +/** + @brief Releases Tapin Surfaces. + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::releaseTapinLocked(struct preview_stream_ops *tapin) +{ + status_t ret = NO_ERROR; + char id[OP_STR_SIZE]; + + LOG_FUNCTION_NAME; + + if (!tapin) { + CAMHAL_LOGD("Missing argument"); + LOG_FUNCTION_NAME_EXIT; + return NO_ERROR; + } + + // Get the name of tapin + ret = mExtendedPreviewStreamOps->get_id(tapin, id, sizeof(id)); + if (NO_ERROR != ret) { + CAMHAL_LOGEB("get_id OPS returned error %d", ret); + return ret; + } + + // 1. Check name of tap-in + // 2. If exist, then free buffers and then remove it + if (mBufferSourceAdapter_In.get() && mBufferSourceAdapter_In->match(id)) { + CAMHAL_LOGD("REMOVE tap in %p previously set as current", tapin); + mBufferSourceAdapter_In.clear(); + } + for (unsigned int i = 0; i < mInAdapters.size(); i++) { + android::sp in; + in = mInAdapters.itemAt(i); + if (in->match(id)) { + CAMHAL_LOGD("REMOVE tap in %p \"%s\" at position %d", tapin, id, i); + mInAdapters.removeAt(i); + break; + } + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + + +/** + @brief Sets ANativeWindow object. + + Buffers provided to CameraHal via this object for tap-in/tap-out + functionality. + + TODO(XXX): this is just going to use preview_stream_ops for now, but we + most likely need to extend it when we want more functionality + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::setBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout) +{ + status_t ret = NO_ERROR; + int index = -1; + + LOG_FUNCTION_NAME; + + android::AutoMutex lock(mLock); + + CAMHAL_LOGD ("setBufferSource(%p, %p)", tapin, tapout); + + ret = setTapoutLocked(tapout); + if (ret != NO_ERROR) { + CAMHAL_LOGE("setTapoutLocked returned error 0x%x", ret); + goto exit; + } + + ret = setTapinLocked(tapin); + if (ret != NO_ERROR) { + CAMHAL_LOGE("setTapinLocked returned error 0x%x", ret); + goto exit; + } + +exit: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + + +/** + @brief Releases ANativeWindow object. + + Release Buffers previously released with setBufferSource() + + TODO(XXX): this is just going to use preview_stream_ops for now, but we + most likely need to extend it when we want more functionality + + @param[in] window The ANativeWindow object created by Surface flinger + @return NO_ERROR If the ANativeWindow object passes validation criteria + @todo Define validation criteria for ANativeWindow object. Define error codes for scenarios + + */ +status_t CameraHal::releaseBufferSource(struct preview_stream_ops *tapin, struct preview_stream_ops *tapout) +{ + status_t ret = NO_ERROR; + int index = -1; + + LOG_FUNCTION_NAME; + + android::AutoMutex lock(mLock); + CAMHAL_LOGD ("releaseBufferSource(%p, %p)", tapin, tapout); + if (tapout) { + ret |= releaseTapoutLocked(tapout); + if (ret != NO_ERROR) { + CAMHAL_LOGE("Error %d to release tap out", ret); + } + } + + if (tapin) { + ret |= releaseTapinLocked(tapin); + if (ret != NO_ERROR) { + CAMHAL_LOGE("Error %d to release tap in", ret); + } + } + +exit: + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} +#endif + + +/** + @brief Stop a previously started preview. + + @param none + @return none + + */ +void CameraHal::stopPreview() +{ + LOG_FUNCTION_NAME; + + if( (!previewEnabled() && !mDisplayPaused) || mRecordingEnabled) + { + LOG_FUNCTION_NAME_EXIT; + return; + } + + bool imageCaptureRunning = (mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) && + (mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE); + if(mDisplayPaused && !imageCaptureRunning) + { + // Display is paused, which essentially means there is no preview active. + // Note: this is done so that when stopPreview is called by client after + // an image capture, we do not de-initialize the camera adapter and + // restart over again. + + return; + } + + forceStopPreview(); + + // Reset Capture-Mode to default, so that when we switch from VideoRecording + // to ImageCapture, CAPTURE_MODE is not left to VIDEO_MODE. + CAMHAL_LOGDA("Resetting Capture-Mode to default"); + mParameters.set(TICameraParameters::KEY_CAP_MODE, ""); + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Returns true if preview is enabled + + @param none + @return true If preview is running currently + false If preview has been stopped + + */ +bool CameraHal::previewEnabled() +{ + LOG_FUNCTION_NAME; + + return (mPreviewEnabled || mPreviewStartInProgress); +} + +/** + @brief Start record mode. + + When a record image is available a CAMERA_MSG_VIDEO_FRAME message is sent with + the corresponding frame. Every record frame must be released by calling + releaseRecordingFrame(). + + @param none + @return NO_ERROR If recording could be started without any issues + @todo Update the header with possible error values in failure scenarios + + */ +status_t CameraHal::startRecording( ) +{ + int w, h; + const char *valstr = NULL; + bool restartPreviewRequired = false; + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + gettimeofday(&mStartPreview, NULL); + +#endif + + if(!previewEnabled()) + { + return NO_INIT; + } + + // set internal recording hint in case camera adapter needs to make some + // decisions....(will only be sent to camera adapter if camera restart is required) + mParameters.set(TICameraParameters::KEY_RECORDING_HINT, android::CameraParameters::TRUE); + + // if application starts recording in continuous focus picture mode... + // then we need to force default capture mode (as opposed to video mode) + if ( ((valstr = mParameters.get(android::CameraParameters::KEY_FOCUS_MODE)) != NULL) && + (strcmp(valstr, android::CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) == 0) ){ + restartPreviewRequired = resetVideoModeParameters(); + } + + // only need to check recording hint if preview restart is not already needed + valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT); + if ( !restartPreviewRequired && + (!valstr || (valstr && (strcmp(valstr, android::CameraParameters::TRUE) != 0))) ) { + restartPreviewRequired = setVideoModeParameters(mParameters); + } + + if (restartPreviewRequired) { + { + android::AutoMutex lock(mLock); + mCapModeBackup = mParameters.get(TICameraParameters::KEY_CAP_MODE); + } + ret = restartPreview(); + } + + if ( NO_ERROR == ret ) + { + int count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)); + mParameters.getPreviewSize(&w, &h); + CAMHAL_LOGDB("%s Video Width=%d Height=%d", __FUNCTION__, mVideoWidth, mVideoHeight); + + if ((w != mVideoWidth) && (h != mVideoHeight)) + { + ret = allocVideoBufs(mVideoWidth, mVideoHeight, count); + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret); + mParameters.remove(TICameraParameters::KEY_RECORDING_HINT); + return ret; + } + + mAppCallbackNotifier->useVideoBuffers(true); + mAppCallbackNotifier->setVideoRes(mVideoWidth, mVideoHeight); + ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, mVideoBuffers); + } + else + { + mAppCallbackNotifier->useVideoBuffers(false); + mAppCallbackNotifier->setVideoRes(mPreviewWidth, mPreviewHeight); + ret = mAppCallbackNotifier->initSharedVideoBuffers(mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, count, NULL); + } + } + + if ( NO_ERROR == ret ) + { + ret = mAppCallbackNotifier->startRecording(); + } + + if ( NO_ERROR == ret ) + { + ///Buffers for video capture (if different from preview) are expected to be allocated within CameraAdapter + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_VIDEO); + } + + if ( NO_ERROR == ret ) + { + mRecordingEnabled = true; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Set the camera parameters specific to Video Recording. + + This function checks for the camera parameters which have to be set for recording. + Video Recording needs CAPTURE_MODE to be VIDEO_MODE. This function sets it. + This function also enables Video Recording specific functions like VSTAB & VNF. + + @param none + @return true if preview needs to be restarted for VIDEO_MODE parameters to take effect. + @todo Modify the policies for enabling VSTAB & VNF usecase based later. + + */ +bool CameraHal::setVideoModeParameters(const android::CameraParameters& params) +{ + const char *valstr = NULL; + const char *valstrRemote = NULL; + bool restartPreviewRequired = false; + + LOG_FUNCTION_NAME; + + // Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview + valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE); + if ( (valstr == NULL) || + ( (valstr != NULL) && ( (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE) != 0) && + (strcmp(valstr, (const char *) TICameraParameters::VIDEO_MODE_HQ ) != 0) ) ) ) { + CAMHAL_LOGDA("Set CAPTURE_MODE to VIDEO_MODE"); + mParameters.set(TICameraParameters::KEY_CAP_MODE, (const char *) TICameraParameters::VIDEO_MODE); + restartPreviewRequired = true; + } + + // set VSTAB, restart is required if VSTAB value has changed + int prevWidth, prevHeight; + params.getPreviewSize(&prevWidth, &prevHeight); + valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION); + if (prevWidth == 1920 && + (mSocFamily == SocFamily_Omap4430 || mSocFamily == SocFamily_Omap4460)) { + // forcibly set to false because of not enough memory for needed buffer size in this case + CAMHAL_LOGDA("Forcing VSTAB off"); + if (strcmp(valstr, android::CameraParameters::FALSE) != 0) { + restartPreviewRequired = true; + } + mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, + android::CameraParameters::FALSE); + } else { + if ((valstrRemote = params.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) != NULL) { + // make sure we support vstab + if (strcmp(mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED), + android::CameraParameters::TRUE) == 0) { + if (strcmp(valstr, valstrRemote) != 0) { + restartPreviewRequired = true; + } + mParameters.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, + valstrRemote); + } + } else if (mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION)) { + // vstab was configured but now unset + restartPreviewRequired = true; + mParameters.remove(android::CameraParameters::KEY_VIDEO_STABILIZATION); + } + } + + // Set VNF + if ((valstrRemote = params.get(TICameraParameters::KEY_VNF)) == NULL) { + CAMHAL_LOGDA("Enable VNF"); + mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE); + restartPreviewRequired = true; + } else { + valstr = mParameters.get(TICameraParameters::KEY_VNF); + if (valstr && strcmp(valstr, valstrRemote) != 0) { + restartPreviewRequired = true; + } + mParameters.set(TICameraParameters::KEY_VNF, valstrRemote); + } + +#if !defined(OMAP_ENHANCEMENT) && !defined(ENHANCED_DOMX) + // For VSTAB alone for 1080p resolution, padded width goes > 2048, which cannot be rendered by GPU. + // In such case, there is support in Ducati for combination of VSTAB & VNF requiring padded width < 2048. + // So we are forcefully enabling VNF, if VSTAB is enabled for 1080p resolution. + int w, h; + params.getPreviewSize(&w, &h); + valstr = mParameters.get(android::CameraParameters::KEY_VIDEO_STABILIZATION); + if (valstr && (strcmp(valstr, android::CameraParameters::TRUE) == 0) && (w == 1920)) { + CAMHAL_LOGDA("Force Enable VNF for 1080p"); + const char *valKeyVnf = mParameters.get(TICameraParameters::KEY_VNF); + if(!valKeyVnf || (strcmp(valKeyVnf, android::CameraParameters::TRUE) != 0)) { + mParameters.set(TICameraParameters::KEY_VNF, android::CameraParameters::TRUE); + restartPreviewRequired = true; + } + } +#endif + + LOG_FUNCTION_NAME_EXIT; + + return restartPreviewRequired; +} + +/** + @brief Reset the camera parameters specific to Video Recording. + + This function resets CAPTURE_MODE and disables Recording specific functions like VSTAB & VNF. + + @param none + @return true if preview needs to be restarted for VIDEO_MODE parameters to take effect. + + */ +bool CameraHal::resetVideoModeParameters() +{ + const char *valstr = NULL; + bool restartPreviewRequired = false; + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + // ignore this if we are already recording + if (mRecordingEnabled) { + return false; + } + + // Set CAPTURE_MODE to VIDEO_MODE, if not set already and Restart Preview + valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE); + if ((valstr != NULL) && (strcmp(valstr, TICameraParameters::VIDEO_MODE) == 0)) { + CAMHAL_LOGDA("Reset Capture-Mode to default"); + mParameters.set(TICameraParameters::KEY_CAP_MODE, ""); + restartPreviewRequired = true; + } + + LOG_FUNCTION_NAME_EXIT; + + return restartPreviewRequired; +} + +/** + @brief Restart the preview with setParameter. + + This function restarts preview, for some VIDEO_MODE parameters to take effect. + + @param none + @return NO_ERROR If recording parameters could be set without any issues + + */ +status_t CameraHal::restartPreview() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + // Retain CAPTURE_MODE before calling stopPreview(), since it is reset in stopPreview(). + + forceStopPreview(); + + { + android::AutoMutex lock(mLock); + if (!mCapModeBackup.isEmpty()) { + mParameters.set(TICameraParameters::KEY_CAP_MODE, mCapModeBackup.string()); + } else { + mParameters.set(TICameraParameters::KEY_CAP_MODE, ""); + } + mCameraAdapter->setParameters(mParameters); + } + + ret = startPreview(); + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Stop a previously started recording. + + @param none + @return none + + */ +void CameraHal::stopRecording() +{ + CameraAdapter::AdapterState currentState; + + LOG_FUNCTION_NAME; + + android::AutoMutex lock(mLock); + + if (!mRecordingEnabled ) + { + return; + } + + currentState = mCameraAdapter->getState(); + if (currentState == CameraAdapter::VIDEO_CAPTURE_STATE) { + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE); + } + + mAppCallbackNotifier->stopRecording(); + + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_VIDEO); + + mRecordingEnabled = false; + + if ( mAppCallbackNotifier->getUesVideoBuffers() ){ + freeVideoBufs(mVideoBuffers); + if (mVideoBuffers){ + CAMHAL_LOGVB(" FREEING mVideoBuffers %p", mVideoBuffers); + delete [] mVideoBuffers; + } + mVideoBuffers = NULL; + } + + // reset internal recording hint in case camera adapter needs to make some + // decisions....(will only be sent to camera adapter if camera restart is required) + mParameters.remove(TICameraParameters::KEY_RECORDING_HINT); + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Returns true if recording is enabled. + + @param none + @return true If recording is currently running + false If recording has been stopped + + */ +int CameraHal::recordingEnabled() +{ + LOG_FUNCTION_NAME; + + LOG_FUNCTION_NAME_EXIT; + + return mRecordingEnabled; +} + +/** + @brief Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME. + + @param[in] mem MemoryBase pointer to the frame being released. Must be one of the buffers + previously given by CameraHal + @return none + + */ +void CameraHal::releaseRecordingFrame(const void* mem) +{ + LOG_FUNCTION_NAME; + + //CAMHAL_LOGDB(" 0x%x", mem->pointer()); + + if ( ( mRecordingEnabled ) && mem != NULL) + { + mAppCallbackNotifier->releaseRecordingFrame(mem); + } + + LOG_FUNCTION_NAME_EXIT; + + return; +} + +/** + @brief Start auto focus + + This call asynchronous. + The notification callback routine is called with CAMERA_MSG_FOCUS once when + focusing is complete. autoFocus() will be called again if another auto focus is + needed. + + @param none + @return NO_ERROR + @todo Define the error codes if the focus is not locked + + */ +status_t CameraHal::autoFocus() +{ + status_t ret = NO_ERROR; + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + gettimeofday(&mStartFocus, NULL); + +#endif + + LOG_FUNCTION_NAME; + + android::AutoMutex lock(mLock); + + mMsgEnabled |= CAMERA_MSG_FOCUS; + + if ( NULL == mCameraAdapter ) + { + ret = -1; + goto EXIT; + } + + CameraAdapter::AdapterState state; + ret = mCameraAdapter->getState(state); + if (ret != NO_ERROR) + { + goto EXIT; + } + + if ((state == CameraAdapter::AF_STATE) || (state == CameraAdapter::VIDEO_AF_STATE)) + { + CAMHAL_LOGI("Ignoring start-AF (already in progress)"); + goto EXIT; + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //pass the autoFocus timestamp along with the command to camera adapter + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS, ( int ) &mStartFocus); + +#else + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_PERFORM_AUTOFOCUS); + +#endif + +EXIT: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Cancels auto-focus function. + + If the auto-focus is still in progress, this function will cancel it. + Whether the auto-focus is in progress or not, this function will return the + focus position to the default. If the camera does not support auto-focus, this is a no-op. + + + @param none + @return NO_ERROR If the cancel succeeded + @todo Define error codes if cancel didnt succeed + + */ +status_t CameraHal::cancelAutoFocus() +{ + LOG_FUNCTION_NAME; + + android::AutoMutex lock(mLock); + android::CameraParameters adapterParams = mParameters; + mMsgEnabled &= ~CAMERA_MSG_FOCUS; + + if( NULL != mCameraAdapter ) + { + adapterParams.set(TICameraParameters::KEY_AUTO_FOCUS_LOCK, android::CameraParameters::FALSE); + mCameraAdapter->setParameters(adapterParams); + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_CANCEL_AUTOFOCUS); + mAppCallbackNotifier->flushEventQueue(); + } + + LOG_FUNCTION_NAME_EXIT; + return NO_ERROR; +} + +void CameraHal::setEventProvider(int32_t eventMask, MessageNotifier * eventNotifier) +{ + + LOG_FUNCTION_NAME; + + if ( NULL != mEventProvider ) + { + mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS); + delete mEventProvider; + mEventProvider = NULL; + } + + mEventProvider = new EventProvider(eventNotifier, this, eventCallbackRelay); + if ( NULL == mEventProvider ) + { + CAMHAL_LOGEA("Error in creating EventProvider"); + } + else + { + mEventProvider->enableEventNotification(eventMask); + } + + LOG_FUNCTION_NAME_EXIT; +} + +void CameraHal::eventCallbackRelay(CameraHalEvent* event) +{ + LOG_FUNCTION_NAME; + + CameraHal *appcbn = ( CameraHal * ) (event->mCookie); + appcbn->eventCallback(event ); + + LOG_FUNCTION_NAME_EXIT; +} + +void CameraHal::eventCallback(CameraHalEvent* event) +{ + LOG_FUNCTION_NAME; + + LOG_FUNCTION_NAME_EXIT; +} + +status_t CameraHal::startImageBracketing() +{ + status_t ret = NO_ERROR; + CameraFrame frame; + CameraAdapter::BuffersDescriptor desc; + unsigned int max_queueable = 0; + + + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + gettimeofday(&mStartCapture, NULL); + +#endif + + LOG_FUNCTION_NAME; + + if(!previewEnabled() && !mDisplayPaused) + { + LOG_FUNCTION_NAME_EXIT; + return NO_INIT; + } + + if ( !mBracketingEnabled ) + { + return ret; + } + + if ( NO_ERROR == ret ) + { + mBracketingRunning = true; + } + + if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) ) + { + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE, + ( int ) &frame, + ( mBracketRangeNegative + 1 )); + + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret); + } + } + + if ( NO_ERROR == ret ) + { + if ( NULL != mAppCallbackNotifier.get() ) + { + mAppCallbackNotifier->setBurst(true); + } + } + + if ( NO_ERROR == ret ) + { + mParameters.getPictureSize(( int * ) &frame.mWidth, + ( int * ) &frame.mHeight); + + ret = allocImageBufs(frame.mWidth, + frame.mHeight, + frame.mLength, + mParameters.getPictureFormat(), + ( mBracketRangeNegative + 1 )); + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret); + } + } + + if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) ) + { + + desc.mBuffers = mImageBuffers; + desc.mOffsets = mImageOffsets; + desc.mFd = mImageFd; + desc.mLength = mImageLength; + desc.mCount = ( size_t ) ( mBracketRangeNegative + 1 ); + desc.mMaxQueueable = ( size_t ) ( mBracketRangeNegative + 1 ); + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE, + ( int ) &desc); + + if ( NO_ERROR == ret ) + { + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //pass capture timestamp along with the camera adapter command + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 ), (int) &mStartCapture); + +#else + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_BRACKET_CAPTURE, ( mBracketRangePositive + 1 )); + +#endif + + } + } + + return ret; +} + +status_t CameraHal::stopImageBracketing() +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if( !previewEnabled() ) + { + return NO_INIT; + } + + mBracketingRunning = false; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE); + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Take a picture. + + @param none + @return NO_ERROR If able to switch to image capture + @todo Define error codes if unable to switch to image capture + + */ +status_t CameraHal::takePicture(const char *params) +{ + // cancel AF state if needed (before any operation and mutex lock) + if ((mCameraAdapter->getState() == CameraAdapter::AF_STATE) || + (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE)) { + cancelAutoFocus(); + } + + android::AutoMutex lock(mLock); + return __takePicture(params); +} + +/** + @brief Internal function for getting a captured image. + shared by takePicture and reprocess. + @param none + @return NO_ERROR If able to switch to image capture + @todo Define error codes if unable to switch to image capture + + */ +status_t CameraHal::__takePicture(const char *params, struct timeval *captureStart) +{ + status_t ret = NO_ERROR; + CameraFrame frame; + CameraAdapter::BuffersDescriptor desc; + int burst = -1; + const char *valstr = NULL; + unsigned int bufferCount = 1; + unsigned int max_queueable = 0; + unsigned int rawBufferCount = 1; + bool isCPCamMode = false; + android::sp outAdapter = 0; + bool reuseTapout = false; +#ifdef MOTOROLA_CAMERA + unsigned int intensity = DEFAULT_INTENSITY; +#endif + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + if ( NULL == captureStart ) { + gettimeofday(&mStartCapture, NULL); + } else { + memcpy(&mStartCapture, captureStart, sizeof(struct timeval)); + } + +#endif + + LOG_FUNCTION_NAME; + + if(!previewEnabled() && !mDisplayPaused) + { + LOG_FUNCTION_NAME_EXIT; + CAMHAL_LOGEA("Preview not started..."); + return NO_INIT; + } + + valstr = mParameters.get(TICameraParameters::KEY_CAP_MODE); + + isCPCamMode = valstr && !strcmp(valstr, TICameraParameters::CP_CAM_MODE); + + // return error if we are already capturing + // however, we can queue a capture when in cpcam mode + if ( ((mCameraAdapter->getState() == CameraAdapter::CAPTURE_STATE && + mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) || + (mCameraAdapter->getState() == CameraAdapter::VIDEO_CAPTURE_STATE && + mCameraAdapter->getNextState() != CameraAdapter::VIDEO_STATE)) && + !isCPCamMode) { + CAMHAL_LOGEA("Already capturing an image..."); + return NO_INIT; + } + + // we only support video snapshot if we are in video mode (recording hint is set) + if ( (mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) && + (valstr && ( strcmp(valstr, TICameraParameters::VIDEO_MODE) && + strcmp(valstr, TICameraParameters::VIDEO_MODE_HQ ) ) ) ) { + CAMHAL_LOGEA("Trying to capture while recording without recording hint set..."); + return INVALID_OPERATION; + } + +#ifdef OMAP_ENHANCEMENT_CPCAM + // check if camera application is using shots parameters + // api. parameters set here override anything set using setParameters + // TODO(XXX): Just going to use legacy TI parameters for now. Need + // add new APIs in CameraHal to utilize android::ShotParameters later, so + // we don't have to parse through the whole set of parameters + // in camera adapter + if (strlen(params) > 0) { + android::ShotParameters shotParams; + const char *valStr; + const char *valExpComp, *valExpGain; + int valNum; + + android::String8 shotParams8(params); + + shotParams.unflatten(shotParams8); + mParameters.remove(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE); + mParameters.remove(TICameraParameters::KEY_EXP_BRACKETING_RANGE); + + valExpGain = shotParams.get(android::ShotParameters::KEY_EXP_GAIN_PAIRS); + valExpComp = shotParams.get(android::ShotParameters::KEY_EXP_COMPENSATION); + if (NULL != valExpComp) { + mParameters.set(TICameraParameters::KEY_EXP_BRACKETING_RANGE, valExpComp); + } else if (NULL != valExpGain) { + mParameters.set(TICameraParameters::KEY_EXP_GAIN_BRACKETING_RANGE, valExpGain); + } + + valNum = shotParams.getInt(android::ShotParameters::KEY_BURST); + if (valNum >= 0) { + mParameters.set(TICameraParameters::KEY_BURST, valNum); + burst = valNum; + } + + valStr = shotParams.get(android::ShotParameters::KEY_FLUSH_CONFIG); + if (valStr!= NULL) { + if ( 0 == strcmp(valStr, android::ShotParameters::TRUE) ) { + mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE, + android::CameraParameters::TRUE); + } else if ( 0 == strcmp(valStr, android::ShotParameters::FALSE) ) { + mParameters.set(TICameraParameters::KEY_FLUSH_SHOT_CONFIG_QUEUE, + android::CameraParameters::FALSE); + } + } + + valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_OUT); + if (valStr != NULL) { + int index = -1; + for (unsigned int i = 0; i < mOutAdapters.size(); i++) { + if(mOutAdapters.itemAt(i)->match(valStr)) { + index = i; + break; + } + } + if (index < 0) { + CAMHAL_LOGE("Invalid tap out surface passed to camerahal"); + return BAD_VALUE; + } + CAMHAL_LOGD("Found matching out adapter at %d", index); + outAdapter = mOutAdapters.itemAt(index); + if ( outAdapter == mBufferSourceAdapter_Out ) { + reuseTapout = true; + } + } + + mCameraAdapter->setParameters(mParameters); + } else +#endif + { + // TODO(XXX): Should probably reset burst and bracketing params + // when we remove legacy TI parameters implementation + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Takepicture parameters set: ", &mStartCapture); + +#endif + + // if we are already in the middle of a capture and using the same + // tapout ST...then we just need setParameters and start image + // capture to queue more shots + if (((mCameraAdapter->getState() & CameraAdapter::CAPTURE_STATE) == + CameraAdapter::CAPTURE_STATE) && + (mCameraAdapter->getNextState() != CameraAdapter::PREVIEW_STATE) && + (reuseTapout) ) { +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + //pass capture timestamp along with the camera adapter command + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE, + (int) &mStartCapture); +#else + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE); +#endif + return ret; + } + + if ( !mBracketingRunning ) + { + // if application didn't set burst through android::ShotParameters + // then query from TICameraParameters + if ((burst == -1) && (NO_ERROR == ret)) { + burst = mParameters.getInt(TICameraParameters::KEY_BURST); + } + + //Allocate all buffers only in burst capture case + if ( burst > 0 ) { + // For CPCam mode...allocate for worst case burst + bufferCount = isCPCamMode || (burst > CameraHal::NO_BUFFERS_IMAGE_CAPTURE) ? + CameraHal::NO_BUFFERS_IMAGE_CAPTURE : burst; + + if (outAdapter.get()) { + if ( reuseTapout ) { + bufferCount = mImageCount; + } else { + bufferCount = outAdapter->getBufferCount(); + if (bufferCount < 1) { + bufferCount = NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP; + } + } + } + + if ( NULL != mAppCallbackNotifier.get() ) { + mAppCallbackNotifier->setBurst(true); + } + } else if ( mBracketingEnabled ) { + bufferCount = mBracketRangeNegative + 1; + if ( NULL != mAppCallbackNotifier.get() ) { + mAppCallbackNotifier->setBurst(false); + } + } else { + if ( NULL != mAppCallbackNotifier.get() ) { + mAppCallbackNotifier->setBurst(false); + } + } + + // pause preview during normal image capture + // do not pause preview if recording (video state) + if ( (NO_ERROR == ret) && (NULL != mDisplayAdapter.get()) ) { + if ((mCameraAdapter->getState() != CameraAdapter::VIDEO_STATE) && + (mCameraAdapter->getState() != CameraAdapter::VIDEO_AF_STATE)) { + mDisplayPaused = true; + mPreviewEnabled = false; + ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); + // since preview is paused we should stop sending preview frames too + if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { + mAppCallbackNotifier->disableMsgType (CAMERA_MSG_PREVIEW_FRAME); + } + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + mDisplayAdapter->setSnapshotTimeRef(&mStartCapture); +#endif + } + + // if we taking video snapshot... + if ((NO_ERROR == ret) && ((mCameraAdapter->getState() == CameraAdapter::VIDEO_STATE) || + (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE))) { + // enable post view frames if not already enabled so we can internally + // save snapshot frames for generating thumbnail + if((mMsgEnabled & CAMERA_MSG_POSTVIEW_FRAME) == 0) { + mAppCallbackNotifier->enableMsgType(CAMERA_MSG_POSTVIEW_FRAME); + } + } + + if ( (NO_ERROR == ret) && (NULL != mCameraAdapter) ) + { +#ifdef MOTOROLA_CAMERA + intensity = getFlashIntensity(); + + if (intensity == 0) + { + //notification callback can be triggered with this to inform user + mParameters.set(android::CameraParameters::KEY_FLASH_MODE, android::CameraParameters::FLASH_MODE_OFF); + } + else if (intensity <= DEFAULT_INTENSITY) + { + mParameters.set(TICameraParameters::KEY_MOT_LEDFLASH, (int) intensity); + mParameters.set(TICameraParameters::KEY_MOT_LEDTORCH, (int) intensity); + } +#endif + + if ( NO_ERROR == ret ) + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE, + ( int ) &frame, + bufferCount); + + if ( NO_ERROR != ret ) + { + CAMHAL_LOGEB("CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE returned error 0x%x", ret); + } + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Takepicture buffer size queried: ", &mStartCapture); + +#endif + + if (outAdapter.get()) { + // Avoid locking the tapout again when reusing it + if (!reuseTapout) { + // Need to reset buffers if we are switching adapters since we don't know + // the state of the new buffer list + ret = outAdapter->maxQueueableBuffers(max_queueable); + if (NO_ERROR != ret) { + CAMHAL_LOGE("Couldn't get max queuable"); + return ret; + } + mImageBuffers = outAdapter->getBuffers(true); + mImageOffsets = outAdapter->getOffsets(); + mImageFd = outAdapter->getFd(); + mImageLength = outAdapter->getSize(); + mImageCount = bufferCount; + mBufferSourceAdapter_Out = outAdapter; + } + } else { + mBufferSourceAdapter_Out.clear(); + // allocImageBufs will only allocate new buffers if mImageBuffers is NULL + if ( NO_ERROR == ret ) { + max_queueable = bufferCount; + ret = allocImageBufs(frame.mAlignment / getBPP(mParameters.getPictureFormat()), + frame.mHeight, + frame.mLength, + mParameters.getPictureFormat(), + bufferCount); + if ( NO_ERROR != ret ) { + CAMHAL_LOGEB("allocImageBufs returned error 0x%x", ret); + } + } + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Takepicture buffers allocated: ", &mStartCapture); + memcpy(&mImageBuffers->ppmStamp, &mStartCapture, sizeof(struct timeval)); + +#endif + + if ( (NO_ERROR == ret) && ( NULL != mCameraAdapter ) ) + { + desc.mBuffers = mImageBuffers; + desc.mOffsets = mImageOffsets; + desc.mFd = mImageFd; + desc.mLength = mImageLength; + desc.mCount = ( size_t ) bufferCount; + desc.mMaxQueueable = ( size_t ) max_queueable; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE, + ( int ) &desc); + } + if (mRawCapture) { + if ( NO_ERROR == ret ) { + CAMHAL_LOGDB("Raw capture buffers setup - %s", mParameters.getPictureFormat()); + ret = allocRawBufs(mParameters.getInt(TICameraParameters::RAW_WIDTH), + mParameters.getInt(TICameraParameters::RAW_HEIGHT), + android::CameraParameters::PIXEL_FORMAT_BAYER_RGGB, + rawBufferCount); + + if ( NO_ERROR != ret ) { + CAMHAL_LOGEB("allocRawBufs (for RAW capture) returned error 0x%x", ret); + } + } + + if ((NO_ERROR == ret) && ( NULL != mCameraAdapter )) { + desc.mBuffers = mVideoBuffers; + desc.mOffsets = mVideoOffsets; + desc.mFd = mVideoFd; + desc.mLength = mVideoLength; + desc.mCount = ( size_t ) rawBufferCount; + desc.mMaxQueueable = ( size_t ) rawBufferCount; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE, + ( int ) &desc); + } + } + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Takepicture buffers registered: ", &mStartCapture); + +#endif + + if ((ret == NO_ERROR) && mBufferSourceAdapter_Out.get()) { + mBufferSourceAdapter_Out->enableDisplay(0, 0, NULL); + } + + if ((NO_ERROR == ret) && (NULL != mCameraAdapter)) { + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //pass capture timestamp along with the camera adapter command + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE, (int) &mStartCapture); + + CameraHal::PPM("Takepicture capture started: ", &mStartCapture); + +#else + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_IMAGE_CAPTURE); + +#endif + + } + + return ret; +} + +/** + @brief Cancel a picture that was started with takePicture. + + Calling this method when no picture is being taken is a no-op. + + @param none + @return NO_ERROR If cancel succeeded. Cancel can succeed if image callback is not sent + @todo Define error codes + + */ +status_t CameraHal::cancelPicture( ) +{ + LOG_FUNCTION_NAME; + status_t ret = NO_ERROR; + + ret = signalEndImageCapture(); + return NO_ERROR; +} + +/** + @brief Return the camera parameters. + + @param none + @return Currently configured camera parameters + + */ +char* CameraHal::getParameters() +{ + android::String8 params_str8; + char* params_string; + const char * valstr = NULL; + + LOG_FUNCTION_NAME; + + if( NULL != mCameraAdapter ) + { + mCameraAdapter->getParameters(mParameters); + } + + if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT)) != NULL ) { + if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES)); + } else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES)); + } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr)) + || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES)); + } + } + + if ( (valstr = mParameters.get(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT)) != NULL ) { + if (!strcmp(TICameraParameters::S3D_TB_FULL, valstr)) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES)); + } else if (!strcmp(TICameraParameters::S3D_SS_FULL, valstr)) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES)); + } else if ((!strcmp(TICameraParameters::S3D_TB_SUBSAMPLED, valstr)) + || (!strcmp(TICameraParameters::S3D_SS_SUBSAMPLED, valstr))) { + mParameters.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mParameters.get(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES)); + } + } + + android::CameraParameters mParams = mParameters; + + // Handle RECORDING_HINT to Set/Reset Video Mode Parameters + valstr = mParameters.get(android::CameraParameters::KEY_RECORDING_HINT); + if(valstr != NULL) + { + if(strcmp(valstr, android::CameraParameters::TRUE) == 0) + { + //HACK FOR MMS MODE + resetPreviewRes(&mParams); + } + } + + // do not send internal parameters to upper layers + mParams.remove(TICameraParameters::KEY_RECORDING_HINT); + mParams.remove(TICameraParameters::KEY_AUTO_FOCUS_LOCK); + + params_str8 = mParams.flatten(); + + // camera service frees this string... + params_string = (char*) malloc(sizeof(char) * (params_str8.length()+1)); + strcpy(params_string, params_str8.string()); + + LOG_FUNCTION_NAME_EXIT; + + ///Return the current set of parameters + + return params_string; +} + + +#ifdef OMAP_ENHANCEMENT_CPCAM +/** + @brief Starts reprocessing operation. + */ +status_t CameraHal::reprocess(const char *params) +{ + status_t ret = NO_ERROR; + int bufferCount = 0; + CameraAdapter::BuffersDescriptor desc; + CameraBuffer *reprocBuffers = NULL; + android::ShotParameters shotParams; + const char *valStr = NULL; + struct timeval startReprocess; + + android::AutoMutex lock(mLock); + + LOG_FUNCTION_NAME; + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + gettimeofday(&startReprocess, NULL); + +#endif + + // 0. Get tap in surface + if (strlen(params) > 0) { + android::String8 shotParams8(params); + shotParams.unflatten(shotParams8); + } + + valStr = shotParams.get(android::ShotParameters::KEY_CURRENT_TAP_IN); + if (valStr != NULL) { + int index = -1; + for (unsigned int i = 0; i < mInAdapters.size(); i++) { + if(mInAdapters.itemAt(i)->match(valStr)) { + index = i; + break; + } + } + if (index < 0) { + CAMHAL_LOGE("Invalid tap in surface passed to camerahal"); + return BAD_VALUE; + } + CAMHAL_LOGD("Found matching in adapter at %d", index); + mBufferSourceAdapter_In = mInAdapters.itemAt(index); + } else { + CAMHAL_LOGE("No tap in surface sent with shot config!"); + return BAD_VALUE; + } + + // 1. Get buffers + if (mBufferSourceAdapter_In.get()) { + reprocBuffers = mBufferSourceAdapter_In->getBufferList(&bufferCount); + } + + if (!reprocBuffers) { + CAMHAL_LOGE("Error: couldn't get input buffers for reprocess()"); + goto exit; + } + + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Got reprocess buffers: ", &startReprocess); + +#endif + + // 2. Get buffer information and parse parameters + { + shotParams.setBurst(bufferCount); + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + memcpy(&reprocBuffers->ppmStamp, &startReprocess, sizeof(struct timeval)); + +#endif + + // 3. Give buffer to camera adapter + desc.mBuffers = reprocBuffers; + desc.mOffsets = 0; + desc.mFd = 0; + desc.mLength = 0; + desc.mCount = (size_t) bufferCount; + desc.mMaxQueueable = (size_t) bufferCount; + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS, (int) &desc); + if (ret != NO_ERROR) { + CAMHAL_LOGE("Error calling camera use buffers"); + goto exit; + } + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + CameraHal::PPM("Reprocess buffers registered: ", &startReprocess); + +#endif + + // 4. Start reprocessing + ret = mBufferSourceAdapter_In->enableDisplay(0, 0, NULL); + if (ret != NO_ERROR) { + CAMHAL_LOGE("Error enabling tap in point"); + goto exit; + } + + // 4.5. cancel AF state if needed (before any operation and mutex lock) + if ((mCameraAdapter->getState() == CameraAdapter::AF_STATE) || + (mCameraAdapter->getState() == CameraAdapter::VIDEO_AF_STATE)) { + cancelAutoFocus(); + } + + // 5. Start capturing + ret = __takePicture(shotParams.flatten().string(), &startReprocess); + +exit: + return ret; +} + +/** + @brief Cancels current reprocessing operation + + */ +status_t CameraHal::cancel_reprocess( ) +{ + LOG_FUNCTION_NAME; + status_t ret = NO_ERROR; + + ret = signalEndImageCapture(); + return NO_ERROR; +} +#endif + + +void CameraHal::putParameters(char *parms) +{ + free(parms); +} + +/** + @brief Send command to camera driver. + + @param none + @return NO_ERROR If the command succeeds + @todo Define the error codes that this function can return + + */ +status_t CameraHal::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) +{ + status_t ret = NO_ERROR; + + LOG_FUNCTION_NAME; + + if ( ( NO_ERROR == ret ) && ( NULL == mCameraAdapter ) ) + { + CAMHAL_LOGEA("No CameraAdapter instance"); + return -EINVAL; + } + + /////////////////////////////////////////////////////// + // Following commands NEED preview to be started + /////////////////////////////////////////////////////// + + if ((!previewEnabled()) && ((cmd == CAMERA_CMD_START_SMOOTH_ZOOM) + || (cmd == CAMERA_CMD_STOP_SMOOTH_ZOOM) + || (cmd == CAMERA_CMD_START_FACE_DETECTION) +#ifdef OMAP_ENHANCEMENT_VTC + || (cmd == CAMERA_CMD_PREVIEW_DEINITIALIZATION) +#endif + )) + { + CAMHAL_LOGEA("sendCommand with cmd = 0x%x need preview to be started", cmd); + return BAD_VALUE; + } + + if ( NO_ERROR == ret ) + { + switch(cmd) + { + case CAMERA_CMD_START_SMOOTH_ZOOM: + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_SMOOTH_ZOOM, arg1); + + break; + + case CAMERA_CMD_STOP_SMOOTH_ZOOM: + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM); + + break; + + case CAMERA_CMD_START_FACE_DETECTION: + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_FD); + + break; + + case CAMERA_CMD_STOP_FACE_DETECTION: + if (previewEnabled()) { + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD); + } + + break; + +#ifdef OMAP_ENHANCEMENT_VTC + case CAMERA_CMD_PREVIEW_DEINITIALIZATION: + if(mDisplayAdapter.get() != NULL) { + ///Stop the buffer display first + mDisplayAdapter->disableDisplay(); + } + + if(mAppCallbackNotifier.get() != NULL) { + //Stop the callback sending + mAppCallbackNotifier->stop(); + mAppCallbackNotifier->flushAndReturnFrames(); + mAppCallbackNotifier->stopPreviewCallbacks(); + } + + ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_DESTROY_TUNNEL); + mTunnelSetup = false; + + break; + + case CAMERA_CMD_PREVIEW_INITIALIZATION: + ret = cameraPreviewInitialization(); + + break; +#endif + +#ifdef ANDROID_API_JB_OR_LATER + case CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG: + { + const bool enable = static_cast(arg1); + android::AutoMutex lock(mLock); + if ( enable ) { + mMsgEnabled |= CAMERA_MSG_FOCUS_MOVE; + } else { + mMsgEnabled &= ~CAMERA_MSG_FOCUS_MOVE; + } + break; + } +#endif + + default: + break; + }; + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +/** + @brief Release the hardware resources owned by this object. + + Note that this is *not* done in the destructor. + + @param none + @return none + + */ +void CameraHal::release() +{ + LOG_FUNCTION_NAME; + ///@todo Investigate on how release is used by CameraService. Vaguely remember that this is called + ///just before CameraHal object destruction + deinitialize(); + LOG_FUNCTION_NAME_EXIT; +} + + +/** + @brief Dump state of the camera hardware + + @param[in] fd File descriptor + @param[in] args Arguments + @return NO_ERROR Dump succeeded + @todo Error codes for dump fail + + */ +status_t CameraHal::dump(int fd) const +{ + LOG_FUNCTION_NAME; + ///Implement this method when the h/w dump function is supported on Ducati side + return NO_ERROR; +} + +/*-------------Camera Hal Interface Method definitions ENDS here--------------------*/ + + + + +/*-------------Camera Hal Internal Method definitions STARTS here--------------------*/ + +/** + @brief Constructor of CameraHal + + Member variables are initialized here. No allocations should be done here as we + don't use c++ exceptions in the code. + + */ +CameraHal::CameraHal(int cameraId) + : mSocFamily(getSocFamily()) +{ + LOG_FUNCTION_NAME; + + ///Initialize all the member variables to their defaults + mPreviewEnabled = false; + mPreviewBuffers = NULL; + mImageBuffers = NULL; + mBufProvider = NULL; + mPreviewStartInProgress = false; + mVideoBuffers = NULL; + mVideoBufProvider = NULL; + mRecordingEnabled = false; + mDisplayPaused = false; + mSetPreviewWindowCalled = false; + mMsgEnabled = 0; + mAppCallbackNotifier = NULL; + mMemoryManager = NULL; + mCameraAdapter = NULL; + mBracketingEnabled = false; + mBracketingRunning = false; + mEventProvider = NULL; + mBracketRangePositive = 1; + mBracketRangeNegative = 1; + mMaxZoomSupported = 0; + mShutterEnabled = true; + mMeasurementEnabled = false; + mPreviewDataBuffers = NULL; + mCameraProperties = NULL; + mCurrentTime = 0; + mFalsePreview = 0; + mImageOffsets = NULL; + mImageLength = 0; + mImageFd = 0; + mImageCount = 0; + mVideoOffsets = NULL; + mVideoFd = 0; + mVideoLength = 0; + mPreviewDataOffsets = NULL; + mPreviewDataFd = 0; + mPreviewDataLength = 0; + mPreviewFd = 0; + mPreviewWidth = 0; + mPreviewHeight = 0; + mPreviewLength = 0; + mPreviewOffsets = NULL; + mPreviewRunning = 0; + mPreviewStateOld = 0; + mRecordingEnabled = 0; + mRecordEnabled = 0; + mSensorListener = NULL; + mVideoWidth = 0; + mVideoHeight = 0; +#ifdef OMAP_ENHANCEMENT_VTC + mVTCUseCase = false; + mTunnelSetup = false; +#endif + mPreviewInitializationDone = false; + +#ifdef OMAP_ENHANCEMENT_CPCAM + mExtendedPreviewStreamOps = 0; +#endif + + //These values depends on the sensor characteristics + + mRawCapture = false; + +#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS + + //Initialize the CameraHAL constructor timestamp, which is used in the + // PPM() method as time reference if the user does not supply one. + gettimeofday(&ppm_start, NULL); + +#endif + + mCameraIndex = cameraId; + + mExternalLocking = false; + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Destructor of CameraHal + + This function simply calls deinitialize() to free up memory allocate during construct + phase + */ +CameraHal::~CameraHal() +{ + LOG_FUNCTION_NAME; + + ///Call de-initialize here once more - it is the last chance for us to relinquish all the h/w and s/w resources + deinitialize(); + + if ( NULL != mEventProvider ) + { + mEventProvider->disableEventNotification(CameraHalEvent::ALL_EVENTS); + delete mEventProvider; + mEventProvider = NULL; + } + + /// Free the callback notifier + mAppCallbackNotifier.clear(); + + /// Free the display adapter + mDisplayAdapter.clear(); + + if ( NULL != mCameraAdapter ) { + int strongCount = mCameraAdapter->getStrongCount(); + + mCameraAdapter->decStrong(mCameraAdapter); + + mCameraAdapter = NULL; + } + + freeImageBufs(); + freeRawBufs(); + + /// Free the memory manager + mMemoryManager.clear(); + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Initialize the Camera HAL + + Creates CameraAdapter, AppCallbackNotifier, DisplayAdapter and MemoryManager + + @param None + @return NO_ERROR - On success + NO_MEMORY - On failure to allocate memory for any of the objects + @remarks Camera Hal internal function + + */ + +status_t CameraHal::initialize(CameraProperties::Properties* properties) +{ + LOG_FUNCTION_NAME; + + int sensor_index = 0; + const char* sensor_name = NULL; + + ///Initialize the event mask used for registering an event provider for AppCallbackNotifier + ///Currently, registering all events as to be coming from CameraAdapter + int32_t eventMask = CameraHalEvent::ALL_EVENTS; + + // Get my camera properties + mCameraProperties = properties; + + if(!mCameraProperties) + { + goto fail_loop; + } + + // Dump the properties of this Camera + // will only print if DEBUG macro is defined + mCameraProperties->dump(); + + if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX)) != 0 ) + { + sensor_index = atoi(mCameraProperties->get(CameraProperties::CAMERA_SENSOR_INDEX)); + } + + if (strcmp(CameraProperties::DEFAULT_VALUE, mCameraProperties->get(CameraProperties::CAMERA_NAME)) != 0 ) { + sensor_name = mCameraProperties->get(CameraProperties::CAMERA_NAME); + } + CAMHAL_LOGDB("Sensor index= %d; Sensor name= %s", sensor_index, sensor_name); + + if (strcmp(sensor_name, V4L_CAMERA_NAME_USB) == 0) { +#ifdef V4L_CAMERA_ADAPTER + mCameraAdapter = V4LCameraAdapter_Factory(sensor_index, this); +#endif + } + else { +#ifdef OMX_CAMERA_ADAPTER + mCameraAdapter = OMXCameraAdapter_Factory(sensor_index); +#endif + } + + if ( ( NULL == mCameraAdapter ) || (mCameraAdapter->initialize(properties)!=NO_ERROR)) + { + CAMHAL_LOGEA("Unable to create or initialize CameraAdapter"); + mCameraAdapter = NULL; + goto fail_loop; + } + + mCameraAdapter->incStrong(mCameraAdapter); + mCameraAdapter->registerImageReleaseCallback(releaseImageBuffers, (void *) this); + mCameraAdapter->registerEndCaptureCallback(endImageCapture, (void *)this); + + if(!mAppCallbackNotifier.get()) + { + /// Create the callback notifier + mAppCallbackNotifier = new AppCallbackNotifier(); + if( ( NULL == mAppCallbackNotifier.get() ) || ( mAppCallbackNotifier->initialize() != NO_ERROR)) + { + CAMHAL_LOGEA("Unable to create or initialize AppCallbackNotifier"); + goto fail_loop; + } + } + + if(!mMemoryManager.get()) + { + /// Create Memory Manager + mMemoryManager = new MemoryManager(); + if( ( NULL == mMemoryManager.get() ) || ( mMemoryManager->initialize() != NO_ERROR)) + { + CAMHAL_LOGEA("Unable to create or initialize MemoryManager"); + goto fail_loop; + } + } + + ///Setup the class dependencies... + + ///AppCallbackNotifier has to know where to get the Camera frames and the events like auto focus lock etc from. + ///CameraAdapter is the one which provides those events + ///Set it as the frame and event providers for AppCallbackNotifier + ///@remarks setEventProvider API takes in a bit mask of events for registering a provider for the different events + /// That way, if events can come from DisplayAdapter in future, we will be able to add it as provider + /// for any event + mAppCallbackNotifier->setEventProvider(eventMask, mCameraAdapter); + mAppCallbackNotifier->setFrameProvider(mCameraAdapter); + + ///Any dynamic errors that happen during the camera use case has to be propagated back to the application + ///via CAMERA_MSG_ERROR. AppCallbackNotifier is the class that notifies such errors to the application + ///Set it as the error handler for CameraAdapter + mCameraAdapter->setErrorHandler(mAppCallbackNotifier.get()); + + ///Start the callback notifier + if(mAppCallbackNotifier->start() != NO_ERROR) + { + CAMHAL_LOGEA("Couldn't start AppCallbackNotifier"); + goto fail_loop; + } + + CAMHAL_LOGDA("Started AppCallbackNotifier.."); + mAppCallbackNotifier->setMeasurements(mMeasurementEnabled); + + ///Initialize default parameters + initDefaultParameters(); + + + if ( setParameters(mParameters) != NO_ERROR ) + { + CAMHAL_LOGEA("Failed to set default parameters?!"); + } + + // register for sensor events + mSensorListener = new SensorListener(); + if (mSensorListener.get()) { + if (mSensorListener->initialize() == NO_ERROR) { + mSensorListener->setCallbacks(orientation_cb, this); + mSensorListener->enableSensor(SensorListener::SENSOR_ORIENTATION); + } else { + CAMHAL_LOGEA("Error initializing SensorListener. not fatal, continuing"); + mSensorListener.clear(); + mSensorListener = NULL; + } + } + + LOG_FUNCTION_NAME_EXIT; + + return NO_ERROR; + + fail_loop: + + ///Free up the resources because we failed somewhere up + deinitialize(); + LOG_FUNCTION_NAME_EXIT; + + return NO_MEMORY; + +} + +bool CameraHal::isResolutionValid(unsigned int width, unsigned int height, const char *supportedResolutions) +{ + bool ret = false; + status_t status = NO_ERROR; + char tmpBuffer[MAX_PROP_VALUE_LENGTH]; + char *pos = NULL; + + LOG_FUNCTION_NAME; + + if (NULL == supportedResolutions) { + CAMHAL_LOGEA("Invalid supported resolutions string"); + goto exit; + } + + status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%dx%d", width, height); + if (0 > status) { + CAMHAL_LOGEA("Error encountered while generating validation string"); + goto exit; + } + + ret = isParameterValid(tmpBuffer, supportedResolutions); + +exit: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +bool CameraHal::isFpsRangeValid(int fpsMin, int fpsMax, const char *supportedFpsRanges) +{ + bool ret = false; + char supported[MAX_PROP_VALUE_LENGTH]; + char *pos; + int suppFpsRangeArray[2]; + int i = 0; + + LOG_FUNCTION_NAME; + + if ( NULL == supportedFpsRanges ) { + CAMHAL_LOGEA("Invalid supported FPS ranges string"); + return false; + } + + if (fpsMin <= 0 || fpsMax <= 0 || fpsMin > fpsMax) { + return false; + } + + strncpy(supported, supportedFpsRanges, MAX_PROP_VALUE_LENGTH); + pos = strtok(supported, " (,)"); + while (pos != NULL) { + suppFpsRangeArray[i] = atoi(pos); + if (i++) { + if (fpsMin >= suppFpsRangeArray[0] && fpsMax <= suppFpsRangeArray[1]) { + ret = true; + break; + } + i = 0; + } + pos = strtok(NULL, " (,)"); + } + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +bool CameraHal::isParameterValid(const char *param, const char *supportedParams) +{ + bool ret = false; + char *pos; + char supported[MAX_PROP_VALUE_LENGTH]; + + LOG_FUNCTION_NAME; + + if (NULL == supportedParams) { + CAMHAL_LOGEA("Invalid supported parameters string"); + goto exit; + } + + if (NULL == param) { + CAMHAL_LOGEA("Invalid parameter string"); + goto exit; + } + + strncpy(supported, supportedParams, MAX_PROP_VALUE_LENGTH - 1); + + pos = strtok(supported, ","); + while (pos != NULL) { + if (!strcmp(pos, param)) { + ret = true; + break; + } + pos = strtok(NULL, ","); + } + +exit: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +bool CameraHal::isParameterValid(int param, const char *supportedParams) +{ + bool ret = false; + status_t status; + char tmpBuffer[MAX_PROP_VALUE_LENGTH]; + + LOG_FUNCTION_NAME; + + if (NULL == supportedParams) { + CAMHAL_LOGEA("Invalid supported parameters string"); + goto exit; + } + + status = snprintf(tmpBuffer, MAX_PROP_VALUE_LENGTH - 1, "%d", param); + if (0 > status) { + CAMHAL_LOGEA("Error encountered while generating validation string"); + goto exit; + } + + ret = isParameterValid(tmpBuffer, supportedParams); + +exit: + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +status_t CameraHal::doesSetParameterNeedUpdate(const char* new_param, const char* old_param, bool& update) { + if (!new_param || !old_param) { + return -EINVAL; + } + + // if params mismatch we should update parameters for camera adapter + if ((strcmp(new_param, old_param) != 0)) { + update = true; + } + + return NO_ERROR; +} + +status_t CameraHal::parseResolution(const char *resStr, int &width, int &height) +{ + status_t ret = NO_ERROR; + char *ctx, *pWidth, *pHeight; + const char *sep = "x"; + + LOG_FUNCTION_NAME; + + if ( NULL == resStr ) + { + return -EINVAL; + } + + //This fixes "Invalid input resolution" + char *resStr_copy = (char *)malloc(strlen(resStr) + 1); + if ( NULL != resStr_copy ) + { + strcpy(resStr_copy, resStr); + pWidth = strtok_r(resStr_copy, sep, &ctx); + + if ( NULL != pWidth ) + { + width = atoi(pWidth); + } + else + { + CAMHAL_LOGEB("Invalid input resolution %s", resStr); + ret = -EINVAL; + } + } + + if ( NO_ERROR == ret ) + { + pHeight = strtok_r(NULL, sep, &ctx); + + if ( NULL != pHeight ) + { + height = atoi(pHeight); + } + else + { + CAMHAL_LOGEB("Invalid input resolution %s", resStr); + ret = -EINVAL; + } + } + + free(resStr_copy); + resStr_copy = NULL; + + LOG_FUNCTION_NAME_EXIT; + + return ret; +} + +void CameraHal::insertSupportedParams() +{ + LOG_FUNCTION_NAME; + + android::CameraParameters &p = mParameters; + + ///Set the name of the camera + p.set(TICameraParameters::KEY_CAMERA_NAME, mCameraProperties->get(CameraProperties::CAMERA_NAME)); + + mMaxZoomSupported = atoi(mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES)); + + p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIZES)); + p.set(android::CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_FORMATS)); + p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIZES)); + p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FORMATS)); + p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SUBSAMPLED_SIZES)); + p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_SIDEBYSIDE_SIZES)); + p.set(TICameraParameters::KEY_SUPPORTED_PICTURE_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PICTURE_TOPBOTTOM_SIZES)); + p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SUBSAMPLED_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SUBSAMPLED_SIZES)); + p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_SIDEBYSIDE_SIZES)); + p.set(TICameraParameters::KEY_SUPPORTED_PREVIEW_TOPBOTTOM_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_TOPBOTTOM_SIZES)); + p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES)); + p.set(TICameraParameters::KEY_FRAMERATES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_PREVIEW_FRAME_RATES_EXT)); + p.set(android::CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_SUPPORTED)); + p.set(TICameraParameters::KEY_FRAMERATE_RANGES_EXT_SUPPORTED, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE_EXT_SUPPORTED)); + p.set(android::CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES, mCameraProperties->get(CameraProperties::SUPPORTED_THUMBNAIL_SIZES)); + p.set(android::CameraParameters::KEY_SUPPORTED_WHITE_BALANCE, mCameraProperties->get(CameraProperties::SUPPORTED_WHITE_BALANCE)); + p.set(android::CameraParameters::KEY_SUPPORTED_EFFECTS, mCameraProperties->get(CameraProperties::SUPPORTED_EFFECTS)); + p.set(android::CameraParameters::KEY_SUPPORTED_SCENE_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_SCENE_MODES)); + p.set(android::CameraParameters::KEY_SUPPORTED_FLASH_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FLASH_MODES)); + p.set(android::CameraParameters::KEY_SUPPORTED_FOCUS_MODES, mCameraProperties->get(CameraProperties::SUPPORTED_FOCUS_MODES)); + p.set(android::CameraParameters::KEY_SUPPORTED_ANTIBANDING, mCameraProperties->get(CameraProperties::SUPPORTED_ANTIBANDING)); + p.set(android::CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MAX)); + p.set(android::CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::SUPPORTED_EV_MIN)); + p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_EV_STEP)); + p.set(TICameraParameters::KEY_SUPPORTED_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_EXPOSURE_MODES)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MAX)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_EXPOSURE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_STEP)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MAX)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_GAIN_ISO_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_STEP)); + p.set(TICameraParameters::KEY_SUPPORTED_ISO_VALUES, mCameraProperties->get(CameraProperties::SUPPORTED_ISO_VALUES)); + p.set(android::CameraParameters::KEY_ZOOM_RATIOS, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_RATIOS)); + p.set(android::CameraParameters::KEY_MAX_ZOOM, mCameraProperties->get(CameraProperties::SUPPORTED_ZOOM_STAGES)); + p.set(android::CameraParameters::KEY_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::ZOOM_SUPPORTED)); + p.set(android::CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, mCameraProperties->get(CameraProperties::SMOOTH_ZOOM_SUPPORTED)); + p.set(TICameraParameters::KEY_SUPPORTED_IPP, mCameraProperties->get(CameraProperties::SUPPORTED_IPP_MODES)); + p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT_VALUES)); + p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT_VALUES, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT_VALUES)); + p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE_VALUES, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE_VALUES)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MIN, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MIN)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_MAX, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_MAX)); + p.set(TICameraParameters::KEY_SUPPORTED_MANUAL_CONVERGENCE_STEP, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_CONVERGENCE_STEP)); + p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED, mCameraProperties->get(CameraProperties::VSTAB_SUPPORTED)); + p.set(TICameraParameters::KEY_VNF_SUPPORTED, mCameraProperties->get(CameraProperties::VNF_SUPPORTED)); + p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK_SUPPORTED)); + p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK_SUPPORTED)); + p.set(android::CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED, mCameraProperties->get(CameraProperties::VIDEO_SNAPSHOT_SUPPORTED)); + p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION_SUPPORTED)); + p.set(TICameraParameters::KEY_CAP_MODE_VALUES, mCameraProperties->get(CameraProperties::CAP_MODE_VALUES)); + + LOG_FUNCTION_NAME_EXIT; + +} + +void CameraHal::initDefaultParameters() +{ + //Purpose of this function is to initialize the default current and supported parameters for the currently + //selected camera. + + android::CameraParameters &p = mParameters; + int currentRevision, adapterRevision; + status_t ret = NO_ERROR; + int width, height; + const char *valstr; + + LOG_FUNCTION_NAME; + + insertSupportedParams(); + + ret = parseResolution(mCameraProperties->get(CameraProperties::PREVIEW_SIZE), width, height); + + if ( NO_ERROR == ret ) + { + p.setPreviewSize(width, height); + } + else + { + p.setPreviewSize(MIN_WIDTH, MIN_HEIGHT); + } + + ret = parseResolution(mCameraProperties->get(CameraProperties::PICTURE_SIZE), width, height); + + if ( NO_ERROR == ret ) + { + p.setPictureSize(width, height); + } + else + { + p.setPictureSize(PICTURE_WIDTH, PICTURE_HEIGHT); + } + + ret = parseResolution(mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_SIZE), width, height); + + if ( NO_ERROR == ret ) + { + p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width); + p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height); + } + else + { + p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, MIN_WIDTH); + p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, MIN_HEIGHT); + } + + //Insert default values + p.setPreviewFrameRate(atoi(mCameraProperties->get(CameraProperties::PREVIEW_FRAME_RATE))); + p.set(android::CameraParameters::KEY_PREVIEW_FPS_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE)); + p.set(TICameraParameters::KEY_PREVIEW_FRAME_RATE_RANGE, mCameraProperties->get(CameraProperties::FRAMERATE_RANGE)); + p.setPreviewFormat(mCameraProperties->get(CameraProperties::PREVIEW_FORMAT)); + p.setPictureFormat(mCameraProperties->get(CameraProperties::PICTURE_FORMAT)); + p.set(android::CameraParameters::KEY_JPEG_QUALITY, mCameraProperties->get(CameraProperties::JPEG_QUALITY)); + p.set(android::CameraParameters::KEY_WHITE_BALANCE, mCameraProperties->get(CameraProperties::WHITEBALANCE)); + p.set(android::CameraParameters::KEY_EFFECT, mCameraProperties->get(CameraProperties::EFFECT)); + p.set(android::CameraParameters::KEY_ANTIBANDING, mCameraProperties->get(CameraProperties::ANTIBANDING)); + p.set(android::CameraParameters::KEY_FLASH_MODE, mCameraProperties->get(CameraProperties::FLASH_MODE)); + p.set(android::CameraParameters::KEY_FOCUS_MODE, mCameraProperties->get(CameraProperties::FOCUS_MODE)); + p.set(android::CameraParameters::KEY_EXPOSURE_COMPENSATION, mCameraProperties->get(CameraProperties::EV_COMPENSATION)); + p.set(android::CameraParameters::KEY_SCENE_MODE, mCameraProperties->get(CameraProperties::SCENE_MODE)); + p.set(android::CameraParameters::KEY_ZOOM, mCameraProperties->get(CameraProperties::ZOOM)); + p.set(TICameraParameters::KEY_CONTRAST, mCameraProperties->get(CameraProperties::CONTRAST)); + p.set(TICameraParameters::KEY_SATURATION, mCameraProperties->get(CameraProperties::SATURATION)); + p.set(TICameraParameters::KEY_BRIGHTNESS, mCameraProperties->get(CameraProperties::BRIGHTNESS)); + p.set(TICameraParameters::KEY_SHARPNESS, mCameraProperties->get(CameraProperties::SHARPNESS)); + p.set(TICameraParameters::KEY_EXPOSURE_MODE, mCameraProperties->get(CameraProperties::EXPOSURE_MODE)); + p.set(TICameraParameters::KEY_MANUAL_EXPOSURE, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN)); + p.set(TICameraParameters::KEY_MANUAL_EXPOSURE_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_EXPOSURE_MIN)); + p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN)); + p.set(TICameraParameters::KEY_MANUAL_GAIN_ISO_RIGHT, mCameraProperties->get(CameraProperties::SUPPORTED_MANUAL_GAIN_ISO_MIN)); + p.set(TICameraParameters::KEY_ISO, mCameraProperties->get(CameraProperties::ISO_MODE)); + p.set(TICameraParameters::KEY_IPP, mCameraProperties->get(CameraProperties::IPP)); + p.set(TICameraParameters::KEY_GBCE, mCameraProperties->get(CameraProperties::GBCE)); + p.set(TICameraParameters::KEY_GBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GBCE)); + p.set(TICameraParameters::KEY_GLBCE, mCameraProperties->get(CameraProperties::GLBCE)); + p.set(TICameraParameters::KEY_GLBCE_SUPPORTED, mCameraProperties->get(CameraProperties::SUPPORTED_GLBCE)); + p.set(TICameraParameters::KEY_S3D_PRV_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_PRV_FRAME_LAYOUT)); + p.set(TICameraParameters::KEY_S3D_CAP_FRAME_LAYOUT, mCameraProperties->get(CameraProperties::S3D_CAP_FRAME_LAYOUT)); + p.set(TICameraParameters::KEY_AUTOCONVERGENCE_MODE, mCameraProperties->get(CameraProperties::AUTOCONVERGENCE_MODE)); + p.set(TICameraParameters::KEY_MANUAL_CONVERGENCE, mCameraProperties->get(CameraProperties::MANUAL_CONVERGENCE)); + p.set(android::CameraParameters::KEY_VIDEO_STABILIZATION, mCameraProperties->get(CameraProperties::VSTAB)); + p.set(TICameraParameters::KEY_VNF, mCameraProperties->get(CameraProperties::VNF)); + p.set(android::CameraParameters::KEY_FOCAL_LENGTH, mCameraProperties->get(CameraProperties::FOCAL_LENGTH)); + p.set(android::CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::HOR_ANGLE)); + p.set(android::CameraParameters::KEY_VERTICAL_VIEW_ANGLE, mCameraProperties->get(CameraProperties::VER_ANGLE)); + p.set(TICameraParameters::KEY_SENSOR_ORIENTATION, mCameraProperties->get(CameraProperties::SENSOR_ORIENTATION)); + p.set(TICameraParameters::KEY_EXIF_MAKE, mCameraProperties->get(CameraProperties::EXIF_MAKE)); + p.set(TICameraParameters::KEY_EXIF_MODEL, mCameraProperties->get(CameraProperties::EXIF_MODEL)); + p.set(android::CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, mCameraProperties->get(CameraProperties::JPEG_THUMBNAIL_QUALITY)); + p.set(android::CameraParameters::KEY_VIDEO_FRAME_FORMAT, "OMX_TI_COLOR_FormatYUV420PackedSemiPlanar"); + p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, mCameraProperties->get(CameraProperties::MAX_FD_HW_FACES)); + p.set(android::CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW, mCameraProperties->get(CameraProperties::MAX_FD_SW_FACES)); + p.set(TICameraParameters::KEY_MECHANICAL_MISALIGNMENT_CORRECTION, mCameraProperties->get(CameraProperties::MECHANICAL_MISALIGNMENT_CORRECTION)); + // Only one area a.k.a Touch AF for now. + // TODO: Add support for multiple focus areas. + p.set(android::CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, mCameraProperties->get(CameraProperties::MAX_FOCUS_AREAS)); + p.set(android::CameraParameters::KEY_AUTO_EXPOSURE_LOCK, mCameraProperties->get(CameraProperties::AUTO_EXPOSURE_LOCK)); + p.set(android::CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, mCameraProperties->get(CameraProperties::AUTO_WHITEBALANCE_LOCK)); + p.set(android::CameraParameters::KEY_MAX_NUM_METERING_AREAS, mCameraProperties->get(CameraProperties::MAX_NUM_METERING_AREAS)); + p.set(TICameraParameters::RAW_WIDTH, mCameraProperties->get(CameraProperties::RAW_WIDTH)); + p.set(TICameraParameters::RAW_HEIGHT,mCameraProperties->get(CameraProperties::RAW_HEIGHT)); + + // TI extensions for enable/disable algos + // Hadcoded for now + p.set(TICameraParameters::KEY_ALGO_EXTERNAL_GAMMA, android::CameraParameters::FALSE); + p.set(TICameraParameters::KEY_ALGO_NSF1, android::CameraParameters::TRUE); + p.set(TICameraParameters::KEY_ALGO_NSF2, android::CameraParameters::TRUE); + p.set(TICameraParameters::KEY_ALGO_SHARPENING, android::CameraParameters::TRUE); + p.set(TICameraParameters::KEY_ALGO_THREELINCOLORMAP, android::CameraParameters::TRUE); + p.set(TICameraParameters::KEY_ALGO_GIC, android::CameraParameters::TRUE); + +#ifdef MOTOROLA_CAMERA + p.set(TICameraParameters::KEY_MOT_LEDFLASH, DEFAULT_INTENSITY); + p.set(TICameraParameters::KEY_MOT_LEDTORCH, DEFAULT_INTENSITY); +#endif + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Stop a previously started preview. + @param none + @return none + + */ +void CameraHal::forceStopPreview() +{ + LOG_FUNCTION_NAME; + + // stop bracketing if it is running + if ( mBracketingRunning ) { + stopImageBracketing(); + } + + if(mDisplayAdapter.get() != NULL) { + ///Stop the buffer display first + mDisplayAdapter->disableDisplay(); + } + + if(mAppCallbackNotifier.get() != NULL) { + //Stop the callback sending + mAppCallbackNotifier->stop(); + mAppCallbackNotifier->flushAndReturnFrames(); + mAppCallbackNotifier->stopPreviewCallbacks(); + } + + if ( NULL != mCameraAdapter ) { + // only need to send these control commands to state machine if we are + // passed the LOADED_PREVIEW_STATE + if (mCameraAdapter->getState() > CameraAdapter::LOADED_PREVIEW_STATE) { + // according to javadoc...FD should be stopped in stopPreview + // and application needs to call startFaceDection again + // to restart FD + mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_FD); + } + + mCameraAdapter->rollbackToInitializedState(); + + } + + freePreviewBufs(); + freePreviewDataBufs(); + + mPreviewEnabled = false; + mDisplayPaused = false; + mPreviewStartInProgress = false; + + LOG_FUNCTION_NAME_EXIT; +} + +/** + @brief Deallocates memory for all the resources held by Camera HAL. + + Frees the following objects- CameraAdapter, AppCallbackNotifier, DisplayAdapter, + and Memory Manager + + @param none + @return none + + */ +void CameraHal::deinitialize() +{ + LOG_FUNCTION_NAME; + + if ( mPreviewEnabled || mDisplayPaused ) { + forceStopPreview(); + } + + mSetPreviewWindowCalled = false; + + if (mSensorListener.get()) { + mSensorListener->disableSensor(SensorListener::SENSOR_ORIENTATION); + mSensorListener.clear(); + mSensorListener = NULL; + } + + mBufferSourceAdapter_Out.clear(); + mBufferSourceAdapter_In.clear(); + mOutAdapters.clear(); + mInAdapters.clear(); + + LOG_FUNCTION_NAME_EXIT; + +} + +status_t CameraHal::storeMetaDataInBuffers(bool enable) +{ + LOG_FUNCTION_NAME; + + return mAppCallbackNotifier->useMetaDataBufferMode(enable); + + LOG_FUNCTION_NAME_EXIT; +} + +void CameraHal::setExternalLocking(bool extBuffLocking) +{ + mExternalLocking = extBuffLocking; +} + +void CameraHal::resetPreviewRes(android::CameraParameters *params) +{ + LOG_FUNCTION_NAME; + + if ( (mVideoWidth <= 320) && (mVideoHeight <= 240)){ + params->setPreviewSize(mVideoWidth, mVideoHeight); + } + + LOG_FUNCTION_NAME_EXIT; +} + +#ifdef MOTOROLA_CAMERA +#include +#include +#include + +#define EXT_MODULE_VENDOR_STRING "SHARP,OV8820" +#define INT_MODULE_VENDOR_STRING "SEMCO,OV7739" + +#define DCM_CAM_CONFIG_FILE "/data/system/dcm_camera.config" +#define CAMERA_ENABLED 0x73 +#define CAMERA_DISABLED 0x45 + +#define MOT_BURST_COUNT "mot-burst-picture-count" +#define MOT_BURST_COUNT_VALUES "mot-burst-picture-count-values" +#define MOT_MAX_BURST_SIZE "mot-max-burst-size" +//Wide screen aspect ratio (16:9) +#define WIDE_AR 1.7 + +// TI supports arbitrary burst limits, so we +// go with what we've used on other platforms +#define SUPPORTED_BURSTS "0,1,3,6,9" + +#define TORCH_DRIVER_DEVICE "/dev/i2c-3" +#define TORCH_DEVICE_SLAVE_ADDR 0x53 +#define TORCH_DEVICE_CONTROL_REG 0x10 +#define TORCH_BRIGHTNESS_CONTROL_REG 0xA0 +#define TORCH_DEFAULT_BRIGHTNESS 0x02 +#define TORCH_ENABLE 0x0A +#define TORCH_DISABLE 0x0 +#define MAX_EXPOSURE_COMPENSATION 30 + +bool CameraHal::i2cRW(int read_size, int write_size, unsigned char *read_data, unsigned char *write_data) +{ + + int i2cfd = -1; + int i,j; + int ioctl_ret; + struct i2c_msg msgs[2]; + struct i2c_rdwr_ioctl_data i2c_trans; + bool retL = 0; + + enum { I2C_WRITE, I2C_READ }; + enum { ARG_BUS = 1, ARG_ADDR, ARG_READCNT, ARG_DATA }; + + msgs[0].addr = TORCH_DEVICE_SLAVE_ADDR; + msgs[0].flags = 0; + msgs[0].len = write_size; + msgs[0].buf = write_data; + + msgs[1].addr = TORCH_DEVICE_SLAVE_ADDR; + msgs[1].flags = I2C_M_RD; + msgs[1].len = read_size; + msgs[1].buf = read_data; + + i2c_trans.msgs = NULL; + i2c_trans.nmsgs = 0; + + if ((i2cfd = open(TORCH_DRIVER_DEVICE, O_RDWR)) < 0) { + CAMHAL_LOGD("failed to open %s", TORCH_DRIVER_DEVICE); + return 1; + } + + if ( write_size && read_size ) { + i2c_trans.msgs = &msgs[0]; + i2c_trans.nmsgs = 2; + } + else if (write_size) { + i2c_trans.msgs = &msgs[0]; + i2c_trans.nmsgs = 1; + } + else if (read_size) { + i2c_trans.msgs = &msgs[1]; + i2c_trans.nmsgs = 1; + } + else { + goto done; + } + + if ( write_size > 0 ) { + CAMHAL_LOGD("I2C_WRITE"); + for( i = 0; i < write_size; i++ ) + { + CAMHAL_LOGD( "%02X ", write_data[i] ); + } + } + + if( (ioctl_ret = ioctl( i2cfd, I2C_RDWR, &(i2c_trans))) < 0 ) + { + CAMHAL_LOGD("* failed driver call: ioctl returned %d", ioctl_ret); + retL = 1; + goto done; + } + + + if ( read_size > 0 ) { + CAMHAL_LOGD("I2C_READ"); + for( i = 0; i < read_size; i++ ) + { + CAMHAL_LOGD( "%02X ", read_data[i] ); + } + } + +done: + /* close the hardware */ + close(i2cfd); + + return retL; + +} + +unsigned int CameraHal::getFlashIntensity() +{ + unsigned int flashIntensity = DEFAULT_INTENSITY; + char value[PROPERTY_VALUE_MAX]; + unsigned long minFlashThreshold; + + if (property_get("ro.media.capture.flashIntensity", value, 0) > 0) + { + flashIntensity = atoi(value); + } + if (property_get("ro.media.capture.flashMinV", value, 0) > 0) + { + minFlashThreshold = atoi(value); + } + else + { + minFlashThreshold = FLASH_VOLTAGE_THRESHOLD2; + } + if ( minFlashThreshold != 0) + { + int fd = open("/sys/class/power_supply/battery/voltage_now", O_RDONLY); + if (fd < 0) + { + CAMHAL_LOGE("Battery status is unavailable, defaulting Flash intensity to MAX"); + } + else + { + char buf[8]; + if ( read(fd, buf, 8) < 0 ) + { + CAMHAL_LOGE("Unable to read battery status, defaulting flash intensity to MAX\n"); + } + else + { + unsigned long batteryLevel; + buf[7] = '\0'; + batteryLevel = atol(buf); + CAMHAL_LOGE("Current battery Level, %d uv", batteryLevel); + if (batteryLevel < minFlashThreshold) + { + CAMHAL_LOGE("Disabling flash due to low Battery"); + flashIntensity = 0; + } + else if (batteryLevel < FLASH_VOLTAGE_THRESHOLD1) + { + flashIntensity = flashIntensity >> 1 ; + } + } + close(fd); + } + } + CAMHAL_LOGE("flashIntensity = %d", flashIntensity); + return flashIntensity; +} + +bool CameraHal::SetFlashLedTorch( unsigned intensity ) +{ + android::CameraParameters params; + mCameraAdapter->getParameters(params); + CAMHAL_LOGE("CameraHalTI::SetFlashLedTorch %d", intensity); + unsigned char write_data[2]; + + if (intensity == 0) + { + write_data[0] = TORCH_DEVICE_CONTROL_REG; + write_data[1] = TORCH_DISABLE; + i2cRW(0, 2, NULL, write_data); + } + else + { + write_data[0] = TORCH_BRIGHTNESS_CONTROL_REG; + write_data[1] = TORCH_DEFAULT_BRIGHTNESS; + i2cRW(0, 2, NULL, write_data); + + write_data[0] = TORCH_DEVICE_CONTROL_REG; + write_data[1] = TORCH_ENABLE; + i2cRW(0, 2, NULL, write_data); + } + + return true; +} + +#endif + +void * +camera_buffer_get_omx_ptr (CameraBuffer *buffer) +{ + CAMHAL_LOGV("buffer_type %d opaque %p", buffer->type, buffer->opaque); + + if (buffer->type == CAMERA_BUFFER_ANW) { + buffer_handle_t *handle = (buffer_handle_t *)buffer->opaque; + CAMHAL_LOGV("anw %08x", *handle); + return (void *)*handle; + } else if (buffer->type == CAMERA_BUFFER_ION) { + return (void *)buffer->fd; + } else { + CAMHAL_LOGV("other %08x", buffer->opaque); + return (void *)buffer->opaque; + } +} + +} // namespace Camera +} // namespace Ti -- cgit v1.1