388 lines
13 KiB
C++
388 lines
13 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) 2010. 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 LOG_NDEBUG 0
|
|
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
|
|
|
#include "SurfaceFlinger.h"
|
|
#include "mediatek/SFProperty.h"
|
|
#include <cutils/properties.h>
|
|
#include <android-base/properties.h>
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#include <composer_ext_intf/client_interface.h>
|
|
#endif
|
|
|
|
#if ((defined MTK_SF_CPU_POLICY) || (defined MTK_SF_CPU_POLICY_FOR_LEGACY))
|
|
#include "mediatek/SfCpuPolicyAdapter/SfCpuPolicyAdapter.h"
|
|
#endif
|
|
|
|
#ifdef MTK_SF_DEBUG_SUPPORT
|
|
#include <gui/LayerDebugInfo.h>
|
|
#include "Layer.h"
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MSYNC
|
|
#include "mediatek/MSync/MSyncSfApi.h"
|
|
#endif
|
|
|
|
#ifdef MTK_DYNAMIC_DURATION
|
|
#include <mediatek/MtkDuration.h>
|
|
#endif
|
|
|
|
#ifdef MTK_SF_KICK_IDLE
|
|
#include "mediatek/KickIdleHelper.h"
|
|
#endif
|
|
|
|
namespace android {
|
|
|
|
#ifdef MTK_COMPOSER_EXT
|
|
class MtkComposerExtCallbackHandler : public ::ComposerExt::ConfigCallback {
|
|
public:
|
|
MtkComposerExtCallbackHandler(SurfaceFlinger& flinger)
|
|
: mFlinger(flinger) {
|
|
}
|
|
void NotifyTestCallback(bool value) {
|
|
ALOGI("NotifyTestCallback, %p, value %d", &mFlinger, value);
|
|
}
|
|
bool NotifyTestCallbackWithReturnValue(bool value) {
|
|
ALOGI("NotifyTestCallbackWithReturnValue, %p, value %d", &mFlinger, value);
|
|
return value;
|
|
}
|
|
void NotifyHwcHwBinderTidCallback(int tid) {
|
|
ALOGI("NotifyHwcHwBinderTidCallback, %p, tid %d", &mFlinger, tid);
|
|
#if ((defined MTK_SF_CPU_POLICY) || (defined MTK_SF_CPU_POLICY_FOR_LEGACY))
|
|
mFlinger.notifyHwcHwbinderTid(tid);
|
|
#endif
|
|
}
|
|
void NotifyHwcComposition(ComposerExt::HwcCompositionStruct composition) {
|
|
ALOGI("%s(), id %" PRIu64 ", mode %d", __FUNCTION__, composition.disp_id, composition.composition_mode);
|
|
ATRACE_NAME(android::base::StringPrintf("MBRAIN: NotifyHwcComposition(), id %" PRIu64 ", mode %d",
|
|
composition.disp_id, composition.composition_mode).c_str());
|
|
#ifdef MTK_DYNAMIC_DURATION
|
|
MtkDuration::getInstance().setDecoupleMode(static_cast<uint64_t>(composition.disp_id)
|
|
, static_cast<int>(composition.composition_mode) > 0 ? true : false);
|
|
#endif
|
|
}
|
|
uint32_t NotifyExtraVsyncPresent(const ComposerExt::ExtraVsyncRequestStruct& request) {
|
|
ALOGI("disp_id =%" PRIu64 ", num_vsync=%" PRIu32, request.disp_id, request.num_vsync);
|
|
ATRACE_NAME(android::base::StringPrintf("MBRAIN: NotifyExtraVsyncPresent(), disp_id =%" PRIu64 ", num_vsync=%" PRIu32,
|
|
request.disp_id, request.num_vsync).c_str());
|
|
for (const auto& layerId: request.layer_id) {
|
|
ALOGV("layerId=%" PRIu64, layerId);
|
|
}
|
|
#ifdef MTK_DYNAMIC_DURATION
|
|
return MtkDuration::getInstance().setExtraVsyncCount(request.disp_id, request.num_vsync);
|
|
#else
|
|
return request.num_vsync;
|
|
#endif
|
|
}
|
|
|
|
private:
|
|
SurfaceFlinger& mFlinger;
|
|
};
|
|
|
|
MtkComposerExtCallbackHandler* mMtkComposerExtCallbackHandler = nullptr;
|
|
|
|
void SurfaceFlinger::initMtkComposerExt() {
|
|
mMtkComposerExtCallbackHandler = new MtkComposerExtCallbackHandler(*this);
|
|
int ret = ::ComposerExt::ClientInterface::create("SurfaceFlinger" + std::to_string(0),
|
|
mMtkComposerExtCallbackHandler,
|
|
&mMtkComposerExtIntf, false);
|
|
if (ret || !mMtkComposerExtIntf) {
|
|
ALOGE("ComposerExt HIDL not present\n");
|
|
mMtkComposerExtIntf = nullptr;
|
|
}
|
|
#ifdef MTK_SF_KICK_IDLE
|
|
if (mMtkComposerExtIntf != nullptr) {
|
|
KickIdleHelper::getInstance().setComposerExtInf((void*) mMtkComposerExtIntf);
|
|
}
|
|
#endif
|
|
#ifdef MTK_DYNAMIC_DURATION
|
|
if (mMtkComposerExtIntf != nullptr) {
|
|
int isExtraVsyncSupported = 0;
|
|
mMtkComposerExtIntf->isFeatureSupported(ComposerExt::HwcFeature::kExtraVsyncPresent, &isExtraVsyncSupported);
|
|
ALOGI("isExtraVsyncSupported %s", isExtraVsyncSupported ? "yes" : "no");
|
|
MtkDuration::getInstance().setIsExtraVsyncSupported(isExtraVsyncSupported > 0);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
#ifdef MTK_COMPOSER_EXT
|
|
#if ((defined MTK_SF_CPU_POLICY) || (defined MTK_SF_CPU_POLICY_FOR_LEGACY))
|
|
void SurfaceFlinger::notifyHwcHwbinderTid(const int& tid) {
|
|
if (mSfCpuPolicy) {
|
|
mSfCpuPolicy->notifyHwcHwbinderTid(tid);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if ((defined MTK_SF_CPU_POLICY) || (defined MTK_SF_CPU_POLICY_FOR_LEGACY))
|
|
void SurfaceFlinger::notifyVpLpEnable(bool enable) {
|
|
if (mSfCpuPolicy) {
|
|
mSfCpuPolicy->notifyVpLpEnable(enable);
|
|
}
|
|
}
|
|
|
|
void SurfaceFlinger::notifyLayerConnect(const void * token, const std::string& name){
|
|
if (mSfCpuPolicy) {
|
|
mSfCpuPolicy->notifyLayerConnect(token, name);
|
|
}
|
|
}
|
|
|
|
void SurfaceFlinger::notifyLayerDisconnect(const void * token) {
|
|
if (mSfCpuPolicy) {
|
|
mSfCpuPolicy->notifyLayerDisconnect(token);
|
|
}
|
|
}
|
|
|
|
void SurfaceFlinger::notifyLayerSetBuffer(const void * token, const sp<GraphicBuffer>& buffer){
|
|
if (mSfCpuPolicy) {
|
|
mSfCpuPolicy->notifyLayerSetBuffer(token, buffer);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_DEBUG_SUPPORT
|
|
void SurfaceFlinger::mtkDump(std::string& result) {
|
|
// for run-time enable property
|
|
SFProperty::getInstance().setMTKProperties(result);
|
|
}
|
|
|
|
void SurfaceFlinger::mtkDumpLayerDebug(std::string& result) const {
|
|
ALOGI("mtkDumpLayerDebug");
|
|
for (const auto& [token, display] : mDisplays) {
|
|
const DisplayDevice* disp_ref = display.get();
|
|
mDrawingState.traverseInZOrder([&](Layer* layer) {
|
|
gui::LayerDebugInfo ldi = layer->getLayerDebugInfo(disp_ref);
|
|
base::StringAppendF(&result, "%s", to_string(ldi).c_str());});
|
|
}
|
|
}
|
|
|
|
status_t SurfaceFlinger::getProcessName(int pid, std::string& name) {
|
|
FILE *fp = fopen(String8::format("/proc/%d/cmdline", pid), "r");
|
|
if (fp != NULL) {
|
|
const size_t size = 64;
|
|
char proc_name[size] = {0};
|
|
char* result = fgets(proc_name, size - 1, fp);
|
|
int ret = fclose(fp);
|
|
if (CC_UNLIKELY(ret != 0)) {
|
|
ALOGE("%s(), fclose fail", __FUNCTION__);
|
|
}
|
|
if (CC_LIKELY(result != nullptr)) {
|
|
name = proc_name;
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return INVALID_OPERATION;
|
|
}
|
|
|
|
bool SurfaceFlinger::mtkCheckTransactCodeCredentials(uint32_t code) {
|
|
switch (code) {
|
|
case 100001:
|
|
case 100002:
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool SurfaceFlinger::mtkIsTransact(uint32_t code) {
|
|
switch (code) {
|
|
case 100001:
|
|
case 100002:
|
|
return true;
|
|
default:
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
status_t SurfaceFlinger::mtkOnTransact(uint32_t code, const Parcel& data, Parcel* /*reply*/, uint32_t /*flags*/) {
|
|
switch (code) {
|
|
case 100001: {
|
|
int n = data.readInt32();
|
|
ALOGI("mtkOnTransact(%u) n=%d", code, n);
|
|
break;
|
|
}
|
|
case 100002: {
|
|
const int isDumpLayers = data.readInt32();
|
|
if (isDumpLayers == 0) {
|
|
mIsDumpLayers = false;
|
|
} else {
|
|
mIsDumpLayers = true;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
void SurfaceFlinger::BufferCountTracker::unTrack(Layer* layer) {
|
|
std::lock_guard<std::mutex> lock(mLock);
|
|
if (0 == mWhereByLayer.erase(layer)) {
|
|
ALOGE("LayerTracker: not in map, name=%s, HandleAlive=%d", layer->getName().c_str(), layer->isHandleAlive());
|
|
}
|
|
}
|
|
|
|
void SurfaceFlinger::BufferCountTracker::dumpLayers() {
|
|
static nsecs_t sLastDumpLayerTrackerTime = 0;
|
|
nsecs_t now = systemTime();
|
|
if (ns2ms(now - sLastDumpLayerTrackerTime) > 15000) {
|
|
sLastDumpLayerTrackerTime = now;
|
|
|
|
std::lock_guard<std::mutex> lock(mLock);
|
|
std::vector<std::string> vecDumpString;
|
|
for (auto [layer, where] : mWhereByLayer) {
|
|
vecDumpString.push_back(android::base::StringPrintf("LayerTracker: %s, Where: %s, HandleAlive=%d",
|
|
layer->getName().c_str(), where.c_str(), layer->isHandleAlive()));
|
|
}
|
|
|
|
std::thread thread([=]() {
|
|
for (auto dumpString : vecDumpString) {
|
|
ALOGE("%s", dumpString.c_str());
|
|
}
|
|
});
|
|
thread.detach();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MSYNC_3
|
|
void SurfaceFlinger::changeToForeground() {
|
|
#ifdef MTK_SF_CPU_POLICY
|
|
if (SfCpuPolicyAdapter::isEnabled()) {
|
|
ATRACE_NAME("SF: changeToForeground & notifySpeedUpRE");
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).changeToForeground();
|
|
// 370 is upper bound for uclmap.min perf range 0-1024
|
|
SfCpuPolicyAdapter::getInstance(*mFrameTimeline).notifySpeedUpRE(370);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_HINT_DISPLAY_INFO
|
|
void SurfaceFlinger::hintDisplayInfo(const int& policy, const bool& enable)
|
|
{
|
|
switch(policy) {
|
|
case Hwc2::impl::PowerAdvisor::MULTI_DISPLAY: {
|
|
mPowerAdvisor->hintMultiDisplay(enable, mHintFps);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_HINT_LOW_POWER
|
|
#include <ftl/fake_guard.h>
|
|
|
|
void SurfaceFlinger::hintLowPower(bool enabled) {
|
|
mPowerAdvisor->hintSFLowPower(enabled);
|
|
const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
|
|
if (display) {
|
|
display->changeRefreshRate(enabled);
|
|
}
|
|
}
|
|
|
|
bool SurfaceFlinger::setPELT32(bool enabled) {
|
|
return mScheduler->setPELT32(enabled);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_VDS_HDCP
|
|
void SurfaceFlinger::setNextDisplayUsage(bool isWFD, bool isSecure) {
|
|
ALOGV("setNextDisplayUsage %d, %d", (isWFD?1:0), (isSecure?1:0));
|
|
#ifdef MTK_COMPOSER_EXT
|
|
if (mMtkComposerExtIntf) {
|
|
uint32_t vdsUsage = static_cast<uint32_t>(ComposerExt::DisplayUsage::kUnknown);
|
|
if (isWFD) vdsUsage |= static_cast<uint32_t>(ComposerExt::DisplayUsage::kIsWFD);
|
|
if (isSecure) vdsUsage |= static_cast<uint32_t>(ComposerExt::DisplayUsage::kIsSecure);
|
|
mMtkComposerExtIntf->setNextDisplayUsage(static_cast<ComposerExt::DisplayUsage>(vdsUsage));
|
|
ALOGI("mMtkComposerExtIntf->setNextDisplayUsage(%" PRIu32 ")", vdsUsage);
|
|
} else {
|
|
ALOGI("mMtkComposerExtIntf null");
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_UPDATE_DISPLAY_CAP
|
|
bool SurfaceFlinger::updateDisplayCapability() {
|
|
static bool supportDsiSwitch = base::GetBoolProperty("ro.vendor.mtk_hwc_dsi_switch", false);
|
|
if (!supportDsiSwitch) return false;
|
|
ATRACE_CALL();
|
|
for (const auto& [token, display] : mDisplays) {
|
|
if (const auto halDispId = HalDisplayId::tryCast(display->getId())) {
|
|
getHwComposer().updateDisplayCapability(halDispId.value());
|
|
} else {
|
|
ALOGE("!halDispId");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MSYNC
|
|
bool SurfaceFlinger::isMsyncOn() const {
|
|
return mMSyncSfApi && mMSyncSfApi->isOn();
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_GUI_DEBUG_SUPPORT
|
|
void SurfaceFlinger::fastMtkDumpLayerDebug(std::vector<gui::LayerDebugInfo>& layerInfo) const {
|
|
ALOGI("fastMtkDumpLayerDebug");
|
|
for (const auto& [token, display] : mDisplays) {
|
|
const DisplayDevice* disp_ref = display.get();
|
|
mDrawingState.traverseInZOrder([&](Layer* layer) {
|
|
gui::LayerDebugInfo ldi = layer->getLayerDebugInfo(disp_ref);
|
|
layerInfo.push_back(ldi);});
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef MTK_SF_MBRAIN_FPS_SUPPORT
|
|
int64_t SurfaceFlinger::getDisplayFrameCount() const {
|
|
return mDisplayFrameCount;
|
|
}
|
|
#endif
|
|
}; // namespace android
|