Merge "media: Add level 6+ OMX enums for AVC/H.264"
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e0e211f..0f987c3 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -444,7 +444,7 @@
}
virtual bool updateInfo() {
- mInfo.token = mServerChannel->getToken();
+ mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
mInfo.name = mName;
mInfo.layoutParamsFlags = 0;
mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
@@ -474,8 +474,8 @@
}
void releaseChannel() {
+ mServerChannel.clear();
InputWindowHandle::releaseChannel();
- mDispatcher->unregisterInputChannel(mServerChannel);
}
protected:
virtual bool handled() {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 2a70293..f514fe3 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -152,6 +152,7 @@
"Scheduler/MessageQueue.cpp",
"Scheduler/Scheduler.cpp",
"Scheduler/SchedulerUtils.cpp",
+ "Scheduler/PhaseOffsets.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 9b2a6fc..075e238 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -757,18 +757,7 @@
const uint32_t hwcLatency = 0;
// Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
- const nsecs_t nextRefresh = computeNextRefresh(hwcLatency);
-
- // The DispSync time is already adjusted for the difference between
- // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
- // we don't need to factor that in here. Pad a little to avoid
- // weird effects if apps might be requesting times right on the edge.
- nsecs_t extraPadding = 0;
- if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
- extraPadding = 1000000; // 1ms (6% of 60Hz)
- }
-
- return nextRefresh + extraPadding;
+ return computeNextRefresh(hwcLatency);
}
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
new file mode 100644
index 0000000..a0a4455
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "PhaseOffsets.h"
+
+#include <cutils/properties.h>
+
+#include "SurfaceFlingerProperties.h"
+
+namespace android {
+using namespace android::sysprop;
+
+namespace scheduler {
+
+PhaseOffsets::~PhaseOffsets() = default;
+
+namespace impl {
+PhaseOffsets::PhaseOffsets() {
+ int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
+
+ int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.early_phase_offset_ns", value, "-1");
+ const int earlySfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
+ const int earlyGlSfOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
+ const int earlyAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
+ const int earlyGlAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1");
+ const int highFpsEarlySfOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1");
+ const int highFpsEarlyGlSfOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1");
+ const int highFpsEarlyAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1");
+ const int highFpsEarlyGlAppOffsetNs = atoi(value);
+
+ // TODO(b/122905996): Define these in device.mk.
+ property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000");
+ const int highFpsLateAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000");
+ const int highFpsLateSfOffsetNs = atoi(value);
+
+ mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
+ : sfVsyncPhaseOffsetNs,
+ earlyAppOffsetNs != -1 ? earlyAppOffsetNs
+ : vsyncPhaseOffsetNs};
+ mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs
+ : sfVsyncPhaseOffsetNs,
+ earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs
+ : vsyncPhaseOffsetNs};
+ mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
+
+ mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
+ : highFpsLateAppOffsetNs,
+ highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+ : highFpsLateSfOffsetNs};
+ mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+ : highFpsLateAppOffsetNs,
+ highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+ : highFpsLateSfOffsetNs};
+ mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs};
+}
+
+PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
+ switch (mRefreshRateType) {
+ case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
+ return mHighRefreshRateOffsets;
+ default:
+ return mDefaultRefreshRateOffsets;
+ }
+}
+
+void PhaseOffsets::dump(std::string& result) const {
+ const auto [early, earlyGl, late] = getCurrentOffsets();
+ base::StringAppendF(&result,
+ " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 " ns\n"
+ " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 " ns\n"
+ "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n",
+ late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf);
+}
+
+nsecs_t PhaseOffsets::getCurrentAppOffset() {
+ return getCurrentOffsets().late.app;
+}
+
+nsecs_t PhaseOffsets::getCurrentSfOffset() {
+ return getCurrentOffsets().late.sf;
+}
+
+} // namespace impl
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
new file mode 100644
index 0000000..cbcaade
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cinttypes>
+
+#include "RefreshRateConfigs.h"
+#include "VSyncModulator.h"
+
+namespace android {
+namespace scheduler {
+
+/*
+ * This class encapsulates offsets for different refresh rates. Depending
+ * on what refresh rate we are using, and wheter we are composing in GL,
+ * different offsets will help us with latency. This class keeps track of
+ * which mode the device is on, and returns approprate offsets when needed.
+ */
+class PhaseOffsets {
+public:
+ struct Offsets {
+ VSyncModulator::Offsets early;
+ VSyncModulator::Offsets earlyGl;
+ VSyncModulator::Offsets late;
+ };
+
+ virtual ~PhaseOffsets();
+
+ virtual nsecs_t getCurrentAppOffset() = 0;
+ virtual nsecs_t getCurrentSfOffset() = 0;
+ virtual Offsets getCurrentOffsets() const = 0;
+ virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
+ virtual void dump(std::string& result) const = 0;
+};
+
+namespace impl {
+class PhaseOffsets : public scheduler::PhaseOffsets {
+public:
+ PhaseOffsets();
+
+ nsecs_t getCurrentAppOffset() override;
+ nsecs_t getCurrentSfOffset() override;
+
+ // Returns early, early GL, and late offsets for Apps and SF.
+ Offsets getCurrentOffsets() const override;
+
+ // This function should be called when the device is switching between different
+ // refresh rates, to properly update the offsets.
+ void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override {
+ mRefreshRateType = refreshRateType;
+ }
+
+ // Returns current offsets in human friendly format.
+ void dump(std::string& result) const override;
+
+private:
+ Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
+ Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
+
+ std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
+ RefreshRateConfigs::RefreshRateType::DEFAULT;
+
+ Offsets mDefaultRefreshRateOffsets;
+ Offsets mHighRefreshRateOffsets;
+};
+} // namespace impl
+
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b003451..00820f1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -70,7 +70,7 @@
mEventControlThread = std::make_unique<impl::EventControlThread>(function);
char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.set_idle_timer_ms", value, "0");
+ property_get("debug.sf.set_idle_timer_ms", value, "30");
mSetIdleTimerMs = atoi(value);
if (mSetIdleTimerMs > 0) {
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dde0c57..d7ec733 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -18,9 +18,10 @@
#include <utils/Errors.h>
+#include <cinttypes>
#include <mutex>
-using namespace android::surfaceflinger;
+#include "Scheduler.h"
namespace android {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ee202a3..2cf2cd8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -211,8 +211,6 @@
constexpr float kSrgbWhiteZ = 1.0891f;
// ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
-int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
uint64_t SurfaceFlinger::maxVirtualDisplaySize;
@@ -273,6 +271,7 @@
mLayersRemoved(false),
mLayersAdded(false),
mBootTime(systemTime()),
+ mPhaseOffsets{getFactory().createPhaseOffsets()},
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
@@ -298,10 +297,6 @@
: SurfaceFlinger(factory, SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
- vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
-
- sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
-
hasSyncFramework = running_without_sync_framework(true);
dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);
@@ -400,29 +395,11 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- property_get("debug.sf.early_phase_offset_ns", value, "-1");
- const int earlySfOffsetNs = atoi(value);
-
- property_get("debug.sf.early_gl_phase_offset_ns", value, "-1");
- const int earlyGlSfOffsetNs = atoi(value);
-
- property_get("debug.sf.early_app_phase_offset_ns", value, "-1");
- const int earlyAppOffsetNs = atoi(value);
-
- property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1");
- const int earlyGlAppOffsetNs = atoi(value);
-
property_get("debug.sf.use_scheduler", value, "0");
mUseScheduler = atoi(value);
- const VSyncModulator::Offsets earlyOffsets =
- {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
- earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
- const VSyncModulator::Offsets earlyGlOffsets =
- {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
- earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
- mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
- {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
@@ -629,7 +606,7 @@
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
- ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
+ ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
Mutex::Autolock _l(mStateLock);
@@ -640,13 +617,17 @@
mScheduler = getFactory().createScheduler([this](bool enabled) {
setVsyncEnabled(EventThread::DisplayType::Primary, enabled);
});
+ // TODO(b/113612090): Currently we assume that if scheduler is turned on, then the refresh
+ // rate is 90. Once b/122905403 is completed, this should be updated accordingly.
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
mAppConnectionHandle =
- mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
+ mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
- mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
+ mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
@@ -657,14 +638,14 @@
} else {
mEventThreadSource =
std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
+ mPhaseOffsets->getCurrentAppOffset(), true, "app");
mEventThread =
std::make_unique<impl::EventThread>(mEventThreadSource.get(),
impl::EventThread::InterceptVSyncsCallback(),
"appEventThread");
mSfEventThreadSource =
std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+ mPhaseOffsets->getCurrentSfOffset(), true, "sf");
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
@@ -745,8 +726,20 @@
}
if (mUseScheduler) {
- mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); });
- mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); });
+ mScheduler->setExpiredIdleTimerCallback([this]() {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+ setRefreshRateTo(60.f /* fps */);
+ });
+ mScheduler->setResetIdleTimerCallback([this]() {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+ setRefreshRateTo(90.f /* fps */);
+ });
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(
getHwComposer().getConfigs(*display->getId()));
}
@@ -901,7 +894,7 @@
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = 1e9 / hwConfig->getVsyncPeriod();
- info.appVsyncOffset = vsyncPhaseOffsetNs;
+ info.appVsyncOffset = mPhaseOffsets->getCurrentAppOffset();
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -915,8 +908,8 @@
//
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
- info.presentationDeadline = hwConfig->getVsyncPeriod() -
- sfVsyncPhaseOffsetNs + 1000000;
+ info.presentationDeadline =
+ hwConfig->getVsyncPeriod() - mPhaseOffsets->getCurrentSfOffset() + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
@@ -1966,11 +1959,11 @@
nsecs_t compositeToPresentLatency) {
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0)
- ? (stats.vsyncPeriod - (sfVsyncPhaseOffsetNs % stats.vsyncPeriod))
- : ((-sfVsyncPhaseOffsetNs) % stats.vsyncPeriod);
+ nsecs_t idealLatency = (mPhaseOffsets->getCurrentSfOffset() > 0)
+ ? (stats.vsyncPeriod - (mPhaseOffsets->getCurrentSfOffset() % stats.vsyncPeriod))
+ : ((-mPhaseOffsets->getCurrentSfOffset()) % stats.vsyncPeriod);
- // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
+ // Just in case mPhaseOffsets->getCurrentSfOffset() == -vsyncInterval.
if (idealLatency <= 0) {
idealLatency = stats.vsyncPeriod;
}
@@ -1979,7 +1972,7 @@
// composition and present times, which often have >1ms of jitter.
// Reducing jitter is important if an app attempts to extrapolate
// something (such as user input) to an accurate diasplay time.
- // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+ // Snapping also allows an app to precisely calculate mPhaseOffsets->getCurrentSfOffset()
// with (presentLatency % interval).
nsecs_t bias = stats.vsyncPeriod / 2;
int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
@@ -4520,15 +4513,10 @@
}
void SurfaceFlinger::dumpVSync(std::string& result) const {
- const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
- const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+ mPhaseOffsets->dump(result);
StringAppendF(&result,
- " app phase: %9" PRId64 " ns\t SF phase: %9" PRId64 " ns\n"
- " early app phase: %9" PRId64 " ns\t early SF phase: %9" PRId64 " ns\n"
- "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n"
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, sfEarlyOffset,
- appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, getVsyncPeriod());
+ dispSyncPresentTimeOffset, getVsyncPeriod());
StringAppendF(&result, "Scheduler: %s\n\n", mUseScheduler ? "enabled" : "disabled");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index dfb01fb..a48e811 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -59,6 +59,7 @@
#include "Scheduler/DispSync.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
@@ -952,7 +953,10 @@
std::unique_ptr<EventControlThread> mEventControlThread;
std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
+ // Calculates correct offsets.
VSyncModulator mVsyncModulator;
+ // Keeps track of all available phase offsets for different refresh types.
+ std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
// Can only accessed from the main thread, these members
// don't need synchronization
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 77679e3..773a5d1 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -33,6 +33,7 @@
#include "Scheduler/DispSync.h"
#include "Scheduler/EventControlThread.h"
#include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
#include "Scheduler/Scheduler.h"
#include "TimeStats/TimeStats.h"
@@ -68,6 +69,10 @@
return std::make_unique<android::impl::MessageQueue>();
}
+ std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+ return std::make_unique<scheduler::impl::PhaseOffsets>();
+ }
+
std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) override {
return std::make_unique<Scheduler>(callback);
}
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index f747684..ac99e2a 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -52,6 +52,10 @@
namespace compositionengine {
class CompositionEngine;
} // namespace compositionengine
+
+namespace scheduler {
+class PhaseOffsets;
+} // namespace scheduler
namespace surfaceflinger {
class NativeWindowSurface;
@@ -66,6 +70,7 @@
std::function<void(bool)> setVSyncEnabled) = 0;
virtual std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) = 0;
virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
+ virtual std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() = 0;
virtual std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) = 0;
virtual std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) = 0;
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
new file mode 100644
index 0000000..0739f15
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "Scheduler/PhaseOffsets.h"
+
+namespace android {
+namespace scheduler {
+
+class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
+ nsecs_t FAKE_PHASE_OFFSET_NS = 0;
+
+public:
+ FakePhaseOffsets() = default;
+ ~FakePhaseOffsets() = default;
+
+ nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
+ nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
+
+ // Returns early, early GL, and late offsets for Apps and SF.
+ PhaseOffsets::Offsets getCurrentOffsets() const override {
+ return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
+ }
+
+ // This function should be called when the device is switching between different
+ // refresh rates, to properly update the offsets.
+ void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+
+ // Returns current offsets in human friendly format.
+ void dump(std::string& /*result*/) const override {}
+};
+
+} // namespace scheduler
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b9b0cf8..3a62c40 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -23,6 +23,7 @@
#include "ColorLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
+#include "FakePhaseOffsets.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
#include "StartPropertySetThread.h"
@@ -75,6 +76,10 @@
return std::make_unique<android::impl::MessageQueue>();
}
+ std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+ return std::make_unique<scheduler::FakePhaseOffsets>();
+ }
+
std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>) override {
// TODO: Use test-fixture controlled factory
return nullptr;