Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #ifndef FRAMEINFO_H_
     17 #define FRAMEINFO_H_
     18 
     19 #include "utils/Macros.h"
     20 
     21 #include <cutils/compiler.h>
     22 #include <utils/Timers.h>
     23 
     24 #include <memory.h>
     25 #include <string>
     26 
     27 namespace android {
     28 namespace uirenderer {
     29 
     30 #define UI_THREAD_FRAME_INFO_SIZE 9
     31 
     32 enum class FrameInfoIndex {
     33     Flags = 0,
     34     IntendedVsync,
     35     Vsync,
     36     OldestInputEvent,
     37     NewestInputEvent,
     38     HandleInputStart,
     39     AnimationStart,
     40     PerformTraversalsStart,
     41     DrawStart,
     42     // End of UI frame info
     43 
     44     SyncQueued,
     45 
     46     SyncStart,
     47     IssueDrawCommandsStart,
     48     SwapBuffers,
     49     FrameCompleted,
     50 
     51     DequeueBufferDuration,
     52     QueueBufferDuration,
     53 
     54     // Must be the last value!
     55     // Also must be kept in sync with FrameMetrics.java#FRAME_STATS_COUNT
     56     NumIndexes
     57 };
     58 
     59 extern const std::string FrameInfoNames[];
     60 
     61 namespace FrameInfoFlags {
     62     enum {
     63         WindowLayoutChanged = 1 << 0,
     64         RTAnimation = 1 << 1,
     65         SurfaceCanvas = 1 << 2,
     66         SkippedFrame = 1 << 3,
     67     };
     68 };
     69 
     70 class ANDROID_API UiFrameInfoBuilder {
     71 public:
     72     explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
     73         memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
     74     }
     75 
     76     UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
     77         set(FrameInfoIndex::Vsync) = vsyncTime;
     78         set(FrameInfoIndex::IntendedVsync) = intendedVsync;
     79         // Pretend the other fields are all at vsync, too, so that naive
     80         // duration calculations end up being 0 instead of very large
     81         set(FrameInfoIndex::HandleInputStart) = vsyncTime;
     82         set(FrameInfoIndex::AnimationStart) = vsyncTime;
     83         set(FrameInfoIndex::PerformTraversalsStart) = vsyncTime;
     84         set(FrameInfoIndex::DrawStart) = vsyncTime;
     85         return *this;
     86     }
     87 
     88     UiFrameInfoBuilder& addFlag(int frameInfoFlag) {
     89         set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
     90         return *this;
     91     }
     92 
     93 private:
     94     inline int64_t& set(FrameInfoIndex index) {
     95         return mBuffer[static_cast<int>(index)];
     96     }
     97 
     98     int64_t* mBuffer;
     99 };
    100 
    101 class FrameInfo {
    102 public:
    103     void importUiThreadInfo(int64_t* info);
    104 
    105     void markSyncStart() {
    106         set(FrameInfoIndex::SyncStart) = systemTime(CLOCK_MONOTONIC);
    107     }
    108 
    109     void markIssueDrawCommandsStart() {
    110         set(FrameInfoIndex::IssueDrawCommandsStart) = systemTime(CLOCK_MONOTONIC);
    111     }
    112 
    113     void markSwapBuffers() {
    114         set(FrameInfoIndex::SwapBuffers) = systemTime(CLOCK_MONOTONIC);
    115     }
    116 
    117     void markFrameCompleted() {
    118         set(FrameInfoIndex::FrameCompleted) = systemTime(CLOCK_MONOTONIC);
    119     }
    120 
    121     void addFlag(int frameInfoFlag) {
    122         set(FrameInfoIndex::Flags) |= static_cast<uint64_t>(frameInfoFlag);
    123     }
    124 
    125     const int64_t* data() const {
    126         return mFrameInfo;
    127     }
    128 
    129     inline int64_t operator[](FrameInfoIndex index) const {
    130         return get(index);
    131     }
    132 
    133     inline int64_t operator[](int index) const {
    134         if (index < 0 || index >= static_cast<int>(FrameInfoIndex::NumIndexes)) return 0;
    135         return mFrameInfo[index];
    136     }
    137 
    138     inline int64_t duration(FrameInfoIndex start, FrameInfoIndex end) const {
    139         int64_t endtime = get(end);
    140         int64_t starttime = get(start);
    141         int64_t gap = endtime - starttime;
    142         gap = starttime > 0 ? gap : 0;
    143         if (end > FrameInfoIndex::SyncQueued &&
    144                 start < FrameInfoIndex::SyncQueued) {
    145             // Need to subtract out the time spent in a stalled state
    146             // as this will be captured by the previous frame's info
    147             int64_t offset = get(FrameInfoIndex::SyncStart)
    148                     - get(FrameInfoIndex::SyncQueued);
    149             if (offset > 0) {
    150                 gap -= offset;
    151             }
    152         }
    153         return gap > 0 ? gap : 0;
    154     }
    155 
    156     inline int64_t totalDuration() const {
    157         return duration(FrameInfoIndex::IntendedVsync, FrameInfoIndex::FrameCompleted);
    158     }
    159 
    160     inline int64_t& set(FrameInfoIndex index) {
    161         return mFrameInfo[static_cast<int>(index)];
    162     }
    163 
    164     inline int64_t get(FrameInfoIndex index) const {
    165         if (index == FrameInfoIndex::NumIndexes) return 0;
    166         return mFrameInfo[static_cast<int>(index)];
    167     }
    168 
    169 private:
    170     int64_t mFrameInfo[static_cast<int>(FrameInfoIndex::NumIndexes)];
    171 };
    172 
    173 } /* namespace uirenderer */
    174 } /* namespace android */
    175 
    176 #endif /* FRAMEINFO_H_ */
    177