Merge "Create consumer state mask(s) immediately after producer allocate new buffer."
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 14edcbe..1674516 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -47,7 +47,7 @@
* (method calls, property get and set) is down through a low-level
* protocol implemented on top of the transact() API.
*/
-class IBinder : public virtual RefBase
+class [[clang::lto_visibility_public]] IBinder : public virtual RefBase
{
public:
enum {
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index e10548f..5dea3c8 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -352,6 +352,11 @@
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
// Add this buffer from our internal queue tracker
{ // Autolock scope
+ // Report the timestamp to the Scheduler.
+ if (mFlinger->mUseScheduler) {
+ mFlinger->mScheduler->addNewFrameTimestamp(item.mTimestamp, item.mIsAutoTimestamp);
+ }
+
Mutex::Autolock lock(mQueueItemLock);
// Reset the frame number tracker when we receive the first buffer after
// a frame number reset
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 18a8bb1..4286cc9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include "Scheduler.h"
#include <cinttypes>
#include <cstdint>
#include <memory>
+#include <numeric>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
@@ -27,6 +30,7 @@
#include <gui/ISurfaceComposer.h>
#include <ui/DisplayStatInfo.h>
+#include <utils/Trace.h>
#include "DispSync.h"
#include "DispSyncSource.h"
@@ -196,4 +200,58 @@
mPrimaryDispSync->setIgnorePresentFences(ignore);
}
+void Scheduler::makeHWSyncAvailable(bool makeAvailable) {
+ std::lock_guard<std::mutex> lock(mHWVsyncLock);
+ mHWVsyncAvailable = makeAvailable;
+}
+
+void Scheduler::addNewFrameTimestamp(const nsecs_t newFrameTimestamp, bool isAutoTimestamp) {
+ ATRACE_INT("AutoTimestamp", isAutoTimestamp);
+ // Video does not have timestamp automatically set, so we discard timestamps that are
+ // coming in from other sources for now.
+ if (isAutoTimestamp) {
+ return;
+ }
+ int64_t differenceMs = (newFrameTimestamp - mPreviousFrameTimestamp) / 1000000;
+ mPreviousFrameTimestamp = newFrameTimestamp;
+
+ if (differenceMs < 10 || differenceMs > 100) {
+ // Dismiss noise.
+ return;
+ }
+ ATRACE_INT("TimestampDiff", differenceMs);
+
+ mTimeDifferences[mCounter % ARRAY_SIZE] = differenceMs;
+ mCounter++;
+ nsecs_t average = calculateAverage();
+ ATRACE_INT("TimestampAverage", average);
+
+ // TODO(b/113612090): This are current numbers from trial and error while running videos
+ // from YouTube at 24, 30, and 60 fps.
+ if (average > 14 && average < 18) {
+ ATRACE_INT("FPS", 60);
+ } else if (average > 31 && average < 34) {
+ ATRACE_INT("FPS", 30);
+ updateFrameSkipping(1);
+ return;
+ } else if (average > 39 && average < 42) {
+ ATRACE_INT("FPS", 24);
+ }
+ updateFrameSkipping(0);
+}
+
+nsecs_t Scheduler::calculateAverage() const {
+ nsecs_t sum = std::accumulate(mTimeDifferences.begin(), mTimeDifferences.end(), 0);
+ return (sum / ARRAY_SIZE);
+}
+
+void Scheduler::updateFrameSkipping(const int64_t skipCount) {
+ ATRACE_INT("FrameSkipCount", skipCount);
+ if (mSkipCount != skipCount) {
+ // Only update DispSync if it hasn't been updated yet.
+ mPrimaryDispSync->setRefreshSkipCount(skipCount);
+ mSkipCount = skipCount;
+ }
+}
+
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index fdafe58..dd1f24b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -102,6 +102,8 @@
void addResyncSample(const nsecs_t timestamp);
void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
void setIgnorePresentFences(bool ignore);
+ void makeHWSyncAvailable(bool makeAvailable);
+ void addNewFrameTimestamp(const nsecs_t newFrameTimestamp, bool isAutoTimestamp);
protected:
virtual std::unique_ptr<EventThread> makeEventThread(
@@ -110,6 +112,9 @@
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
+ nsecs_t calculateAverage() const;
+ void updateFrameSkipping(const int64_t skipCount);
+
// TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
// should make request to Scheduler to compute next refresh.
friend class BufferQueueLayer;
@@ -133,6 +138,18 @@
std::unique_ptr<DispSync> mPrimaryDispSync;
std::unique_ptr<EventControlThread> mEventControlThread;
+
+ // TODO(b/113612090): The following set of variables needs to be revised. For now, this is
+ // a proof of concept. We turn on frame skipping if the difference between the timestamps
+ // is between 32 and 34ms. We expect this currently for 30fps videos, so we render them at 30Hz.
+ nsecs_t mPreviousFrameTimestamp = 0;
+ // Keeping track of whether we are skipping the refresh count. If we want to
+ // simulate 30Hz rendering, we skip every other frame, and this variable is set
+ // to 1.
+ int64_t mSkipCount = 0;
+ static constexpr size_t ARRAY_SIZE = 30;
+ std::array<int64_t, ARRAY_SIZE> mTimeDifferences;
+ size_t mCounter = 0;
};
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 276aa85..d1dab4c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1255,6 +1255,10 @@
if (makeAvailable) {
mHWVsyncAvailable = true;
+ // TODO(b/113612090): This is silly, but necessary evil until we turn on the flag for good.
+ if (mUseScheduler) {
+ mScheduler->makeHWSyncAvailable(true);
+ }
} else if (!mHWVsyncAvailable) {
// Hardware vsync is not currently available, so abort the resync
// attempt for now
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index ace7c1b..9730e8c 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -173,8 +173,8 @@
ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID,
timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime);
+ const std::string& layerName = layerRecord.layerName;
if (prevTimeRecord.ready) {
- const std::string& layerName = layerRecord.layerName;
if (!mTimeStats.stats.count(layerName)) {
mTimeStats.stats[layerName].layerName = layerName;
mTimeStats.stats[layerName].packageName = getPackageName(layerName);
@@ -220,6 +220,18 @@
timeRecords[0].frameTime.frameNumber, presentToPresentMs);
timeStatsLayer.deltas["present2present"].insert(presentToPresentMs);
}
+
+ // Output additional trace points to track frame time.
+ ATRACE_INT64(("TimeStats-Post - " + layerName).c_str(), timeRecords[0].frameTime.postTime);
+ ATRACE_INT64(("TimeStats-Acquire - " + layerName).c_str(),
+ timeRecords[0].frameTime.acquireTime);
+ ATRACE_INT64(("TimeStats-Latch - " + layerName).c_str(),
+ timeRecords[0].frameTime.latchTime);
+ ATRACE_INT64(("TimeStats-Desired - " + layerName).c_str(),
+ timeRecords[0].frameTime.desiredTime);
+ ATRACE_INT64(("TimeStats-Present - " + layerName).c_str(),
+ timeRecords[0].frameTime.presentTime);
+
prevTimeRecord = timeRecords[0];
timeRecords.pop_front();
layerRecord.waitData--;
diff --git a/services/vr/performanced/performance_service_tests.cpp b/services/vr/performanced/performance_service_tests.cpp
index 4065785..a24c889 100644
--- a/services/vr/performanced/performance_service_tests.cpp
+++ b/services/vr/performanced/performance_service_tests.cpp
@@ -12,16 +12,16 @@
#include <thread>
#include <utility>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <dvr/performance_client_api.h>
#include <gtest/gtest.h>
#include <private/android_filesystem_config.h>
#include "stdio_filebuf.h"
-#include "string_trim.h"
#include "unique_file.h"
-using android::dvr::Trim;
+using android::base::Trim;
using android::dvr::UniqueFile;
using android::dvr::stdio_filebuf;
diff --git a/services/vr/performanced/string_trim.h b/services/vr/performanced/string_trim.h
deleted file mode 100644
index 7094e9f..0000000
--- a/services/vr/performanced/string_trim.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
-#define ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
-
-#include <functional>
-#include <locale>
-#include <string>
-
-namespace android {
-namespace dvr {
-
-// Trims whitespace from the left side of |subject| and returns the result as a
-// new string.
-inline std::string LeftTrim(std::string subject) {
- subject.erase(subject.begin(),
- std::find_if(subject.begin(), subject.end(),
- std::not1(std::ptr_fun<int, int>(std::isspace))));
- return subject;
-}
-
-// Trims whitespace from the right side of |subject| and returns the result as a
-// new string.
-inline std::string RightTrim(std::string subject) {
- subject.erase(std::find_if(subject.rbegin(), subject.rend(),
- std::not1(std::ptr_fun<int, int>(std::isspace)))
- .base(),
- subject.end());
- return subject;
-}
-
-// Trims whitespace from the both sides of |subject| and returns the result as a
-// new string.
-inline std::string Trim(std::string subject) {
- subject.erase(subject.begin(),
- std::find_if(subject.begin(), subject.end(),
- std::not1(std::ptr_fun<int, int>(std::isspace))));
- subject.erase(std::find_if(subject.rbegin(), subject.rend(),
- std::not1(std::ptr_fun<int, int>(std::isspace)))
- .base(),
- subject.end());
- return subject;
-}
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_PERFORMANCED_STRING_TRIM_H_
diff --git a/services/vr/performanced/task.cpp b/services/vr/performanced/task.cpp
index bda1682..2fc96bf 100644
--- a/services/vr/performanced/task.cpp
+++ b/services/vr/performanced/task.cpp
@@ -10,10 +10,10 @@
#include <memory>
#include <sstream>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include "stdio_filebuf.h"
-#include "string_trim.h"
namespace {
@@ -102,7 +102,7 @@
// The status file has lines with the format <field>:<value>. Extract the
// value after the colon.
- return Trim(line.substr(offset + field.size() + 1));
+ return android::base::Trim(line.substr(offset + field.size() + 1));
}
}
@@ -123,7 +123,7 @@
}
std::string key = line.substr(0, offset);
- std::string value = Trim(line.substr(offset + 1));
+ std::string value = android::base::Trim(line.substr(offset + 1));
ALOGD_IF(TRACE, "Task::ReadStatusFields: key=\"%s\" value=\"%s\"",
key.c_str(), value.c_str());
@@ -156,7 +156,7 @@
std::string line = "";
std::getline(file_stream, line);
- return Trim(line);
+ return android::base::Trim(line);
} else {
return "";
}