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