1e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza/*
2e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * Copyright 2016 The Android Open Source Project
3e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza *
4e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * Licensed under the Apache License, Version 2.0 (the "License");
5e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * you may not use this file except in compliance with the License.
6e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * You may obtain a copy of the License at
7e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza *
8e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza *      http://www.apache.org/licenses/LICENSE-2.0
9e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza *
10e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * Unless required by applicable law or agreed to in writing, software
11e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * distributed under the License is distributed on an "AS IS" BASIS,
12e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * See the License for the specific language governing permissions and
14e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza * limitations under the License.
15e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza */
16e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
17e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#undef LOG_TAG
18e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#define LOG_TAG "OccupancyTracker"
19e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
20e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#include <gui/OccupancyTracker.h>
21e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#include <binder/Parcel.h>
22e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#include <utils/String8.h>
23e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#include <utils/Trace.h>
24e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
25e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza#include <inttypes.h>
26e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
27e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozanamespace android {
28e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
29e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozastatus_t OccupancyTracker::Segment::writeToParcel(Parcel* parcel) const {
30e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    status_t result = parcel->writeInt64(totalTime);
31e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
32e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
33e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
34e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    result = parcel->writeUint64(static_cast<uint64_t>(numFrames));
35e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
36e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
37e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
38e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    result = parcel->writeFloat(occupancyAverage);
39e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
40e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
41e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
42e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    return parcel->writeBool(usedThirdBuffer);
43e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza}
44e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
45e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozastatus_t OccupancyTracker::Segment::readFromParcel(const Parcel* parcel) {
46e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    status_t result = parcel->readInt64(&totalTime);
47e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
48e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
49e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
50e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    uint64_t uintNumFrames = 0;
51e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    result = parcel->readUint64(&uintNumFrames);
52e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
53e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
54e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
55e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    numFrames = static_cast<size_t>(uintNumFrames);
56e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    result = parcel->readFloat(&occupancyAverage);
57e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (result != OK) {
58e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        return result;
59e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
60e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    return parcel->readBool(&usedThirdBuffer);
61e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza}
62e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
63e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozavoid OccupancyTracker::registerOccupancyChange(size_t occupancy) {
64e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    ATRACE_CALL();
65e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    nsecs_t now = systemTime();
66e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    nsecs_t delta = now - mLastOccupancyChangeTime;
67e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (delta > NEW_SEGMENT_DELAY) {
68e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        recordPendingSegment();
69e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    } else {
70e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        mPendingSegment.totalTime += delta;
71e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        if (mPendingSegment.mOccupancyTimes.count(mLastOccupancy)) {
72e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            mPendingSegment.mOccupancyTimes[mLastOccupancy] += delta;
73e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        } else {
74e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            mPendingSegment.mOccupancyTimes[mLastOccupancy] = delta;
75e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        }
76e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
77e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (occupancy > mLastOccupancy) {
78e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        ++mPendingSegment.numFrames;
79e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
80e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    mLastOccupancyChangeTime = now;
81e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    mLastOccupancy = occupancy;
82e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza}
83e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
84e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozastd::vector<OccupancyTracker::Segment> OccupancyTracker::getSegmentHistory(
85e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        bool forceFlush) {
86e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (forceFlush) {
87e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        recordPendingSegment();
88e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
89e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    std::vector<Segment> segments(mSegmentHistory.cbegin(),
90e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            mSegmentHistory.cend());
91e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    mSegmentHistory.clear();
92e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    return segments;
93e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza}
94e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
95e77c7669bee30b7c0099172cf0c38cef92412040Dan Stozavoid OccupancyTracker::recordPendingSegment() {
96e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    // Only record longer segments to get a better measurement of actual double-
97e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    // vs. triple-buffered time
98e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    if (mPendingSegment.numFrames > LONG_SEGMENT_THRESHOLD) {
99e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        float occupancyAverage = 0.0f;
100e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        bool usedThirdBuffer = false;
101e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        for (const auto& timePair : mPendingSegment.mOccupancyTimes) {
102e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            size_t occupancy = timePair.first;
103e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            float timeRatio = static_cast<float>(timePair.second) /
104e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza                    mPendingSegment.totalTime;
105e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            occupancyAverage += timeRatio * occupancy;
106e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            usedThirdBuffer = usedThirdBuffer || (occupancy > 1);
107e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        }
108e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        mSegmentHistory.push_front({mPendingSegment.totalTime,
109e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza                mPendingSegment.numFrames, occupancyAverage, usedThirdBuffer});
110e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        if (mSegmentHistory.size() > MAX_HISTORY_SIZE) {
111e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza            mSegmentHistory.pop_back();
112e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza        }
113e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    }
114e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza    mPendingSegment.clear();
115e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza}
116e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza
117e77c7669bee30b7c0099172cf0c38cef92412040Dan Stoza} // namespace android
118