Merge "Vulkan: clean up android::Vector in the loader"
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 2e2cc18..e8f513a 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -64,7 +64,8 @@
// system/apex/apexd/apexd_main.cpp.
//
// Only scan the APEX directory under /system (within the chroot dir).
- apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
+ // Cast call to void to suppress warn_unused_result.
+ static_cast<void>(apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir));
return apex::getActivePackages();
}
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 40f6b43..8e762f1 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -46,6 +46,7 @@
static const char* hal_interfaces_to_dump[] {
"android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
+ "android.hardware.biometrics.face@1.0::IBiometricsFace",
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
"android.hardware.drm@1.0::IDrmFactory",
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 9c311a3..b9a4749 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -1132,9 +1132,6 @@
case NATIVE_WINDOW_CONSUMER_IS_PROTECTED:
value = static_cast<int32_t>(mCore->mConsumerIsProtected);
break;
- case NATIVE_WINDOW_MAX_BUFFER_COUNT:
- value = static_cast<int32_t>(mCore->mMaxBufferCount);
- break;
default:
return BAD_VALUE;
}
@@ -1199,6 +1196,7 @@
static_cast<uint32_t>(mCore->mQueue.size());
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
+ output->maxBufferCount = mCore->mMaxBufferCount;
if (listener != nullptr) {
// Set up a death notification so that we can disconnect
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0e03b7d..9db0a7c 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -1141,12 +1141,8 @@
// ----------------------------------------------------------------------------
constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
- return sizeof(width) +
- sizeof(height) +
- sizeof(transformHint) +
- sizeof(numPendingBuffers) +
- sizeof(nextFrameNumber) +
- sizeof(bufferReplaced);
+ return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) +
+ sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount);
}
size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
@@ -1170,6 +1166,7 @@
FlattenableUtils::write(buffer, size, numPendingBuffers);
FlattenableUtils::write(buffer, size, nextFrameNumber);
FlattenableUtils::write(buffer, size, bufferReplaced);
+ FlattenableUtils::write(buffer, size, maxBufferCount);
return frameTimestamps.flatten(buffer, size, fds, count);
}
@@ -1187,6 +1184,7 @@
FlattenableUtils::read(buffer, size, numPendingBuffers);
FlattenableUtils::read(buffer, size, nextFrameNumber);
FlattenableUtils::read(buffer, size, bufferReplaced);
+ FlattenableUtils::read(buffer, size, maxBufferCount);
return frameTimestamps.unflatten(buffer, size, fds, count);
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e6eb327..2e8a5d0 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -96,6 +96,7 @@
mConnectedToCpu = false;
mProducerControlledByApp = controlledByApp;
mSwapIntervalZero = false;
+ mMaxBufferCount = 0;
}
Surface::~Surface() {
@@ -961,6 +962,10 @@
*value = static_cast<int>(mDataSpace);
return NO_ERROR;
}
+ case NATIVE_WINDOW_MAX_BUFFER_COUNT: {
+ *value = mMaxBufferCount;
+ return NO_ERROR;
+ }
}
}
return mGraphicBufferProducer->query(what, value);
@@ -1298,6 +1303,7 @@
mDefaultWidth = output.width;
mDefaultHeight = output.height;
mNextFrameNumber = output.nextFrameNumber;
+ mMaxBufferCount = output.maxBufferCount;
// Ignore transform hint if sticky transform is set or transform to display inverse flag is
// set. Transform hint should be ignored if the client is expected to always submit buffers
diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h
index 3dde8c8..6e002dd 100644
--- a/libs/gui/include/gui/IGraphicBufferProducer.h
+++ b/libs/gui/include/gui/IGraphicBufferProducer.h
@@ -412,6 +412,7 @@
uint64_t nextFrameNumber{0};
FrameEventHistoryDelta frameTimestamps;
bool bufferReplaced{false};
+ int maxBufferCount{0};
};
virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 0c471bb..80469df 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -465,6 +465,7 @@
bool mReportRemovedBuffers = false;
std::vector<sp<GraphicBuffer>> mRemovedBuffers;
+ int mMaxBufferCount;
};
} // namespace android
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 119e888..98dc1e6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -169,6 +169,18 @@
ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
}
+TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) {
+ createBufferQueue();
+ sp<DummyConsumer> dc(new DummyConsumer);
+ mConsumer->consumerConnect(dc, false);
+ int bufferCount = 50;
+ mConsumer->setMaxBufferCount(bufferCount);
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output);
+ ASSERT_EQ(output.maxBufferCount, bufferCount);
+}
+
TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
createBufferQueue();
sp<DummyConsumer> dc(new DummyConsumer);
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 9aa4e85..5b298b4 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -153,9 +153,10 @@
"Scheduler/LayerHistory.cpp",
"Scheduler/LayerInfo.cpp",
"Scheduler/MessageQueue.cpp",
+ "Scheduler/PhaseOffsets.cpp",
"Scheduler/Scheduler.cpp",
"Scheduler/SchedulerUtils.cpp",
- "Scheduler/PhaseOffsets.cpp",
+ "Scheduler/VSyncModulator.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 66906e9..72bbf5d 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -258,7 +258,7 @@
namespace {
// Using Rec. 709 primaries
-float getLuma(float r, float g, float b) {
+inline float getLuma(float r, float g, float b) {
constexpr auto rec709_red_primary = 0.2126f;
constexpr auto rec709_green_primary = 0.7152f;
constexpr auto rec709_blue_primary = 0.0722f;
@@ -293,10 +293,10 @@
const uint32_t* rowBase = data + row * stride;
for (int32_t column = area.left; column < area.right; ++column) {
uint32_t pixel = rowBase[column];
- const float r = (pixel & 0xFF) / 255.0f;
- const float g = ((pixel >> 8) & 0xFF) / 255.0f;
- const float b = ((pixel >> 16) & 0xFF) / 255.0f;
- const uint8_t luma = std::round(getLuma(r, g, b) * 255.0f);
+ const float r = pixel & 0xFF;
+ const float g = (pixel >> 8) & 0xFF;
+ const float b = (pixel >> 16) & 0xFF;
+ const uint8_t luma = std::round(getLuma(r, g, b));
++brightnessBuckets[luma];
if (brightnessBuckets[luma] > majoritySampleNum) return luma / 255.0f;
}
@@ -342,9 +342,19 @@
}
const auto device = mFlinger.getDefaultDisplayDevice();
- const auto display = device->getCompositionDisplay();
- const auto state = display->getState();
- const auto orientation = static_cast<ui::Transform::orientation_flags>(state.orientation);
+ const auto orientation = [](uint32_t orientation) {
+ switch (orientation) {
+ default:
+ case DisplayState::eOrientationDefault:
+ return ui::Transform::ROT_0;
+ case DisplayState::eOrientation90:
+ return ui::Transform::ROT_90;
+ case DisplayState::eOrientation180:
+ return ui::Transform::ROT_180;
+ case DisplayState::eOrientation270:
+ return ui::Transform::ROT_270;
+ }
+ }(device->getOrientation());
std::vector<RegionSamplingThread::Descriptor> descriptors;
Region sampleRegion;
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 81be372..83fd42b 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -92,8 +92,12 @@
mPeriod = period;
if (!mModelLocked && referenceTimeChanged) {
for (auto& eventListener : mEventListeners) {
- eventListener.mLastEventTime =
- mReferenceTime - mPeriod + mPhase + eventListener.mPhase;
+ eventListener.mLastEventTime = mReferenceTime + mPhase + eventListener.mPhase;
+ // If mLastEventTime is after mReferenceTime (can happen when positive phase offsets
+ // are used) we treat it as like it happened in previous period.
+ if (eventListener.mLastEventTime > mReferenceTime) {
+ eventListener.mLastEventTime -= mPeriod;
+ }
}
}
if (mTraceDetailedInfo) {
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 265b8aa..026b557 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -34,6 +34,8 @@
mTraceVsync(traceVsync),
mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
mVsyncEventLabel(base::StringPrintf("VSYNC-%s", name)),
+ mVsyncOffsetLabel(base::StringPrintf("VsyncOffset-%s", name)),
+ mVsyncNegativeOffsetLabel(base::StringPrintf("VsyncNegativeOffset-%s", name)),
mDispSync(dispSync),
mPhaseOffset(phaseOffset),
mOffsetThresholdForNextVsync(offsetThresholdForNextVsync) {}
@@ -41,6 +43,7 @@
void DispSyncSource::setVSyncEnabled(bool enable) {
std::lock_guard lock(mVsyncMutex);
if (enable) {
+ tracePhaseOffset();
status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
static_cast<DispSync::Callback*>(this),
mLastCallbackTime);
@@ -76,6 +79,7 @@
const int numPeriods = phaseOffset / period;
phaseOffset -= numPeriods * period;
mPhaseOffset = phaseOffset;
+ tracePhaseOffset();
// If we're not enabled, we don't need to mess with the listeners
if (!mEnabled) {
@@ -94,11 +98,11 @@
{
std::lock_guard lock(mCallbackMutex);
callback = mCallback;
+ }
- if (mTraceVsync) {
- mValue = (mValue + 1) % 2;
- ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
- }
+ if (mTraceVsync) {
+ mValue = (mValue + 1) % 2;
+ ATRACE_INT(mVsyncEventLabel.c_str(), mValue);
}
if (callback != nullptr) {
@@ -106,4 +110,14 @@
}
}
-} // namespace android
\ No newline at end of file
+void DispSyncSource::tracePhaseOffset() {
+ if (mPhaseOffset > 0) {
+ ATRACE_INT(mVsyncOffsetLabel.c_str(), mPhaseOffset);
+ ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), 0);
+ } else {
+ ATRACE_INT(mVsyncOffsetLabel.c_str(), 0);
+ ATRACE_INT(mVsyncNegativeOffsetLabel.c_str(), -mPhaseOffset);
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index b6785c5..50560a5 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -39,12 +39,16 @@
// The following method is the implementation of the DispSync::Callback.
virtual void onDispSyncEvent(nsecs_t when);
+ void tracePhaseOffset() REQUIRES(mVsyncMutex);
+
const char* const mName;
int mValue = 0;
const bool mTraceVsync;
const std::string mVsyncOnLabel;
const std::string mVsyncEventLabel;
+ const std::string mVsyncOffsetLabel;
+ const std::string mVsyncNegativeOffsetLabel;
nsecs_t mLastCallbackTime GUARDED_BY(mVsyncMutex) = 0;
DispSync* mDispSync;
@@ -58,4 +62,4 @@
bool mEnabled GUARDED_BY(mVsyncMutex) = false;
};
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index 276bce1..8a2604f 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -25,6 +25,7 @@
namespace scheduler {
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
PhaseOffsets::~PhaseOffsets() = default;
namespace impl {
@@ -72,25 +73,32 @@
property_get("debug.sf.phase_offset_threshold_for_next_vsync_ns", value, "-1");
const int phaseOffsetThresholdForNextVsyncNs = 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};
+ Offsets defaultOffsets;
+ Offsets highFpsOffsets;
+ defaultOffsets.early = {RefreshRateType::DEFAULT,
+ earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
+ defaultOffsets.earlyGl = {RefreshRateType::DEFAULT,
+ earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
+ earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
+ defaultOffsets.late = {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs};
- mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
- : highFpsLateSfOffsetNs,
- highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
- : highFpsLateAppOffsetNs};
- mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
- : highFpsLateSfOffsetNs,
- highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
- : highFpsLateAppOffsetNs};
- mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
+ highFpsOffsets.early = {RefreshRateType::PERFORMANCE,
+ highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs
+ : highFpsLateSfOffsetNs,
+ highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+ : highFpsLateAppOffsetNs};
+ highFpsOffsets.earlyGl = {RefreshRateType::PERFORMANCE,
+ highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+ : highFpsLateSfOffsetNs,
+ highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+ : highFpsLateAppOffsetNs};
+ highFpsOffsets.late = {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs,
+ highFpsLateAppOffsetNs};
+
+ mOffsets.insert({RefreshRateType::POWER_SAVING, defaultOffsets});
+ mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets});
+ mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets});
mOffsetThresholdForNextVsync = phaseOffsetThresholdForNextVsyncNs != -1
? phaseOffsetThresholdForNextVsyncNs
@@ -99,12 +107,7 @@
PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(
android::scheduler::RefreshRateConfigs::RefreshRateType refreshRateType) const {
- switch (refreshRateType) {
- case RefreshRateConfigs::RefreshRateType::PERFORMANCE:
- return mHighRefreshRateOffsets;
- default:
- return mDefaultRefreshRateOffsets;
- }
+ return mOffsets.at(refreshRateType);
}
void PhaseOffsets::dump(std::string& result) const {
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index dc71e6e..2b5c2f1 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -17,6 +17,7 @@
#pragma once
#include <cinttypes>
+#include <unordered_map>
#include "RefreshRateConfigs.h"
#include "VSyncModulator.h"
@@ -79,14 +80,10 @@
void dump(std::string& result) const override;
private:
- Offsets getDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
- Offsets getHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
-
std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
RefreshRateConfigs::RefreshRateType::DEFAULT;
- Offsets mDefaultRefreshRateOffsets;
- Offsets mHighRefreshRateOffsets;
+ std::unordered_map<RefreshRateConfigs::RefreshRateType, Offsets> mOffsets;
nsecs_t mOffsetThresholdForNextVsync;
};
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
new file mode 100644
index 0000000..d452c19
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "VSyncModulator.h"
+
+#include <cutils/properties.h>
+#include <utils/Trace.h>
+
+#include <cinttypes>
+#include <mutex>
+
+namespace android {
+
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+VSyncModulator::VSyncModulator() {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.vsync_trace_detailed_info", value, "0");
+ mTraceDetailedInfo = atoi(value);
+ // Populate the offset map with some default offsets.
+ const Offsets defaultOffsets = {RefreshRateType::DEFAULT, 0, 0};
+ setPhaseOffsets(defaultOffsets, defaultOffsets, defaultOffsets, 0);
+}
+
+void VSyncModulator::setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
+ nsecs_t thresholdForNextVsync) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mOffsetMap.insert_or_assign(OffsetType::Early, early);
+ mOffsetMap.insert_or_assign(OffsetType::EarlyGl, earlyGl);
+ mOffsetMap.insert_or_assign(OffsetType::Late, late);
+ mThresholdForNextVsync = thresholdForNextVsync;
+ updateOffsetsLocked();
+}
+
+void VSyncModulator::setTransactionStart(Scheduler::TransactionStart transactionStart) {
+ if (transactionStart == Scheduler::TransactionStart::EARLY) {
+ mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
+ }
+
+ // An early transaction stays an early transaction.
+ if (transactionStart == mTransactionStart ||
+ mTransactionStart == Scheduler::TransactionStart::EARLY) {
+ return;
+ }
+ mTransactionStart = transactionStart;
+ updateOffsets();
+}
+
+void VSyncModulator::onTransactionHandled() {
+ if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
+ mTransactionStart = Scheduler::TransactionStart::NORMAL;
+ updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeInitiated() {
+ if (mRefreshRateChangePending) {
+ return;
+ }
+ mRefreshRateChangePending = true;
+ updateOffsets();
+}
+
+void VSyncModulator::onRefreshRateChangeCompleted() {
+ if (!mRefreshRateChangePending) {
+ return;
+ }
+ mRefreshRateChangePending = false;
+ updateOffsets();
+}
+
+void VSyncModulator::onRefreshed(bool usedRenderEngine) {
+ bool updateOffsetsNeeded = false;
+ if (mRemainingEarlyFrameCount > 0) {
+ mRemainingEarlyFrameCount--;
+ updateOffsetsNeeded = true;
+ }
+ if (usedRenderEngine) {
+ mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
+ updateOffsetsNeeded = true;
+ } else if (mRemainingRenderEngineUsageCount > 0) {
+ mRemainingRenderEngineUsageCount--;
+ updateOffsetsNeeded = true;
+ }
+ if (updateOffsetsNeeded) {
+ updateOffsets();
+ }
+}
+
+VSyncModulator::Offsets VSyncModulator::getOffsets() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mOffsets;
+}
+
+VSyncModulator::Offsets VSyncModulator::getNextOffsets() {
+ return mOffsetMap.at(getNextOffsetType());
+}
+
+VSyncModulator::OffsetType VSyncModulator::getNextOffsetType() {
+ // Early offsets are used if we're in the middle of a refresh rate
+ // change, or if we recently begin a transaction.
+ if (mTransactionStart == Scheduler::TransactionStart::EARLY || mRemainingEarlyFrameCount > 0 ||
+ mRefreshRateChangePending) {
+ return OffsetType::Early;
+ } else if (mRemainingRenderEngineUsageCount > 0) {
+ return OffsetType::EarlyGl;
+ } else {
+ return OffsetType::Late;
+ }
+}
+
+void VSyncModulator::updateOffsets() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ updateOffsetsLocked();
+}
+
+void VSyncModulator::updateOffsetsLocked() {
+ const Offsets desired = getNextOffsets();
+ const Offsets current = mOffsets;
+
+ bool changed = false;
+ if (desired.sf != current.sf) {
+ if (mSfConnectionHandle != nullptr) {
+ mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
+ } else if (mSfEventThread != nullptr) {
+ mSfEventThread->setPhaseOffset(desired.sf);
+ }
+ changed = true;
+ }
+ if (desired.app != current.app) {
+ if (mAppConnectionHandle != nullptr) {
+ mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
+ } else if (mAppEventThread != nullptr) {
+ mAppEventThread->setPhaseOffset(desired.app);
+ }
+ changed = true;
+ }
+
+ if (changed) {
+ flushOffsets();
+ }
+}
+
+void VSyncModulator::flushOffsets() {
+ OffsetType type = getNextOffsetType();
+ mOffsets = mOffsetMap.at(type);
+ if (!mTraceDetailedInfo) {
+ return;
+ }
+ ATRACE_INT("Vsync-EarlyOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Early);
+ ATRACE_INT("Vsync-EarlyGLOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::EarlyGl);
+ ATRACE_INT("Vsync-LateOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::DEFAULT && type == OffsetType::Late);
+ ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Early);
+ ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::EarlyGl);
+ ATRACE_INT("Vsync-HighFpsLateOffsetsOn",
+ mOffsets.fpsMode == RefreshRateType::PERFORMANCE && type == OffsetType::Late);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index 73a1fb9..10cf8e6 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -16,8 +16,6 @@
#pragma once
-#include <utils/Errors.h>
-
#include <cinttypes>
#include <mutex>
@@ -41,11 +39,22 @@
const int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2;
public:
+ VSyncModulator();
+
+ // Wrapper for a collection of surfaceflinger/app offsets for a particular
+ // configuration .
struct Offsets {
+ scheduler::RefreshRateConfigs::RefreshRateType fpsMode;
nsecs_t sf;
nsecs_t app;
};
+ enum class OffsetType {
+ Early,
+ EarlyGl,
+ Late,
+ };
+
// Sets the phase offsets
//
// sfEarly: The phase offset when waking up SF early, which happens when marking a transaction
@@ -57,32 +66,15 @@
// appEarlyGl: Like sfEarlyGl, but for the app-vsync.
// appLate: The regular app vsync phase offset.
void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late,
- nsecs_t thresholdForNextVsync) {
- mEarlyOffsets = early;
- mEarlyGlOffsets = earlyGl;
- mLateOffsets = late;
- mThresholdForNextVsync = thresholdForNextVsync;
+ nsecs_t thresholdForNextVsync) EXCLUDES(mMutex);
- if (mSfConnectionHandle && late.sf != mOffsets.load().sf) {
- mScheduler->setPhaseOffset(mSfConnectionHandle, late.sf);
- }
-
- if (mAppConnectionHandle && late.app != mOffsets.load().app) {
- mScheduler->setPhaseOffset(mAppConnectionHandle, late.app);
- }
-
- mOffsets = late;
- }
-
- Offsets getEarlyOffsets() const { return mEarlyOffsets; }
-
- Offsets getEarlyGlOffsets() const { return mEarlyGlOffsets; }
-
+ // Sets handles to the SF and app event threads.
void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) {
mSfEventThread = sfEventThread;
mAppEventThread = appEventThread;
}
+ // Sets the scheduler and vsync connection handlers.
void setSchedulerAndHandles(Scheduler* scheduler,
Scheduler::ConnectionHandle* appConnectionHandle,
Scheduler::ConnectionHandle* sfConnectionHandle) {
@@ -91,109 +83,42 @@
mSfConnectionHandle = sfConnectionHandle;
}
- void setTransactionStart(Scheduler::TransactionStart transactionStart) {
- if (transactionStart == Scheduler::TransactionStart::EARLY) {
- mRemainingEarlyFrameCount = MIN_EARLY_FRAME_COUNT_TRANSACTION;
- }
+ // Signals that a transaction has started, and changes offsets accordingly.
+ void setTransactionStart(Scheduler::TransactionStart transactionStart);
- // An early transaction stays an early transaction.
- if (transactionStart == mTransactionStart ||
- mTransactionStart == Scheduler::TransactionStart::EARLY) {
- return;
- }
- mTransactionStart = transactionStart;
- updateOffsets();
- }
-
- void onTransactionHandled() {
- if (mTransactionStart == Scheduler::TransactionStart::NORMAL) return;
- mTransactionStart = Scheduler::TransactionStart::NORMAL;
- updateOffsets();
- }
+ // Signals that a transaction has been completed, so that we can finish
+ // special handling for a transaction.
+ void onTransactionHandled();
// Called when we send a refresh rate change to hardware composer, so that
// we can move into early offsets.
- void onRefreshRateChangeInitiated() {
- if (mRefreshRateChangePending) {
- return;
- }
- mRefreshRateChangePending = true;
- updateOffsets();
- }
+ void onRefreshRateChangeInitiated();
// Called when we detect from vsync signals that the refresh rate changed.
// This way we can move out of early offsets if no longer necessary.
- void onRefreshRateChangeCompleted() {
- if (!mRefreshRateChangePending) {
- return;
- }
- mRefreshRateChangePending = false;
- updateOffsets();
- }
+ void onRefreshRateChangeCompleted();
- void onRefreshed(bool usedRenderEngine) {
- bool updateOffsetsNeeded = false;
- if (mRemainingEarlyFrameCount > 0) {
- mRemainingEarlyFrameCount--;
- updateOffsetsNeeded = true;
- }
- if (usedRenderEngine) {
- mRemainingRenderEngineUsageCount = MIN_EARLY_GL_FRAME_COUNT_TRANSACTION;
- updateOffsetsNeeded = true;
- } else if (mRemainingRenderEngineUsageCount > 0) {
- mRemainingRenderEngineUsageCount--;
- updateOffsetsNeeded = true;
- }
+ // Called when the display is presenting a new frame. usedRenderEngine
+ // should be set to true if RenderEngine was involved with composing the new
+ // frame.
+ void onRefreshed(bool usedRenderEngine);
- if (updateOffsetsNeeded) {
- updateOffsets();
- }
- }
-
- Offsets getOffsets() {
- // Early offsets are used if we're in the middle of a refresh rate
- // change, or if we recently begin a transaction.
- if (mTransactionStart == Scheduler::TransactionStart::EARLY ||
- mRemainingEarlyFrameCount > 0 || mRefreshRateChangePending) {
- return mEarlyOffsets;
- } else if (mRemainingRenderEngineUsageCount > 0) {
- return mEarlyGlOffsets;
- } else {
- return mLateOffsets;
- }
- }
+ // Returns the offsets that we are currently using
+ Offsets getOffsets() EXCLUDES(mMutex);
private:
- void updateOffsets() {
- const Offsets desired = getOffsets();
- const Offsets current = mOffsets;
+ // Returns the next offsets that we should be using
+ Offsets getNextOffsets() REQUIRES(mMutex);
+ // Returns the next offset type that we should use.
+ OffsetType getNextOffsetType();
+ // Updates offsets and persists them into the scheduler framework.
+ void updateOffsets() EXCLUDES(mMutex);
+ void updateOffsetsLocked() REQUIRES(mMutex);
+ // Updates the internal offsets and offset type.
+ void flushOffsets() REQUIRES(mMutex);
- bool changed = false;
- if (desired.sf != current.sf) {
- if (mSfConnectionHandle != nullptr) {
- mScheduler->setPhaseOffset(mSfConnectionHandle, desired.sf);
- } else {
- mSfEventThread->setPhaseOffset(desired.sf);
- }
- changed = true;
- }
- if (desired.app != current.app) {
- if (mAppConnectionHandle != nullptr) {
- mScheduler->setPhaseOffset(mAppConnectionHandle, desired.app);
- } else {
- mAppEventThread->setPhaseOffset(desired.app);
- }
- changed = true;
- }
-
- if (changed) {
- mOffsets = desired;
- }
- }
-
- Offsets mLateOffsets;
- Offsets mEarlyOffsets;
- Offsets mEarlyGlOffsets;
+ mutable std::mutex mMutex;
+ std::unordered_map<OffsetType, Offsets> mOffsetMap GUARDED_BY(mMutex);
nsecs_t mThresholdForNextVsync;
EventThread* mSfEventThread = nullptr;
@@ -203,13 +128,15 @@
Scheduler::ConnectionHandle* mAppConnectionHandle = nullptr;
Scheduler::ConnectionHandle* mSfConnectionHandle = nullptr;
- std::atomic<Offsets> mOffsets;
+ Offsets mOffsets GUARDED_BY(mMutex) = {Scheduler::RefreshRateType::DEFAULT, 0, 0};
std::atomic<Scheduler::TransactionStart> mTransactionStart =
Scheduler::TransactionStart::NORMAL;
std::atomic<bool> mRefreshRateChangePending = false;
std::atomic<int> mRemainingEarlyFrameCount = 0;
std::atomic<int> mRemainingRenderEngineUsageCount = 0;
+
+ bool mTraceDetailedInfo = false;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b9d3dd2..0e60b6d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5667,6 +5667,11 @@
captureOrientation = fromSurfaceComposerRotation(
static_cast<ISurfaceComposer::Rotation>(display->getOrientation()));
+ if (captureOrientation == ui::Transform::orientation_flags::ROT_90) {
+ captureOrientation = ui::Transform::orientation_flags::ROT_270;
+ } else if (captureOrientation == ui::Transform::orientation_flags::ROT_270) {
+ captureOrientation = ui::Transform::orientation_flags::ROT_90;
+ }
*outDataspace =
pickDataspaceFromColorMode(display->getCompositionDisplay()->getState().colorMode);
}
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index cb368b0..d03cb7b 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -43,7 +43,7 @@
type: "nano",
},
srcs: ["*.proto"],
- no_framework_libs: true,
+ sdk_version: "core_platform",
target: {
android: {
jarjar_rules: "jarjar-rules.txt",
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index decabd5..a8ec764 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -36,7 +36,7 @@
prop {
api_name: "vsync_event_phase_offset_ns"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns"
}
@@ -44,7 +44,7 @@
prop {
api_name: "vsync_sf_event_phase_offset_ns"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns"
}
@@ -53,7 +53,7 @@
prop {
api_name: "use_context_priority"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.use_context_priority"
}
@@ -62,7 +62,7 @@
prop {
api_name: "max_frame_buffer_acquired_buffers"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers"
}
@@ -80,7 +80,7 @@
prop {
api_name: "has_wide_color_display"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.has_wide_color_display"
}
@@ -90,7 +90,7 @@
prop {
api_name: "running_without_sync_framework"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.running_without_sync_framework"
}
@@ -108,7 +108,7 @@
prop {
api_name: "has_HDR_display"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.has_HDR_display"
}
@@ -117,7 +117,7 @@
prop {
api_name: "present_time_offset_from_vsync_ns"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns"
}
@@ -129,7 +129,7 @@
prop {
api_name: "force_hwc_copy_for_virtual_displays"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays"
}
@@ -139,7 +139,7 @@
prop {
api_name: "max_virtual_display_dimension"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.max_virtual_display_dimension"
}
@@ -151,7 +151,7 @@
prop {
api_name: "use_vr_flinger"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.use_vr_flinger"
}
@@ -161,7 +161,7 @@
prop {
api_name: "start_graphics_allocator_service"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.start_graphics_allocator_service"
}
@@ -171,7 +171,7 @@
api_name: "primary_display_orientation"
type: Enum
enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270"
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.primary_display_orientation"
}
@@ -182,7 +182,7 @@
prop {
api_name: "use_color_management"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.use_color_management"
}
@@ -209,7 +209,7 @@
prop {
api_name: "default_composition_dataspace"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.default_composition_dataspace"
}
@@ -220,7 +220,7 @@
prop {
api_name: "default_composition_pixel_format"
type: Integer
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.default_composition_pixel_format"
}
@@ -235,7 +235,7 @@
prop {
api_name: "wcg_composition_dataspace"
type: Long
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.wcg_composition_dataspace"
}
@@ -246,7 +246,7 @@
prop {
api_name: "wcg_composition_pixel_format"
type: Integer
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.wcg_composition_pixel_format"
}
@@ -258,7 +258,7 @@
prop {
api_name: "display_primary_red"
type: DoubleList
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.display_primary_red"
}
@@ -266,7 +266,7 @@
prop {
api_name: "display_primary_green"
type: DoubleList
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.display_primary_green"
}
@@ -274,7 +274,7 @@
prop {
api_name: "display_primary_blue"
type: DoubleList
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.display_primary_blue"
}
@@ -282,7 +282,7 @@
prop {
api_name: "display_primary_white"
type: DoubleList
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.display_primary_white"
}
@@ -293,7 +293,7 @@
prop {
api_name: "set_idle_timer_ms"
type: Integer
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.set_idle_timer_ms"
}
@@ -304,7 +304,7 @@
prop {
api_name: "set_touch_timer_ms"
type: Integer
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.set_touch_timer_ms"
}
@@ -314,7 +314,7 @@
prop {
api_name: "use_smart_90_for_video"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.use_smart_90_for_video"
}
@@ -322,7 +322,7 @@
prop {
api_name: "enable_protected_contents"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.protected_contents"
}
@@ -332,7 +332,7 @@
prop {
api_name: "support_kernel_idle_timer"
type: Boolean
- scope: System
+ scope: Public
access: Readonly
prop_name: "ro.surface_flinger.support_kernel_idle_timer"
}
diff --git a/services/surfaceflinger/test.png b/services/surfaceflinger/test.png
new file mode 100644
index 0000000..773dcc3
--- /dev/null
+++ b/services/surfaceflinger/test.png
Binary files differ
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index 96121bb..1d75011 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -23,6 +23,8 @@
namespace android {
namespace scheduler {
+using RefreshRateType = RefreshRateConfigs::RefreshRateType;
+
class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
nsecs_t FAKE_PHASE_OFFSET_NS = 0;
@@ -34,20 +36,20 @@
nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
PhaseOffsets::Offsets getOffsetsForRefreshRate(
- RefreshRateConfigs::RefreshRateType /*refreshRateType*/) const override {
+ RefreshRateType /*refreshRateType*/) const override {
return getCurrentOffsets();
}
// 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}};
+ return Offsets{{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {RefreshRateType::DEFAULT, 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 {}
+ void setRefreshRateType(RefreshRateType /*refreshRateType*/) override {}
nsecs_t getOffsetThresholdForNextVsync() const override { return FAKE_PHASE_OFFSET_NS; }
@@ -56,4 +58,4 @@
};
} // namespace scheduler
-} // namespace android
\ No newline at end of file
+} // namespace android