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    int 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    if ( 0 != mDoAFSem.Count() )
106        {
107        CAMHAL_LOGEB("Error mDoAFSem semaphore count %d", mDoAFSem.Count());
108        return NO_INIT;
109        }
110
111    if( ((AF_ACTIVE & getState()) != AF_ACTIVE) && ((AF_ACTIVE & getNextState()) != AF_ACTIVE) ) {
112       CAMHAL_LOGDA("Auto focus got canceled before doAutoFocus could be called");
113       return NO_ERROR;
114    }
115
116    // If the app calls autoFocus, the camera will stop sending face callbacks.
117    pauseFaceDetection(true);
118
119    // This is needed for applying FOCUS_REGION correctly
120    if ( (!mFocusAreas.isEmpty()) && (!mFocusAreas.itemAt(0)->isZeroArea()))
121    {
122    //Disable face priority
123    setAlgoPriority(FACE_PRIORITY, FOCUS_ALGO, false);
124
125    //Enable region algorithm priority
126    setAlgoPriority(REGION_PRIORITY, FOCUS_ALGO, true);
127    }
128
129    OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
130    focusControl.eFocusControl = ( OMX_IMAGE_FOCUSCONTROLTYPE ) mParameters3A.Focus;
131
132    if (mParameters3A.FocusLock) {
133        // this basically means user never called cancelAutoFocus after a scan...
134        // if this is the case we need to unlock AF to ensure we will do a scan
135        if (set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_FALSE) != NO_ERROR) {
136            CAMHAL_LOGEA("Error Unlocking 3A locks");
137        } else {
138            CAMHAL_LOGDA("AE/AWB unlocked successfully");
139        }
140
141    } else if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAuto ) {
142        // In case we have CAF running we should first check the AF status.
143        // If it has managed to lock, then do as usual and return status
144        // immediately. If lock is not available, then switch temporarily
145        // to 'autolock' and do normal AF.
146        ret = checkFocus(&focusStatus);
147        if ( NO_ERROR != ret ) {
148            CAMHAL_LOGEB("Focus status check failed 0x%x!", ret);
149            return ret;
150        } else {
151            CAMHAL_LOGDB("Focus status check 0x%x!", focusStatus.eFocusStatus);
152        }
153    }
154
155    if ( (focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto
156            && (focusStatus.eFocusStatus == OMX_FocusStatusRequest
157             || focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach) ) ||
158            (mParameters3A.Focus !=  (OMX_IMAGE_FOCUSCONTROLTYPE)OMX_IMAGE_FocusControlAuto) )
159        {
160        OMX_INIT_STRUCT_PTR (&bOMX, OMX_CONFIG_BOOLEANTYPE);
161        bOMX.bEnabled = OMX_TRUE;
162
163        //Enable focus scanning
164        eError = OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
165                               (OMX_INDEXTYPE)OMX_TI_IndexConfigAutofocusEnable,
166                               &bOMX);
167
168        ret = RegisterForEvent(mCameraAdapterParameters.mHandleComp,
169                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
170                                    OMX_ALL,
171                                    OMX_IndexConfigCommonFocusStatus,
172                                    mDoAFSem);
173
174        // force AF, Ducati will take care of whether CAF
175        // or AF will be performed, depending on light conditions
176        if ( focusControl.eFocusControl == OMX_IMAGE_FocusControlAuto
177		&& focusStatus.eFocusStatus == OMX_FocusStatusUnableToReach )
178			{
179			focusControl.eFocusControl = OMX_IMAGE_FocusControlAutoLock;
180			}
181
182        if ( focusControl.eFocusControl != OMX_IMAGE_FocusControlAuto )
183            {
184            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
185                                    OMX_IndexConfigFocusControl,
186                                    &focusControl);
187            }
188
189        if ( OMX_ErrorNone != eError ) {
190            CAMHAL_LOGEB("Error while starting focus 0x%x", eError);
191            return INVALID_OPERATION;
192        } else {
193            CAMHAL_LOGDA("Autofocus started successfully");
194        }
195
196        // configure focus timeout based on capture mode
197        timeout = (mCapMode == VIDEO_MODE) ? AF_VIDEO_CALLBACK_TIMEOUT : AF_IMAGE_CALLBACK_TIMEOUT;
198
199        ret = mDoAFSem.WaitTimeout(timeout);
200        //If somethiing bad happened while we wait
201        if (mComponentState == OMX_StateInvalid) {
202          CAMHAL_LOGEA("Invalid State after Auto Focus Exitting!!!");
203          return EINVAL;
204        }
205
206        if( ret != NO_ERROR) {
207            //Disable auto focus callback from Ducati
208            setFocusCallback(false);
209            CAMHAL_LOGEA("Autofocus callback timeout expired");
210            RemoveEvent(mCameraAdapterParameters.mHandleComp,
211                                        (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
212                                        OMX_ALL,
213                                        OMX_IndexConfigCommonFocusStatus,
214                                        NULL );
215            returnFocusStatus(true);
216        } else {
217            ret = returnFocusStatus(false);
218        }
219    } else { // Focus mode in continuous
220        if ( NO_ERROR == ret ) {
221            ret = returnFocusStatus(false);
222            mPending3Asettings |= SetFocus;
223        }
224    }
225
226    LOG_FUNCTION_NAME_EXIT;
227
228    return ret;
229}
230
231status_t OMXCameraAdapter::stopAutoFocus()
232{
233    status_t ret = NO_ERROR;
234    OMX_ERRORTYPE eError = OMX_ErrorNone;
235    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusControl;
236
237    LOG_FUNCTION_NAME;
238
239    if ( OMX_StateInvalid == mComponentState )
240      {
241        CAMHAL_LOGEA("OMX component in Invalid state");
242        returnFocusStatus(false);
243        return -EINVAL;
244      }
245
246    if ( OMX_StateExecuting != mComponentState )
247        {
248          CAMHAL_LOGEA("OMX component not in executing state");
249        return NO_ERROR;
250        }
251
252    if ( mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity ) {
253        // No need to stop focus if we are in infinity mode. Nothing to stop.
254        return NO_ERROR;
255    }
256
257    if ( NO_ERROR == ret )
258        {
259        OMX_INIT_STRUCT_PTR (&focusControl, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
260        focusControl.eFocusControl = OMX_IMAGE_FocusControlOff;
261
262        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
263                                OMX_IndexConfigFocusControl,
264                                &focusControl);
265        if ( OMX_ErrorNone != eError )
266            {
267            CAMHAL_LOGEB("Error while stopping focus 0x%x", eError);
268            return ErrorUtils::omxToAndroidError(eError);
269            }
270        }
271
272    LOG_FUNCTION_NAME_EXIT;
273
274    return ret;
275}
276
277status_t OMXCameraAdapter::getFocusMode(OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE &focusMode)
278{;
279    OMX_ERRORTYPE eError = OMX_ErrorNone;
280
281    LOG_FUNCTION_NAME;
282
283    if ( OMX_StateInvalid == mComponentState ) {
284        CAMHAL_LOGEA("OMX component is in invalid state");
285        return NO_INIT;
286    }
287
288    OMX_INIT_STRUCT_PTR (&focusMode, OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE);
289    focusMode.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
290
291    eError =  OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
292                            OMX_IndexConfigFocusControl,
293                            &focusMode);
294
295    if ( OMX_ErrorNone != eError ) {
296        CAMHAL_LOGEB("Error while retrieving focus mode 0x%x", eError);
297    }
298
299    LOG_FUNCTION_NAME_EXIT;
300
301    return ErrorUtils::omxToAndroidError(eError);
302}
303
304status_t OMXCameraAdapter::cancelAutoFocus()
305{
306    status_t ret = NO_ERROR;
307    OMX_ERRORTYPE eError = OMX_ErrorNone;
308    OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE focusMode;
309
310    LOG_FUNCTION_NAME;
311
312    ret = getFocusMode(focusMode);
313    if ( NO_ERROR != ret ) {
314        return ret;
315    }
316
317    //Stop the AF only for modes other than CAF  or Inifinity
318    if ( ( focusMode.eFocusControl != OMX_IMAGE_FocusControlAuto ) &&
319         ( focusMode.eFocusControl != ( OMX_IMAGE_FOCUSCONTROLTYPE )
320                 OMX_IMAGE_FocusControlAutoInfinity ) ) {
321        stopAutoFocus();
322        //Signal a dummy AF event so that in case the callback from ducati
323        //does come then it doesnt crash after
324        //exiting this function since eventSem will go out of scope.
325        ret |= SignalEvent(mCameraAdapterParameters.mHandleComp,
326                                    (OMX_EVENTTYPE) OMX_EventIndexSettingChanged,
327                                    OMX_ALL,
328                                    OMX_IndexConfigCommonFocusStatus,
329                                    NULL );
330    } else if (focusMode.eFocusControl == OMX_IMAGE_FocusControlAuto) {
331       // re-apply CAF after unlocking and canceling
332       mPending3Asettings |= SetFocus;
333    }
334
335    // If the apps call #cancelAutoFocus()}, the face callbacks will also resume.
336    pauseFaceDetection(false);
337
338    LOG_FUNCTION_NAME_EXIT;
339
340    return ret;
341
342}
343
344status_t OMXCameraAdapter::setFocusCallback(bool enabled)
345{
346    status_t ret = NO_ERROR;
347    OMX_ERRORTYPE eError = OMX_ErrorNone;
348    OMX_CONFIG_CALLBACKREQUESTTYPE focusRequstCallback;
349
350    LOG_FUNCTION_NAME;
351
352    if ( OMX_StateInvalid == mComponentState )
353      {
354        CAMHAL_LOGEA("OMX component in Invalid state");
355        ret = -EINVAL;
356      }
357
358    if ( OMX_StateExecuting != mComponentState )
359        {
360          CAMHAL_LOGEA("OMX component not in executing state");
361        ret = NO_ERROR;
362        }
363
364    if ( NO_ERROR == ret )
365        {
366
367        OMX_INIT_STRUCT_PTR (&focusRequstCallback, OMX_CONFIG_CALLBACKREQUESTTYPE);
368        focusRequstCallback.nPortIndex = OMX_ALL;
369        focusRequstCallback.nIndex = OMX_IndexConfigCommonFocusStatus;
370
371        if ( enabled )
372            {
373            focusRequstCallback.bEnable = OMX_TRUE;
374            }
375        else
376            {
377            focusRequstCallback.bEnable = OMX_FALSE;
378            }
379
380        eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
381                                (OMX_INDEXTYPE) OMX_IndexConfigCallbackRequest,
382                                &focusRequstCallback);
383        if ( OMX_ErrorNone != eError )
384            {
385            CAMHAL_LOGEB("Error registering focus callback 0x%x", eError);
386            ret = -1;
387            }
388        else
389            {
390            CAMHAL_LOGDB("Autofocus callback for index 0x%x registered successfully",
391                         OMX_IndexConfigCommonFocusStatus);
392            }
393        }
394
395    LOG_FUNCTION_NAME_EXIT;
396
397    return ret;
398}
399
400status_t OMXCameraAdapter::returnFocusStatus(bool timeoutReached)
401{
402    status_t ret = NO_ERROR;
403    OMX_PARAM_FOCUSSTATUSTYPE eFocusStatus;
404    bool focusStatus = false;
405    BaseCameraAdapter::AdapterState state, nextState;
406    BaseCameraAdapter::getState(state);
407    BaseCameraAdapter::getNextState(nextState);
408
409    LOG_FUNCTION_NAME;
410
411    OMX_INIT_STRUCT(eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
412
413    if( ((AF_ACTIVE & state ) != AF_ACTIVE) && ((AF_ACTIVE & nextState ) != AF_ACTIVE) )
414       {
415        /// We don't send focus callback if focus was not started
416       CAMHAL_LOGDA("Not sending focus callback because focus was not started");
417       return NO_ERROR;
418       }
419
420    if ( NO_ERROR == ret )
421        {
422
423        if ( !timeoutReached )
424            {
425            ret = checkFocus(&eFocusStatus);
426
427            if ( NO_ERROR != ret )
428                {
429                CAMHAL_LOGEA("Focus status check failed!");
430                }
431            }
432        }
433
434    if ( NO_ERROR == ret )
435        {
436
437        if ( timeoutReached )
438            {
439            focusStatus = false;
440            }
441        else
442            {
443            switch (eFocusStatus.eFocusStatus)
444                {
445                    case OMX_FocusStatusReached:
446                        {
447                        focusStatus = true;
448                        break;
449                        }
450                    case OMX_FocusStatusOff:
451                    case OMX_FocusStatusUnableToReach:
452                    case OMX_FocusStatusRequest:
453                    default:
454                        {
455                        focusStatus = false;
456                        break;
457                        }
458                }
459            // Lock CAF after AF call
460            if( set3ALock(mUserSetExpLock, mUserSetWbLock, OMX_TRUE) != NO_ERROR) {
461                CAMHAL_LOGEA("Error Applying 3A locks");
462            } else {
463                CAMHAL_LOGDA("Focus locked. Applied focus locks successfully");
464            }
465
466            stopAutoFocus();
467            }
468        //Query current focus distance after AF is complete
469        updateFocusDistances(mParameters);
470       }
471
472    ret =  BaseCameraAdapter::setState(CAMERA_CANCEL_AUTOFOCUS);
473    if ( NO_ERROR == ret )
474        {
475        ret = BaseCameraAdapter::commitState();
476        }
477    else
478        {
479        ret |= BaseCameraAdapter::rollbackState();
480        }
481
482    if ( NO_ERROR == ret )
483        {
484        notifyFocusSubscribers(focusStatus);
485        }
486
487    // After focus, face detection will resume sending face callbacks
488    pauseFaceDetection(false);
489
490    LOG_FUNCTION_NAME_EXIT;
491
492    return ret;
493}
494
495status_t OMXCameraAdapter::checkFocus(OMX_PARAM_FOCUSSTATUSTYPE *eFocusStatus)
496{
497    status_t ret = NO_ERROR;
498    OMX_ERRORTYPE eError = OMX_ErrorNone;
499
500    LOG_FUNCTION_NAME;
501
502    if ( NULL == eFocusStatus )
503        {
504        CAMHAL_LOGEA("Invalid focus status");
505        ret = -EINVAL;
506        }
507
508    if ( OMX_StateInvalid == mComponentState )
509      {
510        CAMHAL_LOGEA("OMX component in Invalid state");
511        ret = -EINVAL;
512      }
513
514    if ( OMX_StateExecuting != mComponentState )
515        {
516        CAMHAL_LOGEA("OMX component not in executing state");
517        ret = NO_ERROR;
518        }
519
520    if ( NO_ERROR == ret )
521        {
522        OMX_INIT_STRUCT_PTR (eFocusStatus, OMX_PARAM_FOCUSSTATUSTYPE);
523
524        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
525                               OMX_IndexConfigCommonFocusStatus,
526                               eFocusStatus);
527        if ( OMX_ErrorNone != eError )
528            {
529            CAMHAL_LOGEB("Error while retrieving focus status: 0x%x", eError);
530            ret = -1;
531            }
532        }
533
534    if ( NO_ERROR == ret )
535        {
536        CAMHAL_LOGDB("Focus Status: %d", eFocusStatus->eFocusStatus);
537        }
538
539    LOG_FUNCTION_NAME_EXIT;
540
541    return ret;
542}
543
544status_t OMXCameraAdapter::updateFocusDistances(CameraParameters &params)
545{
546    OMX_U32 focusNear, focusOptimal, focusFar;
547    status_t ret = NO_ERROR;
548
549    LOG_FUNCTION_NAME;
550
551    ret = getFocusDistances(focusNear, focusOptimal, focusFar);
552    if ( NO_ERROR == ret)
553        {
554        ret = addFocusDistances(focusNear, focusOptimal, focusFar, params);
555            if ( NO_ERROR != ret )
556                {
557                CAMHAL_LOGEB("Error in call to addFocusDistances() 0x%x", ret);
558                }
559        }
560    else
561        {
562        CAMHAL_LOGEB("Error in call to getFocusDistances() 0x%x", ret);
563        }
564
565    LOG_FUNCTION_NAME_EXIT;
566
567    return ret;
568}
569
570status_t OMXCameraAdapter::getFocusDistances(OMX_U32 &near,OMX_U32 &optimal, OMX_U32 &far)
571{
572    status_t ret = NO_ERROR;
573    OMX_ERRORTYPE eError;
574
575    OMX_TI_CONFIG_FOCUSDISTANCETYPE focusDist;
576
577    LOG_FUNCTION_NAME;
578
579    if ( OMX_StateInvalid == mComponentState )
580        {
581        CAMHAL_LOGEA("OMX component is in invalid state");
582        ret = UNKNOWN_ERROR;
583        }
584
585    if ( NO_ERROR == ret )
586        {
587        OMX_INIT_STRUCT_PTR(&focusDist, OMX_TI_CONFIG_FOCUSDISTANCETYPE);
588        focusDist.nPortIndex = mCameraAdapterParameters.mPrevPortIndex;
589
590        eError = OMX_GetConfig(mCameraAdapterParameters.mHandleComp,
591                               ( OMX_INDEXTYPE ) OMX_TI_IndexConfigFocusDistance,
592                               &focusDist);
593        if ( OMX_ErrorNone != eError )
594            {
595            CAMHAL_LOGEB("Error while querying focus distances 0x%x", eError);
596            ret = UNKNOWN_ERROR;
597            }
598
599        }
600
601    if ( NO_ERROR == ret )
602        {
603        near = focusDist.nFocusDistanceNear;
604        optimal = focusDist.nFocusDistanceOptimal;
605        far = focusDist.nFocusDistanceFar;
606        }
607
608    LOG_FUNCTION_NAME_EXIT;
609
610    return ret;
611}
612
613status_t OMXCameraAdapter::encodeFocusDistance(OMX_U32 dist, char *buffer, size_t length)
614{
615    status_t ret = NO_ERROR;
616    uint32_t focusScale = 1000;
617    float distFinal;
618
619    LOG_FUNCTION_NAME;
620
621    if(mParameters3A.Focus == OMX_IMAGE_FocusControlAutoInfinity)
622        {
623        dist=0;
624        }
625
626    if ( NO_ERROR == ret )
627        {
628        if ( 0 == dist )
629            {
630            strncpy(buffer, CameraParameters::FOCUS_DISTANCE_INFINITY, ( length - 1 ));
631            }
632        else
633            {
634            distFinal = dist;
635            distFinal /= focusScale;
636            snprintf(buffer, ( length - 1 ) , "%5.3f", distFinal);
637            }
638        }
639
640    LOG_FUNCTION_NAME_EXIT;
641
642    return ret;
643}
644
645status_t OMXCameraAdapter::addFocusDistances(OMX_U32 &near,
646                                             OMX_U32 &optimal,
647                                             OMX_U32 &far,
648                                             CameraParameters& params)
649{
650    status_t ret = NO_ERROR;
651
652    LOG_FUNCTION_NAME;
653
654    if ( NO_ERROR == ret )
655        {
656        ret = encodeFocusDistance(near, mFocusDistNear, FOCUS_DIST_SIZE);
657        if ( NO_ERROR != ret )
658            {
659            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
660            }
661        }
662
663    if ( NO_ERROR == ret )
664        {
665        ret = encodeFocusDistance(optimal, mFocusDistOptimal, FOCUS_DIST_SIZE);
666        if ( NO_ERROR != ret )
667            {
668            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
669            }
670        }
671
672    if ( NO_ERROR == ret )
673        {
674        ret = encodeFocusDistance(far, mFocusDistFar, FOCUS_DIST_SIZE);
675        if ( NO_ERROR != ret )
676            {
677            CAMHAL_LOGEB("Error encoding near focus distance 0x%x", ret);
678            }
679        }
680
681    if ( NO_ERROR == ret )
682        {
683        snprintf(mFocusDistBuffer, ( FOCUS_DIST_BUFFER_SIZE - 1) ,"%s,%s,%s", mFocusDistNear,
684                                                                              mFocusDistOptimal,
685                                                                              mFocusDistFar);
686
687        params.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistBuffer);
688        }
689
690    LOG_FUNCTION_NAME_EXIT;
691
692    return ret;
693}
694
695status_t OMXCameraAdapter::setTouchFocus()
696{
697    status_t ret = NO_ERROR;
698    OMX_ERRORTYPE eError = OMX_ErrorNone;
699
700    OMX_ALGOAREASTYPE **focusAreas;
701    OMX_TI_CONFIG_SHAREDBUFFER sharedBuffer;
702    MemoryManager memMgr;
703    int areasSize = 0;
704
705    LOG_FUNCTION_NAME;
706
707    if ( OMX_StateInvalid == mComponentState )
708        {
709        CAMHAL_LOGEA("OMX component is in invalid state");
710        ret = -1;
711        }
712
713    if ( NO_ERROR == ret )
714        {
715
716        areasSize = ((sizeof(OMX_ALGOAREASTYPE)+4095)/4096)*4096;
717        focusAreas = (OMX_ALGOAREASTYPE**) memMgr.allocateBuffer(0, 0, NULL, areasSize, 1);
718
719        OMXCameraPortParameters * mPreviewData = NULL;
720        mPreviewData = &mCameraAdapterParameters.mCameraPortParams[mCameraAdapterParameters.mPrevPortIndex];
721
722        if (!focusAreas)
723            {
724            CAMHAL_LOGEB("Error allocating buffer for focus areas %d", eError);
725            return -ENOMEM;
726            }
727
728        OMX_INIT_STRUCT_PTR (focusAreas[0], OMX_ALGOAREASTYPE);
729
730        focusAreas[0]->nPortIndex = OMX_ALL;
731        focusAreas[0]->nNumAreas = mFocusAreas.size();
732        focusAreas[0]->nAlgoAreaPurpose = OMX_AlgoAreaFocus;
733
734        // If the area is the special case of (0, 0, 0, 0, 0), then
735        // the algorithm needs nNumAreas to be set to 0,
736        // in order to automatically choose the best fitting areas.
737        if ( mFocusAreas.itemAt(0)->isZeroArea() )
738            {
739            focusAreas[0]->nNumAreas = 0;
740            }
741
742        for ( unsigned int n = 0; n < mFocusAreas.size(); n++)
743            {
744            // transform the coordinates to 3A-type coordinates
745            mFocusAreas.itemAt(n)->transfrom((size_t)mPreviewData->mWidth,
746                                            (size_t)mPreviewData->mHeight,
747                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nTop,
748                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nLeft,
749                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nWidth,
750                                            (size_t&)focusAreas[0]->tAlgoAreas[n].nHeight);
751
752            focusAreas[0]->tAlgoAreas[n].nLeft =
753                    ( focusAreas[0]->tAlgoAreas[n].nLeft * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
754            focusAreas[0]->tAlgoAreas[n].nTop =
755                    ( focusAreas[0]->tAlgoAreas[n].nTop* TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
756            focusAreas[0]->tAlgoAreas[n].nWidth =
757                    ( focusAreas[0]->tAlgoAreas[n].nWidth * TOUCH_FOCUS_RANGE ) / mPreviewData->mWidth;
758            focusAreas[0]->tAlgoAreas[n].nHeight =
759                    ( focusAreas[0]->tAlgoAreas[n].nHeight * TOUCH_FOCUS_RANGE ) / mPreviewData->mHeight;
760            focusAreas[0]->tAlgoAreas[n].nPriority = mFocusAreas.itemAt(n)->getWeight();
761
762             CAMHAL_LOGDB("Focus area %d : top = %d left = %d width = %d height = %d prio = %d",
763                    n, (int)focusAreas[0]->tAlgoAreas[n].nTop, (int)focusAreas[0]->tAlgoAreas[n].nLeft,
764                    (int)focusAreas[0]->tAlgoAreas[n].nWidth, (int)focusAreas[0]->tAlgoAreas[n].nHeight,
765                    (int)focusAreas[0]->tAlgoAreas[n].nPriority);
766             }
767
768        OMX_INIT_STRUCT_PTR (&sharedBuffer, OMX_TI_CONFIG_SHAREDBUFFER);
769
770        sharedBuffer.nPortIndex = OMX_ALL;
771        sharedBuffer.nSharedBuffSize = areasSize;
772        sharedBuffer.pSharedBuff = (OMX_U8 *) focusAreas[0];
773
774        if ( NULL == sharedBuffer.pSharedBuff )
775            {
776            CAMHAL_LOGEA("No resources to allocate OMX shared buffer");
777            ret = -ENOMEM;
778            goto EXIT;
779            }
780
781            eError =  OMX_SetConfig(mCameraAdapterParameters.mHandleComp,
782                                      (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgoAreas, &sharedBuffer);
783
784        if ( OMX_ErrorNone != eError )
785            {
786            CAMHAL_LOGEB("Error while setting Focus Areas configuration 0x%x", eError);
787            ret = -EINVAL;
788            }
789
790    EXIT:
791        if (NULL != focusAreas)
792            {
793            memMgr.freeBuffer((void*) focusAreas);
794            focusAreas = NULL;
795            }
796        }
797
798    LOG_FUNCTION_NAME_EXIT;
799
800    return ret;
801}
802
803};
804