/* Copyright (c) 2015-2019, 2021, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #define LOG_TAG "QCameraPerf" // To remove #include #include // System dependencies #include #include #include // Camera dependencies #include "QCameraPerf.h" #include "QCameraTrace.h" #include "QCameraCommon.h" #include extern "C" { #include "mm_camera_dbg.h" } namespace qcamera { typedef enum { MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0 = 0x40800000, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1 = 0x40800010, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_2 = 0x40800020, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_3 = 0x40800030, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40800100, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1 = 0x40800110, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2 = 0x40800120, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3 = 0x40800130, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0 = 0x40804000, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1 = 0x40804010, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_2 = 0x40804020, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_3 = 0x40804030, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40804100, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1 = 0x40804110, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2 = 0x40804120, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3 = 0x40804130, MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG = 0x41000000, MPCTLV3_MIN_ONLINE_CPU_CLUSTER_LITTLE = 0x41000100, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG = 0x41004000, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_LITTLE = 0x41004100, MPCTLV3_ALL_CPUS_PWR_CLPS_DIS = 0x40400000 } perf_lock_params; static int32_t perfLockParamsOpenCamera[] = { #ifndef TARGET_MSM8996 // Make sure big cluster is online MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x4, #endif // Disable power collapse and set CPU cloks to turbo MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF }; static int32_t perfLockParamsCloseCamera[] = { #ifndef TARGET_MSM8996 // Make sure big cluster is online MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x4, #endif // Disable power collapse and set CPU cloks to turbo MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF }; static int32_t perfLockParamsStartPreview[] = { #ifndef TARGET_MSM8996 // Make sure big cluster is online MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x4, #endif // Disable power collapse and set CPU cloks to turbo MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF }; static int32_t perfLockParamsTakeSnapshot[] = { // Disable power collapse MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, #ifdef TARGET_MSM8996 // Set little cluster and big cluster cores to 1.555 GHz MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1, 0x613 #elif TARGET_TRINKET //set CPU cloks to turbo MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF #else // Set little cluster cores to 1.555 GHz MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3, 0x613, // Set big cluster offline MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x0 #endif }; static int32_t perfLockParamsTakeSnapshotSDM429[] = { // Set little cluster cores to 1.555 GHz MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_2, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_3, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_1, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_2, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_3, 0x613, // Set big cluster offline MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x4 }; static int32_t perfLockParamsTakeSnapshotQM215[] = { // Disable power collapse MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4 }; static int32_t perfLockParamsTakeSnapshotQM2150[] = { // Disable power collapse MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4 }; static int32_t perfLockParamsBokehSnapshot[] = { #ifndef TARGET_MSM8996 // Make sure big cluster is online MPCTLV3_MIN_ONLINE_CPU_CLUSTER_BIG, 0x4, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_BIG, 0x4, #endif // Disable power collapse MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, // Set little cluster cores to turbo MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, // Set big cluster cores to turbo MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF }; static int32_t perfLockParamsTakeSnapshotsdm630[] = { MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_1, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_2, 0x613, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_3, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_1, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_2, 0x613, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_3, 0x613, MPCTLV3_MAX_ONLINE_CPU_CLUSTER_LITTLE, 0x0 }; static int32_t perfLockParamsFlush[] = { // Disable power collapse and set CPU cloks to turbo MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 0x1, MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF, MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF, MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF }; PerfLockInfo QCameraPerfLock::mPerfLockInfo[] = { { //PERF_LOCK_OPEN_CAMERA perfLockParamsOpenCamera, sizeof(perfLockParamsOpenCamera)/sizeof(int32_t) }, { //PERF_LOCK_CLOSE_CAMERA perfLockParamsCloseCamera, sizeof(perfLockParamsCloseCamera)/sizeof(int32_t) }, { //PERF_LOCK_START_PREVIEW perfLockParamsStartPreview, sizeof(perfLockParamsStartPreview)/sizeof(int32_t) }, { //PERF_LOCK_TAKE_SNAPSHOT perfLockParamsTakeSnapshot, sizeof(perfLockParamsTakeSnapshot)/sizeof(int32_t) }, { //PERF_LOCK_POWERHINT_PREVIEW NULL, 0}, { //PERF_LOCK_POWERHINT_ENCODE NULL, 0}, { //PERF_LOCK_BOKEH_SNAPSHOT perfLockParamsBokehSnapshot, sizeof(perfLockParamsBokehSnapshot)/sizeof(int32_t) }, { //PERF_LOCK_FLUSH perfLockParamsFlush, sizeof(perfLockParamsFlush)/sizeof(int32_t) }, }; Mutex QCameraPerfLockIntf::mMutex; QCameraPerfLockIntf* QCameraPerfLockIntf::mInstance = NULL; /*=========================================================================== * FUNCTION : QCameraPerfLockMgr constructor * * DESCRIPTION: Initialize the perf locks * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ QCameraPerfLockMgr::QCameraPerfLockMgr() : mState(LOCK_MGR_STATE_UNINITIALIZED) { for (int i = 0; i < PERF_LOCK_COUNT; ++i) { mPerfLock[i] = QCameraPerfLock::create((PerfLockEnum)i); if (mPerfLock[i] == NULL) { mState = LOCK_MGR_STATE_ERROR; LOGE("Could not allocate perf locks"); // Set the remaining perf locks to NULL for (int j = i+1; j < PERF_LOCK_COUNT; ++j) { mPerfLock[j] = NULL; } return; } } mState = LOCK_MGR_STATE_READY; } /*=========================================================================== * FUNCTION : QCameraPerfLockMgr destructor * * DESCRIPTION: class destructor * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ QCameraPerfLockMgr::~QCameraPerfLockMgr() { for (int i = 0; i < PERF_LOCK_COUNT; ++i) { if (mPerfLock[i]) { delete mPerfLock[i]; } } } #ifdef SUPPORT_POWER_HINT_XML bool QCameraPerfLock::perfHint(int hint_type, int duration) { bool ret = true; if(mRefCount == 0) { mHandle = (*mPerfLockIntf->perfHintIntf())(hint_type, NULL , duration, -1); if (mHandle > 0) { ++mRefCount; } else { LOGE("Failed to acquire perfHintIntf()"); ret = false; } } else { ++mRefCount; } return ret ; } #endif /*=========================================================================== * FUNCTION : acquirePerfLock * * DESCRIPTION: Call acquirePerfLock function for the requested perf lock * * PARAMETERS : * @perfLockType: Perf lock enum * @timer: Timer value in ms * * RETURN : true on success * false on failure *==========================================================================*/ bool QCameraPerfLockMgr::acquirePerfLock( PerfLockEnum perfLockType, uint32_t timer) { bool ret = false; if ((mState == LOCK_MGR_STATE_READY) && isValidPerfLockEnum(perfLockType)) { ret = mPerfLock[perfLockType]->acquirePerfLock(true, timer); } return ret; } /*=========================================================================== * FUNCTION : acquirePerfLockIfExpired * * DESCRIPTION: Call acquirePerfLock function for the requested perf lock * * PARAMETERS : * @perfLockType: Type of perf lock * @timer: Timer value in ms * * RETURN : true on success * false on failure *==========================================================================*/ bool QCameraPerfLockMgr::acquirePerfLockIfExpired( PerfLockEnum perfLockType, uint32_t timer) { bool ret = false; if ((mState == LOCK_MGR_STATE_READY) && isValidPerfLockEnum(perfLockType)) { ret = mPerfLock[perfLockType]->acquirePerfLock(false, timer); } return ret; } /*=========================================================================== * FUNCTION : releasePerfLock * * DESCRIPTION: Call releasePerfLock function for the requested perf lock * * PARAMETERS : * @perfLockType: Enum of perf lock * * RETURN : true on success * false on failure *==========================================================================*/ bool QCameraPerfLockMgr::releasePerfLock( PerfLockEnum perfLockType) { bool ret = false; if ((mState == LOCK_MGR_STATE_READY) && isValidPerfLockEnum(perfLockType)) { ret = mPerfLock[perfLockType]->releasePerfLock(); } return ret; } /*=========================================================================== * FUNCTION : powerHintInternal * * DESCRIPTION: Calls the appropriate perf lock's powerHintInternal function * * PARAMETERS : * @perfLockType: Type of perf lock * @hint : Power hint * @enable : Enable power hint if set to 1. Disable if set to 0. * * RETURN : void * *==========================================================================*/ void QCameraPerfLockMgr::powerHintInternal( PerfLockEnum perfLockType, power_hint_t powerHint, bool enable) { if ((mState == LOCK_MGR_STATE_READY) && isValidPerfLockEnum(perfLockType)) { mPerfLock[perfLockType]->powerHintInternal(powerHint, enable); } } /*=========================================================================== * FUNCTION : create * * DESCRIPTION: This is a static method to create perf lock object. It calls * protected constructor of the class and only returns a valid object * if it can successfully initialize the perf lock. * * PARAMETERS : None * * RETURN : QCameraPerfLock object pointer on success * NULL on failure * *==========================================================================*/ QCameraPerfLock* QCameraPerfLock::create( PerfLockEnum perfLockType) { QCameraPerfLock *perfLock = NULL; if (perfLockType < PERF_LOCK_COUNT) { QCameraPerfLockIntf *perfLockIntf = QCameraPerfLockIntf::createSingleton(); if (perfLockIntf) { perfLock = new QCameraPerfLock(perfLockType, perfLockIntf); if ((perfLockType == PERF_LOCK_TAKE_SNAPSHOT) && (QCameraCommon::is_target_SDM630())) { memcpy (perfLockParamsTakeSnapshot,perfLockParamsTakeSnapshotsdm630, sizeof(perfLockParamsTakeSnapshotsdm630)); mPerfLockInfo[perfLockType].perfLockParamsCount = sizeof(perfLockParamsTakeSnapshotsdm630)/sizeof(int32_t); } else if((perfLockType == PERF_LOCK_TAKE_SNAPSHOT) && (QCameraCommon::is_target_QM215())) { memcpy (perfLockParamsTakeSnapshot,perfLockParamsTakeSnapshotQM215, sizeof(perfLockParamsTakeSnapshotQM215)); mPerfLockInfo[perfLockType].perfLockParamsCount = sizeof(perfLockParamsTakeSnapshotQM215)/sizeof(int32_t); } else if((perfLockType == PERF_LOCK_TAKE_SNAPSHOT) && (QCameraCommon::is_target_QM2150())) { memcpy (perfLockParamsTakeSnapshot,perfLockParamsTakeSnapshotQM2150, sizeof(perfLockParamsTakeSnapshotQM2150)); mPerfLockInfo[perfLockType].perfLockParamsCount = sizeof(perfLockParamsTakeSnapshotQM2150)/sizeof(int32_t); } else if ((perfLockType == PERF_LOCK_TAKE_SNAPSHOT) && (QCameraCommon::is_target_SDM429())) { memcpy (perfLockParamsTakeSnapshot,perfLockParamsTakeSnapshotSDM429, sizeof(perfLockParamsTakeSnapshotSDM429)); mPerfLockInfo[perfLockType].perfLockParamsCount = sizeof(perfLockParamsTakeSnapshotSDM429)/sizeof(int32_t); } } } return perfLock; } /*=========================================================================== * FUNCTION : QCameraPerfLock constructor * * DESCRIPTION: Initialize member variables * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ QCameraPerfLock::QCameraPerfLock( PerfLockEnum perfLockType, QCameraPerfLockIntf *perfLockIntf) : mHandle(0), mRefCount(0), mEnable(false), mTimeOut(0), mPerfLockType(perfLockType), mPerfLockIntf(perfLockIntf) { mIsPerfdEnabled = android::base::GetBoolProperty("persist.camera.perfd.enable", false); } /*=========================================================================== * FUNCTION : QCameraPerfLock destructor * * DESCRIPTION: class destructor * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ QCameraPerfLock::~QCameraPerfLock() { if (mHandle > 0) { (*mPerfLockIntf->perfLockRel())(mHandle); } QCameraPerfLockIntf::deleteInstance(); } /*=========================================================================== * FUNCTION : isTimedOut * * DESCRIPTION: Check if the perf lock is timed out * * PARAMETERS : None * * RETURN : boolean indicating if the perf lock is timed out * *==========================================================================*/ bool QCameraPerfLock::isTimedOut() { if (mTimeOut && (systemTime() > mTimeOut)) { return true; } return false; } /*=========================================================================== * FUNCTION : restartTimer * * DESCRIPTION: Restart the timer for the duration specified * * PARAMETERS : * @timer : timer duration in milliseconds * * RETURN : void * *==========================================================================*/ void inline QCameraPerfLock::restartTimer( uint32_t timer) { if (timer > 0) { mTimeOut = systemTime() + ms2ns(timer); } } /*=========================================================================== * FUNCTION : acquirePerfLock * * DESCRIPTION: Acquires the perf lock for the duration specified. Do not acquire * the perf lock is reacquire flag is set to false provided the perf * lock is already acquired. * * PARAMETERS : * @forceReaquirePerfLock: Reacquire * @timer : Duration of the perf lock * * RETURN : true on success * false on failure * *==========================================================================*/ bool QCameraPerfLock::acquirePerfLock( bool forceReaquirePerfLock, uint32_t timer) { bool ret = true; Mutex::Autolock lock(mMutex); #ifdef SUPPORT_POWER_HINT_XML if ((mPerfLockType == PERF_LOCK_POWERHINT_PREVIEW) || (mPerfLockType == PERF_LOCK_POWERHINT_ENCODE)) { ret = perfHint(PERF_LOCK_POWERHINT_PREVIEW_ENCODE, 0); //POWER_HINT } else if(mPerfLockType == PERF_LOCK_POWERHINT_HFR) { #ifdef TARGET_TRINKET ret = perfHint(PERF_LOCK_POWERHINT_HFR_ENCODE, 0); //POWER_HINT #else ret = perfHint(PERF_LOCK_POWERHINT_PREVIEW_ENCODE, 0); //POWER_HINT #endif } else if ((mRefCount == 0) || forceReaquirePerfLock) { mHandle = (*mPerfLockIntf->perfLockAcq())( mHandle, timer, mPerfLockInfo[mPerfLockType].perfLockParams, mPerfLockInfo[mPerfLockType].perfLockParamsCount); if (mHandle > 0) { ++mRefCount; restartTimer(timer); LOGD("perfLockHandle %d, updated refCount: %d, perfLockType: %d", mHandle, mRefCount, mPerfLockType); } else { LOGE("Failed to acquire the perf lock"); ret = false; } } else { ++mRefCount; } #else if ((mPerfLockType == PERF_LOCK_POWERHINT_PREVIEW) || (mPerfLockType == PERF_LOCK_POWERHINT_ENCODE)) { powerHintInternal(POWER_HINT_VIDEO_ENCODE, true); return true; } if (mPerfLockType == PERF_LOCK_POWERHINT_HFR) { powerHintInternal(POWER_HINT_VIDEO_DECODE, true); return true; } if (!mIsPerfdEnabled) return ret; if (isTimedOut()) { mHandle = 0; mRefCount = 0; } if ((mRefCount == 0) || forceReaquirePerfLock) { mHandle = (*mPerfLockIntf->perfLockAcq())( mHandle, timer, mPerfLockInfo[mPerfLockType].perfLockParams, mPerfLockInfo[mPerfLockType].perfLockParamsCount); if (mHandle > 0) { ++mRefCount; restartTimer(timer); LOGD("perfLockHandle %d, updated refCount: %d, perfLockType: %d", mHandle, mRefCount, mPerfLockType); } else { LOGE("Failed to acquire the perf lock"); ret = false; } } else { LOGD("Perf lock already acquired, not re-aquiring"); } #endif return ret; } /*=========================================================================== * FUNCTION : releasePerfLock * * DESCRIPTION: Releases the perf lock * * PARAMETERS : None * * RETURN : true on success * false on failure * *==========================================================================*/ bool QCameraPerfLock::releasePerfLock() { bool ret = true; Mutex::Autolock lock(mMutex); #ifdef SUPPORT_POWER_HINT_XML if (mHandle > 0) { if (--mRefCount == 0) { int32_t rc = (*mPerfLockIntf->perfLockRel())(mHandle); mHandle = 0; if (rc < 0) { ret = false; } } } else { LOGW("Perf lock %d either not acquired or already released", mPerfLockType); } #else if ((mPerfLockType == PERF_LOCK_POWERHINT_PREVIEW) || (mPerfLockType == PERF_LOCK_POWERHINT_ENCODE)) { powerHintInternal(POWER_HINT_VIDEO_ENCODE, false); return true; } if (mPerfLockType == PERF_LOCK_POWERHINT_HFR) { powerHintInternal(POWER_HINT_VIDEO_DECODE, false); return true; } if (!mIsPerfdEnabled) return ret; if (mHandle > 0) { if (isTimedOut()) { LOGD("perfLockHandle %d, refCount: %d, perfLockType: %d", mHandle, mRefCount, mPerfLockType); mHandle = 0; mRefCount = 0; } else if (--mRefCount == 0) { int32_t rc = (*mPerfLockIntf->perfLockRel())(mHandle); mHandle = 0; mTimeOut = 0; if (rc < 0) { LOGE("Failed to release the perf lock"); ret = false; } } } else { LOGW("Perf lock %d either not acquired or already released", mPerfLockType); } #endif return ret; } /*=========================================================================== * FUNCTION : powerHintInternal * * DESCRIPTION: Sets the requested power hint and state to power HAL. * * PARAMETERS : * @hint : Power hint * @enable : Enable power hint if set to 1. Disable if set to 0. * * RETURN : void * *==========================================================================*/ void QCameraPerfLock::powerHintInternal( power_hint_t powerHint, bool enable) { #ifdef HAS_MULTIMEDIA_HINTS if ((enable == true) && !(mEnable)) { mEnable = true; mPerfLockIntf->powerHintIntf()->powerHint(mPerfLockIntf->powerHintIntf(), powerHint, (void *)"state=1"); } else if ((enable == false) && (mEnable)) { mEnable = false; mPerfLockIntf->powerHintIntf()->powerHint(mPerfLockIntf->powerHintIntf(), powerHint, (void *)"state=0"); } #endif } /*=========================================================================== * FUNCTION : createSingleton * * DESCRIPTION: Open the perf lock library, query the function pointers and * create a singleton object upon success * * PARAMETERS : None * * RETURN : QCameraPerfLockIntf object pointer on success * NULL on failure * *==========================================================================*/ QCameraPerfLockIntf* QCameraPerfLockIntf::createSingleton() { bool error = true; Mutex::Autolock lock(mMutex); if (mInstance == NULL) { // Open perflock library and query for the function pointers uint32_t perfLockEnable = 0; char value[PROPERTY_VALUE_MAX]; property_get("persist.vendor.camera.perflock.enable", value, "1"); perfLockEnable = atoi(value); if (perfLockEnable) { mInstance = new QCameraPerfLockIntf(); if (mInstance) { #ifdef HAS_MULTIMEDIA_HINTS if (hw_get_module(POWER_HARDWARE_MODULE_ID, (const hw_module_t **)(&(mInstance->mPowerModule)))) { LOGE("%s module for powerHAL not found", POWER_HARDWARE_MODULE_ID); } else #endif { /* Retrieve the name of the vendor extension library */ void *dlHandle = NULL; if ((property_get("ro.vendor.extension_library", value, NULL) > 0) && (dlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL))) { perfLockAcquire pLockAcq = (perfLockAcquire)dlsym(dlHandle, "perf_lock_acq"); perfLockRelease pLockRel = (perfLockRelease)dlsym(dlHandle, "perf_lock_rel"); #ifdef SUPPORT_POWER_HINT_XML perf_hint perfhint = (perf_hint)dlsym(dlHandle, "perf_hint"); if (pLockAcq && pLockRel && perfhint) { #else if (pLockAcq && pLockRel) { #endif mInstance->mDlHandle = dlHandle; mInstance->mPerfLockAcq = pLockAcq; mInstance->mPerfLockRel = pLockRel; #ifdef SUPPORT_POWER_HINT_XML mInstance->mperfHint = perfhint; #endif error = false; } else { LOGE("Failed to link the symbols- perf_lock_acq, perf_lock_rel"); } } else { LOGE("Unable to load lib: %s", value); } } if (error && mInstance) { delete mInstance; mInstance = NULL; } } } } if (mInstance) { ++(mInstance->mRefCount); } return mInstance; } /*=========================================================================== * FUNCTION : deleteInstance * * DESCRIPTION: Delete the object if refCount is 0 * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ void QCameraPerfLockIntf::deleteInstance() { Mutex::Autolock lock(mMutex); if (mInstance && (--(mInstance->mRefCount) == 0)) { delete mInstance; mInstance = NULL; } } /*=========================================================================== * FUNCTION : QCameraPerfLockIntf destructor * * DESCRIPTION: class destructor * * PARAMETERS : None * * RETURN : void * *==========================================================================*/ QCameraPerfLockIntf::~QCameraPerfLockIntf() { if (mDlHandle) { dlclose(mDlHandle); } } }; // namespace qcamera