1ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck/*
2ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Copyright (C) 2015 The Android Open Source Project
3ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck *
4ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * you may not use this file except in compliance with the License.
6ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * You may obtain a copy of the License at
7ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck *
8ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck *      http://www.apache.org/licenses/LICENSE-2.0
9ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck *
10ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * Unless required by applicable law or agreed to in writing, software
11ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * distributed under the License is distributed on an "AS IS" BASIS,
12ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * See the License for the specific language governing permissions and
14ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * limitations under the License.
15ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */
1696bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn
17ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck#include "JankTracker.h"
18ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
1952eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <errno.h>
2052eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <inttypes.h>
2196bf5985d5a360568832fd26b6d5b44236c9343eMark Salyzyn#include <sys/mman.h>
22c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck
23e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck#include <algorithm>
2452eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <cmath>
25ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck#include <cstdio>
265ed587f25b367cfd1f68279d6cd96ee403bd6f34John Reck#include <limits>
27ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
2852eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <cutils/ashmem.h>
2952eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include <log/log.h>
3052eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn
3152eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include "Properties.h"
3252eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn#include "utils/TimeUtils.h"
3352eb4e01a49fe2e94555c000de38bbcbbb13401bMark Salyzyn
34ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Recknamespace android {
35ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Recknamespace uirenderer {
36ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
37ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const char* JANK_TYPE_NAMES[] = {
38ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        "Missed Vsync",
39ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        "High input latency",
40ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        "Slow UI thread",
41ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        "Slow bitmap uploads",
42be3fba05e823f740f65b2679929347dc3dd282adJohn Reck        "Slow issue draw commands",
43ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck};
44ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
45ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstruct Comparison {
46c87be99c6ead0720a8918ea38ce3b25e5c49e1c6John Reck    FrameInfoIndex start;
47c87be99c6ead0720a8918ea38ce3b25e5c49e1c6John Reck    FrameInfoIndex end;
48ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck};
49ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
50ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const Comparison COMPARISONS[] = {
511b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik        {FrameInfoIndex::IntendedVsync, FrameInfoIndex::Vsync},
521b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik        {FrameInfoIndex::OldestInputEvent, FrameInfoIndex::Vsync},
531b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik        {FrameInfoIndex::Vsync, FrameInfoIndex::SyncStart},
541b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik        {FrameInfoIndex::SyncStart, FrameInfoIndex::IssueDrawCommandsStart},
551b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik        {FrameInfoIndex::IssueDrawCommandsStart, FrameInfoIndex::FrameCompleted},
56ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck};
57ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
58ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck// If the event exceeds 10 seconds throw it away, this isn't a jank event
59ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck// it's an ANR and will be handled as such
60ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckstatic const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10);
61ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
62ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck/*
63660108075e61d7b7e6c138000890011510d5b079John Reck * We don't track direct-drawing via Surface:lockHardwareCanvas()
64ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * for now
65ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck *
66ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * TODO: kSurfaceCanvas can negatively impact other drawing by using up
67ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck * time on the RenderThread, figure out how to attribute that as a jank-causer
68ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck */
69660108075e61d7b7e6c138000890011510d5b079John Reckstatic const int64_t EXEMPT_FRAMES_FLAGS = FrameInfoFlags::SurfaceCanvas;
70ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
71edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// The bucketing algorithm controls so to speak
72edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is <= to this it goes in bucket 0
73660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kBucketMinThreshold = 5;
74edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is > this, start counting in increments of 2ms
75edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic const uint32_t kBucket2msIntervals = 32;
76edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// If a frame is > this, start counting in increments of 4ms
77edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckstatic const uint32_t kBucket4msIntervals = 48;
78edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
79c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// For testing purposes to try and eliminate test infra overhead we will
80c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// consider any unknown delay of frame start as part of the test infrastructure
81c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck// and filter it out of the frame profile data
82c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reckstatic FrameInfoIndex sFrameStart = FrameInfoIndex::IntendedVsync;
83c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck
84660108075e61d7b7e6c138000890011510d5b079John Reck// The interval of the slow frame histogram
85660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kSlowFrameBucketIntervalMs = 50;
86660108075e61d7b7e6c138000890011510d5b079John Reck// The start point of the slow frame bucket in ms
87660108075e61d7b7e6c138000890011510d5b079John Reckstatic const uint32_t kSlowFrameBucketStartMs = 150;
88660108075e61d7b7e6c138000890011510d5b079John Reck
89edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// This will be called every frame, performance sensitive
90edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// Uses bit twiddling to avoid branching while achieving the packing desired
91660108075e61d7b7e6c138000890011510d5b079John Reckstatic uint32_t frameCountIndexForFrameTime(nsecs_t frameTime) {
92edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    uint32_t index = static_cast<uint32_t>(ns2ms(frameTime));
93edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // If index > kBucketMinThreshold mask will be 0xFFFFFFFF as a result
94edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // of negating 1 (twos compliment, yaay) else mask will be 0
95edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    uint32_t mask = -(index > kBucketMinThreshold);
96edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // If index > threshold, this will essentially perform:
97edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // amountAboveThreshold = index - threshold;
98edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // index = threshold + (amountAboveThreshold / 2)
99edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // However if index is <= this will do nothing. It will underflow, do
100edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // a right shift by 0 (no-op), then overflow back to the original value
101edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    index = ((index - kBucket4msIntervals) >> (index > kBucket4msIntervals))
102edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            + kBucket4msIntervals;
103edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    index = ((index - kBucket2msIntervals) >> (index > kBucket2msIntervals))
104edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            + kBucket2msIntervals;
105edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // If index was < minThreshold at the start of all this it's going to
106edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // be a pretty garbage value right now. However, mask is 0 so we'll end
107edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // up with the desired result of 0.
108edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    index = (index - kBucketMinThreshold) & mask;
109660108075e61d7b7e6c138000890011510d5b079John Reck    return index;
110edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
111edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
112edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck// Only called when dumping stats, less performance sensitive
113df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reckint32_t JankTracker::frameTimeForFrameCountIndex(uint32_t index) {
114edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    index = index + kBucketMinThreshold;
115edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (index > kBucket2msIntervals) {
116edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        index += (index - kBucket2msIntervals);
117edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
118edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (index > kBucket4msIntervals) {
119edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        // This works because it was already doubled by the above if
120edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        // 1 is added to shift slightly more towards the middle of the bucket
121edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        index += (index - kBucket4msIntervals) + 1;
122edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
123edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    return index;
124edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
125edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
126df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reckint32_t JankTracker::frameTimeForSlowFrameCountIndex(uint32_t index) {
127df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    return (index * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
128df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck}
129df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck
1302d5b8d73929a38b019c6b6276d4a19542b990f0cJohn ReckJankTracker::JankTracker(const DisplayInfo& displayInfo) {
131edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // By default this will use malloc memory. It may be moved later to ashmem
132edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // if there is shared space for it and a request comes in to do that.
133edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData = new ProfileData;
134ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    reset();
1352d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
1362d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck#if USE_HWC2
1372d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
1382d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset;
1392d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    // There are two different offset cases. If the offsetDelta is positive
1402d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    // and small, then the intention is to give apps extra time by leveraging
1412d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    // pipelining between the UI & RT threads. If the offsetDelta is large or
1422d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    // negative, the intention is to subtract time from the total duration
1432d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    // in which case we can't afford to wait for dequeueBuffer blockage.
1442d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    if (offsetDelta <= 4_ms && offsetDelta >= 0) {
1452d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        // SF will begin composition at VSYNC-app + offsetDelta. If we are triple
1462d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        // buffered, this is the expected time at which dequeueBuffer will
1472d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        // return due to the staggering of VSYNC-app & VSYNC-sf.
1482d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        mDequeueTimeForgiveness = offsetDelta + 4_ms;
1492d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    }
1502d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck#endif
151ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    setFrameInterval(frameIntervalNanos);
152ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}
153ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
154edc524c90506d80e0fc5fb67e8de7b8f3ef53439John ReckJankTracker::~JankTracker() {
155edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    freeData();
156edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
157edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
158edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::freeData() {
159edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (mIsMapped) {
160edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        munmap(mData, sizeof(ProfileData));
161edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    } else {
162edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        delete mData;
163edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
164edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mIsMapped = false;
165edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData = nullptr;
166edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
167edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
168df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reckvoid JankTracker::rotateStorage() {
169df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    // If we are mapped we want to stop using the ashmem backend and switch to malloc
170df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    // We are expecting a switchStorageToAshmem call to follow this, but it's not guaranteed
171df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    // If we aren't sitting on top of ashmem then just do a reset() as it's functionally
172df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    // equivalent do a free, malloc, reset.
173df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    if (mIsMapped) {
174df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        freeData();
175df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        mData = new ProfileData;
176df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    }
177df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    reset();
178df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck}
179df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck
180edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckvoid JankTracker::switchStorageToAshmem(int ashmemfd) {
181edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    int regionSize = ashmem_get_size_region(ashmemfd);
182df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    if (regionSize < 0) {
183df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        int err = errno;
184df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        ALOGW("Failed to get ashmem region size from fd %d, err %d %s", ashmemfd, err, strerror(err));
185df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        return;
186df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    }
187edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (regionSize < static_cast<int>(sizeof(ProfileData))) {
188edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        ALOGW("Ashmem region is too small! Received %d, required %u",
18998fa0a322e6bf4f6b543487c820955d8598193b5John Reck                regionSize, static_cast<unsigned int>(sizeof(ProfileData)));
190edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        return;
191edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
192edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    ProfileData* newData = reinterpret_cast<ProfileData*>(
193edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            mmap(NULL, sizeof(ProfileData), PROT_READ | PROT_WRITE,
194edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            MAP_SHARED, ashmemfd, 0));
195edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (newData == MAP_FAILED) {
196edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        int err = errno;
197edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        ALOGW("Failed to move profile data to ashmem fd %d, error = %d",
198edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck                ashmemfd, err);
199edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        return;
200edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
201edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
202edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // The new buffer may have historical data that we want to build on top of
203edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    // But let's make sure we don't overflow Just In Case
204edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    uint32_t divider = 0;
205edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    if (newData->totalFrameCount > (1 << 24)) {
206edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        divider = 4;
207edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
208edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    for (size_t i = 0; i < mData->jankTypeCounts.size(); i++) {
209edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        newData->jankTypeCounts[i] >>= divider;
210edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        newData->jankTypeCounts[i] += mData->jankTypeCounts[i];
211edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
212edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    for (size_t i = 0; i < mData->frameCounts.size(); i++) {
213edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        newData->frameCounts[i] >>= divider;
214edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        newData->frameCounts[i] += mData->frameCounts[i];
215edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
216edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    newData->jankFrameCount >>= divider;
217edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    newData->jankFrameCount += mData->jankFrameCount;
218edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    newData->totalFrameCount >>= divider;
219edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    newData->totalFrameCount += mData->totalFrameCount;
220379f264bb62ace2cf2053d4765307234bf66552fJohn Reck    if (newData->statStartTime > mData->statStartTime
221379f264bb62ace2cf2053d4765307234bf66552fJohn Reck            || newData->statStartTime == 0) {
222379f264bb62ace2cf2053d4765307234bf66552fJohn Reck        newData->statStartTime = mData->statStartTime;
223379f264bb62ace2cf2053d4765307234bf66552fJohn Reck    }
224edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
225edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    freeData();
226edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData = newData;
227edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mIsMapped = true;
228edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck}
229edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck
230ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::setFrameInterval(nsecs_t frameInterval) {
231ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mFrameInterval = frameInterval;
232ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mThresholds[kMissedVsync] = 1;
233ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    /*
234ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * Due to interpolation and sample rate differences between the touch
235ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * panel and the display (example, 85hz touch panel driving a 60hz display)
236ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * we call high latency 1.5 * frameinterval
237ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     *
238ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
239ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
240ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     * Thus this must always be larger than frameInterval, or it will fail
241ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck     */
242ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
243ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
244ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    // Note that these do not add up to 1. This is intentional. It's to deal
245ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    // with variance in values, and should be sort of an upper-bound on what
246ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    // is reasonable to expect.
247ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
248ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
249ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
250ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
251ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}
252ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
253ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::addFrame(const FrameInfo& frame) {
254edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->totalFrameCount++;
255ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    // Fast-path for jank-free frames
256126720aa65fd90105bdf54c04f327f146763c5cfJohn Reck    int64_t totalDuration = frame.duration(sFrameStart, FrameInfoIndex::FrameCompleted);
2572d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    if (mDequeueTimeForgiveness
2582d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck            && frame[FrameInfoIndex::DequeueBufferDuration] > 500_us) {
2592d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        nsecs_t expectedDequeueDuration =
2602d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck                mDequeueTimeForgiveness + frame[FrameInfoIndex::Vsync]
2612d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck                - frame[FrameInfoIndex::IssueDrawCommandsStart];
2622d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        if (expectedDequeueDuration > 0) {
2632d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck            // Forgive only up to the expected amount, but not more than
2642d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck            // the actual time spent blocked.
2652d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck            nsecs_t forgiveAmount = std::min(expectedDequeueDuration,
2662d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck                    frame[FrameInfoIndex::DequeueBufferDuration]);
2671b7184f8d206505804042833a3825a3b8a9649dcJohn Reck            LOG_ALWAYS_FATAL_IF(forgiveAmount >= totalDuration,
2681b7184f8d206505804042833a3825a3b8a9649dcJohn Reck                    "Impossible dequeue duration! dequeue duration reported %" PRId64
2691b7184f8d206505804042833a3825a3b8a9649dcJohn Reck                    ", total duration %" PRId64, forgiveAmount, totalDuration);
2702d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck            totalDuration -= forgiveAmount;
2712d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck        }
2722d5b8d73929a38b019c6b6276d4a19542b990f0cJohn Reck    }
2731b7184f8d206505804042833a3825a3b8a9649dcJohn Reck    LOG_ALWAYS_FATAL_IF(totalDuration <= 0, "Impossible totalDuration %" PRId64, totalDuration);
274660108075e61d7b7e6c138000890011510d5b079John Reck    uint32_t framebucket = frameCountIndexForFrameTime(totalDuration);
2751b7184f8d206505804042833a3825a3b8a9649dcJohn Reck    LOG_ALWAYS_FATAL_IF(framebucket < 0, "framebucket < 0 (%u)", framebucket);
276e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck    // Keep the fast path as fast as possible.
277ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    if (CC_LIKELY(totalDuration < mFrameInterval)) {
278edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        mData->frameCounts[framebucket]++;
279ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        return;
280ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    }
281ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
282660108075e61d7b7e6c138000890011510d5b079John Reck    // Only things like Surface.lockHardwareCanvas() are exempt from tracking
2831b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik    if (frame[FrameInfoIndex::Flags] & EXEMPT_FRAMES_FLAGS) {
284ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        return;
285ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    }
286ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
287660108075e61d7b7e6c138000890011510d5b079John Reck    if (framebucket <= mData->frameCounts.size()) {
288660108075e61d7b7e6c138000890011510d5b079John Reck        mData->frameCounts[framebucket]++;
289660108075e61d7b7e6c138000890011510d5b079John Reck    } else {
290660108075e61d7b7e6c138000890011510d5b079John Reck        framebucket = (ns2ms(totalDuration) - kSlowFrameBucketStartMs)
291660108075e61d7b7e6c138000890011510d5b079John Reck                / kSlowFrameBucketIntervalMs;
292660108075e61d7b7e6c138000890011510d5b079John Reck        framebucket = std::min(framebucket,
293660108075e61d7b7e6c138000890011510d5b079John Reck                static_cast<uint32_t>(mData->slowFrameCounts.size() - 1));
294660108075e61d7b7e6c138000890011510d5b079John Reck        framebucket = std::max(framebucket, 0u);
295660108075e61d7b7e6c138000890011510d5b079John Reck        mData->slowFrameCounts[framebucket]++;
296660108075e61d7b7e6c138000890011510d5b079John Reck    }
297660108075e61d7b7e6c138000890011510d5b079John Reck
298edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->jankFrameCount++;
299ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
300ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    for (int i = 0; i < NUM_BUCKETS; i++) {
301be3fba05e823f740f65b2679929347dc3dd282adJohn Reck        int64_t delta = frame.duration(COMPARISONS[i].start, COMPARISONS[i].end);
302ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
303edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            mData->jankTypeCounts[i]++;
304ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck        }
305ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    }
306ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}
307ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
308df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reckvoid JankTracker::dumpData(int fd, const ProfileDataDescription* description, const ProfileData* data) {
309df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck    if (description) {
310df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        switch (description->type) {
311df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck            case JankTrackerType::Generic:
312df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck                break;
313df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck            case JankTrackerType::Package:
314df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck                dprintf(fd, "\nPackage: %s", description->name.c_str());
315df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck                break;
316df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck            case JankTrackerType::Window:
317df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck                dprintf(fd, "\nWindow: %s", description->name.c_str());
318df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck                break;
319df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        }
320edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    }
321c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck    if (sFrameStart != FrameInfoIndex::IntendedVsync) {
322c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck        dprintf(fd, "\nNote: Data has been filtered!");
323c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck    }
32405f5674ae8cae94c9cc3f039e55747f0e787f959Ying Wang    dprintf(fd, "\nStats since: %" PRIu64 "ns", data->statStartTime);
325edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\nTotal frames rendered: %u", data->totalFrameCount);
326edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\nJanky frames: %u (%.2f%%)", data->jankFrameCount,
327edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            (float) data->jankFrameCount / (float) data->totalFrameCount * 100.0f);
328682573c84b7c21dc8ce4a2375da3961147442c4aJohn Reck    dprintf(fd, "\n50th percentile: %ums", findPercentile(data, 50));
329edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\n90th percentile: %ums", findPercentile(data, 90));
330edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\n95th percentile: %ums", findPercentile(data, 95));
331edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\n99th percentile: %ums", findPercentile(data, 99));
332ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    for (int i = 0; i < NUM_BUCKETS; i++) {
333edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        dprintf(fd, "\nNumber %s: %u", JANK_TYPE_NAMES[i], data->jankTypeCounts[i]);
334ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck    }
335660108075e61d7b7e6c138000890011510d5b079John Reck    dprintf(fd, "\nHISTOGRAM:");
336660108075e61d7b7e6c138000890011510d5b079John Reck    for (size_t i = 0; i < data->frameCounts.size(); i++) {
337660108075e61d7b7e6c138000890011510d5b079John Reck        dprintf(fd, " %ums=%u", frameTimeForFrameCountIndex(i),
338660108075e61d7b7e6c138000890011510d5b079John Reck                data->frameCounts[i]);
339660108075e61d7b7e6c138000890011510d5b079John Reck    }
340660108075e61d7b7e6c138000890011510d5b079John Reck    for (size_t i = 0; i < data->slowFrameCounts.size(); i++) {
341df1742ed47da1e9b61afeae16fa448d5302a8aa0John Reck        dprintf(fd, " %ums=%u", frameTimeForSlowFrameCountIndex(i),
342660108075e61d7b7e6c138000890011510d5b079John Reck                data->slowFrameCounts[i]);
343660108075e61d7b7e6c138000890011510d5b079John Reck    }
344edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    dprintf(fd, "\n");
345ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}
346ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
347ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reckvoid JankTracker::reset() {
348edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->jankTypeCounts.fill(0);
349edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->frameCounts.fill(0);
3508f55d00c2aa351d6914dca4d0cc2c07725002d90John Reck    mData->slowFrameCounts.fill(0);
351edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->totalFrameCount = 0;
352edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    mData->jankFrameCount = 0;
353379f264bb62ace2cf2053d4765307234bf66552fJohn Reck    mData->statStartTime = systemTime(CLOCK_MONOTONIC);
354c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck    sFrameStart = Properties::filterOutTestOverhead
355c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck            ? FrameInfoIndex::HandleInputStart
356c7cd9cf25d9775446ffcb6b5f20b0a4c1e3c99c5John Reck            : FrameInfoIndex::IntendedVsync;
357ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck}
358ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck
359edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reckuint32_t JankTracker::findPercentile(const ProfileData* data, int percentile) {
360edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    int pos = percentile * data->totalFrameCount / 100;
361edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    int remaining = data->totalFrameCount - pos;
362660108075e61d7b7e6c138000890011510d5b079John Reck    for (int i = data->slowFrameCounts.size() - 1; i >= 0; i--) {
363660108075e61d7b7e6c138000890011510d5b079John Reck        remaining -= data->slowFrameCounts[i];
364660108075e61d7b7e6c138000890011510d5b079John Reck        if (remaining <= 0) {
365660108075e61d7b7e6c138000890011510d5b079John Reck            return (i * kSlowFrameBucketIntervalMs) + kSlowFrameBucketStartMs;
366660108075e61d7b7e6c138000890011510d5b079John Reck        }
367660108075e61d7b7e6c138000890011510d5b079John Reck    }
368edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck    for (int i = data->frameCounts.size() - 1; i >= 0; i--) {
369edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck        remaining -= data->frameCounts[i];
370e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck        if (remaining <= 0) {
371edc524c90506d80e0fc5fb67e8de7b8f3ef53439John Reck            return frameTimeForFrameCountIndex(i);
372e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck        }
373e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck    }
374e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck    return 0;
375e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck}
376e70c5754d01f2ab0ff47ea3eabaa88aca5ed2a36John Reck
377ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} /* namespace uirenderer */
378ba6adf66d3c44c0aa2fd8a224862ff1901d64300John Reck} /* namespace android */
379