184 lines
6.6 KiB
C++
184 lines
6.6 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) 2022. 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <log/log.h>
|
|
#include <thread>
|
|
#include <utils/Trace.h>
|
|
#include <utils/Mutex.h>
|
|
#include <android-base/properties.h>
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#include <utils/NativeHandle.h> // client_interface needs
|
|
#include <composer_ext_intf/client_interface.h>
|
|
#endif
|
|
|
|
namespace android {
|
|
// ---------------------------------------------------------------------------
|
|
class KickIdleHelper
|
|
{
|
|
private:
|
|
nsecs_t mTsForLastKickTime;
|
|
Mutex mKickIdleMutex;
|
|
nsecs_t mIdleTimer;
|
|
nsecs_t mLastKickTime;
|
|
// TO-DO: Be able to kick other display.
|
|
bool mActiveDisplayPowerOn;
|
|
uint64_t mDisplayIdToKick;
|
|
#ifdef MTK_COMPOSER_EXT
|
|
::ComposerExt::ClientInterface* mMtkComposerExtIntf;
|
|
#endif
|
|
std::thread::id mMainThreadId;
|
|
nsecs_t mScheduledPresentTime;
|
|
int mMode;
|
|
|
|
KickIdleHelper() {
|
|
mTsForLastKickTime = 0;
|
|
mActiveDisplayPowerOn = false;
|
|
mDisplayIdToKick = 0;
|
|
mIdleTimer = 0;
|
|
mLastKickTime = 0;
|
|
#ifdef MTK_COMPOSER_EXT
|
|
mMtkComposerExtIntf = nullptr;
|
|
#endif
|
|
mScheduledPresentTime = 0;
|
|
mMode = base::GetIntProperty("vendor.debug.sf.kickidle.mode", 0);
|
|
}
|
|
|
|
bool isEnabled() { return mMode > 0; }
|
|
|
|
void kick() REQUIRES(mKickIdleMutex) {
|
|
#ifdef MTK_COMPOSER_EXT
|
|
if (mMtkComposerExtIntf) {
|
|
ATRACE_NAME("kickIdle");
|
|
mMtkComposerExtIntf->kickIdle(mDisplayIdToKick /*disp_id*/);
|
|
} else {
|
|
ALOGE("kickIdle mMtkComposerExtIntf null");
|
|
}
|
|
#else
|
|
ALOGE("kickIdle miss COMPOSER_EXT");
|
|
#endif
|
|
}
|
|
|
|
public:
|
|
static KickIdleHelper& getInstance() {
|
|
static KickIdleHelper gInstance;
|
|
return gInstance;
|
|
}
|
|
|
|
~KickIdleHelper() {};
|
|
|
|
void setComposerExtInf(void* composerExt) {
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
#ifdef MTK_COMPOSER_EXT
|
|
mMtkComposerExtIntf = (::ComposerExt::ClientInterface*) composerExt;
|
|
#endif
|
|
}
|
|
|
|
void updateIdleTimer(nsecs_t period) {
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
if (period == 8333333) {
|
|
mIdleTimer = uint32_t(period * 4.5);
|
|
} else {
|
|
mIdleTimer = uint32_t(period * 3.5);
|
|
}
|
|
}
|
|
|
|
void updateDisplayInfo(bool power, uint64_t id) {
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
mActiveDisplayPowerOn = power;
|
|
mDisplayIdToKick = id;
|
|
}
|
|
|
|
void updateMainThreadId(std::thread::id id) {
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
mMainThreadId = id;
|
|
}
|
|
|
|
bool isMainThread () {
|
|
// Our purpose is to kick idle earier before main thread runs.
|
|
// So, we only do it on sub thread. Skipping can prevent
|
|
// potential deadlock on mStateLock as well.
|
|
if (std::this_thread::get_id() == mMainThreadId) {
|
|
ALOGV("kickIdle skip on main thread");
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void updateSchedulePresentTime(nsecs_t time) {
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
mScheduledPresentTime = time;
|
|
}
|
|
|
|
/**
|
|
* If we kickIdle with known target vsync time,
|
|
* we only need to check whether it's idle or not at target vsync time.
|
|
* If it's idle, we kick it.
|
|
*/
|
|
void kickIdle(nsecs_t expectedPresentTime) {
|
|
if (!isEnabled()) return;
|
|
if (isMainThread()) return;
|
|
Mutex::Autolock lock(mKickIdleMutex);
|
|
if (!mActiveDisplayPowerOn) {
|
|
ALOGV("kickIdle activeDisplay is off");
|
|
return;
|
|
}
|
|
// If we already do kickidle for more future ts, we skip this.
|
|
if (expectedPresentTime < mTsForLastKickTime) return;
|
|
|
|
nsecs_t _diff_lastpresent = expectedPresentTime - mScheduledPresentTime;
|
|
nsecs_t _diff_lastkick = expectedPresentTime - mLastKickTime;
|
|
/* for debug
|
|
ATRACE_NAME(android::base::StringPrintf("kickIdle mIdleTimer=%" PRIu64
|
|
", expectedPresentTime=%" PRIu64 ", mScheduledPresentTime=%" PRIu64
|
|
", diff_lastpresent=%" PRIu64 ", mLastKickTime=%" PRIu64
|
|
", diff_lastkick=%" PRIu64, mIdleTimer,
|
|
expectedPresentTime, mScheduledPresentTime,
|
|
_diff_lastpresent, mLastKickTime, _diff_lastkick).c_str());
|
|
*/
|
|
if (_diff_lastpresent >= mIdleTimer && _diff_lastkick >= mIdleTimer) {
|
|
mTsForLastKickTime = expectedPresentTime;
|
|
mLastKickTime = systemTime();
|
|
kick();
|
|
}
|
|
}
|
|
};
|
|
// ---------------------------------------------------------------------------
|
|
}; // namespace android
|