unplugged-vendor/frameworks/native/services/surfaceflinger/mediatek/SfCpuPolicyAdapter/SfCpuPolicyAdapter.cpp

829 lines
31 KiB
C++

/* Copyright Statement:
*
* This software/firmware and related documentation ("MediaTek Software") are
* protected under relevant copyright laws. The information contained herein is
* confidential and proprietary to MediaTek Inc. and/or its licensors. Without
* the prior written permission of MediaTek inc. and/or its licensors, any
* reproduction, modification, use or disclosure of MediaTek Software, and
* information contained herein, in whole or in part, shall be strictly
* prohibited.
*
* MediaTek Inc. (C) 2021. All rights reserved.
*
* BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
* ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
* WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
* RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
* INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
* TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
* RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
* OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
* SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
* RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
* STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
* ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
* RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
* MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
* CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
*
* The following software/firmware and/or related documentation ("MediaTek
* Software") have been modified by MediaTek Inc. All revisions are subject to
* any receiver's applicable license agreements with MediaTek Inc.
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "SfCpuPolicyAdapter.h"
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Trace.h>
#include <sys/utsname.h>
#include <dlfcn.h>
#ifdef MTK_COMPOSER_EXT
#include <composer_ext_intf/client_interface.h>
#endif
namespace android {
#ifndef MTK_CUTTLESTONE
const SfCpuPolicy::Config SfCpuPolicyAdapter::HighPerfCong = {125000000, 30, 125000000, 10};
const SfCpuPolicy::Config SfCpuPolicyAdapter::NormalPerfCong = {125000000, 10, 125000000, 5};
#endif
static int CONFIG_HW_COMP_RATE_MIN_ENABLE_CPU_POLICY = 60; //eg HW comp, min rate to start the cpu policy, eg 60 hz
static int CONFIG_GPU_COMP_RATE_MIN_ENABLE_CPU_POLICY = 60; //eg GPU comp, min rate to start the cpu policy, eg 60hz & gpu is using
static int CONFIG_HW_COMP_SUSPEND_CPU_POLICY = 0 ; // [0 ~ 1], suspend the comunication of XGF, ie auto control by scheduler per min resource requirement
static int CONFIG_HW_COMP_HFR_SUSPEND_CPU_POLICY = 0 ; // [0 ~ 1], suspend the comunication of XGF, ie auto control by scheduler per min resource requirement
static int CONFIG_VP_LP_SUSPEND_CPU_POLICY = 0 ; // [0 ~ 1], suspend if VPLP hint got
static int CONFIG_FORCE_SUSPEND_CPU_POLICY = 0 ; // testing only, force suspend mode
static int CONFIG_POWER_UP_MARGIN_120 = 500000; // 500000 nsec, 0.5 ms
static int CONFIG_POWER_DOWN_MARGIN_120 = 2000000; // 2000000 nsec
static int CONFIG_POWER_UP_MARGIN_90 = 500000; // 500000 nsec, 0.5 ms
static int CONFIG_POWER_DOWN_MARGIN_90 = 2000000; // 2000000 nsec
static int CONFIG_POWER_UP_MARGIN = 500000; // 500000 nsec, 0.5 ms
static int CONFIG_POWER_DOWN_MARGIN = 2000000; // 2000000 nsec
static bool logEnabled() {
static bool checked = false;
static bool enabled = false;
if (!checked){
char value[PROPERTY_VALUE_MAX] = {};
property_get("vendor.debug.sf.cpupolicy.log", value, "1");
enabled = (atoi(value)>=2);
checked = true;
}
return enabled;
}
SfCpuPolicyAdapter& SfCpuPolicyAdapter::getInstance(frametimeline::FrameTimeline & frameTimeline) {
static SfCpuPolicyAdapter gInstance(frameTimeline);
return gInstance;
}
bool SfCpuPolicyAdapter::isEnabled() {
static bool checked = false;
static bool enabled = false;
if (!checked){
char value[PROPERTY_VALUE_MAX] = {};
property_get("vendor.debug.sf.cpupolicy", value, "1");
enabled = (atoi(value) != 0);
struct utsname u;
if (uname (&u) < 0){
enabled = false;
checked = true;
return enabled;
}
std::string str = u.release;
// eg: str = "5.10.41-android12-5-gdce53f229c13";
if (enabled) {
std::string const delims{ ".-"};
std::string str_big_version;
std::string str_middle_version;
int big_version;
int middle_version;
size_t beg = 0;
size_t pos = 0;
beg = str.find_first_not_of(delims, pos);
if ( beg != std::string::npos) {
pos = str.find_first_of(delims, beg + 1);
str_big_version = str.substr(beg, pos - beg);
}
beg = str.find_first_not_of(delims, pos);
if ( beg != std::string::npos) {
pos = str.find_first_of(delims, beg + 1);
str_middle_version = str.substr(beg, pos - beg);
}
big_version = std::stoi(str_big_version); // eg 5
middle_version = std::stoi(str_middle_version); //eg 10
if ((big_version > 5) || (big_version == 5 && middle_version >=10)) {
enabled = true;
}else {
enabled = false;
}
}
ALOGI("release %s enabled %d", u.release, enabled);
checked = true;
}
return enabled;
}
void SfCpuPolicyAdapter::notifyPowerSuspend(bool enable) {
mPowerSuspend = enable;
}
void SfCpuPolicyAdapter::notifyHwcHwbinderTid(int tid) {
ALOGV("notifyHwcHwbinderTid");
if (mCpuPolicy == nullptr) return;
if (mFnNotifyHwcHwbinderTid) {
mFnNotifyHwcHwbinderTid(mCpuPolicy, tid);
} else {
ALOGE("!mFnNotifyHwcHwbinderTid");
}
}
void SfCpuPolicyAdapter::notifyVpLpEnable(bool enable) {
std::lock_guard lock(mMutex);
mVpLpEnableDbg = enable;
ALOGD("%s enable %d", __FUNCTION__, enable);
}
bool SfCpuPolicyAdapter::getVpLpEnable() {
bool enable = false;
{
std::lock_guard lock(mMutex);
int layerCnt = 0;
bool vplpFound = false;
for (auto it = mVpLpLayers.begin(); it != mVpLpLayers.end(); ++it) {
if(it->second == VPLP_LAYER_CHECKED_OK) {
vplpFound = true;
}
layerCnt ++;
}
mVpLpEnable = (vplpFound && (layerCnt == 1)); // allowed only one surfaceview/vp layer
enable = mVpLpEnable || mVpLpEnableDbg;
ALOGV("%s: vplp layer cnt %d", __FUNCTION__, layerCnt);
}
return enable;
}
void SfCpuPolicyAdapter::notifyLayerConnect(const void * token, const std::string& name) {
std::lock_guard lock(mMutex);
if (token == nullptr) return;
bool layerMatch = false;
#define SURFACEVIEW_LAYER_NAME "SurfaceView"
std::vector<std::string> LayerNameArr = {SURFACEVIEW_LAYER_NAME};
for(size_t i = 0; i < LayerNameArr.size(); ++i) {
if (name.find(LayerNameArr[i]) != std::string::npos) {
layerMatch = true;
break;
}
}
if (layerMatch) {
// add mVpLpLayers
if (logEnabled()) {
ALOGD("%s: token=%p , %s", __FUNCTION__, token, name.c_str());
}
mVpLpLayers.emplace(token, VPLP_LAYER_UNCHECKED); // pending check
}
}
void SfCpuPolicyAdapter::notifyLayerDisconnect(const void * token){
std::lock_guard lock(mMutex);
if (token == nullptr) return;
auto it = mVpLpLayers.find(token);
if (it != mVpLpLayers.end()) {
if (logEnabled()) {
ALOGD("%s: token=%p", __FUNCTION__, token);
}
mVpLpLayers.erase(it);
}
}
void SfCpuPolicyAdapter::notifyLayerSetBuffer(const void * token, const sp<GraphicBuffer>& buffer){
#ifndef MTK_CUTTLESTONE
std::lock_guard lock(mMutex);
if (token != nullptr && buffer != nullptr) {
uint32_t w = buffer->getWidth();
uint32_t h = buffer->getHeight();
auto it = mVpLpLayers.find(token);
if (it != mVpLpLayers.end()) {
if (it->second == VPLP_LAYER_UNCHECKED) {
if (w <=2000 && h <=2000 ) { // quick check for 1920x1080p
gralloc_extra_ion_sf_info_t extInfo;
GRALLOC_EXTRA_RESULT result = gralloc_extra_query(buffer->handle,
GRALLOC_EXTRA_GET_IOCTL_ION_SF_INFO, &extInfo);
if (result == GRALLOC_EXTRA_OK &&
((unsigned int)extInfo.status & GRALLOC_EXTRA_MASK_TYPE)
== GRALLOC_EXTRA_BIT_TYPE_VIDEO) {
it->second = VPLP_LAYER_CHECKED_OK; // checked and valid vp layer
if (logEnabled()) {
ALOGD("%s: token=%p", __FUNCTION__, token);
}
} else {
it->second = VPLP_LAYER_CHECKED_NOT_OK; // checked and not valid vp layer
}
} else {
it->second = VPLP_LAYER_CHECKED_NOT_OK; // checked and not valid vp layer
}
}
}
}
#else
if (token != nullptr && buffer != nullptr) {
if (logEnabled()) {
ALOGV("%s: token=%p", __FUNCTION__, token);
}
}
#endif //MTK_CUTTLESTONE
}
SfCpuPolicy::EnableReason SfCpuPolicyAdapter::checkIfNeedSuspend(int rate, bool gpu_comp, bool * sus_mid, nsecs_t *targetTime) {
bool needSuspend = true; // true to disable the SF CPU policy
#ifdef MTK_COMPOSER_EXT
bool vpLpState = false;
#endif
SfCpuPolicy::EnableReason ret = SfCpuPolicy::EnableReason::NONE;
// init the min required resource, not set to none at beginig
if (rate > 95 ){
ret = SfCpuPolicy::EnableReason::MIN_SPEED_120;
}
else if (rate > 65 ){
ret = SfCpuPolicy::EnableReason::MIN_SPEED_90;
} else {
ret = SfCpuPolicy::EnableReason::MIN_SPEED_60;
}
// simple rule to enable cpu policy
if (rate >= CONFIG_HW_COMP_RATE_MIN_ENABLE_CPU_POLICY) {
needSuspend = false;
ret = SfCpuPolicy::EnableReason::SF_SPEED;
}
else if (gpu_comp && rate >= CONFIG_GPU_COMP_RATE_MIN_ENABLE_CPU_POLICY) {
needSuspend = false;
ret = SfCpuPolicy::EnableReason::RE_SPEED;
}
if (!mPowerSuspend){
/* update lastFps while screen on */
mLastFps = mFrameTimeline.computeFps(0,0);
ATRACE_INT("SfCpu_fps", (int)mLastFps);
}
if (rate) {
// estiminate the fps and provide the min resource
static SfCpuPolicy::EnableReason suspendSpeed =
SfCpuPolicy::EnableReason::MIN_SPEED_120;
static SfCpuPolicy::EnableReason oldSuspendSpeed =
SfCpuPolicy::EnableReason::MIN_SPEED_120;
static int count_90 = 0;
static int count_60 = 0;
static int count_30 = 0;
if (!mPowerSuspend){
oldSuspendSpeed = suspendSpeed;
if (mLastFps >= 95.0f) {
static int credit = 0;
suspendSpeed = SfCpuPolicy::EnableReason::MIN_SPEED_120;
if (!gpu_comp) {
credit ++;
if (credit >= 5) credit = 5;
}else {
credit = 0;
}
if (!gpu_comp && (credit >= 5) && CONFIG_HW_COMP_HFR_SUSPEND_CPU_POLICY) {
needSuspend = true;
ret = SfCpuPolicy::EnableReason::MIN_SPEED_120;
}
} else if (mLastFps < 95.0f && mLastFps >= 69.0f) {
// ie take 70~95 fps as 90 fps, 5 is the margin
suspendSpeed = SfCpuPolicy::EnableReason::MIN_SPEED_90;
if (oldSuspendSpeed != suspendSpeed) {
count_90 = 0;
}else {
count_90 ++;
}
if (count_90 >= 45) {
/*
The time would be more than 0.5s below 95 fps.
Suspend the cpu policy.
*/
if (!gpu_comp && CONFIG_HW_COMP_HFR_SUSPEND_CPU_POLICY) {
needSuspend = true;
ret = SfCpuPolicy::EnableReason::MIN_SPEED_90;
}
nsecs_t predictTarget = calcTargetTime ((int)90);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
count_90 = 45;
}
}
else if (mLastFps < 69.0f) {
// ie take 0-69 fps as 60 fps, 9 is the margin
suspendSpeed = SfCpuPolicy::EnableReason::MIN_SPEED_60;
if (oldSuspendSpeed > suspendSpeed) {
count_60 = 0;
}else {
count_60 ++;
}
if (count_60 >= 20) {
/*
The time would be more than 0.3s below 69 fps.
Suspend the cpu policy.
*/
if (!gpu_comp && CONFIG_HW_COMP_SUSPEND_CPU_POLICY) {
needSuspend = true;
ret = SfCpuPolicy::EnableReason::MIN_SPEED_60;
}
nsecs_t predictTarget = calcTargetTime ((int)60);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
count_60 = 20;
}
if (mLastFps <= 35.0f) {
suspendSpeed = SfCpuPolicy::EnableReason::MIN_SPEED_30;
if (oldSuspendSpeed > suspendSpeed) {
count_30 = 0;
}else {
count_30 ++;
}
if (count_30 >= 20) {
/*
The time would be more than 0.6s below 35 fps.
Suspend the cpu policy.
*/
if (!gpu_comp && CONFIG_VP_LP_SUSPEND_CPU_POLICY) {
if(getVpLpEnable()) {
needSuspend = true;
ret = SfCpuPolicy::EnableReason::MIN_SPEED_30;
#ifdef MTK_COMPOSER_EXT
vpLpState = true;
#endif
if (sus_mid){
*sus_mid = true;
}
}
} else if (!gpu_comp && CONFIG_HW_COMP_SUSPEND_CPU_POLICY) {
needSuspend = true;
ret = SfCpuPolicy::EnableReason::MIN_SPEED_30;
}
nsecs_t predictTarget = calcTargetTime ((int)60);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
count_30 = 20;
}
}
}
if (logEnabled()){
ALOGD("needSuspend %d suspendSpeed %d count_30 %d count_60 %d count_90 %d avg fps %f",
needSuspend, suspendSpeed, count_30, count_60, count_90, mLastFps);
}
}
}
if (!mPowerSuspend) {
static nsecs_t lastFrameEndTime = 0;
nsecs_t currentTime = systemTime();
bool longTime = lastFrameEndTime &&
(currentTime - lastFrameEndTime) >= 1000000000 ; //1s
bool reset_workaround = lastFrameEndTime &&
(currentTime - lastFrameEndTime) >= 100000000 ; //100 ms , 10 fps
if (!gpu_comp && reset_workaround) {
// avoid calculate if end 2 end too long
// Idle mode pattern check, 10 fps
notifyResetCalculation();
}
static int old_mS2sFps = 0;
if (old_mS2sFps != (int)mS2sFps) {
// reduce trace. it is 0 for most cases
ATRACE_INT("SfCpu_fps_curr", (int)mS2sFps);
old_mS2sFps = (int)mS2sFps;
}
if (!gpu_comp && (mS2sFps > 0) && (mS2sFps <=10.0f) ){
// Idle mode pattern check, 10 fps
needSuspend = true;
nsecs_t predictTarget = calcTargetTime ((int)10);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
notifyResetCalculation();
}
if (!gpu_comp && (mS2sFps > 0) && (mLastFps <= 10.0f)) { // low frame rate
// Idle mode pattern check, 10 fps
// make the target time longer since perfmance is not needed.
needSuspend = true;
nsecs_t predictTarget = calcTargetTime ((int)10);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
notifyResetCalculation();
}
if ((mS2sFps > 0) && (mS2sFps <= 5.0f)){
// Idle mode pattern check, 0-5 fps
needSuspend = true;
nsecs_t predictTarget = calcTargetTime ((int)10);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
notifyResetCalculation();
}
if (mLastFps < 1.0f && longTime) { // almost idle screen
needSuspend = true;
ret = SfCpuPolicy::EnableReason::NONE;
// make the target time longer since perfmance is not needed.
nsecs_t predictTarget = calcTargetTime ((int)10);
if (targetTime != nullptr) {
*targetTime = predictTarget;
}
}
if (CONFIG_FORCE_SUSPEND_CPU_POLICY) {
needSuspend = true;
}
lastFrameEndTime = currentTime;
}
mSuspendNeed = needSuspend;
bool oldSuspend = mSuspend;
mSuspend = (mPowerSuspend || mSuspendNeed);
#ifdef MTK_COMPOSER_EXT
#ifndef MTK_CUTTLESTONE
if (vpLpState != mLastVpLpState) {
if (mMtkComposerExtIntf) {
ComposerExt::ScenarioHint val = vpLpState ? ComposerExt::ScenarioHint::kVideoPlyback:
ComposerExt::ScenarioHint::kGeneral;
mMtkComposerExtIntf->setScenarioHint(val, ComposerExt::ScenarioHint::kVideoPlyback);
}
mLastVpLpState = vpLpState;
}
#else //MTK_CUTTLESTONE
mLastVpLpState = false;
#endif //MTK_CUTTLESTONE
#endif
if (mPowerSuspend) {
ret = SfCpuPolicy::EnableReason::NONE;
}
if (logEnabled()){
ALOGD("mSuspend %d mPowerSuspend %d mSuspendNeed %d gpu %d",
mSuspend, mPowerSuspend, mSuspendNeed, gpu_comp);
}
if (mSuspend && !oldSuspend){
notifyResetCalculation();
}
if (targetTime != nullptr) {
ATRACE_INT("SfCpu_targetTime", (int)(*targetTime)/10000);
}
return ret;
}
SfCpuPolicyAdapter::SfCpuPolicyAdapter(frametimeline::FrameTimeline & frameTimeline):
mFrameTimeline(frameTimeline),
mSoHandle(nullptr),
mFnCreateSfCpuPolicy(nullptr),
mFnDestroySfCpuPolicy(nullptr),
mFnSetupConfig(nullptr),
mFnSetupPerfMeas(nullptr),
mFnNotifyFrameStart(nullptr),
mFnNotifySpeedUpRE(nullptr),
mFnNotifyFrameEnd(nullptr),
mFnNotifyClearCorrection(nullptr),
mFnNotifyResetCalculation(nullptr),
mFnNotifyHwcHwbinderTid(nullptr)
{
ALOGV("SfCpuPolicyAdapter");
mSoHandle = dlopen("libsf_cpupolicy.so", RTLD_LAZY);
typedef SfCpuPolicy* (*CreateSfCpuPolicy)();
typedef void (*DestroySfCpuPolicy)(SfCpuPolicy*);
typedef void (*SetupConfig)(SfCpuPolicy*,SfCpuPolicy::Config & conf,bool suspend);
typedef void (*SetupPerfMeas)(SfCpuPolicy* cpuPolicy, SfCpuPolicy::PerfMeas * perfMeas);
typedef void (*NotifyFrameStart)(SfCpuPolicy* cpuPolicy, nsecs_t startTime, int64_t vsyncId, bool suspend);
typedef void (*NotifySpeedUpRE)(SfCpuPolicy* cpuPolicy, int resource, int64_t vsyncId);
typedef void (*NotifyFrameEnd)(SfCpuPolicy* cpuPolicy, nsecs_t endTime, int64_t vsyncId, bool suspend);
typedef void (*NotifyClearCorrection)(SfCpuPolicy* cpuPolicy, int64_t vsyncId, bool clear, bool heavyLoading);
typedef void (*NotifyResetCalculation)(SfCpuPolicy* cpuPolicy, int64_t vsyncId);
typedef void (*NotifyHwcHwbinderTid)(SfCpuPolicy* cpuPolicy, int tid);
mFnCreateSfCpuPolicy = reinterpret_cast<CreateSfCpuPolicy>(dlsym(mSoHandle, "createSfCpuPolicy"));
mFnDestroySfCpuPolicy = reinterpret_cast<DestroySfCpuPolicy>(dlsym(mSoHandle, "destroySfCpuPolicy"));
mFnSetupConfig = reinterpret_cast<SetupConfig>(dlsym(mSoHandle, "setupConfig"));
mFnSetupPerfMeas = reinterpret_cast<SetupPerfMeas>(dlsym(mSoHandle, "setupPerfMeas"));
mFnNotifyFrameStart = reinterpret_cast<NotifyFrameStart>(dlsym(mSoHandle, "notifyFrameStart"));
mFnNotifySpeedUpRE = reinterpret_cast<NotifySpeedUpRE>(dlsym(mSoHandle, "notifySpeedUpRE"));
mFnNotifyFrameEnd = reinterpret_cast<NotifyFrameEnd>(dlsym(mSoHandle, "notifyFrameEnd"));
mFnNotifyClearCorrection = reinterpret_cast<NotifyClearCorrection>(dlsym(mSoHandle, "notifyClearCorrection"));
mFnNotifyResetCalculation = reinterpret_cast<NotifyResetCalculation>(dlsym(mSoHandle, "notifyResetCalculation"));
mFnNotifyHwcHwbinderTid = reinterpret_cast<NotifyHwcHwbinderTid>(dlsym(mSoHandle, "notifyHwcHwbinderTid"));
if (mSoHandle) {
if (nullptr == mFnCreateSfCpuPolicy) {
ALOGE("finding createSfCpuPolicy() failed");
} else if (nullptr == mFnSetupPerfMeas) {
ALOGE("finding setupPerfMeas() failed");
} else {
mCpuPolicy = createSfCpuPolicy();
}
if (nullptr == mFnDestroySfCpuPolicy) {
ALOGE("finding destroySfCpuPolicy() failed");
}
if (nullptr == mFnSetupConfig) {
ALOGE("finding setupConfig() failed");
}
if (nullptr == mFnNotifyFrameStart) {
ALOGE("finding notifyFrameStart() failed");
}
if (nullptr == mFnNotifySpeedUpRE) {
ALOGE("finding notifySpeedUpRE() failed");
}
if (nullptr == mFnNotifyFrameEnd) {
ALOGE("finding notifyFrameEnd() failed");
}
if (nullptr == mFnNotifyClearCorrection) {
ALOGE("finding notifyClearCorrection() failed");
}
if (nullptr == mFnNotifyResetCalculation) {
ALOGE("finding notifyResetCalculation() failed");
}
if (nullptr == mFnNotifyHwcHwbinderTid) {
ALOGE("finding notifyHwcHwbinderTid() failed");
}
} else {
ALOGE("open libsf_cpupolicy failed");
}
InitProp();
}
void SfCpuPolicyAdapter::InitProp(){
char value[PROPERTY_VALUE_MAX] = {};
int iValue = 0;
property_get("vendor.debug.sf.cpupolicy.hw_comp_min", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_HW_COMP_RATE_MIN_ENABLE_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.gpu_comp_min", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_GPU_COMP_RATE_MIN_ENABLE_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.hw_comp_suspend", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_HW_COMP_SUSPEND_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.hw_hfr_suspend", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_HW_COMP_HFR_SUSPEND_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.vp_lp_suspend", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_VP_LP_SUSPEND_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.force_suspend", value, "-1");
iValue = (atoi(value));
if (iValue >= 0) {
CONFIG_FORCE_SUSPEND_CPU_POLICY = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_up_120", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_UP_MARGIN_120 = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_up_90", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_UP_MARGIN_90 = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_up_margin", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_UP_MARGIN = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_down_120", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_DOWN_MARGIN_120 = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_down_90", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_DOWN_MARGIN_90 = iValue;
}
property_get("vendor.debug.sf.cpupolicy.power_down_margin", value, "-1");
iValue = (atoi(value));
if (iValue != -1) {
CONFIG_POWER_DOWN_MARGIN = iValue;
}
}
SfCpuPolicy* SfCpuPolicyAdapter::createSfCpuPolicy(){
ALOGV("createSfCpuPolicy");
if (mFnCreateSfCpuPolicy) {
SfCpuPolicy *cpuPolicy = mFnCreateSfCpuPolicy();
if (mFnSetupPerfMeas) {
mFnSetupPerfMeas (cpuPolicy, this);
}
return cpuPolicy;
}
return nullptr;
}
void SfCpuPolicyAdapter::destroySfCpuPolicy(){
if (mCpuPolicy == nullptr) return;
if (mFnDestroySfCpuPolicy) {
mFnDestroySfCpuPolicy(mCpuPolicy);
}
}
void SfCpuPolicyAdapter::setupConfig(SfCpuPolicy::Config & conf) {
if (mCpuPolicy == nullptr) return;
if (mIsLastFrameFinished && mSuspend) {
if (mFnSetupConfig) {
mFnSetupConfig(mCpuPolicy, conf, true);
}
return;
}
if (mFnSetupConfig) {
mFnSetupConfig(mCpuPolicy, conf, false);
}
}
void SfCpuPolicyAdapter::notifyFrameStart(
nsecs_t startTime, int64_t vsyncId) {
ALOGV("notifyFrameStart %" PRId64" ", vsyncId);
if (mCpuPolicy == nullptr){
ALOGE("mCpuPolicy == null");
return;
}
static nsecs_t lastFrameStartTimeChk = 0;
static int count = 0;
nsecs_t currentTime = systemTime();
bool longTime = lastFrameStartTimeChk && mLastFrameEndTime &&
(currentTime - mLastFrameEndTime) >= 40000000 ; // 40 ms
// calculate the current fps if the last start is long time.
if (longTime) {
count ++;
if (currentTime- lastFrameStartTimeChk >= 300000000) { // 300 ms
mS2sFps = count * 1000000000 /(currentTime- lastFrameStartTimeChk);
}
}else {
lastFrameStartTimeChk = mLastFrameEndTime;
count = 0;
mS2sFps = 0;
}
// notify frame end if last frame just contains start and no end
if (!mIsLastFrameFinished) {
if (mFnNotifyFrameEnd) {
//notify 0 endTime , ie. the frame should be cancel.
mFnNotifyFrameEnd(mCpuPolicy, 0, mLastVsyncId, false);
mIsLastFrameFinished = true;
}
}
if (mSuspend) {
if (mFnNotifyFrameStart) {
mFnNotifyFrameStart(mCpuPolicy, startTime, vsyncId, mSuspend);
}
return;
}
if (mFnNotifyFrameStart) {
mFnNotifyFrameStart(mCpuPolicy, startTime, vsyncId, mSuspend);
mLastVsyncId = vsyncId;
}
mIsLastFrameFinished = false;
}
void SfCpuPolicyAdapter::notifySpeedUpRE(int resource) {
ALOGV("notifySpeedUpRE %" PRId64" ", mLastVsyncId);
if (mCpuPolicy == nullptr){
ALOGE("mCpuPolicy == null");
return;
}
if (mFnNotifySpeedUpRE) {
mFnNotifySpeedUpRE(mCpuPolicy, resource, mLastVsyncId);
} else {
ALOGE("!mFnNotifySpeedUpRE");
}
}
void SfCpuPolicyAdapter::notifyFrameEnd(
nsecs_t endTime) {
ALOGV("notifyFrameEnd %" PRId64" ", mLastVsyncId);
mLastFrameEndTime = systemTime();
if (mCpuPolicy == nullptr) return;
if (mIsLastFrameFinished && mSuspend) {
if (mFnNotifyFrameEnd) {
mFnNotifyFrameEnd(mCpuPolicy, endTime, mLastVsyncId, true);
}
return;
}
if (mFnNotifyFrameEnd) {
mFnNotifyFrameEnd(mCpuPolicy, endTime, mLastVsyncId, false);
} else {
ALOGE("!mFnNotifyFrameEnd");
}
mIsLastFrameFinished = true;
}
void SfCpuPolicyAdapter::notifyClearCorrection(bool clear, bool heavyLoading) {
ALOGV("notifyClearCorrection");
if (mCpuPolicy == nullptr) return;
if (mIsLastFrameFinished && mSuspend) {
return;
}
if (mFnNotifyClearCorrection) {
mFnNotifyClearCorrection(mCpuPolicy, mLastVsyncId, clear, heavyLoading);
} else {
ALOGE("!mFnNotifyClearCorrection");
}
}
void SfCpuPolicyAdapter::notifyResetCalculation() {
ALOGV("notifyResetCalculation");
if (mCpuPolicy == nullptr) return;
if (mIsLastFrameFinished && mSuspend) {
return;
}
if (mFnNotifyResetCalculation) {
mFnNotifyResetCalculation(mCpuPolicy, mLastVsyncId);
} else {
ALOGE("!mFnNotifyResetCalculation");
}
}
bool SfCpuPolicyAdapter::needIncreasePerf(nsecs_t startTime, nsecs_t endTime, nsecs_t targetTime) {
nsecs_t margin = CONFIG_POWER_UP_MARGIN;
if (targetTime <= 8000000) { // 8ms
margin = CONFIG_POWER_UP_MARGIN_120;
} else if (targetTime <= 11000000){ // 11ms
margin = CONFIG_POWER_UP_MARGIN_90;
}
nsecs_t predictTarget = targetTime - margin ;
bool ret = mFrameTimeline.isPresentLate(startTime, endTime, targetTime, predictTarget);
return ret;
}
bool SfCpuPolicyAdapter::needReducePerf(nsecs_t startTime, nsecs_t endTime, nsecs_t targetTime) {
nsecs_t margin = CONFIG_POWER_DOWN_MARGIN;
if (targetTime <= 8000000) { // 8ms
margin = CONFIG_POWER_DOWN_MARGIN_120;
} else if (targetTime <= 11000000){ // 11ms
margin = CONFIG_POWER_DOWN_MARGIN_90;
}
nsecs_t predictTarget = targetTime - margin ;
bool ret = mFrameTimeline.isPresentEarly(startTime, endTime, targetTime, predictTarget);
return ret;
}
nsecs_t SfCpuPolicyAdapter::calcTargetTime(int fps){
nsecs_t targetTime = 16* 1000000;
if(fps > 125) { // 144 fps
targetTime = 6* 1000000; // 6ms
}else if (fps > 95) { // 120 fps
targetTime = 8* 1000000; // 8ms
}else if (fps > 68) { // 90 fps
targetTime = 11* 1000000; // 11ms
}
else if (fps > 35){ // 60 fps
targetTime = 16* 1000000; // 16ms
}
else {
targetTime = 25* 1000000; // 25ms
}
ALOGV("refresh rate fps %d", fps);
return targetTime;
}
SfCpuPolicyAdapter::~SfCpuPolicyAdapter(){
if (mSoHandle) {
dlclose(mSoHandle);
mSoHandle = nullptr;
}
if (mCpuPolicy != nullptr) {
destroySfCpuPolicy();
mCpuPolicy = nullptr;
}
}
#ifdef MTK_COMPOSER_EXT
void SfCpuPolicyAdapter::setComposerExtIntf(ComposerExt::ClientInterface* intf) {
mMtkComposerExtIntf = intf;
}
#endif
}// namespace android