182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis/*
282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * Copyright (C) 2012 The Android Open Source Project
382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis *
482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * you may not use this file except in compliance with the License.
682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * You may obtain a copy of the License at
782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis *
882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis *
1082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * Unless required by applicable law or agreed to in writing, software
1182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
1282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * See the License for the specific language governing permissions and
1482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis * limitations under the License.
1582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis */
1682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
1782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#ifndef ANDROID_FRAMETRACKER_H
1882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#define ANDROID_FRAMETRACKER_H
1982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
2082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#include <stddef.h>
2182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
224b0eba949cc026ffb2c75313042d8a7bcb3fcf86Jamie Gennis#include <utils/Mutex.h>
2382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#include <utils/Timers.h>
2482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#include <utils/RefBase.h>
2582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
2682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisnamespace android {
2782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
2882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisclass String8;
2982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisclass Fence;
3082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
3182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// FrameTracker tracks information about the most recently rendered frames. It
3282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// uses a circular buffer of frame records, and is *NOT* thread-safe -
3382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// mutexing must be done at a higher level if multi-threaded access is
3482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// possible.
3582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis//
3682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// Some of the time values tracked may be set either as a specific timestamp
3782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// or a fence.  When a non-NULL fence is set for a given time value, the
3882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis// signal time of that fence is used instead of the timestamp.
3982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisclass FrameTracker {
4082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
4182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennispublic:
4282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // NUM_FRAME_RECORDS is the size of the circular buffer used to track the
4382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // frame time history.
4482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    enum { NUM_FRAME_RECORDS = 128 };
4582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
466547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    enum { NUM_FRAME_BUCKETS = 7 };
476547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
4882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    FrameTracker();
4982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
5082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // setDesiredPresentTime sets the time at which the current frame
5182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // should be presented to the user under ideal (i.e. zero latency)
5282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // conditions.
5382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void setDesiredPresentTime(nsecs_t desiredPresentTime);
5482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
5582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // setFrameReadyTime sets the time at which the current frame became ready
5682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // to be presented to the user.  For example, if the frame contents is
5782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // being written to memory by some asynchronous hardware, this would be
5882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // the time at which those writes completed.
5982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void setFrameReadyTime(nsecs_t readyTime);
6082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
6182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // setFrameReadyFence sets the fence that is used to get the time at which
6282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // the current frame became ready to be presented to the user.
6382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void setFrameReadyFence(const sp<Fence>& readyFence);
6482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
6582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // setActualPresentTime sets the timestamp at which the current frame became
6682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // visible to the user.
6782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void setActualPresentTime(nsecs_t displayTime);
6882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
6982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // setActualPresentFence sets the fence that is used to get the time
7082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // at which the current frame became visible to the user.
7182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void setActualPresentFence(const sp<Fence>& fence);
7282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
736547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // setDisplayRefreshPeriod sets the display refresh period in nanoseconds.
746547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // This is used to compute frame presentation duration statistics relative
756547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // to this period.
766547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    void setDisplayRefreshPeriod(nsecs_t displayPeriod);
776547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
7882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // advanceFrame advances the frame tracker to the next frame.
7982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    void advanceFrame();
8082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
81d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    // clearStats clears the tracked frame stats.
82d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    void clearStats();
83d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav
84d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    // getStats gets the tracked frame stats.
85d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    void getStats(FrameStats* outStats) const;
8682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
876547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // logAndResetStats dumps the current statistics to the binary event log
886547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // and then resets the accumulated statistics to their initial values.
896547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    void logAndResetStats(const String8& name);
906547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
91d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    // dumpStats dump appends the current frame display time history to the result string.
92d85084b2b65828442eafaff9b811e9b6c9ca9fadSvetoslav    void dumpStats(String8& result) const;
9382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
9482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennisprivate:
9582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    struct FrameRecord {
9682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        FrameRecord() :
9782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis            desiredPresentTime(0),
9882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis            frameReadyTime(0),
9982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis            actualPresentTime(0) {}
10082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        nsecs_t desiredPresentTime;
10182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        nsecs_t frameReadyTime;
10282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        nsecs_t actualPresentTime;
10382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        sp<Fence> frameReadyFence;
10482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis        sp<Fence> actualPresentFence;
10582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    };
10682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
10782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // processFences iterates over all the frame records that have a fence set
10882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // and replaces that fence with a timestamp if the fence has signaled.  If
10982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // the fence is not signaled the record's displayTime is set to INT64_MAX.
11082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    //
11182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // This method is const because although it modifies the frame records it
11282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // does so in such a way that the information represented should not
11382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // change.  This allows it to be called from the dump method.
1144b0eba949cc026ffb2c75313042d8a7bcb3fcf86Jamie Gennis    void processFencesLocked() const;
11582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
1166547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // updateStatsLocked updates the running statistics that are gathered
1176547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // about the frame times.
1186547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    void updateStatsLocked(size_t newFrameIdx) const;
1196547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
1206547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // resetFrameCounteresLocked sets all elements of the mNumFrames array to
1216547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // 0.
1226547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    void resetFrameCountersLocked();
1236547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
1246547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // logStatsLocked dumps the current statistics to the binary event log.
1256547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    void logStatsLocked(const String8& name) const;
1266547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
1276547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // isFrameValidLocked returns true if the data for the given frame index is
1286547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // valid and has all arrived (i.e. there are no oustanding fences).
1296547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    bool isFrameValidLocked(size_t idx) const;
1306547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
13182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // mFrameRecords is the circular buffer storing the tracked data for each
13282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // frame.
13382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    FrameRecord mFrameRecords[NUM_FRAME_RECORDS];
13482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
13582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // mOffset is the offset into mFrameRecords of the current frame.
13682dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    size_t mOffset;
13782dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
13882dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // mNumFences is the total number of fences set in the frame records.  It
13982dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // is incremented each time a fence is added and decremented each time a
14082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // signaled fence is removed in processFences or if advanceFrame clobbers
14182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // a fence.
14282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    //
14382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // The number of fences is tracked so that the run time of processFences
14482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    // doesn't grow with NUM_FRAME_RECORDS.
14582dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis    int mNumFences;
1464b0eba949cc026ffb2c75313042d8a7bcb3fcf86Jamie Gennis
1476547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // mNumFrames keeps a count of the number of frames with a duration in a
1486547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // particular range of vsync periods.  Element n of the array stores the
1496547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // number of frames with duration in the half-inclusive range
1506547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // [2^n, 2^(n+1)).  The last element of the array contains the count for
1516547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // all frames with duration greater than 2^(NUM_FRAME_BUCKETS-1).
1526547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    int32_t mNumFrames[NUM_FRAME_BUCKETS];
1536547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
1546547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // mDisplayPeriod is the display refresh period of the display for which
1556547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    // this FrameTracker is gathering information.
1566547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis    nsecs_t mDisplayPeriod;
1576547ff4327aa320fbc9635668d3fc66db7dd78f6Jamie Gennis
1584b0eba949cc026ffb2c75313042d8a7bcb3fcf86Jamie Gennis    // mMutex is used to protect access to all member variables.
1594b0eba949cc026ffb2c75313042d8a7bcb3fcf86Jamie Gennis    mutable Mutex mMutex;
16082dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis};
16182dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
16282dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis}
16382dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis
16482dbc7429f5f9f2b303b31dc5b9f2bfd1bbe6addJamie Gennis#endif // ANDROID_FRAMETRACKER_H
165