unplugged-system/frameworks/native/services/surfaceflinger/mediatek/SurfaceFlinger.cpp

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