diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/DeviceInfo.cpp | 29 | ||||
| -rw-r--r-- | libs/hwui/DeviceInfo.h | 3 | ||||
| -rw-r--r-- | libs/hwui/JankTracker.cpp | 32 | ||||
| -rw-r--r-- | libs/hwui/JankTracker.h | 1 | ||||
| -rw-r--r-- | libs/hwui/ProfileData.cpp | 3 | ||||
| -rw-r--r-- | libs/hwui/ProfileData.h | 1 | ||||
| -rw-r--r-- | libs/hwui/Properties.cpp | 1 | ||||
| -rw-r--r-- | libs/hwui/Properties.h | 1 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.cpp | 113 | ||||
| -rw-r--r-- | libs/hwui/renderthread/RenderThread.h | 12 | ||||
| -rw-r--r-- | libs/hwui/service/GraphicsStatsService.cpp | 3 | ||||
| -rw-r--r-- | libs/hwui/tests/common/scenes/JankyScene.cpp | 51 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/main.cpp | 2 | 
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); |