/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define LOG_TAG "QCameraStateMachine"
#include <utils/Errors.h>
#include "QCamera2HWI.h"
#include "QCameraStateMachine.h"
namespace qcamera {
/*===========================================================================
* FUNCTION : smEvtProcRoutine
*
* DESCRIPTION: Statemachine process thread routine to handle events
* in different state.
*
* PARAMETERS :
* @data : ptr to QCameraStateMachine object
*
* RETURN : none
*==========================================================================*/
void *QCameraStateMachine::smEvtProcRoutine(void *data)
{
int running = 1, ret;
QCameraStateMachine *pme = (QCameraStateMachine *)data;
CDBG_HIGH("%s: E", __func__);
do {
do {
ret = cam_sem_wait(&pme->cmd_sem);
if (ret != 0 && errno != EINVAL) {
ALOGE("%s: cam_sem_wait error (%s)",
__func__, strerror(errno));
return NULL;
}
} while (ret != 0);
// we got notified about new cmd avail in cmd queue
// first check API cmd queue
qcamera_sm_cmd_t *node = (qcamera_sm_cmd_t *)pme->api_queue.dequeue();
if (node == NULL) {
// no API cmd, then check evt cmd queue
node = (qcamera_sm_cmd_t *)pme->evt_queue.dequeue();
}
if (node != NULL) {
switch (node->cmd) {
case QCAMERA_SM_CMD_TYPE_API:
pme->stateMachine(node->evt, node->evt_payload);
// API is in a way sync call, so evt_payload is managed by HWI
// no need to free payload for API
break;
case QCAMERA_SM_CMD_TYPE_EVT:
pme->stateMachine(node->evt, node->evt_payload);
// EVT is async call, so payload need to be free after use
free(node->evt_payload);
node->evt_payload = NULL;
break;
case QCAMERA_SM_CMD_TYPE_EXIT:
running = 0;
break;
default:
break;
}
free(node);
node = NULL;
}
} while (running);
CDBG_HIGH("%s: X", __func__);
return NULL;
}
/*===========================================================================
* FUNCTION : QCameraStateMachine
*
* DESCRIPTION: constructor of QCameraStateMachine. Will start process thread
*
* PARAMETERS :
* @ctrl : ptr to HWI object
*
* RETURN : none
*==========================================================================*/
QCameraStateMachine::QCameraStateMachine(QCamera2HardwareInterface *ctrl) :
api_queue(),
evt_queue()
{
m_parent = ctrl;
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
cmd_pid = 0;
cam_sem_init(&cmd_sem, 0);
pthread_create(&cmd_pid,
NULL,
smEvtProcRoutine,
this);
pthread_setname_np(cmd_pid, "CAM_stMachine");
m_bDelayPreviewMsgs = false;
m_DelayedMsgs = 0;
}
/*===========================================================================
* FUNCTION : ~QCameraStateMachine
*
* DESCRIPTION: desctructor of QCameraStateMachine. Will stop process thread.
*
* PARAMETERS : none
*
* RETURN : none
*==========================================================================*/
QCameraStateMachine::~QCameraStateMachine()
{
cam_sem_destroy(&cmd_sem);
}
/*===========================================================================
* FUNCTION : releaseThread
*
* DESCRIPTION: Sends an exit command and terminates the state machine thread
*
* PARAMETERS : none
*
* RETURN : none
*==========================================================================*/
void QCameraStateMachine::releaseThread()
{
if (cmd_pid != 0) {
qcamera_sm_cmd_t *node =
(qcamera_sm_cmd_t *)malloc(sizeof(qcamera_sm_cmd_t));
if (NULL != node) {
memset(node, 0, sizeof(qcamera_sm_cmd_t));
node->cmd = QCAMERA_SM_CMD_TYPE_EXIT;
if (api_queue.enqueue((void *)node)) {
cam_sem_post(&cmd_sem);
} else {
free(node);
node = NULL;
}
/* wait until cmd thread exits */
if (pthread_join(cmd_pid, NULL) != 0) {
CDBG_HIGH("%s: pthread dead already\n", __func__);
}
}
cmd_pid = 0;
}
}
/*===========================================================================
* FUNCTION : applyDelayedMsgs
*
* DESCRIPTION: Enable if needed any delayed message types
*
* PARAMETERS : None
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::applyDelayedMsgs()
{
int32_t rc = NO_ERROR;
if (m_bDelayPreviewMsgs && m_DelayedMsgs) {
rc = m_parent->enableMsgType(m_DelayedMsgs);
m_bDelayPreviewMsgs = false;
m_DelayedMsgs = 0;
} else if (m_bDelayPreviewMsgs) {
m_bDelayPreviewMsgs = false;
}
return rc;
}
/*===========================================================================
* FUNCTION : procAPI
*
* DESCRIPTION: process incoming API request from framework layer.
*
* PARAMETERS :
* @evt : event to be processed
* @api_payload : API payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procAPI(qcamera_sm_evt_enum_t evt,
void *api_payload)
{
qcamera_sm_cmd_t *node =
(qcamera_sm_cmd_t *)malloc(sizeof(qcamera_sm_cmd_t));
if (NULL == node) {
ALOGE("%s: No memory for qcamera_sm_cmd_t", __func__);
return NO_MEMORY;
}
memset(node, 0, sizeof(qcamera_sm_cmd_t));
node->cmd = QCAMERA_SM_CMD_TYPE_API;
node->evt = evt;
node->evt_payload = api_payload;
if (api_queue.enqueue((void *)node)) {
cam_sem_post(&cmd_sem);
return NO_ERROR;
} else {
free(node);
return UNKNOWN_ERROR;
}
}
/*===========================================================================
* FUNCTION : procEvt
*
* DESCRIPTION: process incoming envent from mm-camera-interface and
* mm-jpeg-interface.
*
* PARAMETERS :
* @evt : event to be processed
* @evt_payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvt(qcamera_sm_evt_enum_t evt,
void *evt_payload)
{
qcamera_sm_cmd_t *node =
(qcamera_sm_cmd_t *)malloc(sizeof(qcamera_sm_cmd_t));
if (NULL == node) {
ALOGE("%s: No memory for qcamera_sm_cmd_t", __func__);
return NO_MEMORY;
}
memset(node, 0, sizeof(qcamera_sm_cmd_t));
node->cmd = QCAMERA_SM_CMD_TYPE_EVT;
node->evt = evt;
node->evt_payload = evt_payload;
if (evt_queue.enqueue((void *)node)) {
cam_sem_post(&cmd_sem);
return NO_ERROR;
} else {
free(node);
return UNKNOWN_ERROR;
}
}
/*===========================================================================
* FUNCTION : stateMachine
*
* DESCRIPTION: finite state machine entry function. Depends on state,
* incoming event will be handled differently.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::stateMachine(qcamera_sm_evt_enum_t evt, void *payload)
{
int32_t rc = NO_ERROR;
ALOGV("%s: m_state %d, event (%d)", __func__, m_state, evt);
switch (m_state) {
case QCAMERA_SM_STATE_PREVIEW_STOPPED:
rc = procEvtPreviewStoppedState(evt, payload);
break;
case QCAMERA_SM_STATE_PREVIEW_READY:
rc = procEvtPreviewReadyState(evt, payload);
break;
case QCAMERA_SM_STATE_PREVIEWING:
rc = procEvtPreviewingState(evt, payload);
break;
case QCAMERA_SM_STATE_PREPARE_SNAPSHOT:
rc = procEvtPrepareSnapshotState(evt, payload);
break;
case QCAMERA_SM_STATE_PIC_TAKING:
rc = procEvtPicTakingState(evt, payload);
break;
case QCAMERA_SM_STATE_RECORDING:
rc = procEvtRecordingState(evt, payload);
break;
case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
rc = procEvtVideoPicTakingState(evt, payload);
break;
case QCAMERA_SM_STATE_PREVIEW_PIC_TAKING:
rc = procEvtPreviewPicTakingState(evt, payload);
break;
default:
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPreviewStoppedState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PREVIEW_STOPPED.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPreviewStoppedState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
rc = m_parent->setPreviewWindow((struct preview_stream_ops *)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (needRestart) {
// Clear memory pools
m_parent->m_memoryPool.clear();
}
if (rc == NO_ERROR) {
rc = m_parent->commitParameterChanges();
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_PREVIEW:
{
if (m_parent->mPreviewWindow == NULL) {
rc = m_parent->preparePreview();
if(rc == NO_ERROR) {
// preview window is not set yet, move to previewReady state
m_state = QCAMERA_SM_STATE_PREVIEW_READY;
} else {
ALOGE("%s: preparePreview failed",__func__);
}
} else {
rc = m_parent->preparePreview();
if (rc == NO_ERROR) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
} else {
// start preview success, move to previewing state
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
{
rc = m_parent->preparePreview();
if (rc == NO_ERROR) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
} else {
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
// no op needed here
CDBG_HIGH("%s: already in preview stopped state, do nothing", __func__);
result.status = NO_ERROR;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
result.status = NO_ERROR;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RELEASE:
{
rc = m_parent->release();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_TAKE_PICTURE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
case QCAMERA_SM_EVT_CANCEL_PICTURE:
{
// no op needed here
CDBG_HIGH("%s: No ops for evt(%d) in state(%d)", __func__, evt, m_state);
result.status = NO_ERROR;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
// No ops, but need to notify
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
rc = m_parent->mParameters.updateFlashMode(internal_evt->led_data);
break;
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPreviewReadyState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PREVIEW_READY.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPreviewReadyState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
m_parent->setPreviewWindow((struct preview_stream_ops *)payload);
if (m_parent->mPreviewWindow != NULL) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
} else {
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
if (needRestart) {
// need restart preview for parameters to take effect
m_parent->unpreparePreview();
// Clear memory pools
m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// prepare preview again
rc = m_parent->preparePreview();
if (rc != NO_ERROR) {
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
}
} else {
rc = m_parent->commitParameterChanges();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_PREVIEW:
{
// no ops here
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
m_parent->unpreparePreview();
rc = 0;
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = 0;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_TAKE_PICTURE:
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
// No ops, but need to notify
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
rc = m_parent->mParameters.updateFlashMode(internal_evt->led_data);
break;
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPreviewingState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PREVIEWING.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPreviewingState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
// Error setting preview window during previewing
ALOGE("Error!! cannot set preview window when preview is running");
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
int32_t enable_msgs = *((int32_t *)payload);
if (m_bDelayPreviewMsgs &&
(enable_msgs & CAMERA_MSG_PREVIEW_FRAME)) {
enable_msgs &= ~CAMERA_MSG_PREVIEW_FRAME;
m_DelayedMsgs = CAMERA_MSG_PREVIEW_FRAME;
}
rc = m_parent->enableMsgType(enable_msgs);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
int32_t disable_msgs = *((int32_t *)payload);
if (m_bDelayPreviewMsgs && m_DelayedMsgs) {
m_DelayedMsgs &= ~disable_msgs;
if (0 == m_DelayedMsgs) {
m_bDelayPreviewMsgs = false;
}
}
rc = m_parent->disableMsgType(disable_msgs);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int32_t msgs = *((int32_t *)payload);
int enabled = m_parent->msgTypeEnabled(msgs);
if (m_bDelayPreviewMsgs && m_DelayedMsgs) {
enabled |= (msgs & m_DelayedMsgs);
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
if (needRestart) {
// need restart preview for parameters to take effect
// stop preview
m_parent->stopPreview();
// Clear memory pools
m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// start preview again
rc = m_parent->preparePreview();
if (rc == NO_ERROR) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
}
}
if (rc != NO_ERROR) {
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
}
} else {
rc = m_parent->commitParameterChanges();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
{
// no ops here
CDBG_HIGH("%s: Already in previewing, no ops here to start preview", __func__);
applyDelayedMsgs();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
rc = m_parent->stopPreview();
applyDelayedMsgs();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
applyDelayedMsgs();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_RECORDING:
{
rc = m_parent->startRecording();
if (rc == NO_ERROR) {
// move state to recording state
m_state = QCAMERA_SM_STATE_RECORDING;
applyDelayedMsgs();
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
{
rc = m_parent->prepareHardwareForSnapshot(FALSE);
if (rc == NO_ERROR) {
// Do not signal API result in this case.
// Need to wait for snapshot done in metadta.
m_state = QCAMERA_SM_STATE_PREPARE_SNAPSHOT;
applyDelayedMsgs();
} else {
// Do not change state in this case.
ALOGE("%s: prepareHardwareForSnapshot failed %d",
__func__, rc);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
}
break;
case QCAMERA_SM_EVT_TAKE_PICTURE:
{
ALOGV("%s: QCAMERA_SM_EVT_TAKE_PICTURE ", __func__);
if ( m_parent->mParameters.getRecordingHintValue() == false) {
if (m_parent->isZSLMode() || m_parent->isLongshotEnabled()) {
m_state = QCAMERA_SM_STATE_PREVIEW_PIC_TAKING;
m_bDelayPreviewMsgs = true;
rc = m_parent->takePicture();
if (rc != NO_ERROR) {
// move state to previewing state
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
if (!(m_parent->isRetroPicture()) || (rc != NO_ERROR)) {
ALOGD("%s: signal API result, m_state = %d",
__func__, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
} else {
m_state = QCAMERA_SM_STATE_PIC_TAKING;
rc = m_parent->takePicture();
if (rc != NO_ERROR) {
// move state to preview stopped state
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
} else {
m_state = QCAMERA_SM_STATE_PREVIEW_PIC_TAKING;
rc = m_parent->takeLiveSnapshot();
if (rc != NO_ERROR ) {
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
#ifndef VANILLA_HAL
if (CAMERA_CMD_LONGSHOT_ON == cmd_payload->cmd) {
if (QCAMERA_SM_EVT_RESTART_PERVIEW == cmd_payload->arg1) {
m_parent->stopPreview();
// Clear memory pools
m_parent->m_memoryPool.clear();
// start preview again
rc = m_parent->preparePreview();
if (rc == NO_ERROR) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
}
}
}
}
#endif
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
rc = m_parent->processFaceDetectionResult(&internal_evt->faces_data);
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
rc = m_parent->processHistogramStats(internal_evt->stats_data);
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
rc = m_parent->mParameters.updateFlashMode(internal_evt->led_data);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, internal_evt->evt_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
CDBG_HIGH("%s: no handling for server evt (%d) at this state",
__func__, cam_evt->server_event_type);
break;
}
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
// No ops, but need to notify
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPrepareSnapshotState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PREPARE_SNAPSHOT.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPrepareSnapshotState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
case QCAMERA_SM_EVT_SET_CALLBACKS:
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
case QCAMERA_SM_EVT_SET_PARAMS:
case QCAMERA_SM_EVT_GET_PARAMS:
case QCAMERA_SM_EVT_PUT_PARAMS:
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_STOP_PREVIEW:
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
case QCAMERA_SM_EVT_RECORDING_ENABLED:
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
case QCAMERA_SM_EVT_DUMP:
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_TAKE_PICTURE:
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_SEND_COMMAND:
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
CDBG("%s: Received QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE event",
__func__);
m_parent->processPrepSnapshotDoneEvent(internal_evt->prep_snapshot_state);
m_state = QCAMERA_SM_STATE_PREVIEWING;
result.status = NO_ERROR;
result.request_api = QCAMERA_SM_EVT_PREPARE_SNAPSHOT;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
rc = m_parent->processFaceDetectionResult(&internal_evt->faces_data);
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
rc = m_parent->processHistogramStats(internal_evt->stats_data);
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, internal_evt->evt_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
// No ops, but need to notify
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPicTakingState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PIC_TAKING.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPicTakingState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
// Error setting preview window during previewing
ALOGE("Error!! cannot set preview window when preview is running");
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
rc = m_parent->commitParameterChanges();
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
// cancel picture first
rc = m_parent->cancelPicture();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
#ifndef VANILLA_HAL
if ( CAMERA_CMD_LONGSHOT_OFF == cmd_payload->cmd ) {
// move state to previewing state
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
#endif
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
{
rc = m_parent->cancelPicture();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_TAKE_PICTURE:
{
if ( m_parent->isLongshotEnabled() ) {
rc = m_parent->longShot();
} else {
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
// Send internal events to release statemachine
// thread to process CAMERA_ERROR_SERVER_DIED error
result.status = rc;
result.request_api = QCAMERA_SM_EVT_PREPARE_SNAPSHOT;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
result.status = rc;
result.request_api = QCAMERA_SM_EVT_TAKE_PICTURE;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
CDBG_HIGH("%s: no handling for server evt (%d) at this state",
__func__, cam_evt->server_event_type);
break;
}
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
{
qcamera_jpeg_evt_payload_t *jpeg_job =
(qcamera_jpeg_evt_payload_t *)payload;
rc = m_parent->processJpegNotify(jpeg_job);
}
break;
case QCAMERA_SM_EVT_STOP_CAPTURE_CHANNEL:
{
bool restartPreview = m_parent->isPreviewRestartEnabled();
rc = m_parent->stopCaptureChannel(restartPreview);
if (restartPreview && (NO_ERROR == rc)) {
rc = m_parent->preparePreview();
if (NO_ERROR == rc) {
m_parent->m_bPreviewStarted = true;
applyDelayedMsgs();
rc = m_parent->startPreview();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
rc = m_parent->cancelPicture();
bool restartPreview = m_parent->isPreviewRestartEnabled();
if (restartPreview) {
m_state = QCAMERA_SM_STATE_PREVIEWING;
} else {
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtRecordingState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_RECORDING.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtRecordingState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
// WA: CTS test VideoSnapshot will try to
// start preview during video recording.
CDBG_HIGH("CTS video restart op");
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
if (needRestart) {
// cannot set parameters that requires restart during recording
ALOGE("%s: Error!! cannot set parameters that requires restart during recording",
__func__);
rc = BAD_VALUE;
} else {
rc = m_parent->commitParameterChanges();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_TAKE_PICTURE:
{
m_state = QCAMERA_SM_STATE_VIDEO_PIC_TAKING;
rc = m_parent->takeLiveSnapshot();
if (rc != NO_ERROR) {
m_state = QCAMERA_SM_STATE_RECORDING;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_RECORDING:
{
// no ops here
CDBG_HIGH("%s: already in recording state, no ops for start_recording", __func__);
rc = 0;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_RECORDING:
{
rc = m_parent->stopRecording();
m_state = QCAMERA_SM_STATE_PREVIEWING;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
rc = m_parent->stopRecording();
m_state = QCAMERA_SM_STATE_PREVIEWING;
rc = m_parent->stopPreview();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
{
rc = m_parent->releaseRecordingFrame((const void *)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
{
//In Video snapshot, prepare hardware is a no-op.
result.status = NO_ERROR;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
rc = m_parent->processFaceDetectionResult(&internal_evt->faces_data);
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
rc = m_parent->processHistogramStats(internal_evt->stats_data);
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
// No ops, but need to notify
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtVideoPicTakingState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_VIDEO_PIC_TAKING.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtVideoPicTakingState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
{
// Error setting preview window during previewing
ALOGE("Error!! cannot set preview window when preview is running");
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
if (needRestart) {
// cannot set parameters that requires restart during recording
ALOGE("%s: Error!! cannot set parameters that requires restart during recording",
__func__);
rc = BAD_VALUE;
} else {
rc = m_parent->commitParameterChanges();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_RECORDING:
{
rc = m_parent->cancelLiveSnapshot();
m_state = QCAMERA_SM_STATE_RECORDING;
rc = m_parent->stopRecording();
m_state = QCAMERA_SM_STATE_PREVIEWING;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
{
rc = m_parent->releaseRecordingFrame((const void *)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
{
rc = m_parent->cancelLiveSnapshot();
m_state = QCAMERA_SM_STATE_RECORDING;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
rc = m_parent->cancelLiveSnapshot();
m_state = QCAMERA_SM_STATE_RECORDING;
rc = m_parent->stopRecording();
m_state = QCAMERA_SM_STATE_PREVIEWING;
rc = m_parent->stopPreview();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_RECORDING:
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
case QCAMERA_SM_EVT_TAKE_PICTURE:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
rc = m_parent->processFaceDetectionResult(&internal_evt->faces_data);
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
rc = m_parent->processHistogramStats(internal_evt->stats_data);
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
{
qcamera_jpeg_evt_payload_t *jpeg_job =
(qcamera_jpeg_evt_payload_t *)payload;
rc = m_parent->processJpegNotify(jpeg_job);
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
rc = m_parent->cancelLiveSnapshot();
m_state = QCAMERA_SM_STATE_RECORDING;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : procEvtPreviewPicTakingState
*
* DESCRIPTION: finite state machine function to handle event in state of
* QCAMERA_SM_STATE_PREVIEW_PIC_TAKING.
*
* PARAMETERS :
* @evt : event to be processed
* @payload : event payload. Can be NULL if not needed.
*
* RETURN : int32_t type of status
* NO_ERROR -- success
* none-zero failure code
*==========================================================================*/
int32_t QCameraStateMachine::procEvtPreviewPicTakingState(qcamera_sm_evt_enum_t evt,
void *payload)
{
int32_t rc = NO_ERROR;
qcamera_api_result_t result;
memset(&result, 0, sizeof(qcamera_api_result_t));
ALOGV("%s: event (%d)", __func__, evt);
switch (evt) {
case QCAMERA_SM_EVT_SET_CALLBACKS:
{
qcamera_sm_evt_setcb_payload_t *setcbs =
(qcamera_sm_evt_setcb_payload_t *)payload;
rc = m_parent->setCallBacks(setcbs->notify_cb,
setcbs->data_cb,
setcbs->data_cb_timestamp,
setcbs->get_memory,
setcbs->user);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_ENABLE_MSG_TYPE:
{
rc = m_parent->enableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DISABLE_MSG_TYPE:
{
rc = m_parent->disableMsgType(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_MSG_TYPE_ENABLED:
{
int enabled = m_parent->msgTypeEnabled(*((int32_t *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = enabled;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SET_PARAMS:
{
bool needRestart = false;
rc = m_parent->updateParameters((char*)payload, needRestart);
if (rc == NO_ERROR) {
if (needRestart) {
// need restart preview for parameters to take effect
// stop preview
m_parent->stopPreview();
// Clear memory pools
m_parent->m_memoryPool.clear();
// commit parameter changes to server
m_parent->commitParameterChanges();
// start preview again
rc = m_parent->preparePreview();
if (rc == NO_ERROR) {
applyDelayedMsgs();
rc = m_parent->startPreview();
if (rc != NO_ERROR) {
m_parent->unpreparePreview();
}
}
if (rc != NO_ERROR) {
m_state = QCAMERA_SM_STATE_PIC_TAKING;
}
} else {
rc = m_parent->commitParameterChanges();
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_GET_PARAMS:
{
result.params = m_parent->getParameters();
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_PARAMS;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PUT_PARAMS:
{
rc = m_parent->putParameters((char*)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREVIEW_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 1;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RECORDING_ENABLED:
{
rc = NO_ERROR;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_ENABLE_FLAG;
result.enabled = 0;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STORE_METADATA_IN_BUFS:
{
rc = m_parent->storeMetaDataInBuffers(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_DUMP:
{
rc = m_parent->dump(*((int *)payload));
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_AUTO_FOCUS:
{
rc = m_parent->autoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_AUTO_FOCUS:
{
rc = m_parent->cancelAutoFocus();
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_SEND_COMMAND:
{
qcamera_sm_evt_command_payload_t *cmd_payload =
(qcamera_sm_evt_command_payload_t *)payload;
rc = m_parent->sendCommand(cmd_payload->cmd,
cmd_payload->arg1,
cmd_payload->arg2);
#ifndef VANILLA_HAL
if ( CAMERA_CMD_LONGSHOT_OFF == cmd_payload->cmd ) {
// move state to previewing state
m_state = QCAMERA_SM_STATE_PREVIEWING;
}
#endif
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_RELEASE_RECORIDNG_FRAME:
{
rc = m_parent->releaseRecordingFrame((const void *)payload);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_CANCEL_PICTURE:
{
if (m_parent->isZSLMode() || m_parent->isLongshotEnabled()) {
rc = m_parent->cancelPicture();
} else {
rc = m_parent->cancelLiveSnapshot();
}
m_state = QCAMERA_SM_STATE_PREVIEWING;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_STOP_PREVIEW:
{
if (m_parent->isZSLMode()) {
// cancel picture first
rc = m_parent->cancelPicture();
m_parent->stopChannel(QCAMERA_CH_TYPE_ZSL);
} else if (m_parent->isLongshotEnabled()) {
// just cancel picture
rc = m_parent->cancelPicture();
} else {
rc = m_parent->cancelLiveSnapshot();
m_parent->stopChannel(QCAMERA_CH_TYPE_PREVIEW);
}
// unprepare preview
m_parent->unpreparePreview();
m_state = QCAMERA_SM_STATE_PREVIEW_STOPPED;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_START_RECORDING:
{
if (m_parent->isZSLMode()) {
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d) in ZSL mode",
__func__, evt, m_state);
rc = INVALID_OPERATION;
} else if (m_parent->isLongshotEnabled()) {
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d) in Longshot mode",
__func__, evt, m_state);
rc = INVALID_OPERATION;
} else {
rc = m_parent->startRecording();
if (rc == NO_ERROR) {
m_state = QCAMERA_SM_STATE_VIDEO_PIC_TAKING;
}
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_REG_FACE_IMAGE:
{
int32_t faceID = 0;
qcamera_sm_evt_reg_face_payload_t *reg_payload =
(qcamera_sm_evt_reg_face_payload_t *)payload;
rc = m_parent->registerFaceImage(reg_payload->img_ptr,
reg_payload->config,
faceID);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_HANDLE;
result.handle = faceID;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_TAKE_PICTURE:
{
if ( m_parent->isLongshotEnabled() ) {
rc = m_parent->longShot();
} else {
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
{
ALOGD("%s: [ZSL Retro]Prepare Snapshot", __func__);
if (m_parent->isRetroPicture()) {
ALOGD("%s: [ZSL Retro] Prepare Snapshot in Retro Mode", __func__);
rc = m_parent->prepareHardwareForSnapshot(FALSE);
if (rc != NO_ERROR) {
ALOGE("%s: [ZSL Retro]prepareHardwareForSnapshot failed %d",
__func__, rc);
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
}
else {
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)",
__func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
}
break;
case QCAMERA_SM_EVT_STOP_RECORDING:
case QCAMERA_SM_EVT_START_PREVIEW:
case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
case QCAMERA_SM_EVT_RELEASE:
{
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
rc = INVALID_OPERATION;
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
break;
case QCAMERA_SM_EVT_EVT_INTERNAL:
{
qcamera_sm_internal_evt_payload_t *internal_evt =
(qcamera_sm_internal_evt_payload_t *)payload;
switch (internal_evt->evt_type) {
case QCAMERA_INTERNAL_EVT_FOCUS_UPDATE:
rc = m_parent->processAutoFocusEvent(internal_evt->focus_data);
break;
case QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE:
ALOGD("%s: [ZSL Retro]Received QCAMERA_INTERNAL_EVT_PREP_SNAPSHOT_DONE event",
__func__);
if (m_parent->isRetroPicture()) {
m_parent->processPrepSnapshotDoneEvent(internal_evt->prep_snapshot_state);
ALOGD("%s: [ZSL Retro] Retro picture", __func__);
result.status = NO_ERROR;
result.request_api = QCAMERA_SM_EVT_PREPARE_SNAPSHOT;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
else {
ALOGE("%s: [ZSL Retro] Invalid Case for "
"QCAMERA_INTERNAL_EVT_READY_FOR_SNAPSHOT event", __func__);
}
break;
case QCAMERA_INTERNAL_EVT_FACE_DETECT_RESULT:
rc = m_parent->processFaceDetectionResult(&internal_evt->faces_data);
break;
case QCAMERA_INTERNAL_EVT_READY_FOR_SNAPSHOT:
// This is valid only in Retro picture Mode
if (m_parent->isRetroPicture()) {
ALOGD("%s: [ZSL Retro] Received QCAMERA_INTERNAL_EVT_READY_FOR_SNAPSHOT event",
__func__);
result.status = NO_ERROR;
result.request_api = QCAMERA_SM_EVT_TAKE_PICTURE;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalAPIResult(&result);
}
else {
ALOGD("%s: [ZSL Retro] Wrong Case for "
"QCAMERA_INTERNAL_EVT_READY_FOR_SNAPSHOT event", __func__);
}
break;
case QCAMERA_INTERNAL_EVT_HISTOGRAM_STATS:
rc = m_parent->processHistogramStats(internal_evt->stats_data);
break;
case QCAMERA_INTERNAL_EVT_CROP_INFO:
rc = m_parent->processZoomEvent(internal_evt->crop_data);
break;
case QCAMERA_INTERNAL_EVT_ASD_UPDATE:
rc = m_parent->processASDUpdate(internal_evt->asd_data);
break;
case QCAMERA_INTERNAL_EVT_LED_MODE_OVERRIDE:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
case QCAMERA_INTERNAL_EVT_AWB_UPDATE:
rc = m_parent->transAwbMetaToParams(internal_evt->awb_data);
break;
case QCAMERA_INTERNAL_EVT_AE_UPDATE:
rc = m_parent->processAEInfo(internal_evt->ae_data);
break;
case QCAMERA_INTERNAL_EVT_FOCUS_POS_UPDATE:
rc = m_parent->processFocusPositionInfo(internal_evt->focus_pos);
break;
case QCAMERA_INTERNAL_EVT_HDR_UPDATE:
rc = m_parent->processHDRData(internal_evt->hdr_data);
break;
case QCAMERA_INTERNAL_EVT_RETRO_AEC_UNLOCK:
rc = m_parent->processRetroAECUnlock();
break;
case QCAMERA_INTERNAL_EVT_ZSL_CAPTURE_DONE:
rc = m_parent->processZSLCaptureDone();
break;
default:
break;
}
}
break;
case QCAMERA_SM_EVT_EVT_NOTIFY:
{
mm_camera_event_t *cam_evt = (mm_camera_event_t *)payload;
switch (cam_evt->server_event_type) {
case CAM_EVENT_TYPE_DAEMON_DIED:
{
//close the camera backend
mm_camera_vtbl_t* handle = m_parent->mCameraHandle;
if (handle && handle->ops) {
handle->ops->error_close_camera(handle->camera_handle);
} else {
ALOGE("%s: Could not close because the handle or ops is NULL",
__func__);
}
m_parent->sendEvtNotify(CAMERA_MSG_ERROR,
CAMERA_ERROR_SERVER_DIED,
0);
}
break;
default:
ALOGE("%s: Invalid internal event %d in state(%d)",
__func__, cam_evt->server_event_type, m_state);
break;
}
}
break;
case QCAMERA_SM_EVT_JPEG_EVT_NOTIFY:
{
ALOGV("%s: [ZSL Retro] Calling Process Jpeg Notify",
__func__);
qcamera_jpeg_evt_payload_t *jpeg_job =
(qcamera_jpeg_evt_payload_t *)payload;
rc = m_parent->processJpegNotify(jpeg_job);
}
break;
case QCAMERA_SM_EVT_SNAPSHOT_DONE:
{
ALOGV("%s: [ZSL Retro] Snapshot Done", __func__);
if (m_parent->isZSLMode() || m_parent->isLongshotEnabled()) {
rc = m_parent->cancelPicture();
} else {
rc = m_parent->cancelLiveSnapshot();
}
m_state = QCAMERA_SM_STATE_PREVIEWING;
if (m_parent->isRetroPicture()){
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
ALOGV("\n Signalling for JPEG snapshot done!!");
m_parent->signalAPIResult(&result);
}
result.status = rc;
result.request_api = evt;
result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
m_parent->signalEvtResult(&result);
}
break;
case QCAMERA_SM_EVT_THERMAL_NOTIFY:
{
rc = m_parent->updateThermalLevel(payload);
}
break;
default:
ALOGE("%s: Error!! cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
break;
}
return rc;
}
/*===========================================================================
* FUNCTION : isRecording
*
* DESCRIPTION: check if recording is in process.
*
* PARAMETERS : None
*
* RETURN : true -- recording
* false -- not in recording mode
*==========================================================================*/
bool QCameraStateMachine::isRecording()
{
switch (m_state) {
case QCAMERA_SM_STATE_RECORDING:
case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
return true;
default:
return false;
}
}
/*===========================================================================
* FUNCTION : isPreviewRunning
*
* DESCRIPTION: check if preview is in process.
*
* PARAMETERS : None
*
* RETURN : true -- preview running
* false -- preview stopped
*==========================================================================*/
bool QCameraStateMachine::isPreviewRunning()
{
switch (m_state) {
case QCAMERA_SM_STATE_PREVIEWING:
case QCAMERA_SM_STATE_RECORDING:
case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
case QCAMERA_SM_STATE_PREVIEW_PIC_TAKING:
case QCAMERA_SM_STATE_PREPARE_SNAPSHOT:
case QCAMERA_SM_STATE_PREVIEW_READY:
return true;
default:
return false;
}
}
/*===========================================================================
* FUNCTION : isPreviewReady
*
* DESCRIPTION: check if preview is in ready state.
*
* PARAMETERS : None
*
* RETURN : true -- preview is in ready state
* false -- preview is stopped
*==========================================================================*/
bool QCameraStateMachine::isPreviewReady()
{
switch (m_state) {
case QCAMERA_SM_STATE_PREVIEW_READY:
return true;
default:
return false;
}
}
/*===========================================================================
* FUNCTION : isCaptureRunning
*
* DESCRIPTION: check if image capture is in process.
*
* PARAMETERS : None
*
* RETURN : true -- capture running
* false -- capture stopped
*==========================================================================*/
bool QCameraStateMachine::isCaptureRunning()
{
switch (m_state) {
case QCAMERA_SM_STATE_PIC_TAKING:
case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
case QCAMERA_SM_STATE_PREVIEW_PIC_TAKING:
return true;
default:
return false;
}
}
/*===========================================================================
* FUNCTION : isNonZSLCaptureRunning
*
* DESCRIPTION: check if image capture is in process in non ZSL mode.
*
* PARAMETERS : None
*
* RETURN : true -- capture running in non ZSL mode
* false -- Either in not capture mode or captur is not in non ZSL mode
*==========================================================================*/
bool QCameraStateMachine::isNonZSLCaptureRunning()
{
switch (m_state) {
case QCAMERA_SM_STATE_PIC_TAKING:
return true;
default:
return false;
}
}
/*===========================================================================
* FUNCTION : dump
*
* DESCRIPTION: Composes a string based on current configuration
*
* PARAMETERS : none
*
* RETURN : Formatted string
*==========================================================================*/
String8 QCameraStateMachine::dump()
{
String8 str("\n");
char s[128];
snprintf(s, 128, "Is Preview Running: %d\n", isPreviewRunning());
str += s;
snprintf(s, 128, "Is Capture Running: %d\n", isCaptureRunning());
str += s;
snprintf(s, 128, "Is Non ZSL Capture Running: %d\n",
isNonZSLCaptureRunning());
str += s;
snprintf(s, 128, "Current State: %d \n", m_state);
str += s;
switch(m_state){
case QCAMERA_SM_STATE_PREVIEW_STOPPED:
snprintf(s, 128, " QCAMERA_SM_STATE_PREVIEW_STOPPED \n");
break;
case QCAMERA_SM_STATE_PREVIEW_READY:
snprintf(s, 128, " QCAMERA_SM_STATE_PREVIEW_READY \n");
break;
case QCAMERA_SM_STATE_PREVIEWING:
snprintf(s, 128, " QCAMERA_SM_STATE_PREVIEWING \n");
break;
case QCAMERA_SM_STATE_PREPARE_SNAPSHOT:
snprintf(s, 128, " QCAMERA_SM_STATE_PREPARE_SNAPSHOT \n");
break;
case QCAMERA_SM_STATE_PIC_TAKING:
snprintf(s, 128, " QCAMERA_SM_STATE_PIC_TAKING \n");
break;
case QCAMERA_SM_STATE_RECORDING:
snprintf(s, 128, " QCAMERA_SM_STATE_RECORDING \n");
break;
case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
snprintf(s, 128, " QCAMERA_SM_STATE_VIDEO_PIC_TAKING \n");
break;
case QCAMERA_SM_STATE_PREVIEW_PIC_TAKING:
snprintf(s, 128, " QCAMERA_SM_STATE_PREVIEW_PIC_TAKING \n");
break;
}
str += s;
return str;
}
}; // namespace qcamera