OMXFocus.cpp revision 5703f6d63cead1c511f23531cfb13c5ba6de576b
1c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/*
2c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Copyright (C) Texas Instruments - http://www.ti.com/
3c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
4c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License");
5c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * you may not use this file except in compliance with the License.
6c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * You may obtain a copy of the License at
7c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
8c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *      http://www.apache.org/licenses/LICENSE-2.0
9c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev *
10c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Unless required by applicable law or agreed to in writing, software
11c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS,
12c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * See the License for the specific language governing permissions and
14c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * limitations under the License.
15c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */
16c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
17c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
18c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/**
19c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* @file OMXFocus.cpp
20c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev*
21c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev* This file contains functionality for handling focus configurations.
22c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev*
23c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev*/
24c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
25c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#undef LOG_TAG
26c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
27c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define LOG_TAG "CameraHAL"
28c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
29c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "CameraHal.h"
30c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#include "OMXCameraAdapter.h"
3100479a8f1d791824870513b8b0b9edd67d2560ffSundar Raman#include "ErrorUtils.h"
32c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
33c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define TOUCH_FOCUS_RANGE 0xFF
3405ea07dfe04d915b4288d3e71afbf70f8082fea4Tyler Luu#define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout
3505ea07dfe04d915b4288d3e71afbf70f8082fea4Tyler Luu#define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout
36c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
37c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevnamespace android {
38c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
39c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
40c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                              BaseCameraAdapter::AdapterState state)
41c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
42c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
43c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    const char *str = NULL;
445458bdc45048501d1919b14d22456de91f7e8950Tyler Luu    Vector< sp<CameraArea> > tempAreas;
45708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    size_t MAX_FOCUS_AREAS;
46708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
47c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
48c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
495458bdc45048501d1919b14d22456de91f7e8950Tyler Luu    Mutex::Autolock lock(mFocusAreasLock);
505458bdc45048501d1919b14d22456de91f7e8950Tyler Luu
51c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    str = params.get(CameraParameters::KEY_FOCUS_AREAS);
52708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
53708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    MAX_FOCUS_AREAS = atoi(params.get(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
54708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
559e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu    if ( NULL != str ) {
565458bdc45048501d1919b14d22456de91f7e8950Tyler Luu        ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
579e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu    }
589e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu
595458bdc45048501d1919b14d22456de91f7e8950Tyler Luu    if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) {
605458bdc45048501d1919b14d22456de91f7e8950Tyler Luu        mFocusAreas.clear();
615458bdc45048501d1919b14d22456de91f7e8950Tyler Luu        mFocusAreas = tempAreas;
629e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu        if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) {
639e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu            CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d",
649e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu                         MAX_FOCUS_AREAS,
659e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu                         mFocusAreas.size());
669e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu            ret = -EINVAL;
67c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
68f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov        else {
69f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov            if ( !mFocusAreas.isEmpty() ) {
70f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov                setTouchFocus();
71f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov            }
72f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov        }
739e5cb561cc54d061fe9f3d05eae78f6efb70f2c2Tyler Luu    }
74c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
75c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
76c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
77c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
78c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
79c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
80c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::doAutoFocus()
81c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
82c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
83c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
84c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
8585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
862136042f80a20aeeef3ece24bab027c401426334Milen Mitkov    OMX_CONFIG_BOOLEANTYPE bOMX;
87ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev    nsecs_t timeout = 0;
88c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
89c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
90c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
91b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng    if ( OMX_StateInvalid == mComponentState )
92b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      {
93b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        CAMHAL_LOGEA("OMX component in Invalid state");
94b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        returnFocusStatus(false);
95b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        return -EINVAL;
96b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      }
97b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng
98c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateExecuting != mComponentState )
99c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
100c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEA("OMX component not in executing state");
101c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        returnFocusStatus(false);
102b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        return NO_ERROR;
103c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
104c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
105c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
106030e1a5962195aa5914e76e3d071669869555a9fTyler Luu    if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) {
107030e1a5962195aa5914e76e3d071669869555a9fTyler Luu       CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called");
108030e1a5962195aa5914e76e3d071669869555a9fTyler Luu       return NO_ERROR;
109030e1a5962195aa5914e76e3d071669869555a9fTyler Luu    }
110030e1a5962195aa5914e76e3d071669869555a9fTyler Luu
111aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    // If the app calls autoFocus, the camera will stop sending face callbacks.
112aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    pauseFaceDetection(true);
113aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu
114f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    // This is needed for applying FOCUS_REGION correctly
115f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
116f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    {
117f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    //Disable face priority
118f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
119f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov
120f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    //Enable region algorithm priority
121f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
122f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov    }
123f2ac1cc4c58440d94972f0015f50bcbb13838611Atanas Stefov
12485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
12585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
12685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
1270e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu    if (mParameters3A.FocusLock) {
1280e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        // this basically means user never called cancelAutoFocus after a scan...
1290e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        // if this is the case we need to unlock AF to ensure we will do a scan
1300e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
1310e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            CAMHAL_LOGEA("Error Unlocking 3A locks");
1320e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        } else {
1330e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            CAMHAL_LOGDA("AE/AWB unlocked successfully");
1340e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        }
135f5f41aa7943adde4e7bfb3fc181de154c4b0b9b0Sundar Raman
1360e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu    } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
1370e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        // In case we have CAF running we should first check the AF status.
1380e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        // If it has managed to lock, then do as usual and return status
139057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        // immediately.
14085c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        ret = checkFocus(&focusStatus);
14185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        if ( NO_ERROR != ret ) {
14285c859b69b3c003b8db810371e24fe41599fc7deSundar Raman            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
14385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman            return ret;
14485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        } else {
14585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
14685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        }
14785c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
148c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
1493c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov    if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto
150b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov            && (focusStatus.eFocusStatus == OMX_FocusStatusRequest
151b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov             || focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach) ) ||
1523c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov            (mParameters3A.Focus !=  (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) )
1533c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov        {
1542136042f80a20aeeef3ece24bab027c401426334Milen Mitkov        OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
1552136042f80a20aeeef3ece24bab027c401426334Milen Mitkov        bOMX.bEnabled = OMX_TRUE;
1562136042f80a20aeeef3ece24bab027c401426334Milen Mitkov
1572136042f80a20aeeef3ece24bab027c401426334Milen Mitkov        //Enable focus scanning
1582136042f80a20aeeef3ece24bab027c401426334Milen Mitkov        eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
1592136042f80a20aeeef3ece24bab027c401426334Milen Mitkov                               (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
1602136042f80a20aeeef3ece24bab027c401426334Milen Mitkov                               &bOMX);
161c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
162b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov        // force AF, Ducati will take care of whether CAF
163b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov        // or AF will be performed, depending on light conditions
1647a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng        if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto
165b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov		&& focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach )
166b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov			{
167b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov			focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
168b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov			}
169b92d77425f939a35c0404a5317c3dcd6c2008ecbMilen Mitkov
1703c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov        if ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto )
1713c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov            {
1723c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
1733c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov                                    OMX_IndexConfigFocusControl,
1743c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov                                    &focusControl);
1753c272a993dfc4ca153b09e5ec1e651f75eab90c4Milen Mitkov            }
1766b5eaf29c3d17a24731bf9271bd0d199d433813eAkwasi Boateng
1770e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        if ( OMX_ErrorNone != eError ) {
1780e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
1790e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            return INVALID_OPERATION;
1800e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        } else {
1810e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            CAMHAL_LOGDA("Autofocus started successfully");
1820e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu        }
1836b5eaf29c3d17a24731bf9271bd0d199d433813eAkwasi Boateng
1847a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng        // configure focus timeout based on capture mode
185ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev        timeout = (mCapMode == VIDEO_MODE) ?
186ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev                        ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) :
187ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev                        ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 );
188ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev
189ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            {
190ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            Mutex::Autolock lock(mDoAFMutex);
191ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            ret = mDoAFCond.waitRelative(mDoAFMutex, timeout);
192ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            }
19305ea07dfe04d915b4288d3e71afbf70f8082fea4Tyler Luu
1947a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng        //If somethiing bad happened while we wait
1957a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng        if (mComponentState == OMX_StateInvalid) {
1967a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng          CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
197057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu          return -EINVAL;
1987a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng        }
1996b5eaf29c3d17a24731bf9271bd0d199d433813eAkwasi Boateng
200057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        if(ret != NO_ERROR) {
2017a1746145a89cca0dafe26478a7675c15d5623a3Akwasi Boateng            CAMHAL_LOGEA("Autofocus callback timeout expired");
202057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            ret = returnFocusStatus(true);
20385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        } else {
204c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            ret = returnFocusStatus(false);
205c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
2060e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu    } else { // Focus mode in continuous
20785c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        if ( NO_ERROR == ret ) {
208ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            ret = returnFocusStatus(true);
209f50bf42f39a1d1ca8505d198b41c557e8ca83668Heechan Park            mPending3Asettings |= SetFocus;
210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
21185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
21285c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
213c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
214c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
215c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
216c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
217c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
218c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::stopAutoFocus()
219c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
220c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
221c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
222c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
223c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
224c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
225b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng    if ( OMX_StateInvalid == mComponentState )
226b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      {
227b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        CAMHAL_LOGEA("OMX component in Invalid state");
228b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        returnFocusStatus(false);
229b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        return -EINVAL;
230b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      }
231b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng
232c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateExecuting != mComponentState )
233c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
234b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng          CAMHAL_LOGEA("OMX component not in executing state");
235b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        return NO_ERROR;
236c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
237c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
238c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
239c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        // No need to stop focus if we are in infinity mode. Nothing to stop.
240c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        return NO_ERROR;
241c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    }
242c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2435703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
2445703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
2455703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev
2465703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
2475703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev                            OMX_IndexConfigFocusControl,
2485703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev                            &focusControl);
2495703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    if ( OMX_ErrorNone != eError )
250c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
2515703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
2525703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        return ErrorUtils::omxToAndroidError(eError);
2535703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    } else {
2545703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        // This is a WA. Usually the OMX Camera component should
2555703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        // generate AF status change OMX event fairly quickly
2565703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        // ( after one preview frame ) and this notification should
2575703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        // actually come from 'handleFocusCallback()'.
2585703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        Mutex::Autolock lock(mDoAFMutex);
2595703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev        mDoAFCond.broadcast();
2605703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    }
261c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
262c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
263c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
264c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
2655703f6d63cead1c511f23531cfb13c5ba6de576bEmilian Peev    return NO_ERROR;
266c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
267c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
26885c859b69b3c003b8db810371e24fe41599fc7deSundar Ramanstatus_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
26985c859b69b3c003b8db810371e24fe41599fc7deSundar Raman{;
27085c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    OMX_ERRORTYPE eError = OMX_ErrorNone;
27185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
27285c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    LOG_FUNCTION_NAME;
27385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
27485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    if ( OMX_StateInvalid == mComponentState ) {
27585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        CAMHAL_LOGEA("OMX component is in invalid state");
27685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        return NO_INIT;
27785c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
27885c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
27985c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
28085c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
28185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
28285c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
28385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman                            OMX_IndexConfigFocusControl,
28485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman                            &focusMode);
28585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
28685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    if ( OMX_ErrorNone != eError ) {
28785c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
28885c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
28985c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
29085c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    LOG_FUNCTION_NAME_EXIT;
29185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
29285c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    return ErrorUtils::omxToAndroidError(eError);
29385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman}
29485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
295c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::cancelAutoFocus()
296c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
297c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
298c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
29985c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
300c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
301c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
302c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
30385c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    ret = getFocusMode(focusMode);
30485c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    if ( NO_ERROR != ret ) {
30585c859b69b3c003b8db810371e24fe41599fc7deSundar Raman        return ret;
30685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
30785c859b69b3c003b8db810371e24fe41599fc7deSundar Raman
3088cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman    //Stop the AF only for modes other than CAF  or Inifinity
30985c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
31085c859b69b3c003b8db810371e24fe41599fc7deSundar Raman         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
31185c859b69b3c003b8db810371e24fe41599fc7deSundar Raman                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
3128cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman        stopAutoFocus();
3138a35a0ca4d30702b693c92f8cee360a8d102f49eTyler Luu    } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
3148a35a0ca4d30702b693c92f8cee360a8d102f49eTyler Luu       // re-apply CAF after unlocking and canceling
3158a35a0ca4d30702b693c92f8cee360a8d102f49eTyler Luu       mPending3Asettings |= SetFocus;
31685c859b69b3c003b8db810371e24fe41599fc7deSundar Raman    }
317c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
318aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
319aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    pauseFaceDetection(false);
320aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu
321c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
322c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
323c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
324c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
325c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
326c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
327c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::setFocusCallback(bool enabled)
328c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
329c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
330c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
331c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
332c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
333c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
334c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
335b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng    if ( OMX_StateInvalid == mComponentState )
336b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      {
337b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        CAMHAL_LOGEA("OMX component in Invalid state");
338b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        ret = -EINVAL;
339b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      }
340b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng
341c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateExecuting != mComponentState )
342c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
343b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng          CAMHAL_LOGEA("OMX component not in executing state");
344b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        ret = NO_ERROR;
345c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
346c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
347c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
348c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
349c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
350c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
351c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        focusRequstCallback.nPortIndex = OMX_ALL;
352c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
353c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
354c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( enabled )
355c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
356c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            focusRequstCallback.bEnable = OMX_TRUE;
357c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
358c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        else
359c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
360c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            focusRequstCallback.bEnable = OMX_FALSE;
361c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
362c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
363c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
364c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
365c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                &focusRequstCallback);
366c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( OMX_ErrorNone != eError )
367c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
368c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
369c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            ret = -1;
370c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
371c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        else
372c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
373c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
374c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                         OMX_IndexConfigCommonFocusStatus);
375c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
376c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
377c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
378c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
379c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
380c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
381c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
382c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
383c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
384c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
385c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
386c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
387057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
388bbdc0fa0b8720bcfcf602861f62802c1fa1995c4Tyler Luu    BaseCameraAdapter::AdapterState state, nextState;
389c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    BaseCameraAdapter::getState(state);
390bbdc0fa0b8720bcfcf602861f62802c1fa1995c4Tyler Luu    BaseCameraAdapter::getNextState(nextState);
391c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
392c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
393c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
394c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
395c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
396bbdc0fa0b8720bcfcf602861f62802c1fa1995c4Tyler Luu    if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
397c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev       {
398c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        /// We don't send focus callback if focus was not started
399bbdc0fa0b8720bcfcf602861f62802c1fa1995c4Tyler Luu       CAMHAL_LOGDA("Not sending focus callback because focus was not started");
400c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev       return NO_ERROR;
401c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev       }
402c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
403c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
404c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
405c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
406c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( !timeoutReached )
407c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
408c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            ret = checkFocus(&eFocusStatus);
409c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
410c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            if ( NO_ERROR != ret )
411c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                {
412c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                CAMHAL_LOGEA("Focus status check failed!");
413c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                }
414c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
415c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
416c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
417c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
418c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
419c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
420c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( timeoutReached )
421c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
422057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
423c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
424c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        else
425c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
426c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            switch (eFocusStatus.eFocusStatus)
427c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                {
428c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                    case OMX_FocusStatusReached:
429c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        {
430057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu                        focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS;
431c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        break;
432c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        }
433ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev                    case OMX_FocusStatusOff: // AF got canceled
434ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev                        return NO_ERROR;
435c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                    case OMX_FocusStatusUnableToReach:
436c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                    case OMX_FocusStatusRequest:
437c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                    default:
438c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        {
439057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu                        focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
440c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        break;
441c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                        }
442c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                }
4430e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            // Lock CAF after AF call
4440e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
4457d56715ab78f6b4be347597dc439d598cfe47dc9Sundar Raman                CAMHAL_LOGEA("Error Applying 3A locks");
4460e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            } else {
4477d56715ab78f6b4be347597dc439d598cfe47dc9Sundar Raman                CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
4480e2a9f1fabc12a1a1123f8374d0e4d6faf5a2d62Tyler Luu            }
449c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            stopAutoFocus();
450c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
451ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev
452fd705eb8b757a4f3d1d80b736cf20cade04524d7Tyler Luu        //Query current focus distance after AF is complete
453fd705eb8b757a4f3d1d80b736cf20cade04524d7Tyler Luu        updateFocusDistances(mParameters);
454fd705eb8b757a4f3d1d80b736cf20cade04524d7Tyler Luu       }
455c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
4568cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
457c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
458c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
4598cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman        ret = BaseCameraAdapter::commitState();
4608cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman        }
4618cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman    else
4628cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman        {
4638cb48e582f4f3c93aa25159c1116a7c83bfa388aSundar Raman        ret |= BaseCameraAdapter::rollbackState();
464c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
465c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
466c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
467c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
468c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        notifyFocusSubscribers(focusStatus);
469c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
470c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
471aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    // After focus, face detection will resume sending face callbacks
472aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu    pauseFaceDetection(false);
473aa6e62e279cb54ae76c55ba9f8d02da230ce34e7Tyler Luu
474c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
475c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
476c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
477c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
478c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
479c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
480c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
481c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
482c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
483c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
484c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
485c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
486c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NULL == eFocusStatus )
487c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
488c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEA("Invalid focus status");
489c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = -EINVAL;
490c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
491c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
492b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng    if ( OMX_StateInvalid == mComponentState )
493b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      {
494b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        CAMHAL_LOGEA("OMX component in Invalid state");
495b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        ret = -EINVAL;
496b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng      }
497b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng
498c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateExecuting != mComponentState )
499c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
500c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEA("OMX component not in executing state");
501b192289737a7616f76a1cc236ed3cbc704696c03Akwasi Boateng        ret = NO_ERROR;
502c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
503c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
504c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
505c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
506c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
507c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
508c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                               OMX_IndexConfigCommonFocusStatus,
509c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                               eFocusStatus);
510c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( OMX_ErrorNone != eError )
511c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
512c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
513c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            ret = -1;
514c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
515c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
516c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
517c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
518c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
519c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
520c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
521c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
522c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
523c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
524c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
525c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
526c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
527c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::updateFocusDistances(CameraParameters &params)
528c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
529c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_U32 focusNear, focusOptimal, focusFar;
530c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
531c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
532c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
533c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
534c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
535c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret)
536c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
537c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
538c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            if ( NO_ERROR != ret )
539c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                {
540c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
541c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                }
542c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
543c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    else
544c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
545c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
546c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
547c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
548c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
549c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
550c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
551c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
552c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
553c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
554c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
555c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
556c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError;
557c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
558c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
559c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
560c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
561c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
562c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateInvalid == mComponentState )
563c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
564c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEA("OMX component is in invalid state");
565c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = UNKNOWN_ERROR;
566c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
567c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
568c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
569c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
570c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
571c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
572c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
573c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
574c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
575c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                               &focusDist);
576c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( OMX_ErrorNone != eError )
577c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
578c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
579c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            ret = UNKNOWN_ERROR;
580c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
581c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
582c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
583c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
584c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
585c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
586c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        near = focusDist.nFocusDistanceNear;
587c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        optimal = focusDist.nFocusDistanceOptimal;
588c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        far = focusDist.nFocusDistanceFar;
589c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
590c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
591c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
592c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
593c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
594c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
595c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
596c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
597c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
598c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
599c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    uint32_t focusScale = 1000;
600c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    float distFinal;
601c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
602c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
603c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
604c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
605c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
606c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        dist=0;
607c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
608c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
609c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
610c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
611c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( 0 == dist )
612c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
613c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
614c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
615c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        else
616c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
617c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            distFinal = dist;
618c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            distFinal /= focusScale;
619c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
620c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
621c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
622c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
623c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
624c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
625c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
626c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
627c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
628c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchevstatus_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
629c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                             OMX_U32 &optimal,
630c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                             OMX_U32 &far,
631c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                             CameraParameters& params)
632c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
633c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
634c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
635c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
636c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
637c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
638c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
639c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
640c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( NO_ERROR != ret )
641c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
642c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
643c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
644c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
645c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
646c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
647c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
648c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
649c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( NO_ERROR != ret )
650c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
651c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
652c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
653c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
654c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
655c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
656c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
657c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
658c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( NO_ERROR != ret )
659c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
660c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
661c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
662c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
663c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
664c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
665c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
666c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
667c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                                                              mFocusDistOptimal,
668c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev                                                                              mFocusDistFar);
669c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
670c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
671c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
672c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
673c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
674c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
675c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
676c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
677c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
678708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchevstatus_t OMXCameraAdapter::setTouchFocus()
679c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev{
680c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    status_t ret = NO_ERROR;
681c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    OMX_ERRORTYPE eError = OMX_ErrorNone;
682708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
683708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    OMX_ALGOAREASTYPE **focusAreas;
684708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
685708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    MemoryManager memMgr;
686708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    int areasSize = 0;
687c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
688c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME;
689c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
690c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( OMX_StateInvalid == mComponentState )
691c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
692c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        CAMHAL_LOGEA("OMX component is in invalid state");
693c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        ret = -1;
694c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
695c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
696c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    if ( NO_ERROR == ret )
697c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        {
698c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
699708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
700708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1);
701708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
702708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        OMXCameraPortParameters * mPreviewData = NULL;
703708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
704708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
705708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        if (!focusAreas)
706708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            {
707708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
708708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            return -ENOMEM;
709708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            }
710708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
711708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE);
712708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
713708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        focusAreas[0]->nPortIndex = OMX_ALL;
714708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        focusAreas[0]->nNumAreas = mFocusAreas.size();
715708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
716708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
717708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        // If the area is the special case of (0, 0, 0, 0, 0), then
718708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        // the algorithm needs nNumAreas to be set to 0,
719708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        // in order to automatically choose the best fitting areas.
720708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        if ( mFocusAreas.itemAt(0)->isZeroArea() )
721708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            {
722708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->nNumAreas = 0;
723708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            }
724708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
725708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        for ( unsigned int n = 0; n < mFocusAreas.size(); n++)
726708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            {
727708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            // transform the coordinates to 3A-type coordinates
728708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth,
729708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                            (size_t)mPreviewData->mHeight,
730708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nTop,
731708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft,
732708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth,
733708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight);
734708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
735708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->tAlgoAreas[n].nLeft =
736708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
737708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->tAlgoAreas[n].nTop =
738708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
739708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->tAlgoAreas[n].nWidth =
740708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
741708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->tAlgoAreas[n].nHeight =
742708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
743708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
744708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
745708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev             CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
746708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft,
747708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight,
748708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                    (int)focusAreas[0]->tAlgoAreas[n].nPriority);
749708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev             }
750708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
751708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
752708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
753708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        sharedBuffer.nPortIndex = OMX_ALL;
754708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        sharedBuffer.nSharedBuffSize = areasSize;
755708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0];
756708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
757708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        if ( NULL == sharedBuffer.pSharedBuff )
758708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            {
759708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
760708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            ret = -ENOMEM;
761708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            goto EXIT;
762708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            }
763708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
764708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
765708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev                                      (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
766708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
767c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        if ( OMX_ErrorNone != eError )
768c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
769708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
770708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            ret = -EINVAL;
771c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
772708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev
773708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev    EXIT:
774708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev        if (NULL != focusAreas)
775c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            {
776708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            memMgr.freeBuffer((void*) focusAreas);
777708ed7306c85286aa50d05ba15e0c33106e52ed0Iliyan Malchev            focusAreas = NULL;
778c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev            }
779c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev        }
780c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
781c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    LOG_FUNCTION_NAME_EXIT;
782c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
783c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev    return ret;
784c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev}
785c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev
786057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luuvoid OMXCameraAdapter::handleFocusCallback() {
787057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
788057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
789057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    status_t ret = NO_ERROR;
790057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    BaseCameraAdapter::AdapterState nextState;
791057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    BaseCameraAdapter::getNextState(nextState);
792057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
793057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
794057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
795057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    ret = checkFocus(&eFocusStatus);
796057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
797057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    if (NO_ERROR != ret) {
798057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        CAMHAL_LOGEA("Focus status check failed!");
799057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        // signal and unblock doAutoFocus
800057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        if (AF_ACTIVE & nextState) {
801ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            Mutex::Autolock lock(mDoAFMutex);
802ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev            mDoAFCond.broadcast();
803057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        }
804057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        return;
805ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev    }
806ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev
807ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev    if (eFocusStatus.eFocusStatus != OMX_FocusStatusRequest) {
808057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        // signal doAutoFocus when a end of scan message comes
809057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        // ignore start of scan
810ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev        Mutex::Autolock lock(mDoAFMutex);
811ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev        mDoAFCond.broadcast();
812ac0cf36b98237ec911f49e7b1b93ef6464666e48Emilian Peev    }
813057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
814057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) {
815057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu       CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling");
816057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu       return;
817057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    }
818057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
819057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    // Handling for CAF Callbacks
820057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    switch (eFocusStatus.eFocusStatus) {
821057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        case OMX_FocusStatusRequest:
822057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING;
823057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            break;
824057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        case OMX_FocusStatusReached:
825057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        case OMX_FocusStatusOff:
826057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        case OMX_FocusStatusUnableToReach:
827057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu        default:
828057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            focusStatus = CameraHalEvent::FOCUS_STATUS_DONE;
829057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu            break;
830057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    }
831057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
832057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu    notifyFocusSubscribers(focusStatus);
833057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu}
834057f4fd59ec05ded909e9eb9a3363d9ea345b0caTyler Luu
835c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev};
836