829 lines
31 KiB
C++
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
|
|
|