Switch HWUI to use native performance hint API
Test: None Bug: 194204196 Change-Id: I80dfdb5d56921c465406cc4534e82738c668d46d
This commit is contained in:
@@ -28,7 +28,6 @@ import android.content.res.Configuration;
|
|||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.PerformanceHintManager;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -856,36 +855,6 @@ public class HardwareRenderer {
|
|||||||
callback.onPictureCaptured(picture);
|
callback.onPictureCaptured(picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** called by native */
|
|
||||||
static PerformanceHintManager.Session createHintSession(int[] tids) {
|
|
||||||
PerformanceHintManager performanceHintManager =
|
|
||||||
ProcessInitializer.sInstance.getHintManager();
|
|
||||||
if (performanceHintManager == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// Native code will always set a target duration before reporting actual durations.
|
|
||||||
// So this is just a placeholder value that's never used.
|
|
||||||
long targetDurationNanos = 16666667;
|
|
||||||
return performanceHintManager.createHintSession(tids, targetDurationNanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** called by native */
|
|
||||||
static void updateTargetWorkDuration(PerformanceHintManager.Session session,
|
|
||||||
long targetDurationNanos) {
|
|
||||||
session.updateTargetWorkDuration(targetDurationNanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** called by native */
|
|
||||||
static void reportActualWorkDuration(PerformanceHintManager.Session session,
|
|
||||||
long actualDurationNanos) {
|
|
||||||
session.reportActualWorkDuration(actualDurationNanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** called by native */
|
|
||||||
static void closeHintSession(PerformanceHintManager.Session session) {
|
|
||||||
session.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used to receive callbacks when Webview requests a surface control.
|
* Interface used to receive callbacks when Webview requests a surface control.
|
||||||
*
|
*
|
||||||
@@ -1152,7 +1121,6 @@ public class HardwareRenderer {
|
|||||||
private boolean mIsolated = false;
|
private boolean mIsolated = false;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
private PerformanceHintManager mPerformanceHintManager;
|
|
||||||
private IGraphicsStats mGraphicsStatsService;
|
private IGraphicsStats mGraphicsStatsService;
|
||||||
private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
|
private IGraphicsStatsCallback mGraphicsStatsCallback = new IGraphicsStatsCallback.Stub() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1164,10 +1132,6 @@ public class HardwareRenderer {
|
|||||||
private ProcessInitializer() {
|
private ProcessInitializer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized PerformanceHintManager getHintManager() {
|
|
||||||
return mPerformanceHintManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized void setPackageName(String name) {
|
synchronized void setPackageName(String name) {
|
||||||
if (mInitialized) return;
|
if (mInitialized) return;
|
||||||
mPackageName = name;
|
mPackageName = name;
|
||||||
@@ -1218,10 +1182,6 @@ public class HardwareRenderer {
|
|||||||
|
|
||||||
initDisplayInfo();
|
initDisplayInfo();
|
||||||
|
|
||||||
// HintManager and HintSession are designed to be accessible from isoalted processes
|
|
||||||
// so not checking for isolated process here.
|
|
||||||
initHintSession();
|
|
||||||
|
|
||||||
nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
|
nSetIsHighEndGfx(ActivityManager.isHighEndGfx());
|
||||||
// Defensively clear out the context in case we were passed a context that can leak
|
// Defensively clear out the context in case we were passed a context that can leak
|
||||||
// if we live longer than it, e.g. an activity context.
|
// if we live longer than it, e.g. an activity context.
|
||||||
@@ -1265,11 +1225,6 @@ public class HardwareRenderer {
|
|||||||
mDisplayInitialized = true;
|
mDisplayInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initHintSession() {
|
|
||||||
if (mContext == null) return;
|
|
||||||
mPerformanceHintManager = mContext.getSystemService(PerformanceHintManager.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void rotateBuffer() {
|
private void rotateBuffer() {
|
||||||
nRotateProcessStatsBuffer();
|
nRotateProcessStatsBuffer();
|
||||||
requestBuffer();
|
requestBuffer();
|
||||||
|
|||||||
@@ -44,8 +44,6 @@
|
|||||||
#include <utils/StrongPointer.h>
|
#include <utils/StrongPointer.h>
|
||||||
#include <utils/Timers.h>
|
#include <utils/Timers.h>
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -60,10 +58,6 @@ using namespace android::uirenderer::renderthread;
|
|||||||
struct {
|
struct {
|
||||||
jclass clazz;
|
jclass clazz;
|
||||||
jmethodID invokePictureCapturedCallback;
|
jmethodID invokePictureCapturedCallback;
|
||||||
jmethodID createHintSession;
|
|
||||||
jmethodID updateTargetWorkDuration;
|
|
||||||
jmethodID reportActualWorkDuration;
|
|
||||||
jmethodID closeHintSession;
|
|
||||||
} gHardwareRenderer;
|
} gHardwareRenderer;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -90,14 +84,6 @@ static JNIEnv* getenv(JavaVM* vm) {
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool hasExceptionAndClear(JNIEnv* env) {
|
|
||||||
if (GraphicsJNI::hasException(env)) {
|
|
||||||
env->ExceptionClear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
|
typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
|
||||||
ANW_fromSurface fromSurface;
|
ANW_fromSurface fromSurface;
|
||||||
|
|
||||||
@@ -147,67 +133,6 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class HintSessionWrapper : public LightRefBase<HintSessionWrapper> {
|
|
||||||
public:
|
|
||||||
static sp<HintSessionWrapper> create(JNIEnv* env, RenderProxy* proxy) {
|
|
||||||
if (!Properties::useHintManager) return nullptr;
|
|
||||||
|
|
||||||
// Include UI thread (self), render thread, and thread pool.
|
|
||||||
std::vector<int> tids = CommonPool::getThreadIds();
|
|
||||||
tids.push_back(proxy->getRenderThreadTid());
|
|
||||||
tids.push_back(pthread_gettid_np(pthread_self()));
|
|
||||||
|
|
||||||
jintArray tidsArray = env->NewIntArray(tids.size());
|
|
||||||
if (hasExceptionAndClear(env)) return nullptr;
|
|
||||||
env->SetIntArrayRegion(tidsArray, 0, tids.size(), reinterpret_cast<jint*>(tids.data()));
|
|
||||||
if (hasExceptionAndClear(env)) return nullptr;
|
|
||||||
jobject session = env->CallStaticObjectMethod(
|
|
||||||
gHardwareRenderer.clazz, gHardwareRenderer.createHintSession, tidsArray);
|
|
||||||
if (hasExceptionAndClear(env) || !session) return nullptr;
|
|
||||||
return new HintSessionWrapper(env, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
~HintSessionWrapper() {
|
|
||||||
if (!mSession) return;
|
|
||||||
JNIEnv* env = getenv(mVm);
|
|
||||||
env->CallStaticVoidMethod(gHardwareRenderer.clazz, gHardwareRenderer.closeHintSession,
|
|
||||||
mSession);
|
|
||||||
hasExceptionAndClear(env);
|
|
||||||
env->DeleteGlobalRef(mSession);
|
|
||||||
mSession = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateTargetWorkDuration(long targetDurationNanos) {
|
|
||||||
if (!mSession) return;
|
|
||||||
JNIEnv* env = getenv(mVm);
|
|
||||||
env->CallStaticVoidMethod(gHardwareRenderer.clazz,
|
|
||||||
gHardwareRenderer.updateTargetWorkDuration, mSession,
|
|
||||||
static_cast<jlong>(targetDurationNanos));
|
|
||||||
hasExceptionAndClear(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void reportActualWorkDuration(long actualDurationNanos) {
|
|
||||||
if (!mSession) return;
|
|
||||||
JNIEnv* env = getenv(mVm);
|
|
||||||
env->CallStaticVoidMethod(gHardwareRenderer.clazz,
|
|
||||||
gHardwareRenderer.reportActualWorkDuration, mSession,
|
|
||||||
static_cast<jlong>(actualDurationNanos));
|
|
||||||
hasExceptionAndClear(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
HintSessionWrapper(JNIEnv* env, jobject jobject) {
|
|
||||||
env->GetJavaVM(&mVm);
|
|
||||||
if (jobject) {
|
|
||||||
mSession = env->NewGlobalRef(jobject);
|
|
||||||
LOG_ALWAYS_FATAL_IF(!mSession, "Failed to make global ref");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JavaVM* mVm = nullptr;
|
|
||||||
jobject mSession = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
|
static void android_view_ThreadedRenderer_rotateProcessStatsBuffer(JNIEnv* env, jobject clazz) {
|
||||||
RenderProxy::rotateProcessStatsBuffer();
|
RenderProxy::rotateProcessStatsBuffer();
|
||||||
}
|
}
|
||||||
@@ -235,12 +160,6 @@ static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject claz
|
|||||||
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
|
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
|
||||||
ContextFactoryImpl factory(rootRenderNode);
|
ContextFactoryImpl factory(rootRenderNode);
|
||||||
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
|
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
|
||||||
sp<HintSessionWrapper> wrapper = HintSessionWrapper::create(env, proxy);
|
|
||||||
if (wrapper) {
|
|
||||||
proxy->setHintSessionCallbacks(
|
|
||||||
[wrapper](int64_t nanos) { wrapper->updateTargetWorkDuration(nanos); },
|
|
||||||
[wrapper](int64_t nanos) { wrapper->reportActualWorkDuration(nanos); });
|
|
||||||
}
|
|
||||||
return (jlong) proxy;
|
return (jlong) proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,18 +978,6 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) {
|
|||||||
gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
|
gHardwareRenderer.invokePictureCapturedCallback = GetStaticMethodIDOrDie(env, hardwareRenderer,
|
||||||
"invokePictureCapturedCallback",
|
"invokePictureCapturedCallback",
|
||||||
"(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
|
"(JLandroid/graphics/HardwareRenderer$PictureCapturedCallback;)V");
|
||||||
gHardwareRenderer.createHintSession =
|
|
||||||
GetStaticMethodIDOrDie(env, hardwareRenderer, "createHintSession",
|
|
||||||
"([I)Landroid/os/PerformanceHintManager$Session;");
|
|
||||||
gHardwareRenderer.updateTargetWorkDuration =
|
|
||||||
GetStaticMethodIDOrDie(env, hardwareRenderer, "updateTargetWorkDuration",
|
|
||||||
"(Landroid/os/PerformanceHintManager$Session;J)V");
|
|
||||||
gHardwareRenderer.reportActualWorkDuration =
|
|
||||||
GetStaticMethodIDOrDie(env, hardwareRenderer, "reportActualWorkDuration",
|
|
||||||
"(Landroid/os/PerformanceHintManager$Session;J)V");
|
|
||||||
gHardwareRenderer.closeHintSession =
|
|
||||||
GetStaticMethodIDOrDie(env, hardwareRenderer, "closeHintSession",
|
|
||||||
"(Landroid/os/PerformanceHintManager$Session;)V");
|
|
||||||
|
|
||||||
jclass aSurfaceTransactionCallbackClass =
|
jclass aSurfaceTransactionCallbackClass =
|
||||||
FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
|
FindClassOrDie(env, "android/graphics/HardwareRenderer$ASurfaceTransactionCallback");
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "DrawFrameTask.h"
|
#include "DrawFrameTask.h"
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
#include <gui/TraceUtils.h>
|
#include <gui/TraceUtils.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Log.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -26,11 +27,63 @@
|
|||||||
#include "../RenderNode.h"
|
#include "../RenderNode.h"
|
||||||
#include "CanvasContext.h"
|
#include "CanvasContext.h"
|
||||||
#include "RenderThread.h"
|
#include "RenderThread.h"
|
||||||
|
#include "thread/CommonPool.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace uirenderer {
|
namespace uirenderer {
|
||||||
namespace renderthread {
|
namespace renderthread {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
typedef APerformanceHintManager* (*APH_getManager)();
|
||||||
|
typedef APerformanceHintSession* (*APH_createSession)(APerformanceHintManager*, const int32_t*,
|
||||||
|
size_t, int64_t);
|
||||||
|
typedef void (*APH_updateTargetWorkDuration)(APerformanceHintSession*, int64_t);
|
||||||
|
typedef void (*APH_reportActualWorkDuration)(APerformanceHintSession*, int64_t);
|
||||||
|
typedef void (*APH_closeSession)(APerformanceHintSession* session);
|
||||||
|
|
||||||
|
bool gAPerformanceHintBindingInitialized = false;
|
||||||
|
APH_getManager gAPH_getManagerFn = nullptr;
|
||||||
|
APH_createSession gAPH_createSessionFn = nullptr;
|
||||||
|
APH_updateTargetWorkDuration gAPH_updateTargetWorkDurationFn = nullptr;
|
||||||
|
APH_reportActualWorkDuration gAPH_reportActualWorkDurationFn = nullptr;
|
||||||
|
APH_closeSession gAPH_closeSessionFn = nullptr;
|
||||||
|
|
||||||
|
void ensureAPerformanceHintBindingInitialized() {
|
||||||
|
if (gAPerformanceHintBindingInitialized) return;
|
||||||
|
|
||||||
|
void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
|
||||||
|
LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
|
||||||
|
|
||||||
|
gAPH_getManagerFn = (APH_getManager)dlsym(handle_, "APerformanceHint_getManager");
|
||||||
|
LOG_ALWAYS_FATAL_IF(gAPH_getManagerFn == nullptr,
|
||||||
|
"Failed to find required symbol APerformanceHint_getManager!");
|
||||||
|
|
||||||
|
gAPH_createSessionFn = (APH_createSession)dlsym(handle_, "APerformanceHint_createSession");
|
||||||
|
LOG_ALWAYS_FATAL_IF(gAPH_createSessionFn == nullptr,
|
||||||
|
"Failed to find required symbol APerformanceHint_createSession!");
|
||||||
|
|
||||||
|
gAPH_updateTargetWorkDurationFn = (APH_updateTargetWorkDuration)dlsym(
|
||||||
|
handle_, "APerformanceHint_updateTargetWorkDuration");
|
||||||
|
LOG_ALWAYS_FATAL_IF(
|
||||||
|
gAPH_updateTargetWorkDurationFn == nullptr,
|
||||||
|
"Failed to find required symbol APerformanceHint_updateTargetWorkDuration!");
|
||||||
|
|
||||||
|
gAPH_reportActualWorkDurationFn = (APH_reportActualWorkDuration)dlsym(
|
||||||
|
handle_, "APerformanceHint_reportActualWorkDuration");
|
||||||
|
LOG_ALWAYS_FATAL_IF(
|
||||||
|
gAPH_reportActualWorkDurationFn == nullptr,
|
||||||
|
"Failed to find required symbol APerformanceHint_reportActualWorkDuration!");
|
||||||
|
|
||||||
|
gAPH_closeSessionFn = (APH_closeSession)dlsym(handle_, "APerformanceHint_closeSession");
|
||||||
|
LOG_ALWAYS_FATAL_IF(gAPH_closeSessionFn == nullptr,
|
||||||
|
"Failed to find required symbol APerformanceHint_closeSession!");
|
||||||
|
|
||||||
|
gAPerformanceHintBindingInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
DrawFrameTask::DrawFrameTask()
|
DrawFrameTask::DrawFrameTask()
|
||||||
: mRenderThread(nullptr)
|
: mRenderThread(nullptr)
|
||||||
, mContext(nullptr)
|
, mContext(nullptr)
|
||||||
@@ -39,17 +92,13 @@ DrawFrameTask::DrawFrameTask()
|
|||||||
|
|
||||||
DrawFrameTask::~DrawFrameTask() {}
|
DrawFrameTask::~DrawFrameTask() {}
|
||||||
|
|
||||||
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
|
void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
|
||||||
RenderNode* targetNode) {
|
int32_t uiThreadId, int32_t renderThreadId) {
|
||||||
mRenderThread = thread;
|
mRenderThread = thread;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mTargetNode = targetNode;
|
mTargetNode = targetNode;
|
||||||
}
|
mUiThreadId = uiThreadId;
|
||||||
|
mRenderThreadId = renderThreadId;
|
||||||
void DrawFrameTask::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
|
|
||||||
std::function<void(int64_t)> reportActualWorkDuration) {
|
|
||||||
mUpdateTargetWorkDuration = std::move(updateTargetWorkDuration);
|
|
||||||
mReportActualWorkDuration = std::move(reportActualWorkDuration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
|
void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
|
||||||
@@ -144,27 +193,25 @@ void DrawFrameTask::run() {
|
|||||||
unblockUiThread();
|
unblockUiThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
// These member callbacks are effectively const as they are set once during init, so it's safe
|
if (!mHintSessionWrapper) mHintSessionWrapper.emplace(mUiThreadId, mRenderThreadId);
|
||||||
// to use these directly instead of making local copies.
|
constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
|
||||||
if (mUpdateTargetWorkDuration && mReportActualWorkDuration) {
|
constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
|
||||||
constexpr int64_t kSanityCheckLowerBound = 100000; // 0.1ms
|
int64_t targetWorkDuration = frameDeadline - intendedVsync;
|
||||||
constexpr int64_t kSanityCheckUpperBound = 10000000000; // 10s
|
targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
|
||||||
int64_t targetWorkDuration = frameDeadline - intendedVsync;
|
if (targetWorkDuration > kSanityCheckLowerBound &&
|
||||||
targetWorkDuration = targetWorkDuration * Properties::targetCpuTimePercentage / 100;
|
targetWorkDuration < kSanityCheckUpperBound &&
|
||||||
if (targetWorkDuration > kSanityCheckLowerBound &&
|
targetWorkDuration != mLastTargetWorkDuration) {
|
||||||
targetWorkDuration < kSanityCheckUpperBound &&
|
mLastTargetWorkDuration = targetWorkDuration;
|
||||||
targetWorkDuration != mLastTargetWorkDuration) {
|
mHintSessionWrapper->updateTargetWorkDuration(targetWorkDuration);
|
||||||
mLastTargetWorkDuration = targetWorkDuration;
|
|
||||||
mUpdateTargetWorkDuration(targetWorkDuration);
|
|
||||||
}
|
|
||||||
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
|
|
||||||
int64_t actualDuration = frameDuration -
|
|
||||||
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
|
|
||||||
dequeueBufferDuration;
|
|
||||||
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
|
|
||||||
mReportActualWorkDuration(actualDuration);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
int64_t frameDuration = systemTime(SYSTEM_TIME_MONOTONIC) - frameStartTime;
|
||||||
|
int64_t actualDuration = frameDuration -
|
||||||
|
(std::min(syncDelayDuration, mLastDequeueBufferDuration)) -
|
||||||
|
dequeueBufferDuration;
|
||||||
|
if (actualDuration > kSanityCheckLowerBound && actualDuration < kSanityCheckUpperBound) {
|
||||||
|
mHintSessionWrapper->reportActualWorkDuration(actualDuration);
|
||||||
|
}
|
||||||
|
|
||||||
mLastDequeueBufferDuration = dequeueBufferDuration;
|
mLastDequeueBufferDuration = dequeueBufferDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +263,44 @@ void DrawFrameTask::unblockUiThread() {
|
|||||||
mSignal.signal();
|
mSignal.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawFrameTask::HintSessionWrapper::HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId) {
|
||||||
|
if (!Properties::useHintManager) return;
|
||||||
|
if (uiThreadId < 0 || renderThreadId < 0) return;
|
||||||
|
|
||||||
|
ensureAPerformanceHintBindingInitialized();
|
||||||
|
|
||||||
|
APerformanceHintManager* manager = gAPH_getManagerFn();
|
||||||
|
if (!manager) return;
|
||||||
|
|
||||||
|
std::vector<int32_t> tids = CommonPool::getThreadIds();
|
||||||
|
tids.push_back(uiThreadId);
|
||||||
|
tids.push_back(renderThreadId);
|
||||||
|
|
||||||
|
// DrawFrameTask code will always set a target duration before reporting actual durations.
|
||||||
|
// So this is just a placeholder value that's never used.
|
||||||
|
int64_t dummyTargetDurationNanos = 16666667;
|
||||||
|
mHintSession =
|
||||||
|
gAPH_createSessionFn(manager, tids.data(), tids.size(), dummyTargetDurationNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawFrameTask::HintSessionWrapper::~HintSessionWrapper() {
|
||||||
|
if (mHintSession) {
|
||||||
|
gAPH_closeSessionFn(mHintSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawFrameTask::HintSessionWrapper::updateTargetWorkDuration(long targetDurationNanos) {
|
||||||
|
if (mHintSession) {
|
||||||
|
gAPH_updateTargetWorkDurationFn(mHintSession, targetDurationNanos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawFrameTask::HintSessionWrapper::reportActualWorkDuration(long actualDurationNanos) {
|
||||||
|
if (mHintSession) {
|
||||||
|
gAPH_reportActualWorkDurationFn(mHintSession, actualDurationNanos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace renderthread */
|
} /* namespace renderthread */
|
||||||
} /* namespace uirenderer */
|
} /* namespace uirenderer */
|
||||||
} /* namespace android */
|
} /* namespace android */
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
#ifndef DRAWFRAMETASK_H
|
#ifndef DRAWFRAMETASK_H
|
||||||
#define DRAWFRAMETASK_H
|
#define DRAWFRAMETASK_H
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <performance_hint_private.h>
|
||||||
#include <utils/Condition.h>
|
#include <utils/Condition.h>
|
||||||
#include <utils/Mutex.h>
|
#include <utils/Mutex.h>
|
||||||
#include <utils/StrongPointer.h>
|
#include <utils/StrongPointer.h>
|
||||||
@@ -60,9 +62,8 @@ public:
|
|||||||
DrawFrameTask();
|
DrawFrameTask();
|
||||||
virtual ~DrawFrameTask();
|
virtual ~DrawFrameTask();
|
||||||
|
|
||||||
void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
|
void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode,
|
||||||
void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
|
int32_t uiThreadId, int32_t renderThreadId);
|
||||||
std::function<void(int64_t)> reportActualWorkDuration);
|
|
||||||
void setContentDrawBounds(int left, int top, int right, int bottom) {
|
void setContentDrawBounds(int left, int top, int right, int bottom) {
|
||||||
mContentDrawBounds.set(left, top, right, bottom);
|
mContentDrawBounds.set(left, top, right, bottom);
|
||||||
}
|
}
|
||||||
@@ -85,6 +86,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class HintSessionWrapper {
|
||||||
|
public:
|
||||||
|
HintSessionWrapper(int32_t uiThreadId, int32_t renderThreadId);
|
||||||
|
~HintSessionWrapper();
|
||||||
|
|
||||||
|
void updateTargetWorkDuration(long targetDurationNanos);
|
||||||
|
void reportActualWorkDuration(long actualDurationNanos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
APerformanceHintSession* mHintSession = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
void postAndWait();
|
void postAndWait();
|
||||||
bool syncFrameState(TreeInfo& info);
|
bool syncFrameState(TreeInfo& info);
|
||||||
void unblockUiThread();
|
void unblockUiThread();
|
||||||
@@ -95,6 +108,8 @@ private:
|
|||||||
RenderThread* mRenderThread;
|
RenderThread* mRenderThread;
|
||||||
CanvasContext* mContext;
|
CanvasContext* mContext;
|
||||||
RenderNode* mTargetNode = nullptr;
|
RenderNode* mTargetNode = nullptr;
|
||||||
|
int32_t mUiThreadId = -1;
|
||||||
|
int32_t mRenderThreadId = -1;
|
||||||
Rect mContentDrawBounds;
|
Rect mContentDrawBounds;
|
||||||
|
|
||||||
/*********************************************
|
/*********************************************
|
||||||
@@ -112,8 +127,7 @@ private:
|
|||||||
|
|
||||||
nsecs_t mLastDequeueBufferDuration = 0;
|
nsecs_t mLastDequeueBufferDuration = 0;
|
||||||
nsecs_t mLastTargetWorkDuration = 0;
|
nsecs_t mLastTargetWorkDuration = 0;
|
||||||
std::function<void(int64_t)> mUpdateTargetWorkDuration;
|
std::optional<HintSessionWrapper> mHintSessionWrapper;
|
||||||
std::function<void(int64_t)> mReportActualWorkDuration;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace renderthread */
|
} /* namespace renderthread */
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#include "utils/Macros.h"
|
#include "utils/Macros.h"
|
||||||
#include "utils/TimeUtils.h"
|
#include "utils/TimeUtils.h"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace uirenderer {
|
namespace uirenderer {
|
||||||
namespace renderthread {
|
namespace renderthread {
|
||||||
@@ -39,7 +41,8 @@ RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
|
|||||||
mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
|
mContext = mRenderThread.queue().runSync([&]() -> CanvasContext* {
|
||||||
return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
|
return CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory);
|
||||||
});
|
});
|
||||||
mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
|
mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode,
|
||||||
|
pthread_gettid_np(pthread_self()), getRenderThreadTid());
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderProxy::~RenderProxy() {
|
RenderProxy::~RenderProxy() {
|
||||||
@@ -48,7 +51,7 @@ RenderProxy::~RenderProxy() {
|
|||||||
|
|
||||||
void RenderProxy::destroyContext() {
|
void RenderProxy::destroyContext() {
|
||||||
if (mContext) {
|
if (mContext) {
|
||||||
mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
|
mDrawFrameTask.setContext(nullptr, nullptr, nullptr, -1, -1);
|
||||||
// This is also a fence as we need to be certain that there are no
|
// This is also a fence as we need to be certain that there are no
|
||||||
// outstanding mDrawFrame tasks posted before it is destroyed
|
// outstanding mDrawFrame tasks posted before it is destroyed
|
||||||
mRenderThread.queue().runSync([this]() { delete mContext; });
|
mRenderThread.queue().runSync([this]() { delete mContext; });
|
||||||
@@ -76,12 +79,6 @@ void RenderProxy::setName(const char* name) {
|
|||||||
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
|
mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderProxy::setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
|
|
||||||
std::function<void(int64_t)> reportActualWorkDuration) {
|
|
||||||
mDrawFrameTask.setHintSessionCallbacks(std::move(updateTargetWorkDuration),
|
|
||||||
std::move(reportActualWorkDuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
|
void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
|
||||||
if (window) { ANativeWindow_acquire(window); }
|
if (window) { ANativeWindow_acquire(window); }
|
||||||
mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
|
mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
|
||||||
|
|||||||
@@ -71,8 +71,6 @@ public:
|
|||||||
void setSwapBehavior(SwapBehavior swapBehavior);
|
void setSwapBehavior(SwapBehavior swapBehavior);
|
||||||
bool loadSystemProperties();
|
bool loadSystemProperties();
|
||||||
void setName(const char* name);
|
void setName(const char* name);
|
||||||
void setHintSessionCallbacks(std::function<void(int64_t)> updateTargetWorkDuration,
|
|
||||||
std::function<void(int64_t)> reportActualWorkDuration);
|
|
||||||
|
|
||||||
void setSurface(ANativeWindow* window, bool enableTimeout = true);
|
void setSurface(ANativeWindow* window, bool enableTimeout = true);
|
||||||
void setSurfaceControl(ASurfaceControl* surfaceControl);
|
void setSurfaceControl(ASurfaceControl* surfaceControl);
|
||||||
|
|||||||
Reference in New Issue
Block a user