summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/DeviceInfo.cpp29
-rw-r--r--libs/hwui/DeviceInfo.h3
-rw-r--r--libs/hwui/JankTracker.cpp32
-rw-r--r--libs/hwui/JankTracker.h1
-rw-r--r--libs/hwui/ProfileData.cpp3
-rw-r--r--libs/hwui/ProfileData.h1
-rw-r--r--libs/hwui/Properties.cpp1
-rw-r--r--libs/hwui/Properties.h1
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp113
-rw-r--r--libs/hwui/renderthread/RenderThread.h12
-rw-r--r--libs/hwui/service/GraphicsStatsService.cpp3
-rw-r--r--libs/hwui/tests/common/scenes/JankyScene.cpp51
-rw-r--r--libs/hwui/tests/unit/main.cpp2
13 files changed, 123 insertions, 129 deletions
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index e4162875279c..40cc73a82846 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -16,6 +16,8 @@
#include <DeviceInfo.h>
+#include "Properties.h"
+
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
@@ -29,6 +31,19 @@
namespace android {
namespace uirenderer {
+static constexpr android::DisplayInfo sDummyDisplay {
+ 1080, // w
+ 1920, // h
+ 320.0, // xdpi
+ 320.0, // ydpi
+ 60.0, // fps
+ 2.0, // density
+ 0, // orientation
+ false, // secure?
+ 0, // appVsyncOffset
+ 0, // presentationDeadline
+};
+
static DeviceInfo* sDeviceInfo = nullptr;
static std::once_flag sInitializedFlag;
@@ -47,20 +62,26 @@ void DeviceInfo::initialize() {
void DeviceInfo::initialize(int maxTextureSize) {
std::call_once(sInitializedFlag, [maxTextureSize]() {
sDeviceInfo = new DeviceInfo();
- sDeviceInfo->loadDisplayInfo();
+ sDeviceInfo->mDisplayInfo = DeviceInfo::queryDisplayInfo();
sDeviceInfo->mMaxTextureSize = maxTextureSize;
});
}
void DeviceInfo::load() {
- loadDisplayInfo();
+ mDisplayInfo = queryDisplayInfo();
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
}
-void DeviceInfo::loadDisplayInfo() {
+DisplayInfo DeviceInfo::queryDisplayInfo() {
+ if (Properties::isolatedProcess) {
+ return sDummyDisplay;
+ }
+
+ DisplayInfo displayInfo;
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
+ status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &displayInfo);
LOG_ALWAYS_FATAL_IF(status, "Failed to get display info, error %d", status);
+ return displayInfo;
}
} /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index a0b2f06d8f4a..297b2664414b 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -47,12 +47,13 @@ public:
return di.w * di.h * in;
}
+ static DisplayInfo queryDisplayInfo();
+
private:
DeviceInfo() {}
~DeviceInfo() {}
void load();
- void loadDisplayInfo();
int mMaxTextureSize;
DisplayInfo mDisplayInfo;
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 8110664ad44b..cf29e434a351 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -129,42 +129,22 @@ void JankTracker::finishFrame(const FrameInfo& frame) {
totalDuration -= forgiveAmount;
}
}
-
LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
mData->reportFrame(totalDuration);
(*mGlobalData)->reportFrame(totalDuration);
- // Only things like Surface.lockHardwareCanvas() are exempt from tracking
- if (CC_UNLIKELY(frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS)) {
+ // Keep the fast path as fast as possible.
+ if (CC_LIKELY(totalDuration < mFrameInterval)) {
return;
}
- if (totalDuration > mFrameInterval) {
- mData->reportJank();
- (*mGlobalData)->reportJank();
- }
-
- bool isTripleBuffered = mSwapDeadline > frame[FrameInfoIndex::IntendedVsync];
-
- mSwapDeadline = std::max(mSwapDeadline + mFrameInterval,
- frame[FrameInfoIndex::IntendedVsync] + mFrameInterval);
-
- // If we hit the deadline, cool!
- if (frame[FrameInfoIndex::FrameCompleted] < mSwapDeadline) {
- if (isTripleBuffered) {
- mData->reportJankType(JankType::kHighInputLatency);
- (*mGlobalData)->reportJankType(JankType::kHighInputLatency);
- }
+ // Only things like Surface.lockHardwareCanvas() are exempt from tracking
+ if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
return;
}
- mData->reportJankType(JankType::kMissedDeadline);
- (*mGlobalData)->reportJankType(JankType::kMissedDeadline);
-
- // Janked, reset the swap deadline
- nsecs_t jitterNanos = frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::Vsync];
- nsecs_t lastFrameOffset = jitterNanos % mFrameInterval;
- mSwapDeadline = frame[FrameInfoIndex::FrameCompleted] - lastFrameOffset + mFrameInterval;
+ mData->reportJank();
+ (*mGlobalData)->reportJank();
for (int i = 0; i < NUM_BUCKETS; i++) {
int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 110211eda23a..dc6a7ff5ddb7 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -75,7 +75,6 @@ private:
std::array<int64_t, NUM_BUCKETS> mThresholds;
int64_t mFrameInterval;
- nsecs_t mSwapDeadline;
// The amount of time we will erase from the total duration to account
// for SF vsync offsets with HWC2 blocking dequeueBuffers.
// (Vsync + mDequeueBlockTolerance) is the point at which we expect
diff --git a/libs/hwui/ProfileData.cpp b/libs/hwui/ProfileData.cpp
index f9cf54998032..b392ecdde18f 100644
--- a/libs/hwui/ProfileData.cpp
+++ b/libs/hwui/ProfileData.cpp
@@ -23,7 +23,8 @@ namespace uirenderer {
static const char* JANK_TYPE_NAMES[] = {
"Missed Vsync", "High input latency", "Slow UI thread",
- "Slow bitmap uploads", "Slow issue draw commands", "Frame deadline missed"};
+ "Slow bitmap uploads", "Slow issue draw commands",
+};
// The bucketing algorithm controls so to speak
// If a frame is <= to this it goes in bucket 0
diff --git a/libs/hwui/ProfileData.h b/libs/hwui/ProfileData.h
index 564920b60328..1e688ab6fa68 100644
--- a/libs/hwui/ProfileData.h
+++ b/libs/hwui/ProfileData.h
@@ -33,7 +33,6 @@ enum JankType {
kSlowUI,
kSlowSync,
kSlowRT,
- kMissedDeadline,
// must be last
NUM_BUCKETS,
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index e9adbdc1447b..1602b4b39c91 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -63,6 +63,7 @@ bool Properties::enableRTAnimations = true;
bool Properties::runningInEmulator = false;
bool Properties::debuggingEnabled = false;
+bool Properties::isolatedProcess = false;
static int property_get_int(const char* key, int defaultValue) {
char buf[PROPERTY_VALUE_MAX] = {
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 3f44c211f024..81a36574a097 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -269,6 +269,7 @@ public:
static bool runningInEmulator;
ANDROID_API static bool debuggingEnabled;
+ ANDROID_API static bool isolatedProcess;
private:
static ProfileType sProfileType;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 8e0546b529af..6a2a025da121 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,6 +17,7 @@
#include "RenderThread.h"
#include "CanvasContext.h"
+#include "DeviceInfo.h"
#include "EglManager.h"
#include "OpenGLReadback.h"
#include "RenderProxy.h"
@@ -29,10 +30,9 @@
#include "renderstate/RenderState.h"
#include "renderthread/OpenGLPipeline.h"
#include "utils/FatVector.h"
+#include "utils/TimeUtils.h"
#include <gui/DisplayEventReceiver.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
#include <sys/resource.h>
#include <utils/Condition.h>
#include <utils/Log.h>
@@ -54,6 +54,58 @@ static bool gHasRenderThreadInstance = false;
static void (*gOnStartHook)() = nullptr;
+class DisplayEventReceiverWrapper : public VsyncSource {
+public:
+ DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
+ : mDisplayEventReceiver(std::move(receiver)) {}
+
+ virtual void requestNextVsync() override {
+ status_t status = mDisplayEventReceiver->requestNextVsync();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+ nsecs_t latest = 0;
+ ssize_t n;
+ while ((n = mDisplayEventReceiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+ for (ssize_t i = 0; i < n; i++) {
+ const DisplayEventReceiver::Event& ev = buf[i];
+ switch (ev.header.type) {
+ case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+ latest = ev.header.timestamp;
+ break;
+ }
+ }
+ }
+ if (n < 0) {
+ ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
+ }
+ return latest;
+ }
+
+private:
+ std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+};
+
+class DummyVsyncSource : public VsyncSource {
+public:
+ DummyVsyncSource(RenderThread* renderThread) : mRenderThread(renderThread) {}
+
+ virtual void requestNextVsync() override {
+ mRenderThread->queue().postDelayed(16_ms, [this]() {
+ mRenderThread->drainDisplayEventQueue();
+ });
+ }
+
+ virtual nsecs_t latestVsyncEvent() override {
+ return systemTime(CLOCK_MONOTONIC);
+ }
+
+private:
+ RenderThread* mRenderThread;
+};
+
bool RenderThread::hasInstance() {
return gHasRenderThreadInstance;
}
@@ -74,7 +126,7 @@ RenderThread& RenderThread::getInstance() {
RenderThread::RenderThread()
: ThreadBase()
- , mDisplayEventReceiver(nullptr)
+ , mVsyncSource(nullptr)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
, mRenderState(nullptr)
@@ -89,23 +141,27 @@ RenderThread::~RenderThread() {
}
void RenderThread::initializeDisplayEventReceiver() {
- LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
- mDisplayEventReceiver = new DisplayEventReceiver();
- status_t status = mDisplayEventReceiver->initCheck();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
- "Initialization of DisplayEventReceiver "
- "failed with status: %d",
- status);
+ LOG_ALWAYS_FATAL_IF(mVsyncSource, "Initializing a second DisplayEventReceiver?");
- // Register the FD
- mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
- RenderThread::displayEventReceiverCallback, this);
+ if (!Properties::isolatedProcess) {
+ auto receiver = std::make_unique<DisplayEventReceiver>();
+ status_t status = receiver->initCheck();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+ "Initialization of DisplayEventReceiver "
+ "failed with status: %d",
+ status);
+
+ // Register the FD
+ mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
+ RenderThread::displayEventReceiverCallback, this);
+ mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver));
+ } else {
+ mVsyncSource = new DummyVsyncSource(this);
+ }
}
void RenderThread::initThreadLocals() {
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &mDisplayInfo);
- LOG_ALWAYS_FATAL_IF(status, "Failed to get display info\n");
+ mDisplayInfo = DeviceInfo::queryDisplayInfo();
nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
mTimeLord.setFrameInterval(frameIntervalNanos);
initializeDisplayEventReceiver();
@@ -201,29 +257,9 @@ int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
return 1; // keep the callback
}
-static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
- DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
- nsecs_t latest = 0;
- ssize_t n;
- while ((n = receiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
- for (ssize_t i = 0; i < n; i++) {
- const DisplayEventReceiver::Event& ev = buf[i];
- switch (ev.header.type) {
- case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
- latest = ev.header.timestamp;
- break;
- }
- }
- }
- if (n < 0) {
- ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
- }
- return latest;
-}
-
void RenderThread::drainDisplayEventQueue() {
ATRACE_CALL();
- nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
+ nsecs_t vsyncEvent = mVsyncSource->latestVsyncEvent();
if (vsyncEvent > 0) {
mVsyncRequested = false;
if (mTimeLord.vsyncReceived(vsyncEvent) && !mFrameCallbackTaskPending) {
@@ -256,8 +292,7 @@ void RenderThread::dispatchFrameCallbacks() {
void RenderThread::requestVsync() {
if (!mVsyncRequested) {
mVsyncRequested = true;
- status_t status = mDisplayEventReceiver->requestNextVsync();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "requestNextVsync failed with status: %d", status);
+ mVsyncSource->requestNextVsync();
}
}
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 3aa548773b3b..689f518bad1b 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -39,7 +39,6 @@
namespace android {
class Bitmap;
-class DisplayEventReceiver;
namespace uirenderer {
@@ -63,6 +62,14 @@ protected:
~IFrameCallback() {}
};
+struct VsyncSource {
+ virtual void requestNextVsync() = 0;
+ virtual nsecs_t latestVsyncEvent() = 0;
+ virtual ~VsyncSource() {}
+};
+
+class DummyVsyncSource;
+
class RenderThread : private ThreadBase {
PREVENT_COPY_AND_ASSIGN(RenderThread);
@@ -110,6 +117,7 @@ protected:
private:
friend class DispatchFrameCallbacks;
friend class RenderProxy;
+ friend class DummyVsyncSource;
friend class android::uirenderer::TestUtils;
RenderThread();
@@ -127,7 +135,7 @@ private:
DisplayInfo mDisplayInfo;
- DisplayEventReceiver* mDisplayEventReceiver;
+ VsyncSource* mVsyncSource;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;
// We defer the actual registration of these callbacks until
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 599226bebe84..e0303a8a62d5 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -176,8 +176,6 @@ bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::st
summary->set_slow_bitmap_upload_count(summary->slow_bitmap_upload_count() +
data->jankTypeCount(kSlowSync));
summary->set_slow_draw_count(summary->slow_draw_count() + data->jankTypeCount(kSlowRT));
- summary->set_missed_deadline_count(summary->missed_deadline_count()
- + data->jankTypeCount(kMissedDeadline));
bool creatingHistogram = false;
if (proto->histogram_size() == 0) {
@@ -248,7 +246,6 @@ void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
dprintf(fd, "\nNumber Slow UI thread: %d", summary.slow_ui_thread_count());
dprintf(fd, "\nNumber Slow bitmap uploads: %d", summary.slow_bitmap_upload_count());
dprintf(fd, "\nNumber Slow issue draw commands: %d", summary.slow_draw_count());
- dprintf(fd, "\nNumber Frame deadline missed: %d", summary.missed_deadline_count());
dprintf(fd, "\nHISTOGRAM:");
for (const auto& it : proto->histogram()) {
dprintf(fd, " %dms=%d", it.render_millis(), it.frame_count());
diff --git a/libs/hwui/tests/common/scenes/JankyScene.cpp b/libs/hwui/tests/common/scenes/JankyScene.cpp
deleted file mode 100644
index f5e6b317529a..000000000000
--- a/libs/hwui/tests/common/scenes/JankyScene.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "TestSceneBase.h"
-
-#include <unistd.h>
-
-class JankyScene;
-
-static TestScene::Registrar _JankyScene(TestScene::Info{
- "janky",
- "A scene that intentionally janks just enough to stay in "
- "triple buffering.",
- TestScene::simpleCreateScene<JankyScene>});
-
-class JankyScene : public TestScene {
-public:
- sp<RenderNode> card;
-
- void createContent(int width, int height, Canvas& canvas) override {
- card = TestUtils::createNode(0, 0, 200, 200, [](RenderProperties& props, Canvas& canvas) {
- canvas.drawColor(0xFF0000FF, SkBlendMode::kSrcOver);
- });
- canvas.drawColor(0xFFFFFFFF, SkBlendMode::kSrcOver); // background
- canvas.drawRenderNode(card.get());
- }
-
- void doFrame(int frameNr) override {
- int curFrame = frameNr % 150;
- if (curFrame & 1) {
- usleep(15000);
- }
- // we animate left and top coordinates, which in turn animates width and
- // height (bottom/right coordinates are fixed)
- card->mutateStagingProperties().setLeftTop(curFrame, curFrame);
- card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
- }
-}; \ No newline at end of file
diff --git a/libs/hwui/tests/unit/main.cpp b/libs/hwui/tests/unit/main.cpp
index 406255d61d25..9e6d9a8c27de 100644
--- a/libs/hwui/tests/unit/main.cpp
+++ b/libs/hwui/tests/unit/main.cpp
@@ -21,6 +21,7 @@
#include "debug/GlesDriver.h"
#include "debug/NullGlesDriver.h"
#include "hwui/Typeface.h"
+#include "Properties.h"
#include "tests/common/LeakChecker.h"
#include "thread/TaskManager.h"
@@ -67,6 +68,7 @@ int main(int argc, char* argv[]) {
// Replace the default GLES driver
debug::GlesDriver::replace(std::make_unique<debug::NullGlesDriver>());
+ Properties::isolatedProcess = true;
// Run the tests
testing::InitGoogleTest(&argc, argv);