1/*
2 * Copyright (C) Texas Instruments - http://www.ti.com/
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18/**
19* @file OMXFocus.cpp
20*
21* This file contains functionality for handling focus configurations.
22*
23*/
24
25#undef LOG_TAG
26
27#define LOG_TAG "CameraHAL"
28
29#include "CameraHal.h"
30#include "OMXCameraAdapter.h"
31#include "ErrorUtils.h"
32
33#define TOUCH_FOCUS_RANGE 0xFF
34#define AF_IMAGE_CALLBACK_TIMEOUT 5000000 //5 seconds timeout
35#define AF_VIDEO_CALLBACK_TIMEOUT 2800000 //2.8 seconds timeout
36
37namespace android {
38
39status_t OMXCameraAdapter::setParametersFocus(const CameraParameters &params,
40                                              BaseCameraAdapter::AdapterState state)
41{
42    status_t ret = NO_ERROR;
43    const char *str = NULL;
44    Vector< sp<CameraArea> > tempAreas;
45    size_t MAX_FOCUS_AREAS;
46
47    LOG_FUNCTION_NAME;
48
49    Mutex::Autolock lock(mFocusAreasLock);
50
51    str = params.get(CameraParameters::KEY_FOCUS_AREAS);
52
53    MAX_FOCUS_AREAS = atoi(params.get(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
54
55    if ( NULL != str ) {
56        ret = CameraArea::parseAreas(str, ( strlen(str) + 1 ), tempAreas);
57    }
58
59    if ( (NO_ERROR == ret) && CameraArea::areAreasDifferent(mFocusAreas, tempAreas) ) {
60        mFocusAreas.clear();
61        mFocusAreas = tempAreas;
62        if ( MAX_FOCUS_AREAS < mFocusAreas.size() ) {
63            CAMHAL_LOGEB("Focus areas supported %d, focus areas set %d",
64                         MAX_FOCUS_AREAS,
65                         mFocusAreas.size());
66            ret = -EINVAL;
67        }
68        else {
69            if ( !mFocusAreas.isEmpty() ) {
70                setTouchFocus();
71            }
72        }
73    }
74
75    LOG_FUNCTION_NAME;
76
77    return ret;
78}
79
80status_t OMXCameraAdapter::doAutoFocus()
81{
82    status_t ret = NO_ERROR;
83    OMX_ERRORTYPE eError = OMX_ErrorNone;
84    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
85    OMX_PARAM_FOCUSSTATUSTYPE focusStatus;
86    OMX_CONFIG_BOOLEANTYPE bOMX;
87    nsecs_t timeout = 0;
88
89    LOG_FUNCTION_NAME;
90
91    if ( OMX_StateInvalid == mComponentState )
92      {
93        CAMHAL_LOGEA("OMX component in Invalid state");
94        returnFocusStatus(false);
95        return -EINVAL;
96      }
97
98    if ( OMX_StateExecuting != mComponentState )
99        {
100        CAMHAL_LOGEA("OMX component not in executing state");
101        returnFocusStatus(false);
102        return NO_ERROR;
103        }
104
105
106    if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) {
107       CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called");
108       return NO_ERROR;
109    }
110
111    OMX_INIT_STRUCT_PTR (&focusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
112
113    // If the app calls autoFocus, the camera will stop sending face callbacks.
114    pauseFaceDetection(true);
115
116    // This is needed for applying FOCUS_REGION correctly
117    if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
118    {
119    //Disable face priority
120    setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
121
122    //Enable region algorithm priority
123    setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
124    }
125
126    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
127    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
128
129    if (mParameters3A.FocusLock) {
130        // this basically means user never called cancelAutoFocus after a scan...
131        // if this is the case we need to unlock AF to ensure we will do a scan
132        if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
133            CAMHAL_LOGEA("Error Unlocking 3A locks");
134        } else {
135            CAMHAL_LOGDA("AE/AWB unlocked successfully");
136        }
137
138    } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
139        // In case we have CAF running we should first check the AF status.
140        // If it has managed to lock, then do as usual and return status
141        // immediately.
142        ret = checkFocus(&focusStatus);
143        if ( NO_ERROR != ret ) {
144            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
145            return ret;
146        } else {
147            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
148        }
149    }
150
151    if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
152         ( focusStatus.eFocusStatus == OMX_FocusStatusRequest ||
153           focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
154           focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) ||
155            (mParameters3A.Focus !=  (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) )
156        {
157        OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
158        bOMX.bEnabled = OMX_TRUE;
159
160        //Enable focus scanning
161        eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
162                               (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
163                               &bOMX);
164
165        // force AF, Ducati will take care of whether CAF
166        // or AF will be performed, depending on light conditions
167        if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto &&
168             ( focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach ||
169               focusStatus.eFocusStatus == OMX_FocusStatusLost ) ) {
170            focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
171        }
172
173        if ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto )
174            {
175            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
176                                    OMX_IndexConfigFocusControl,
177                                    &focusControl);
178            }
179
180        if ( OMX_ErrorNone != eError ) {
181            CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
182            return INVALID_OPERATION;
183        } else {
184            CAMHAL_LOGDA("Autofocus started successfully");
185        }
186
187        // configure focus timeout based on capture mode
188        timeout = (mCapMode == VIDEO_MODE) ?
189                        ( ( nsecs_t ) AF_VIDEO_CALLBACK_TIMEOUT * 1000 ) :
190                        ( ( nsecs_t ) AF_IMAGE_CALLBACK_TIMEOUT * 1000 );
191
192            {
193            Mutex::Autolock lock(mDoAFMutex);
194            ret = mDoAFCond.waitRelative(mDoAFMutex, timeout);
195            }
196
197        //If somethiing bad happened while we wait
198        if (mComponentState == OMX_StateInvalid) {
199          CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
200          return -EINVAL;
201        }
202
203        if(ret != NO_ERROR) {
204            CAMHAL_LOGEA("Autofocus callback timeout expired");
205            ret = returnFocusStatus(true);
206        } else {
207            ret = returnFocusStatus(false);
208        }
209    } else { // Focus mode in continuous
210        if ( NO_ERROR == ret ) {
211            ret = returnFocusStatus(true);
212            mPending3Asettings |= SetFocus;
213        }
214    }
215
216    LOG_FUNCTION_NAME_EXIT;
217
218    return ret;
219}
220
221status_t OMXCameraAdapter::stopAutoFocus()
222{
223    OMX_ERRORTYPE eError = OMX_ErrorNone;
224    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
225
226    LOG_FUNCTION_NAME;
227
228    if ( OMX_StateInvalid == mComponentState )
229      {
230        CAMHAL_LOGEA("OMX component in Invalid state");
231        returnFocusStatus(false);
232        return -EINVAL;
233      }
234
235    if ( OMX_StateExecuting != mComponentState )
236        {
237          CAMHAL_LOGEA("OMX component not in executing state");
238        return NO_ERROR;
239        }
240
241    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
242        // No need to stop focus if we are in infinity mode. Nothing to stop.
243        return NO_ERROR;
244    }
245
246    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
247    focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
248
249    eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
250                            OMX_IndexConfigFocusControl,
251                            &focusControl);
252    if ( OMX_ErrorNone != eError )
253        {
254        CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
255        return ErrorUtils::omxToAndroidError(eError);
256    } else {
257        // This is a WA. Usually the OMX Camera component should
258        // generate AF status change OMX event fairly quickly
259        // ( after one preview frame ) and this notification should
260        // actually come from 'handleFocusCallback()'.
261        Mutex::Autolock lock(mDoAFMutex);
262        mDoAFCond.broadcast();
263    }
264
265
266    LOG_FUNCTION_NAME_EXIT;
267
268    return NO_ERROR;
269}
270
271status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
272{;
273    OMX_ERRORTYPE eError = OMX_ErrorNone;
274
275    LOG_FUNCTION_NAME;
276
277    if ( OMX_StateInvalid == mComponentState ) {
278        CAMHAL_LOGEA("OMX component is in invalid state");
279        return NO_INIT;
280    }
281
282    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
283    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
284
285    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
286                            OMX_IndexConfigFocusControl,
287                            &focusMode);
288
289    if ( OMX_ErrorNone != eError ) {
290        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
291    }
292
293    LOG_FUNCTION_NAME_EXIT;
294
295    return ErrorUtils::omxToAndroidError(eError);
296}
297
298status_t OMXCameraAdapter::cancelAutoFocus()
299{
300    status_t ret = NO_ERROR;
301    OMX_ERRORTYPE eError = OMX_ErrorNone;
302    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
303
304    LOG_FUNCTION_NAME;
305
306    ret = getFocusMode(focusMode);
307    if ( NO_ERROR != ret ) {
308        return ret;
309    }
310
311    //Stop the AF only for modes other than CAF  or Inifinity
312    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
313         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
314                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
315        stopAutoFocus();
316    } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
317       // This re-enabling of CAF doesn't seem to
318       // be needed any more.
319       // re-apply CAF after unlocking and canceling
320       // mPending3Asettings |= SetFocus;
321    }
322    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
323    pauseFaceDetection(false);
324
325    LOG_FUNCTION_NAME_EXIT;
326
327    return ret;
328
329}
330
331status_t OMXCameraAdapter::setFocusCallback(bool enabled)
332{
333    status_t ret = NO_ERROR;
334    OMX_ERRORTYPE eError = OMX_ErrorNone;
335    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
336
337    LOG_FUNCTION_NAME;
338
339    if ( OMX_StateInvalid == mComponentState )
340      {
341        CAMHAL_LOGEA("OMX component in Invalid state");
342        ret = -EINVAL;
343      }
344
345    if ( OMX_StateExecuting != mComponentState )
346        {
347          CAMHAL_LOGEA("OMX component not in executing state");
348        ret = NO_ERROR;
349        }
350
351    if ( NO_ERROR == ret )
352        {
353
354        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
355        focusRequstCallback.nPortIndex = OMX_ALL;
356        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
357
358        if ( enabled )
359            {
360            focusRequstCallback.bEnable = OMX_TRUE;
361            }
362        else
363            {
364            focusRequstCallback.bEnable = OMX_FALSE;
365            }
366
367        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
368                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
369                                &focusRequstCallback);
370        if ( OMX_ErrorNone != eError )
371            {
372            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
373            ret = -1;
374            }
375        else
376            {
377            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
378                         OMX_IndexConfigCommonFocusStatus);
379            }
380        }
381
382    LOG_FUNCTION_NAME_EXIT;
383
384    return ret;
385}
386
387status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
388{
389    status_t ret = NO_ERROR;
390    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
391    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
392    BaseCameraAdapter::AdapterState state, nextState;
393    BaseCameraAdapter::getState(state);
394    BaseCameraAdapter::getNextState(nextState);
395
396    LOG_FUNCTION_NAME;
397
398    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
399
400    if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
401       {
402        /// We don't send focus callback if focus was not started
403       CAMHAL_LOGDA("Not sending focus callback because focus was not started");
404       return NO_ERROR;
405       }
406
407    if ( NO_ERROR == ret )
408        {
409
410        if ( !timeoutReached )
411            {
412            ret = checkFocus(&eFocusStatus);
413
414            if ( NO_ERROR != ret )
415                {
416                CAMHAL_LOGEA("Focus status check failed!");
417                }
418            }
419        }
420
421    if ( NO_ERROR == ret )
422        {
423
424        if ( timeoutReached )
425            {
426            focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
427            }
428        else
429            {
430            switch (eFocusStatus.eFocusStatus)
431                {
432                    case OMX_FocusStatusReached:
433                        {
434                        focusStatus = CameraHalEvent::FOCUS_STATUS_SUCCESS;
435                        break;
436                        }
437                    case OMX_FocusStatusOff: // AF got canceled
438                        return NO_ERROR;
439                    case OMX_FocusStatusUnableToReach:
440                    case OMX_FocusStatusRequest:
441                    default:
442                        {
443                        focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
444                        break;
445                        }
446                }
447            // Lock CAF after AF call
448            if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
449                CAMHAL_LOGEA("Error Applying 3A locks");
450            } else {
451                CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
452            }
453            stopAutoFocus();
454            }
455
456        //Query current focus distance after AF is complete
457        updateFocusDistances(mParameters);
458       }
459
460    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
461    if ( NO_ERROR == ret )
462        {
463        ret = BaseCameraAdapter::commitState();
464        }
465    else
466        {
467        ret |= BaseCameraAdapter::rollbackState();
468        }
469
470    if ( NO_ERROR == ret )
471        {
472        notifyFocusSubscribers(focusStatus);
473        }
474
475    // After focus, face detection will resume sending face callbacks
476    pauseFaceDetection(false);
477
478    LOG_FUNCTION_NAME_EXIT;
479
480    return ret;
481}
482
483status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
484{
485    status_t ret = NO_ERROR;
486    OMX_ERRORTYPE eError = OMX_ErrorNone;
487
488    LOG_FUNCTION_NAME;
489
490    if ( NULL == eFocusStatus )
491        {
492        CAMHAL_LOGEA("Invalid focus status");
493        ret = -EINVAL;
494        }
495
496    if ( OMX_StateInvalid == mComponentState )
497      {
498        CAMHAL_LOGEA("OMX component in Invalid state");
499        ret = -EINVAL;
500      }
501
502    if ( OMX_StateExecuting != mComponentState )
503        {
504        CAMHAL_LOGEA("OMX component not in executing state");
505        ret = NO_ERROR;
506        }
507
508    if ( NO_ERROR == ret )
509        {
510        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
511        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
512                               OMX_IndexConfigCommonFocusStatus,
513                               eFocusStatus);
514        if ( OMX_ErrorNone != eError )
515            {
516            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
517            ret = -1;
518            }
519        }
520
521    if ( NO_ERROR == ret )
522        {
523        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
524        }
525
526    LOG_FUNCTION_NAME_EXIT;
527
528    return ret;
529}
530
531status_t OMXCameraAdapter::updateFocusDistances(CameraParameters &params)
532{
533    OMX_U32 focusNear, focusOptimal, focusFar;
534    status_t ret = NO_ERROR;
535
536    LOG_FUNCTION_NAME;
537
538    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
539    if ( NO_ERROR == ret)
540        {
541        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
542            if ( NO_ERROR != ret )
543                {
544                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
545                }
546        }
547    else
548        {
549        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
550        }
551
552    LOG_FUNCTION_NAME_EXIT;
553
554    return ret;
555}
556
557status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
558{
559    status_t ret = NO_ERROR;
560    OMX_ERRORTYPE eError;
561
562    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
563
564    LOG_FUNCTION_NAME;
565
566    if ( OMX_StateInvalid == mComponentState )
567        {
568        CAMHAL_LOGEA("OMX component is in invalid state");
569        ret = UNKNOWN_ERROR;
570        }
571
572    if ( NO_ERROR == ret )
573        {
574        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
575        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
576
577        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
578                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
579                               &focusDist);
580        if ( OMX_ErrorNone != eError )
581            {
582            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
583            ret = UNKNOWN_ERROR;
584            }
585
586        }
587
588    if ( NO_ERROR == ret )
589        {
590        near = focusDist.nFocusDistanceNear;
591        optimal = focusDist.nFocusDistanceOptimal;
592        far = focusDist.nFocusDistanceFar;
593        }
594
595    LOG_FUNCTION_NAME_EXIT;
596
597    return ret;
598}
599
600status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
601{
602    status_t ret = NO_ERROR;
603    uint32_t focusScale = 1000;
604    float distFinal;
605
606    LOG_FUNCTION_NAME;
607
608    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
609        {
610        dist=0;
611        }
612
613    if ( NO_ERROR == ret )
614        {
615        if ( 0 == dist )
616            {
617            strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
618            }
619        else
620            {
621            distFinal = dist;
622            distFinal /= focusScale;
623            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
624            }
625        }
626
627    LOG_FUNCTION_NAME_EXIT;
628
629    return ret;
630}
631
632status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
633                                             OMX_U32 &optimal,
634                                             OMX_U32 &far,
635                                             CameraParameters& params)
636{
637    status_t ret = NO_ERROR;
638
639    LOG_FUNCTION_NAME;
640
641    if ( NO_ERROR == ret )
642        {
643        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
644        if ( NO_ERROR != ret )
645            {
646            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
647            }
648        }
649
650    if ( NO_ERROR == ret )
651        {
652        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
653        if ( NO_ERROR != ret )
654            {
655            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
656            }
657        }
658
659    if ( NO_ERROR == ret )
660        {
661        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
662        if ( NO_ERROR != ret )
663            {
664            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
665            }
666        }
667
668    if ( NO_ERROR == ret )
669        {
670        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
671                                                                              mFocusDistOptimal,
672                                                                              mFocusDistFar);
673
674        params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
675        }
676
677    LOG_FUNCTION_NAME_EXIT;
678
679    return ret;
680}
681
682status_t OMXCameraAdapter::setTouchFocus()
683{
684    status_t ret = NO_ERROR;
685    OMX_ERRORTYPE eError = OMX_ErrorNone;
686
687    OMX_ALGOAREASTYPE **focusAreas;
688    OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
689    MemoryManager memMgr;
690    int areasSize = 0;
691
692    LOG_FUNCTION_NAME;
693
694    if ( OMX_StateInvalid == mComponentState )
695        {
696        CAMHAL_LOGEA("OMX component is in invalid state");
697        ret = -1;
698        }
699
700    if ( NO_ERROR == ret )
701        {
702
703        areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
704        focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1);
705
706        OMXCameraPortParameters * mPreviewData = NULL;
707        mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
708
709        if (!focusAreas)
710            {
711            CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
712            return -ENOMEM;
713            }
714
715        OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE);
716
717        focusAreas[0]->nPortIndex = OMX_ALL;
718        focusAreas[0]->nNumAreas = mFocusAreas.size();
719        focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
720
721        // If the area is the special case of (0, 0, 0, 0, 0), then
722        // the algorithm needs nNumAreas to be set to 0,
723        // in order to automatically choose the best fitting areas.
724        if ( mFocusAreas.itemAt(0)->isZeroArea() )
725            {
726            focusAreas[0]->nNumAreas = 0;
727            }
728
729        for ( unsigned int n = 0; n < mFocusAreas.size(); n++)
730            {
731            // transform the coordinates to 3A-type coordinates
732            mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth,
733                                            (size_t)mPreviewData->mHeight,
734                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nTop,
735                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft,
736                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth,
737                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight);
738
739            focusAreas[0]->tAlgoAreas[n].nLeft =
740                    ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
741            focusAreas[0]->tAlgoAreas[n].nTop =
742                    ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
743            focusAreas[0]->tAlgoAreas[n].nWidth =
744                    ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
745            focusAreas[0]->tAlgoAreas[n].nHeight =
746                    ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
747            focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
748
749             CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
750                    n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft,
751                    (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight,
752                    (int)focusAreas[0]->tAlgoAreas[n].nPriority);
753             }
754
755        OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
756
757        sharedBuffer.nPortIndex = OMX_ALL;
758        sharedBuffer.nSharedBuffSize = areasSize;
759        sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0];
760
761        if ( NULL == sharedBuffer.pSharedBuff )
762            {
763            CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
764            ret = -ENOMEM;
765            goto EXIT;
766            }
767
768            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
769                                      (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
770
771        if ( OMX_ErrorNone != eError )
772            {
773            CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
774            ret = -EINVAL;
775            }
776
777    EXIT:
778        if (NULL != focusAreas)
779            {
780            memMgr.freeBuffer((void*) focusAreas);
781            focusAreas = NULL;
782            }
783        }
784
785    LOG_FUNCTION_NAME_EXIT;
786
787    return ret;
788}
789
790void OMXCameraAdapter::handleFocusCallback() {
791    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
792    CameraHalEvent::FocusStatus focusStatus = CameraHalEvent::FOCUS_STATUS_FAIL;
793    status_t ret = NO_ERROR;
794    BaseCameraAdapter::AdapterState nextState;
795    BaseCameraAdapter::getNextState(nextState);
796
797    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
798
799    ret = checkFocus(&eFocusStatus);
800
801    if (NO_ERROR != ret) {
802        CAMHAL_LOGEA("Focus status check failed!");
803        // signal and unblock doAutoFocus
804        if (AF_ACTIVE & nextState) {
805            Mutex::Autolock lock(mDoAFMutex);
806            mDoAFCond.broadcast();
807        }
808        return;
809    }
810
811    if ( ( eFocusStatus.eFocusStatus != OMX_FocusStatusRequest ) &&
812         ( eFocusStatus.eFocusStatus != OMX_FocusStatusOff ) ) {
813        // signal doAutoFocus when a end of scan message comes
814        // ignore start of scan
815        Mutex::Autolock lock(mDoAFMutex);
816        mDoAFCond.broadcast();
817    }
818
819    if (mParameters3A.Focus != (OMX_IMAGE_FOCUSCONTROLTYPE) OMX_IMAGE_FocusControlAuto) {
820       CAMHAL_LOGDA("unregistered focus callback when not in CAF or doAutoFocus... not handling");
821       return;
822    }
823
824    // Handling for CAF Callbacks
825    switch (eFocusStatus.eFocusStatus) {
826        case OMX_FocusStatusRequest:
827            focusStatus = CameraHalEvent::FOCUS_STATUS_PENDING;
828            break;
829        case OMX_FocusStatusReached:
830        case OMX_FocusStatusOff:
831        case OMX_FocusStatusUnableToReach:
832        default:
833            focusStatus = CameraHalEvent::FOCUS_STATUS_DONE;
834            break;
835    }
836
837    notifyFocusSubscribers(focusStatus);
838}
839
840};
841