1/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
2*
3* Redistribution and use in source and binary forms, with or without
4* modification, are permitted provided that the following conditions are
5* met:
6*     * Redistributions of source code must retain the above copyright
7*       notice, this list of conditions and the following disclaimer.
8*     * Redistributions in binary form must reproduce the above
9*       copyright notice, this list of conditions and the following
10*       disclaimer in the documentation and/or other materials provided
11*       with the distribution.
12*     * Neither the name of The Linux Foundation nor the names of its
13*       contributors may be used to endorse or promote products derived
14*       from this software without specific prior written permission.
15*
16* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*
28*/
29
30#define LOG_TAG "QCameraPerf"
31
32// To remove
33#include <cutils/properties.h>
34#include <utils/Errors.h>
35
36// System dependencies
37#include <stdlib.h>
38#include <dlfcn.h>
39#include <utils/Timers.h>
40// Camera dependencies
41#include "QCameraPerf.h"
42#include "QCameraTrace.h"
43
44#include <android-base/properties.h>
45
46extern "C" {
47#include "mm_camera_dbg.h"
48}
49
50namespace qcamera {
51
52using android::hidl::base::V1_0::IBase;
53using android::hardware::hidl_death_recipient;
54
55static std::mutex gPowerHalMutex;
56static sp<IPower> gPowerHal = nullptr;
57static void getPowerHalLocked();
58
59// struct PowerHalDeathRecipient;
60struct PowerHalDeathRecipient : virtual public hidl_death_recipient {
61    // hidl_death_recipient interface
62    virtual void serviceDied(uint64_t, const wp<IBase>&) override {
63        std::lock_guard<std::mutex> lock(gPowerHalMutex);
64        ALOGE("PowerHAL just died");
65        gPowerHal = nullptr;
66        getPowerHalLocked();
67    }
68};
69
70sp<PowerHalDeathRecipient> gPowerHalDeathRecipient = nullptr;
71
72// The caller must be holding gPowerHalMutex.
73static void getPowerHalLocked() {
74    if (gPowerHal != nullptr) {
75        return;
76    }
77
78    gPowerHal = IPower::getService();
79
80    if (gPowerHal == nullptr) {
81        ALOGE("Unable to get Power service.");
82    } else {
83        if (gPowerHalDeathRecipient == nullptr) {
84            gPowerHalDeathRecipient = new PowerHalDeathRecipient();
85        }
86        hardware::Return<bool> linked = gPowerHal->linkToDeath(
87            gPowerHalDeathRecipient, 0x451F /* cookie */);
88        if (!linked.isOk()) {
89            ALOGE("Transaction error in linking to PowerHAL death: %s",
90                  linked.description().c_str());
91            gPowerHal = nullptr;
92        } else if (!linked) {
93            ALOGW("Unable to link to PowerHal death notifications");
94            gPowerHal = nullptr;
95        } else {
96            ALOGD("Link to death notification successful");
97        }
98    }
99}
100
101typedef enum {
102    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0     = 0x40800000,
103    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1     = 0x40800010,
104    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_2     = 0x40800020,
105    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_3     = 0x40800030,
106    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40800100,
107    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40800110,
108    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40800120,
109    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40800130,
110
111    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0     = 0x40804000,
112    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1     = 0x40804010,
113    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_2     = 0x40804020,
114    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_3     = 0x40804030,
115    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0  = 0x40804100,
116    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1  = 0x40804110,
117    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2  = 0x40804120,
118    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3  = 0x40804130,
119
120    MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG      = 0x41000000,
121    MPCTLV3_MIN_ONLINE_CPU_CLUSTER_LITTLE   = 0x41000100,
122    MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG      = 0x41004000,
123    MPCTLV3_MAX_ONLINE_CPU_CLUSTER_LITTLE   = 0x41004100,
124
125    MPCTLV3_ALL_CPUS_PWR_CLPS_DIS           = 0x40400000,
126    MPCTLV3_CPUBW_HWMON_MIN_FREQ            = 0x41800000,
127    MPCTLV3_CPUBW_HWMON_HYST_OPT            = 0x4180C000
128} perf_lock_params;
129
130
131static int32_t perfLockParamsOpenCamera[] = {
132    // Disable power collapse and set CPU cloks to turbo
133    MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
134    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
135    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
136    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
137    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
138};
139
140static int32_t perfLockParamsCloseCamera[] = {
141    // Disable power collapse and set CPU cloks to turbo
142    MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
143    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
144    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
145    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
146    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
147};
148
149static int32_t perfLockParamsStartPreview[] = {
150    // Disable power collapse and set CPU cloks to turbo
151    MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
152    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
153    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
154    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
155    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF
156};
157
158static int32_t perfLockParamsTakeSnapshot[] = {
159    // Disable power collapse and set CPU cloks to turbo
160    MPCTLV3_ALL_CPUS_PWR_CLPS_DIS,          0x1,
161    MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
162    MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0,    0xFFF,
163    MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
164    MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
165    MPCTLV3_CPUBW_HWMON_HYST_OPT,           0x0,
166    MPCTLV3_CPUBW_HWMON_MIN_FREQ,           0x8C
167};
168
169PerfLockInfo QCameraPerfLock::mPerfLockInfo[] = {
170    { //PERF_LOCK_OPEN_CAMERA
171      perfLockParamsOpenCamera,
172      sizeof(perfLockParamsOpenCamera)/sizeof(int32_t) },
173    { //PERF_LOCK_CLOSE_CAMERA
174      perfLockParamsCloseCamera,
175      sizeof(perfLockParamsCloseCamera)/sizeof(int32_t) },
176    { //PERF_LOCK_START_PREVIEW
177      perfLockParamsStartPreview,
178      sizeof(perfLockParamsStartPreview)/sizeof(int32_t) },
179    { //PERF_LOCK_TAKE_SNAPSHOT
180      perfLockParamsTakeSnapshot,
181      sizeof(perfLockParamsTakeSnapshot)/sizeof(int32_t) },
182    { //PERF_LOCK_POWERHINT_PREVIEW
183      NULL, 0},
184    { //PERF_LOCK_POWERHINT_ENCODE
185      NULL, 0}
186    };
187
188Mutex                QCameraPerfLockIntf::mMutex;
189QCameraPerfLockIntf* QCameraPerfLockIntf::mInstance = NULL;
190
191
192/*===========================================================================
193 * FUNCTION   : QCameraPerfLockMgr constructor
194 *
195 * DESCRIPTION: Initialize the perf locks
196 *
197 * PARAMETERS : None
198 *
199 * RETURN     : void
200 *
201 *==========================================================================*/
202QCameraPerfLockMgr::QCameraPerfLockMgr() :
203    mState(LOCK_MGR_STATE_UNINITIALIZED)
204{
205    for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
206        mPerfLock[i] = QCameraPerfLock::create((PerfLockEnum)i);
207
208        if (mPerfLock[i] == NULL) {
209            mState = LOCK_MGR_STATE_ERROR;
210            LOGE("Could not allocate perf locks");
211
212            // Set the remaining perf locks to NULL
213            for (int j = i+1; j < PERF_LOCK_COUNT; ++j) {
214                mPerfLock[j] = NULL;
215            }
216            return;
217        }
218    }
219    mState = LOCK_MGR_STATE_READY;
220}
221
222
223/*===========================================================================
224 * FUNCTION   : QCameraPerfLockMgr destructor
225 *
226 * DESCRIPTION: class destructor
227 *
228 * PARAMETERS : None
229 *
230 * RETURN     : void
231 *
232 *==========================================================================*/
233QCameraPerfLockMgr::~QCameraPerfLockMgr()
234{
235    for (int i = 0; i < PERF_LOCK_COUNT; ++i) {
236        if (mPerfLock[i]) {
237            delete mPerfLock[i];
238        }
239    }
240}
241
242
243/*===========================================================================
244 * FUNCTION   : acquirePerfLock
245 *
246 * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
247 *
248 * PARAMETERS :
249 * @perfLockType: Perf lock enum
250 * @timer:        Timer value in ms
251 *
252 * RETURN     : true  on success
253 *              false on failure
254 *==========================================================================*/
255bool QCameraPerfLockMgr::acquirePerfLock(
256        PerfLockEnum perfLockType,
257        uint32_t     timer)
258{
259    bool ret = false;
260    if ((mState == LOCK_MGR_STATE_READY) &&
261        isValidPerfLockEnum(perfLockType)) {
262        ret = mPerfLock[perfLockType]->acquirePerfLock(true, timer);
263    }
264    return ret;
265}
266
267
268/*===========================================================================
269 * FUNCTION   : acquirePerfLockIfExpired
270 *
271 * DESCRIPTION: Call acquirePerfLock function for the requested perf lock
272 *
273 * PARAMETERS :
274 * @perfLockType: Type of perf lock
275 * @timer:        Timer value in ms
276 *
277 * RETURN     : true  on success
278 *              false on failure
279 *==========================================================================*/
280bool QCameraPerfLockMgr::acquirePerfLockIfExpired(
281        PerfLockEnum perfLockType,
282        uint32_t     timer)
283{
284    bool ret = false;
285    if ((mState == LOCK_MGR_STATE_READY) &&
286        isValidPerfLockEnum(perfLockType)) {
287        ret = mPerfLock[perfLockType]->acquirePerfLock(false, timer);
288    }
289    return ret;
290
291}
292
293
294/*===========================================================================
295 * FUNCTION   : releasePerfLock
296 *
297 * DESCRIPTION: Call releasePerfLock function for the requested perf lock
298 *
299 * PARAMETERS :
300 * @perfLockType: Enum of perf lock
301 *
302 * RETURN     : true  on success
303 *              false on failure
304 *==========================================================================*/
305bool QCameraPerfLockMgr::releasePerfLock(
306        PerfLockEnum perfLockType)
307{
308    bool ret = false;
309    if ((mState == LOCK_MGR_STATE_READY) &&
310        isValidPerfLockEnum(perfLockType)) {
311        ret = mPerfLock[perfLockType]->releasePerfLock();
312    }
313    return ret;
314}
315
316
317/*===========================================================================
318 * FUNCTION   : powerHintInternal
319 *
320 * DESCRIPTION: Calls the appropriate perf lock's powerHintInternal function
321 *
322 * PARAMETERS :
323 * @perfLockType: Type of perf lock
324 * @hint        : Power hint
325 * @enable      : Enable power hint if set to 1. Disable if set to 0.
326 *
327 * RETURN     : void
328 *
329 *==========================================================================*/
330void QCameraPerfLockMgr::powerHintInternal(
331        PerfLockEnum perfLockType,
332        PowerHint    powerHint,
333        int32_t      time_out)
334{
335    if ((mState == LOCK_MGR_STATE_READY) &&
336        isValidPerfLockEnum(perfLockType)) {
337        mPerfLock[perfLockType]->powerHintInternal(powerHint, time_out);
338    }
339}
340
341
342/*===========================================================================
343 * FUNCTION   : create
344 *
345 * DESCRIPTION: This is a static method to create perf lock object. It calls
346 *              protected constructor of the class and only returns a valid object
347 *              if it can successfully initialize the perf lock.
348 *
349 * PARAMETERS : None
350 *
351 * RETURN     : QCameraPerfLock object pointer on success
352 *              NULL on failure
353 *
354 *==========================================================================*/
355QCameraPerfLock* QCameraPerfLock::create(
356        PerfLockEnum perfLockType)
357{
358    QCameraPerfLock *perfLock = NULL;
359
360    if (perfLockType < PERF_LOCK_COUNT) {
361        QCameraPerfLockIntf *perfLockIntf = QCameraPerfLockIntf::createSingleton();
362        if (perfLockIntf) {
363            perfLock = new QCameraPerfLock(perfLockType, perfLockIntf);
364        }
365    }
366    return perfLock;
367}
368
369
370/*===========================================================================
371 * FUNCTION   : QCameraPerfLock constructor
372 *
373 * DESCRIPTION: Initialize member variables
374 *
375 * PARAMETERS : None
376 *
377 * RETURN     : void
378 *
379 *==========================================================================*/
380QCameraPerfLock::QCameraPerfLock(
381        PerfLockEnum         perfLockType,
382        QCameraPerfLockIntf *perfLockIntf) :
383        mHandle(0),
384        mRefCount(0),
385        mTimeOut(0),
386        mPerfLockType(perfLockType),
387        mPerfLockIntf(perfLockIntf)
388{
389    mIsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
390}
391
392
393/*===========================================================================
394 * FUNCTION   : QCameraPerfLock destructor
395 *
396 * DESCRIPTION: class destructor
397 *
398 * PARAMETERS : None
399 *
400 * RETURN     : void
401 *
402 *==========================================================================*/
403QCameraPerfLock::~QCameraPerfLock()
404{
405    if (mHandle > 0) {
406        (*mPerfLockIntf->perfLockRel())(mHandle);
407    }
408    QCameraPerfLockIntf::deleteInstance();
409}
410
411
412/*===========================================================================
413 * FUNCTION   : isTimedOut
414 *
415 * DESCRIPTION: Check if the perf lock is timed out
416 *
417 * PARAMETERS : None
418 *
419 * RETURN     : boolean indicating if the perf lock is timed out
420 *
421 *==========================================================================*/
422bool QCameraPerfLock::isTimedOut()
423{
424    if (mTimeOut && (systemTime() > mTimeOut)) {
425        return true;
426    }
427    return false;
428}
429
430
431/*===========================================================================
432 * FUNCTION   : restartTimer
433 *
434 * DESCRIPTION: Restart the timer for the duration specified
435 *
436 * PARAMETERS :
437 *  @timer    : timer duration in milliseconds
438 *
439 * RETURN     : void
440 *
441 *==========================================================================*/
442void inline QCameraPerfLock::restartTimer(
443        uint32_t timer)
444{
445    if (timer > 0) {
446        mTimeOut = systemTime() + ms2ns(timer);
447    }
448}
449
450
451/*===========================================================================
452 * FUNCTION   : acquirePerfLock
453 *
454 * DESCRIPTION: Acquires the perf lock for the duration specified. Do not acquire
455 *              the perf lock is reacquire flag is set to false provided the perf
456 *              lock is already acquired.
457 *
458 * PARAMETERS :
459 * @forceReaquirePerfLock: Reacquire
460 * @timer     : Duration of the perf lock
461 *
462 * RETURN     : true  on success
463 *              false on failure
464 *
465 *==========================================================================*/
466bool QCameraPerfLock::acquirePerfLock(
467        bool     forceReaquirePerfLock,
468        uint32_t timer)
469{
470    bool ret = true;
471    Mutex::Autolock lock(mMutex);
472
473    switch (mPerfLockType) {
474        case PERF_LOCK_POWERHINT_PREVIEW:
475        case PERF_LOCK_POWERHINT_ENCODE:
476            powerHintInternal(PowerHint::VIDEO_ENCODE, true);
477            return true;
478        case PERF_LOCK_OPEN_CAMERA:
479        case PERF_LOCK_CLOSE_CAMERA:
480            powerHintInternal(PowerHint::CAMERA_LAUNCH, timer);
481            return true;
482        case PERF_LOCK_START_PREVIEW:
483            powerHintInternal(PowerHint::CAMERA_STREAMING, timer);
484            return true;
485        case PERF_LOCK_TAKE_SNAPSHOT:
486            powerHintInternal(PowerHint::CAMERA_SHOT, timer);
487            return true;
488        default:
489            LOGE("Unknown powerhint %d",(int)mPerfLockType);
490            return false;
491    }
492
493    if (!mIsPerfdEnabled) return ret;
494
495    if (isTimedOut()) {
496        mHandle   = 0;
497        mRefCount = 0;
498    }
499
500    if ((mRefCount == 0) || forceReaquirePerfLock) {
501        mHandle = (*mPerfLockIntf->perfLockAcq())(
502            mHandle, timer,
503            mPerfLockInfo[mPerfLockType].perfLockParams,
504            mPerfLockInfo[mPerfLockType].perfLockParamsCount);
505
506        if (mHandle > 0) {
507            ++mRefCount;
508            restartTimer(timer);
509            LOGD("perfLockHandle %d, updated refCount: %d, perfLockType: %d",
510                mHandle, mRefCount, mPerfLockType);
511        } else {
512            LOGE("Failed to acquire the perf lock");
513            ret = false;
514        }
515    } else {
516        LOGD("Perf lock already acquired, not re-aquiring");
517    }
518
519    return ret;
520}
521
522
523/*===========================================================================
524 * FUNCTION   : releasePerfLock
525 *
526 * DESCRIPTION: Releases the perf lock
527 *
528 * PARAMETERS : None
529 *
530 * RETURN     : true  on success
531 *              false on failure
532 *
533 *==========================================================================*/
534bool QCameraPerfLock::releasePerfLock()
535{
536    bool ret = true;
537    Mutex::Autolock lock(mMutex);
538
539    switch (mPerfLockType) {
540        case PERF_LOCK_POWERHINT_PREVIEW:
541        case PERF_LOCK_POWERHINT_ENCODE:
542            powerHintInternal(PowerHint::VIDEO_ENCODE, false);
543            return true;
544        case PERF_LOCK_OPEN_CAMERA:
545        case PERF_LOCK_CLOSE_CAMERA:
546            powerHintInternal(PowerHint::CAMERA_LAUNCH, false);
547            return true;
548        case PERF_LOCK_START_PREVIEW:
549            powerHintInternal(PowerHint::CAMERA_STREAMING, false);
550            return true;
551        case PERF_LOCK_TAKE_SNAPSHOT:
552            powerHintInternal(PowerHint::CAMERA_SHOT, false);
553            return true;
554        default:
555            LOGE("Unknown powerhint %d",(int)mPerfLockType);
556            return false;
557    }
558
559    if (!mIsPerfdEnabled) return ret;
560
561    if (mHandle > 0) {
562        LOGD("perfLockHandle %d, refCount: %d, perfLockType: %d",
563                    mHandle, mRefCount, mPerfLockType);
564
565        if (isTimedOut()) {
566            mHandle   = 0;
567            mRefCount = 0;
568        } else if (--mRefCount == 0) {
569            int32_t rc = (*mPerfLockIntf->perfLockRel())(mHandle);
570            mHandle = 0;
571            mTimeOut = 0;
572            if (rc < 0) {
573                LOGE("Failed to release the perf lock");
574                ret = false;
575            }
576        }
577    } else {
578        LOGW("Perf lock %d either not acquired or already released", mPerfLockType);
579    }
580
581    return ret;
582}
583
584
585/*===========================================================================
586 * FUNCTION   : powerHintInternal
587 *
588 * DESCRIPTION: Sets the requested power hint and state to power HAL.
589 *
590 * PARAMETERS :
591 * @hint      : Power hint
592 * @enable    : Enable power hint if set to 1. Disable if set to 0.
593 *
594 * RETURN     : void
595 *
596 *==========================================================================*/
597void QCameraPerfLock::powerHintInternal(
598        PowerHint    powerHint,
599        int32_t      time_out)
600{
601#ifdef HAS_MULTIMEDIA_HINTS
602    if (!mPerfLockIntf->powerHint(powerHint, time_out)) {
603        LOGE("Send powerhint to PowerHal failed");
604    }
605#endif
606}
607
608
609
610/*===========================================================================
611 * FUNCTION   : createSingleton
612 *
613 * DESCRIPTION: Open the perf lock library, query the function pointers and
614 *              create a singleton object upon success
615 *
616 * PARAMETERS : None
617 *
618 * RETURN     : QCameraPerfLockIntf object pointer on success
619 *              NULL on failure
620 *
621 *==========================================================================*/
622QCameraPerfLockIntf* QCameraPerfLockIntf::createSingleton()
623{
624    bool error = true;
625    Mutex::Autolock lock(mMutex);
626
627    if (mInstance == NULL) {
628        // Open perflock library and query for the function pointers
629        uint32_t perfLockEnable = 0;
630        char value[PROPERTY_VALUE_MAX];
631
632        property_get("persist.camera.perflock.enable", value, "1");
633        perfLockEnable = atoi(value);
634
635        if (perfLockEnable) {
636            mInstance = new QCameraPerfLockIntf();
637            if (mInstance) {
638                #ifdef HAS_MULTIMEDIA_HINTS
639                std::lock_guard<std::mutex> lock(gPowerHalMutex);
640                getPowerHalLocked();
641                if (gPowerHal == nullptr) {
642                    ALOGE("Couldn't load PowerHAL module");
643                }
644                else
645                #endif
646                {
647                    /* Retrieve the name of the vendor extension library */
648                    void *dlHandle = NULL;
649                    if ((property_get("ro.vendor.extension_library", value, NULL) > 0) &&
650                        (dlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL))) {
651
652                        perfLockAcquire pLockAcq = (perfLockAcquire)dlsym(dlHandle, "perf_lock_acq");
653                        perfLockRelease pLockRel = (perfLockRelease)dlsym(dlHandle, "perf_lock_rel");
654
655                        if (pLockAcq && pLockRel) {
656                            mInstance->mDlHandle    = dlHandle;
657                            mInstance->mPerfLockAcq = pLockAcq;
658                            mInstance->mPerfLockRel = pLockRel;
659                            error = false;
660                        } else {
661                            LOGE("Failed to link the symbols- perf_lock_acq, perf_lock_rel");
662                            bool IsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false);
663                            if (!IsPerfdEnabled) {
664                                mInstance->mDlHandle    = nullptr;
665                                mInstance->mPerfLockAcq = nullptr;
666                                mInstance->mPerfLockRel = nullptr;
667                                error = false;
668                            }
669                        }
670                    } else {
671                        LOGE("Unable to load lib: %s", value);
672                    }
673                }
674                if (error && mInstance) {
675                    delete mInstance;
676                    mInstance = NULL;
677                }
678            }
679        }
680    }
681
682    if (mInstance) {
683        ++(mInstance->mRefCount);
684    }
685
686    return mInstance;
687}
688
689
690/*===========================================================================
691 * FUNCTION   : deleteInstance
692 *
693 * DESCRIPTION: Delete the object if refCount is 0
694 *
695 * PARAMETERS : None
696 *
697 * RETURN     : void
698 *
699 *==========================================================================*/
700void QCameraPerfLockIntf::deleteInstance()
701{
702    Mutex::Autolock lock(mMutex);
703
704    if (mInstance && (--(mInstance->mRefCount) == 0)) {
705        delete mInstance;
706        mInstance = NULL;
707    }
708}
709
710
711/*===========================================================================
712 * FUNCTION   : QCameraPerfLockIntf destructor
713 *
714 * DESCRIPTION: class destructor
715 *
716 * PARAMETERS : None
717 *
718 * RETURN     : void
719 *
720 *==========================================================================*/
721QCameraPerfLockIntf::~QCameraPerfLockIntf()
722{
723    if (mDlHandle) {
724        dlclose(mDlHandle);
725    }
726}
727
728bool QCameraPerfLockIntf::powerHint(PowerHint hint, int32_t data) {
729    std::lock_guard<std::mutex> lock(gPowerHalMutex);
730    getPowerHalLocked();
731    if (gPowerHal == nullptr) {
732        ALOGE("Couldn't do powerHint because of HAL error.");
733        return false;
734    }
735    auto ret = gPowerHal->powerHintAsync_1_2(hint, data);
736    if (!ret.isOk()) {
737        ALOGE("powerHint failed error: %s", ret.description().c_str());
738    }
739    return ret.isOk();
740}
741
742}; // namespace qcamera
743