209a9aec1c
Signed-off-by: Deokgyu Yang <secugyu@gmail.com> Change-Id: I1eb5082082c7af4b7d8f98dbe5a1f8d9a20bebef
545 lines
16 KiB
C++
545 lines
16 KiB
C++
/* Copyright (c) 2015-2016, 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 <cutils/properties.h>
|
|
|
|
// System dependencies
|
|
#include <stdlib.h>
|
|
#include <dlfcn.h>
|
|
#include <utils/Timers.h>
|
|
// Camera dependencies
|
|
#include "QCameraPerf.h"
|
|
#include "QCameraTrace.h"
|
|
|
|
extern "C" {
|
|
#include "mm_camera_dbg.h"
|
|
}
|
|
|
|
namespace qcamera {
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : QCameraPerfLock constructor
|
|
*
|
|
* DESCRIPTION: initialize member variables
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
QCameraPerfLock::QCameraPerfLock() :
|
|
perf_lock_acq(NULL),
|
|
perf_lock_rel(NULL),
|
|
mDlHandle(NULL),
|
|
mPerfLockEnable(0),
|
|
mPerfLockHandle(-1),
|
|
mPerfLockHandleTimed(-1),
|
|
mTimerSet(0),
|
|
mPerfLockTimeout(0),
|
|
mStartTimeofLock(0)
|
|
{
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : QCameraPerfLock destructor
|
|
*
|
|
* DESCRIPTION: class desctructor
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
QCameraPerfLock::~QCameraPerfLock()
|
|
{
|
|
lock_deinit();
|
|
}
|
|
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_init
|
|
*
|
|
* DESCRIPTION: opens the performance lib and initilizes the perf lock functions
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
void QCameraPerfLock::lock_init()
|
|
{
|
|
const char *rc;
|
|
char value[PROPERTY_VALUE_MAX];
|
|
|
|
LOGD("E");
|
|
Mutex::Autolock lock(mLock);
|
|
|
|
// Clear the list of active power hints
|
|
mActivePowerHints.clear();
|
|
mCurrentPowerHint = static_cast<power_hint_t>(0);
|
|
mCurrentPowerHintEnable = false;
|
|
|
|
property_get("persist.camera.perflock.enable", value, "1");
|
|
mPerfLockEnable = atoi(value);
|
|
#ifdef HAS_MULTIMEDIA_HINTS
|
|
if (hw_get_module(POWER_HARDWARE_MODULE_ID, (const hw_module_t **)&m_pPowerModule)) {
|
|
LOGE("%s module not found", POWER_HARDWARE_MODULE_ID);
|
|
}
|
|
#endif
|
|
|
|
if (mPerfLockEnable) {
|
|
perf_lock_acq = NULL;
|
|
perf_lock_rel = NULL;
|
|
mPerfLockHandle = -1;
|
|
/* Retrieve name of vendor extension library */
|
|
if (property_get("ro.vendor.extension_library", value, NULL) <= 0) {
|
|
goto cleanup;
|
|
}
|
|
|
|
mDlHandle = dlopen(value, RTLD_NOW | RTLD_LOCAL);
|
|
if (mDlHandle == NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
dlerror();
|
|
|
|
perf_lock_acq = (int (*) (int, int, int[], int))dlsym(mDlHandle, "perf_lock_acq");
|
|
if ((rc = dlerror()) != NULL) {
|
|
LOGE("failed to perf_lock_acq function handle");
|
|
goto cleanup;
|
|
}
|
|
|
|
perf_lock_rel = (int (*) (int))dlsym(mDlHandle, "perf_lock_rel");
|
|
if ((rc = dlerror()) != NULL) {
|
|
LOGE("failed to perf_lock_rel function handle");
|
|
goto cleanup;
|
|
}
|
|
LOGD("X");
|
|
return;
|
|
|
|
cleanup:
|
|
perf_lock_acq = NULL;
|
|
perf_lock_rel = NULL;
|
|
mPerfLockEnable = 0;
|
|
if (mDlHandle) {
|
|
dlclose(mDlHandle);
|
|
mDlHandle = NULL;
|
|
}
|
|
}
|
|
LOGD("X");
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_deinit
|
|
*
|
|
* DESCRIPTION: deinitialize the perf lock parameters
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
void QCameraPerfLock::lock_deinit()
|
|
{
|
|
Mutex::Autolock lock(mLock);
|
|
if (mPerfLockEnable) {
|
|
LOGD("E");
|
|
|
|
if (mActivePowerHints.empty() == false) {
|
|
// Disable the active power hint
|
|
mCurrentPowerHint = *mActivePowerHints.begin();
|
|
powerHintInternal(mCurrentPowerHint, false);
|
|
mActivePowerHints.clear();
|
|
}
|
|
|
|
if ((NULL != perf_lock_rel) && (mPerfLockHandleTimed >= 0)) {
|
|
(*perf_lock_rel)(mPerfLockHandleTimed);
|
|
}
|
|
|
|
if ((NULL != perf_lock_rel) && (mPerfLockHandle >= 0)) {
|
|
(*perf_lock_rel)(mPerfLockHandle);
|
|
}
|
|
|
|
if (mDlHandle) {
|
|
perf_lock_acq = NULL;
|
|
perf_lock_rel = NULL;
|
|
|
|
dlclose(mDlHandle);
|
|
mDlHandle = NULL;
|
|
}
|
|
mPerfLockEnable = 0;
|
|
LOGD("X");
|
|
}
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : isTimerReset
|
|
*
|
|
* DESCRIPTION: Check if timout duration is reached
|
|
*
|
|
* PARAMETERS : None
|
|
*
|
|
* RETURN : true if timeout reached
|
|
* false if timeout not reached
|
|
*
|
|
*==========================================================================*/
|
|
bool QCameraPerfLock::isTimerReset()
|
|
{
|
|
Mutex::Autolock lock(mLock);
|
|
if (mPerfLockEnable && mTimerSet) {
|
|
nsecs_t timeDiff = systemTime() - mStartTimeofLock;
|
|
if (ns2ms(timeDiff) > (uint32_t)mPerfLockTimeout) {
|
|
resetTimer();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : resetTimer
|
|
*
|
|
* DESCRIPTION: Reset the timer used in timed perf lock
|
|
*
|
|
* PARAMETERS : None
|
|
*
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
void QCameraPerfLock::resetTimer()
|
|
{
|
|
mPerfLockTimeout = 0;
|
|
mTimerSet = 0;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : start_timer
|
|
*
|
|
* DESCRIPTION: get the start of the timer
|
|
*
|
|
* PARAMETERS :
|
|
* @timer_val: timer duration in milliseconds
|
|
*
|
|
* RETURN : int32_t type of status
|
|
* NO_ERROR -- success
|
|
* none-zero failure code
|
|
*
|
|
*==========================================================================*/
|
|
void QCameraPerfLock::startTimer(uint32_t timer_val)
|
|
{
|
|
mStartTimeofLock = systemTime();
|
|
mTimerSet = 1;
|
|
mPerfLockTimeout = timer_val;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_acq_timed
|
|
*
|
|
* DESCRIPTION: Acquire the performance lock for the specified duration.
|
|
* If an existing lock timeout has not elapsed, extend the
|
|
* lock further for the specified duration
|
|
*
|
|
* PARAMETERS :
|
|
* @timer_val: lock duration
|
|
*
|
|
* RETURN : int32_t type of status
|
|
* NO_ERROR -- success
|
|
* none-zero failure code
|
|
*
|
|
*==========================================================================*/
|
|
int32_t QCameraPerfLock::lock_acq_timed(int32_t timer_val)
|
|
{
|
|
int32_t ret = -1;
|
|
|
|
LOGD("E");
|
|
Mutex::Autolock lock(mLock);
|
|
|
|
if (mPerfLockEnable) {
|
|
int32_t perf_lock_params[] = {
|
|
ALL_CPUS_PWR_CLPS_DIS,
|
|
CPU0_MIN_FREQ_TURBO_MAX,
|
|
CPU4_MIN_FREQ_TURBO_MAX
|
|
};
|
|
if (mTimerSet) {
|
|
nsecs_t curElapsedTime = systemTime() - mStartTimeofLock;
|
|
int32_t pendingTimeout = mPerfLockTimeout - ns2ms(curElapsedTime);
|
|
timer_val += pendingTimeout;
|
|
}
|
|
startTimer(timer_val);
|
|
|
|
// Disable power hint when acquiring the perf lock
|
|
if (mCurrentPowerHintEnable) {
|
|
LOGD("mCurrentPowerHintEnable %d" ,mCurrentPowerHintEnable);
|
|
powerHintInternal(mCurrentPowerHint, false);
|
|
}
|
|
|
|
if ((NULL != perf_lock_acq) && (mPerfLockHandleTimed < 0)) {
|
|
ret = (*perf_lock_acq)(mPerfLockHandleTimed, timer_val, perf_lock_params,
|
|
sizeof(perf_lock_params) / sizeof(int32_t));
|
|
LOGD("ret %d", ret);
|
|
if (ret < 0) {
|
|
LOGE("failed to acquire lock");
|
|
} else {
|
|
mPerfLockHandleTimed = ret;
|
|
}
|
|
}
|
|
LOGD("perf_handle_acq %d ", mPerfLockHandleTimed);
|
|
}
|
|
|
|
LOGD("X");
|
|
return ret;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_acq
|
|
*
|
|
* DESCRIPTION: acquire the performance lock
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : int32_t type of status
|
|
* NO_ERROR -- success
|
|
* none-zero failure code
|
|
*
|
|
*==========================================================================*/
|
|
int32_t QCameraPerfLock::lock_acq()
|
|
{
|
|
int32_t ret = -1;
|
|
|
|
LOGD("E");
|
|
Mutex::Autolock lock(mLock);
|
|
|
|
if (mPerfLockEnable) {
|
|
int32_t perf_lock_params[] = {
|
|
ALL_CPUS_PWR_CLPS_DIS,
|
|
CPU0_MIN_FREQ_TURBO_MAX,
|
|
CPU4_MIN_FREQ_TURBO_MAX
|
|
};
|
|
|
|
// Disable power hint when acquiring the perf lock
|
|
if (mCurrentPowerHintEnable) {
|
|
powerHintInternal(mCurrentPowerHint, false);
|
|
}
|
|
|
|
if ((NULL != perf_lock_acq) && (mPerfLockHandle < 0)) {
|
|
ret = (*perf_lock_acq)(mPerfLockHandle, ONE_SEC, perf_lock_params,
|
|
sizeof(perf_lock_params) / sizeof(int32_t));
|
|
LOGD("ret %d", ret);
|
|
if (ret < 0) {
|
|
LOGE("failed to acquire lock");
|
|
} else {
|
|
mPerfLockHandle = ret;
|
|
}
|
|
}
|
|
LOGD("perf_handle_acq %d ", mPerfLockHandle);
|
|
}
|
|
|
|
LOGD("X");
|
|
return ret;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_rel_timed
|
|
*
|
|
* DESCRIPTION: release the performance lock
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : int32_t type of status
|
|
* NO_ERROR -- success
|
|
* none-zero failure code
|
|
*
|
|
*==========================================================================*/
|
|
int32_t QCameraPerfLock::lock_rel_timed()
|
|
{
|
|
int ret = -1;
|
|
Mutex::Autolock lock(mLock);
|
|
if (mPerfLockEnable) {
|
|
LOGD("E");
|
|
if (mPerfLockHandleTimed < 0) {
|
|
LOGW("mPerfLockHandle < 0,check if lock is acquired");
|
|
return ret;
|
|
}
|
|
LOGD("perf_handle_rel %d ", mPerfLockHandleTimed);
|
|
|
|
if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandleTimed)) {
|
|
ret = (*perf_lock_rel)(mPerfLockHandleTimed);
|
|
if (ret < 0) {
|
|
LOGE("failed to release lock");
|
|
}
|
|
mPerfLockHandleTimed = -1;
|
|
resetTimer();
|
|
}
|
|
|
|
if ((mCurrentPowerHintEnable == 1) && (mTimerSet == 0)) {
|
|
powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable);
|
|
}
|
|
LOGD("X");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : lock_rel
|
|
*
|
|
* DESCRIPTION: release the performance lock
|
|
*
|
|
* PARAMETERS :
|
|
* None
|
|
*
|
|
* RETURN : int32_t type of status
|
|
* NO_ERROR -- success
|
|
* none-zero failure code
|
|
*
|
|
*==========================================================================*/
|
|
int32_t QCameraPerfLock::lock_rel()
|
|
{
|
|
int ret = -1;
|
|
Mutex::Autolock lock(mLock);
|
|
if (mPerfLockEnable) {
|
|
LOGD("E");
|
|
if (mPerfLockHandle < 0) {
|
|
LOGW("mPerfLockHandle < 0,check if lock is acquired");
|
|
return ret;
|
|
}
|
|
LOGD("perf_handle_rel %d ", mPerfLockHandle);
|
|
|
|
if ((NULL != perf_lock_rel) && (0 <= mPerfLockHandle)) {
|
|
ret = (*perf_lock_rel)(mPerfLockHandle);
|
|
if (ret < 0) {
|
|
LOGE("failed to release lock");
|
|
}
|
|
mPerfLockHandle = -1;
|
|
}
|
|
|
|
if (mCurrentPowerHintEnable == 1) {
|
|
powerHintInternal(mCurrentPowerHint, mCurrentPowerHintEnable);
|
|
}
|
|
LOGD("X");
|
|
}
|
|
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 hint, bool enable)
|
|
{
|
|
#ifdef HAS_MULTIMEDIA_HINTS
|
|
if (m_pPowerModule != NULL) {
|
|
if (enable == true) {
|
|
m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=1");
|
|
} else {
|
|
m_pPowerModule->powerHint(m_pPowerModule, hint, (void *)"state=0");
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*===========================================================================
|
|
* FUNCTION : powerHint
|
|
*
|
|
* DESCRIPTION: Updates the list containing active/enabled power hints.
|
|
* If needed, calls the internal powerHint function with
|
|
* requested power hint and state.
|
|
* PARAMETERS :
|
|
* hint : Power hint
|
|
* enable : Enable power hint if set to 1. Disable if set to 0.
|
|
* RETURN : void
|
|
*
|
|
*==========================================================================*/
|
|
void QCameraPerfLock::powerHint(power_hint_t hint, bool enable)
|
|
{
|
|
#ifdef HAS_MULTIMEDIA_HINTS
|
|
if (enable == true) {
|
|
if ((hint != mCurrentPowerHint) || (enable != mCurrentPowerHintEnable)) {
|
|
// Disable the current active power hint
|
|
if (mCurrentPowerHintEnable == true) {
|
|
powerHintInternal(mCurrentPowerHint, false);
|
|
}
|
|
// Push the new power hint at the head of the active power hint list
|
|
mActivePowerHints.push_front(hint);
|
|
|
|
// Set the new power hint
|
|
mCurrentPowerHint = hint;
|
|
mCurrentPowerHintEnable = enable;
|
|
powerHintInternal(hint, enable);
|
|
}
|
|
} else {
|
|
// Remove the power hint from the list
|
|
for (List<power_hint_t>::iterator it = mActivePowerHints.begin();
|
|
it != mActivePowerHints.end(); ++it) {
|
|
if (*it == hint) {
|
|
if (it != mActivePowerHints.begin()) {
|
|
LOGW("Request to remove the previous power hint: %d instead of "
|
|
"currently active power hint: %d", static_cast<int>(hint),
|
|
static_cast<int>(mCurrentPowerHint));
|
|
}
|
|
mActivePowerHints.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hint == mCurrentPowerHint) {
|
|
// Disable the power hint
|
|
powerHintInternal(hint, false);
|
|
|
|
// If the active power hint list is not empty,
|
|
// restore the previous power hint from the head of the list
|
|
if (mActivePowerHints.empty() == false) {
|
|
mCurrentPowerHint = *mActivePowerHints.begin();
|
|
mCurrentPowerHintEnable = true;
|
|
powerHintInternal(mCurrentPowerHint, true);
|
|
} else {
|
|
mCurrentPowerHint = static_cast<power_hint_t>(0);
|
|
mCurrentPowerHintEnable = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
}; // namespace qcamera
|