Home | History | Annotate | Download | only in util
      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 
     46 extern "C" {
     47 #include "mm_camera_dbg.h"
     48 }
     49 
     50 namespace qcamera {
     51 
     52 using android::hidl::base::V1_0::IBase;
     53 using android::hardware::hidl_death_recipient;
     54 
     55 static std::mutex gPowerHalMutex;
     56 static sp<IPower> gPowerHal = nullptr;
     57 static void getPowerHalLocked();
     58 
     59 // struct PowerHalDeathRecipient;
     60 struct 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 
     70 sp<PowerHalDeathRecipient> gPowerHalDeathRecipient = nullptr;
     71 
     72 // The caller must be holding gPowerHalMutex.
     73 static 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 
    101 typedef 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 
    131 static 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 
    140 static 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 
    149 static 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 
    158 static 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 
    169 PerfLockInfo 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 
    188 Mutex                QCameraPerfLockIntf::mMutex;
    189 QCameraPerfLockIntf* 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  *==========================================================================*/
    202 QCameraPerfLockMgr::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  *==========================================================================*/
    233 QCameraPerfLockMgr::~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  *==========================================================================*/
    255 bool 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  *==========================================================================*/
    280 bool 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  *==========================================================================*/
    305 bool 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  *==========================================================================*/
    330 void 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  *==========================================================================*/
    355 QCameraPerfLock* 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  *==========================================================================*/
    380 QCameraPerfLock::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  *==========================================================================*/
    403 QCameraPerfLock::~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  *==========================================================================*/
    422 bool 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  *==========================================================================*/
    442 void 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  *==========================================================================*/
    466 bool 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  *==========================================================================*/
    534 bool 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  *==========================================================================*/
    597 void 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  *==========================================================================*/
    622 QCameraPerfLockIntf* 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  *==========================================================================*/
    700 void 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  *==========================================================================*/
    721 QCameraPerfLockIntf::~QCameraPerfLockIntf()
    722 {
    723     if (mDlHandle) {
    724         dlclose(mDlHandle);
    725     }
    726 }
    727 
    728 bool 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