Merge "SF: call onFrameBegin before scheduling the next frame" into main
diff --git a/include/input/Input.h b/include/input/Input.h
index 19f4ab3..00757a7 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -26,6 +26,7 @@
#ifdef __linux__
#include <android/os/IInputConstants.h>
#endif
+#include <android/os/PointerIconType.h>
#include <math.h>
#include <stdint.h>
#include <ui/Transform.h>
@@ -1213,43 +1214,41 @@
*
* Due to backwards compatibility and public api constraints, this is a duplicate (but type safe)
* definition of PointerIcon.java.
- *
- * TODO(b/235023317) move this definition to an aidl and statically assign to the below java public
- * api values.
- *
- * WARNING: Keep these definitions in sync with
- * frameworks/base/core/java/android/view/PointerIcon.java
*/
enum class PointerIconStyle : int32_t {
- TYPE_CUSTOM = -1,
- TYPE_NULL = 0,
- TYPE_NOT_SPECIFIED = 1,
- TYPE_ARROW = 1000,
- TYPE_CONTEXT_MENU = 1001,
- TYPE_HAND = 1002,
- TYPE_HELP = 1003,
- TYPE_WAIT = 1004,
- TYPE_CELL = 1006,
- TYPE_CROSSHAIR = 1007,
- TYPE_TEXT = 1008,
- TYPE_VERTICAL_TEXT = 1009,
- TYPE_ALIAS = 1010,
- TYPE_COPY = 1011,
- TYPE_NO_DROP = 1012,
- TYPE_ALL_SCROLL = 1013,
- TYPE_HORIZONTAL_DOUBLE_ARROW = 1014,
- TYPE_VERTICAL_DOUBLE_ARROW = 1015,
- TYPE_TOP_RIGHT_DOUBLE_ARROW = 1016,
- TYPE_TOP_LEFT_DOUBLE_ARROW = 1017,
- TYPE_ZOOM_IN = 1018,
- TYPE_ZOOM_OUT = 1019,
- TYPE_GRAB = 1020,
- TYPE_GRABBING = 1021,
- TYPE_HANDWRITING = 1022,
+ TYPE_CUSTOM = static_cast<int32_t>(::android::os::PointerIconType::CUSTOM),
+ TYPE_NULL = static_cast<int32_t>(::android::os::PointerIconType::TYPE_NULL),
+ TYPE_NOT_SPECIFIED = static_cast<int32_t>(::android::os::PointerIconType::NOT_SPECIFIED),
+ TYPE_ARROW = static_cast<int32_t>(::android::os::PointerIconType::ARROW),
+ TYPE_CONTEXT_MENU = static_cast<int32_t>(::android::os::PointerIconType::CONTEXT_MENU),
+ TYPE_HAND = static_cast<int32_t>(::android::os::PointerIconType::HAND),
+ TYPE_HELP = static_cast<int32_t>(::android::os::PointerIconType::HELP),
+ TYPE_WAIT = static_cast<int32_t>(::android::os::PointerIconType::WAIT),
+ TYPE_CELL = static_cast<int32_t>(::android::os::PointerIconType::CELL),
+ TYPE_CROSSHAIR = static_cast<int32_t>(::android::os::PointerIconType::CROSSHAIR),
+ TYPE_TEXT = static_cast<int32_t>(::android::os::PointerIconType::TEXT),
+ TYPE_VERTICAL_TEXT = static_cast<int32_t>(::android::os::PointerIconType::VERTICAL_TEXT),
+ TYPE_ALIAS = static_cast<int32_t>(::android::os::PointerIconType::ALIAS),
+ TYPE_COPY = static_cast<int32_t>(::android::os::PointerIconType::COPY),
+ TYPE_NO_DROP = static_cast<int32_t>(::android::os::PointerIconType::NO_DROP),
+ TYPE_ALL_SCROLL = static_cast<int32_t>(::android::os::PointerIconType::ALL_SCROLL),
+ TYPE_HORIZONTAL_DOUBLE_ARROW =
+ static_cast<int32_t>(::android::os::PointerIconType::HORIZONTAL_DOUBLE_ARROW),
+ TYPE_VERTICAL_DOUBLE_ARROW =
+ static_cast<int32_t>(::android::os::PointerIconType::VERTICAL_DOUBLE_ARROW),
+ TYPE_TOP_RIGHT_DOUBLE_ARROW =
+ static_cast<int32_t>(::android::os::PointerIconType::TOP_RIGHT_DOUBLE_ARROW),
+ TYPE_TOP_LEFT_DOUBLE_ARROW =
+ static_cast<int32_t>(::android::os::PointerIconType::TOP_LEFT_DOUBLE_ARROW),
+ TYPE_ZOOM_IN = static_cast<int32_t>(::android::os::PointerIconType::ZOOM_IN),
+ TYPE_ZOOM_OUT = static_cast<int32_t>(::android::os::PointerIconType::ZOOM_OUT),
+ TYPE_GRAB = static_cast<int32_t>(::android::os::PointerIconType::GRAB),
+ TYPE_GRABBING = static_cast<int32_t>(::android::os::PointerIconType::GRABBING),
+ TYPE_HANDWRITING = static_cast<int32_t>(::android::os::PointerIconType::HANDWRITING),
- TYPE_SPOT_HOVER = 2000,
- TYPE_SPOT_TOUCH = 2001,
- TYPE_SPOT_ANCHOR = 2002,
+ TYPE_SPOT_HOVER = static_cast<int32_t>(::android::os::PointerIconType::SPOT_HOVER),
+ TYPE_SPOT_TOUCH = static_cast<int32_t>(::android::os::PointerIconType::SPOT_TOUCH),
+ TYPE_SPOT_ANCHOR = static_cast<int32_t>(::android::os::PointerIconType::SPOT_ANCHOR),
};
} // namespace android
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 3278c23..fed590c 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -30,6 +30,7 @@
"android/os/InputEventInjectionResult.aidl",
"android/os/InputEventInjectionSync.aidl",
"android/os/InputConfig.aidl",
+ "android/os/PointerIconType.aidl",
],
}
diff --git a/libs/input/MotionPredictor.cpp b/libs/input/MotionPredictor.cpp
index e836a4c..1df88dd 100644
--- a/libs/input/MotionPredictor.cpp
+++ b/libs/input/MotionPredictor.cpp
@@ -201,7 +201,7 @@
// device starts to speed up, but avoids producing noisy predictions as it slows down.
break;
}
- if (input_flags::enable_jerk_prediction_pruning()) {
+ if (input_flags::enable_prediction_pruning_via_jerk_thresholding()) {
// TODO(b/266747654): Stop predictions if confidence is < some threshold
// Arbitrarily high pruning index, will correct once jerk thresholding is implemented.
const size_t upperBoundPredictionIndex = std::numeric_limits<size_t>::max();
diff --git a/libs/input/android/os/PointerIconType.aidl b/libs/input/android/os/PointerIconType.aidl
new file mode 100644
index 0000000..f244c62
--- /dev/null
+++ b/libs/input/android/os/PointerIconType.aidl
@@ -0,0 +1,56 @@
+/**
+ * Copyright (c) 2024, 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.
+ */
+
+package android.os;
+
+/**
+ * Represents an icon that can be used as a mouse pointer.
+ * Please look at frameworks/base/core/java/android/view/PointerIcon.java for the detailed
+ * explanation of each constant.
+ * @hide
+ */
+@Backing(type="int")
+enum PointerIconType {
+ CUSTOM = -1,
+ TYPE_NULL = 0,
+ NOT_SPECIFIED = 1,
+ ARROW = 1000,
+ CONTEXT_MENU = 1001,
+ HAND = 1002,
+ HELP = 1003,
+ WAIT = 1004,
+ CELL = 1006,
+ CROSSHAIR = 1007,
+ TEXT = 1008,
+ VERTICAL_TEXT = 1009,
+ ALIAS = 1010,
+ COPY = 1011,
+ NO_DROP = 1012,
+ ALL_SCROLL = 1013,
+ HORIZONTAL_DOUBLE_ARROW = 1014,
+ VERTICAL_DOUBLE_ARROW = 1015,
+ TOP_RIGHT_DOUBLE_ARROW = 1016,
+ TOP_LEFT_DOUBLE_ARROW = 1017,
+ ZOOM_IN = 1018,
+ ZOOM_OUT = 1019,
+ GRAB = 1020,
+ GRABBING = 1021,
+ HANDWRITING = 1022,
+
+ SPOT_HOVER = 2000,
+ SPOT_TOUCH = 2001,
+ SPOT_ANCHOR = 2002,
+}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index c1f5e2a..e041c51 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -130,8 +130,10 @@
}
flag {
- name: "enable_jerk_prediction_pruning"
+ name: "enable_prediction_pruning_via_jerk_thresholding"
namespace: "input"
description: "Enable prediction pruning based on jerk thresholds."
bug: "266747654"
+ is_fixed_read_only: true
+
}
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.cpp b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
index e76a4c3..aa18713 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.cpp
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
@@ -23,6 +23,7 @@
#include <log/log_main.h>
#include <sync/sync.h>
+#include <utils/Trace.h>
namespace android::renderengine::skia {
@@ -33,6 +34,12 @@
info->unref();
}
+std::unique_ptr<SkiaGpuContext> GaneshVkRenderEngine::createContext(
+ VulkanInterface& vulkanInterface) {
+ return SkiaGpuContext::MakeVulkan_Ganesh(vulkanInterface.getGaneshBackendContext(),
+ mSkSLCacheMonitor);
+}
+
void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
if (fenceFd.get() < 0) return;
@@ -51,11 +58,18 @@
context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
}
-base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
+base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) {
sk_sp<GrDirectContext> grContext = context->grDirectContext();
+ {
+ ATRACE_NAME("flush surface");
+ // TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
+ // below.
+ context->grDirectContext()->flush(dstSurface.get());
+ }
+
VulkanInterface& vi = getVulkanInterface(isProtected());
VkSemaphore semaphore = vi.createExportableSemaphore();
-
GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
GrFlushInfo flushInfo;
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.h b/libs/renderengine/skia/GaneshVkRenderEngine.h
index 90e2487..5940d04 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.h
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.h
@@ -27,8 +27,9 @@
protected:
GaneshVkRenderEngine(const RenderEngineCreationArgs& args) : SkiaVkRenderEngine(args) {}
+ std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
- base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
+ base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
};
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index f10c98d..61369ae 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -337,8 +337,14 @@
}
}
-base::unique_fd SkiaGLRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
- base::unique_fd drawFence = flush();
+base::unique_fd SkiaGLRenderEngine::flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) {
+ sk_sp<GrDirectContext> grContext = context->grDirectContext();
+ {
+ ATRACE_NAME("flush surface");
+ grContext->flush(dstSurface.get());
+ }
+ base::unique_fd drawFence = flushGL();
bool requireSync = drawFence.get() < 0;
if (requireSync) {
@@ -346,8 +352,7 @@
} else {
ATRACE_BEGIN("Submit(sync=false)");
}
- bool success =
- context->grDirectContext()->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo);
+ bool success = grContext->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo);
ATRACE_END();
if (!success) {
ALOGE("Failed to flush RenderEngine commands");
@@ -394,7 +399,7 @@
return true;
}
-base::unique_fd SkiaGLRenderEngine::flush() {
+base::unique_fd SkiaGLRenderEngine::flushGL() {
ATRACE_CALL();
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 2e22478..bd177e6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -63,7 +63,7 @@
bool supportsProtectedContentImpl() const override;
bool useProtectedContextImpl(GrProtected isProtected) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
- base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
+ base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
void appendBackendSpecificInfoToDump(std::string& result) override;
private:
@@ -71,7 +71,7 @@
EGLSurface placeholder, EGLContext protectedContext,
EGLSurface protectedPlaceholder);
bool waitGpuFence(base::borrowed_fd fenceFd);
- base::unique_fd flush();
+ base::unique_fd flushGL();
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext,
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index c12c119..2484650 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -90,7 +90,7 @@
// Debugging settings
static const bool kPrintLayerSettings = false;
-static const bool kFlushAfterEveryLayer = kPrintLayerSettings;
+static const bool kGaneshFlushAfterEveryLayer = kPrintLayerSettings;
static constexpr bool kEnableLayerBrightening = true;
} // namespace
@@ -665,8 +665,8 @@
validateOutputBufferUsage(buffer->getBuffer());
auto context = getActiveContext();
- LOG_ALWAYS_FATAL_IF(context->isAbandoned(), "Context is abandoned/device lost at start of %s",
- __func__);
+ LOG_ALWAYS_FATAL_IF(context->isAbandonedOrDeviceLost(),
+ "Context is abandoned/device lost at start of %s", __func__);
// any AutoBackendTexture deletions will now be deferred until cleanupPostRender is called
DeferTextureCleanup dtc(mTextureCleanupMgr);
@@ -1122,21 +1122,21 @@
} else {
canvas->drawRect(bounds.rect(), paint);
}
- if (kFlushAfterEveryLayer) {
+ if (kGaneshFlushAfterEveryLayer) {
ATRACE_NAME("flush surface");
+ // No-op in Graphite. If "flushing" Skia's drawing commands after each layer is desired
+ // in Graphite, then a graphite::Recording would need to be snapped and tracked for each
+ // layer, which is likely possible but adds non-trivial complexity (in both bookkeeping
+ // and refactoring).
skgpu::ganesh::Flush(activeSurface);
}
}
surfaceAutoSaveRestore.restore();
mCapture->endCapture();
- {
- ATRACE_NAME("flush surface");
- LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
- skgpu::ganesh::Flush(activeSurface);
- }
- auto drawFence = sp<Fence>::make(flushAndSubmit(context));
+ LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
+ auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface));
if (ATRACE_ENABLED()) {
static gui::FenceMonitor sMonitor("RE Completion");
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index a39adbe..d7b4910 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -89,7 +89,8 @@
virtual bool supportsProtectedContentImpl() const = 0;
virtual bool useProtectedContextImpl(GrProtected isProtected) = 0;
virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) = 0;
- virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) = 0;
+ virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) = 0;
virtual void appendBackendSpecificInfoToDump(std::string& result) = 0;
size_t getMaxTextureSize() const override final;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 473fa0a..3715859 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -112,12 +112,9 @@
sSetupVulkanInterface();
SkiaRenderEngine::Contexts contexts;
- contexts.first = SkiaGpuContext::MakeVulkan_Ganesh(sVulkanInterface.getGaneshBackendContext(),
- mSkSLCacheMonitor);
+ contexts.first = createContext(sVulkanInterface);
if (supportsProtectedContentImpl()) {
- contexts.second = SkiaGpuContext::MakeVulkan_Ganesh(sProtectedContentVulkanInterface
- .getGaneshBackendContext(),
- mSkSLCacheMonitor);
+ contexts.second = createContext(sProtectedContentVulkanInterface);
}
return contexts;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h
index 5fd911f..371b812 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.h
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.h
@@ -71,9 +71,11 @@
};
protected:
+ virtual std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) = 0;
// Redeclare parent functions that Ganesh vs. Graphite subclasses must implement.
virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override = 0;
- virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) override = 0;
+ virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) override = 0;
SkiaVkRenderEngine(const RenderEngineCreationArgs& args);
diff --git a/libs/renderengine/skia/compat/GaneshGpuContext.cpp b/libs/renderengine/skia/compat/GaneshGpuContext.cpp
index 87f00e4..e3fec19 100644
--- a/libs/renderengine/skia/compat/GaneshGpuContext.cpp
+++ b/libs/renderengine/skia/compat/GaneshGpuContext.cpp
@@ -93,7 +93,7 @@
return mGrContext->maxTextureSize();
};
-bool GaneshGpuContext::isAbandoned() {
+bool GaneshGpuContext::isAbandonedOrDeviceLost() {
return mGrContext->abandoned();
}
diff --git a/libs/renderengine/skia/compat/GaneshGpuContext.h b/libs/renderengine/skia/compat/GaneshGpuContext.h
index ec0162d..d815d15 100644
--- a/libs/renderengine/skia/compat/GaneshGpuContext.h
+++ b/libs/renderengine/skia/compat/GaneshGpuContext.h
@@ -36,7 +36,7 @@
size_t getMaxRenderTargetSize() const override;
size_t getMaxTextureSize() const override;
- bool isAbandoned() override;
+ bool isAbandonedOrDeviceLost() override;
void setResourceCacheLimit(size_t maxResourceBytes) override;
void finishRenderingAndAbandonContext() override;
diff --git a/libs/renderengine/skia/compat/SkiaGpuContext.h b/libs/renderengine/skia/compat/SkiaGpuContext.h
index ddf1642..8222e62 100644
--- a/libs/renderengine/skia/compat/SkiaGpuContext.h
+++ b/libs/renderengine/skia/compat/SkiaGpuContext.h
@@ -68,7 +68,7 @@
*/
virtual sk_sp<SkSurface> createRenderTarget(SkImageInfo imageInfo) = 0;
- virtual bool isAbandoned() = 0;
+ virtual bool isAbandonedOrDeviceLost() = 0;
virtual size_t getMaxRenderTargetSize() const = 0;
virtual size_t getMaxTextureSize() const = 0;
virtual void setResourceCacheLimit(size_t maxResourceBytes) = 0;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 2df86a0..e331e8d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -7157,4 +7157,11 @@
return false;
}
+void InputDispatcher::setInputMethodConnectionIsActive(bool isActive) {
+ std::scoped_lock _l(mLock);
+ if (mTracer) {
+ mTracer->setInputMethodConnectionIsActive(isActive);
+ }
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index edca63e..3579a67 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -158,6 +158,8 @@
bool isPointerInWindow(const sp<IBinder>& token, int32_t displayId, DeviceId deviceId,
int32_t pointerId) override;
+ void setInputMethodConnectionIsActive(bool isActive) override;
+
private:
enum class DropReason {
NOT_DROPPED,
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 7c440e8..6b9262c 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -236,6 +236,11 @@
*/
virtual bool isPointerInWindow(const sp<IBinder>& token, int32_t displayId, DeviceId deviceId,
int32_t pointerId) = 0;
+
+ /*
+ * Notify the dispatcher that the state of the input method connection changed.
+ */
+ virtual void setInputMethodConnectionIsActive(bool isActive) = 0;
};
} // namespace android
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.cpp b/services/inputflinger/dispatcher/trace/InputTracer.cpp
index 55ed5c6..1d4d11c 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracer.cpp
@@ -61,10 +61,10 @@
e.downTime, e.flags, e.repeatCount, type};
}
-void writeEventToBackend(const TracedEvent& event, const TracedEventArgs args,
+void writeEventToBackend(const TracedEvent& event, const TracedEventMetadata metadata,
InputTracingBackendInterface& backend) {
- std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e, args); },
- [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e, args); }},
+ std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e, metadata); },
+ [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e, metadata); }},
event);
}
@@ -126,22 +126,21 @@
const InputTargetInfo& targetInfo = getTargetInfo(target);
if (eventState->isEventProcessingComplete) {
// Disallow adding new targets after eventProcessingComplete() is called.
- if (eventState->targets.find(targetInfo.uid) == eventState->targets.end()) {
+ if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
LOG(FATAL) << __func__ << ": Cannot add new target after eventProcessingComplete";
}
return;
}
if (isDerivedCookie(cookie)) {
// Disallow adding new targets from a derived cookie.
- if (eventState->targets.find(targetInfo.uid) == eventState->targets.end()) {
+ if (eventState->metadata.targets.count(targetInfo.uid) == 0) {
LOG(FATAL) << __func__ << ": Cannot add new target from a derived cookie";
}
return;
}
- eventState->targets.emplace(targetInfo.uid);
- eventState->isSecure |= targetInfo.isSecureWindow;
- // TODO(b/210460522): Set events as sensitive when the IME connection is active.
+ eventState->metadata.targets.emplace(targetInfo.uid);
+ eventState->metadata.isSecure |= targetInfo.isSecureWindow;
}
void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
@@ -177,9 +176,7 @@
// is dispatched, such as in the case of key fallback events. To account for these cases,
// derived events can be traced after the processing is complete for the original event.
const auto& event = eventState->events.back();
- const TracedEventArgs traceArgs{.isSecure = eventState->isSecure,
- .targets = eventState->targets};
- writeEventToBackend(event, std::move(traceArgs), *mBackend);
+ writeEventToBackend(event, eventState->metadata, *mBackend);
}
return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
}
@@ -206,7 +203,7 @@
<< ": Failed to find a previously traced event that matches the dispatched event";
}
- if (eventState->targets.count(dispatchEntry.targetUid) == 0) {
+ if (eventState->metadata.targets.count(dispatchEntry.targetUid) == 0) {
LOG(FATAL) << __func__ << ": Event is being dispatched to UID that it is not targeting";
}
@@ -226,9 +223,7 @@
/*hmac=*/{},
resolvedKeyRepeatCount};
if (eventState->isEventProcessingComplete) {
- const TracedEventArgs traceArgs{.isSecure = eventState->isSecure,
- .targets = eventState->targets};
- mBackend->traceWindowDispatch(std::move(windowDispatchArgs), std::move(traceArgs));
+ mBackend->traceWindowDispatch(std::move(windowDispatchArgs), eventState->metadata);
} else {
eventState->pendingDispatchArgs.emplace_back(std::move(windowDispatchArgs));
}
@@ -246,10 +241,11 @@
// --- InputTracer::EventState ---
void InputTracer::EventState::onEventProcessingComplete() {
+ metadata.isImeConnectionActive = tracer.mIsImeConnectionActive;
+
// Write all of the events known so far to the trace.
for (const auto& event : events) {
- const TracedEventArgs traceArgs{.isSecure = isSecure, .targets = targets};
- writeEventToBackend(event, traceArgs, *tracer.mBackend);
+ writeEventToBackend(event, metadata, *tracer.mBackend);
}
// Write all pending dispatch args to the trace.
for (const auto& windowDispatchArgs : pendingDispatchArgs) {
@@ -263,8 +259,7 @@
<< ": Failed to find a previously traced event that matches the dispatched "
"event";
}
- const TracedEventArgs traceArgs{.isSecure = isSecure, .targets = targets};
- tracer.mBackend->traceWindowDispatch(windowDispatchArgs, std::move(traceArgs));
+ tracer.mBackend->traceWindowDispatch(windowDispatchArgs, metadata);
}
pendingDispatchArgs.clear();
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.h b/services/inputflinger/dispatcher/trace/InputTracer.h
index 717bc1f..ab175be 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.h
+++ b/services/inputflinger/dispatcher/trace/InputTracer.h
@@ -48,9 +48,13 @@
std::unique_ptr<EventTrackerInterface> traceDerivedEvent(const EventEntry&,
const EventTrackerInterface&) override;
void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface&) override;
+ void setInputMethodConnectionIsActive(bool isActive) override {
+ mIsImeConnectionActive = isActive;
+ }
private:
std::unique_ptr<InputTracingBackendInterface> mBackend;
+ bool mIsImeConnectionActive{false};
// The state of a tracked event, shared across all events derived from the original event.
struct EventState {
@@ -64,10 +68,8 @@
bool isEventProcessingComplete{false};
// A queue to hold dispatch args from being traced until event processing is complete.
std::vector<const WindowDispatchArgs> pendingDispatchArgs;
- // True if the event is targeting at least one secure window;
- bool isSecure{false};
- // The list of all possible UIDs that this event could be targeting.
- std::set<gui::Uid> targets;
+ // The metadata should not be modified after event processing is complete.
+ TracedEventMetadata metadata{};
};
// Get the event state associated with a tracking cookie.
diff --git a/services/inputflinger/dispatcher/trace/InputTracerInterface.h b/services/inputflinger/dispatcher/trace/InputTracerInterface.h
index 609d10c..af6eefb 100644
--- a/services/inputflinger/dispatcher/trace/InputTracerInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracerInterface.h
@@ -103,6 +103,11 @@
* provided.
*/
virtual void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface&) = 0;
+
+ /**
+ * Notify that the state of the input method connection changed.
+ */
+ virtual void setInputMethodConnectionIsActive(bool isActive) = 0;
};
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
index 3ff7fab..2b45e3a 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h
@@ -92,11 +92,13 @@
using TracedEvent = std::variant<TracedKeyEvent, TracedMotionEvent>;
/** Additional information about an input event being traced. */
-struct TracedEventArgs {
+struct TracedEventMetadata {
// True if the event is targeting at least one secure window.
bool isSecure;
// The list of possible UIDs that this event could be targeting.
std::set<gui::Uid> targets;
+ // True if the there was an active input method connection while this event was processed.
+ bool isImeConnectionActive;
};
/** Additional information about an input event being dispatched to a window. */
@@ -121,13 +123,13 @@
virtual ~InputTracingBackendInterface() = default;
/** Trace a KeyEvent. */
- virtual void traceKeyEvent(const TracedKeyEvent&, const TracedEventArgs&) = 0;
+ virtual void traceKeyEvent(const TracedKeyEvent&, const TracedEventMetadata&) = 0;
/** Trace a MotionEvent. */
- virtual void traceMotionEvent(const TracedMotionEvent&, const TracedEventArgs&) = 0;
+ virtual void traceMotionEvent(const TracedMotionEvent&, const TracedEventMetadata&) = 0;
/** Trace an event being sent to a window. */
- virtual void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventArgs&) = 0;
+ virtual void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventMetadata&) = 0;
};
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index b76bec3..9c39743 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -98,10 +98,10 @@
}
TraceLevel PerfettoBackend::InputEventDataSource::resolveTraceLevel(
- const TracedEventArgs& args) const {
+ const TracedEventMetadata& metadata) const {
// Check for matches with the rules in the order that they are defined.
for (const auto& rule : mConfig.rules) {
- if (ruleMatches(rule, args)) {
+ if (ruleMatches(rule, metadata)) {
return rule.level;
}
}
@@ -110,17 +110,23 @@
}
bool PerfettoBackend::InputEventDataSource::ruleMatches(const TraceRule& rule,
- const TracedEventArgs& args) const {
+ const TracedEventMetadata& metadata) const {
// By default, a rule will match all events. Return early if the rule does not match.
// Match the event if it is directed to a secure window.
- if (rule.matchSecure.has_value() && *rule.matchSecure != args.isSecure) {
+ if (rule.matchSecure.has_value() && *rule.matchSecure != metadata.isSecure) {
+ return false;
+ }
+
+ // Match the event if it was processed while there was an active InputMethod connection.
+ if (rule.matchImeConnectionActive.has_value() &&
+ *rule.matchImeConnectionActive != metadata.isImeConnectionActive) {
return false;
}
// Match the event if all of its target packages are explicitly allowed in the "match all" list.
if (!rule.matchAllPackages.empty() &&
- !std::all_of(args.targets.begin(), args.targets.end(), [&](const auto& uid) {
+ !std::all_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
return isPermanentlyAllowed(uid) ||
std::any_of(rule.matchAllPackages.begin(), rule.matchAllPackages.end(),
[&](const auto& pkg) { return uid == mUidMap->at(pkg); });
@@ -130,7 +136,7 @@
// Match the event if any of its target packages are allowed in the "match any" list.
if (!rule.matchAnyPackages.empty() &&
- !std::any_of(args.targets.begin(), args.targets.end(), [&](const auto& uid) {
+ !std::any_of(metadata.targets.begin(), metadata.targets.end(), [&](const auto& uid) {
return std::any_of(rule.matchAnyPackages.begin(), rule.matchAnyPackages.end(),
[&](const auto& pkg) { return uid == mUidMap->at(pkg); });
})) {
@@ -166,14 +172,14 @@
}
void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
- const TracedEventArgs& args) {
+ const TracedEventMetadata& metadata) {
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
dataSource->initializeUidMap(mGetPackageUid);
if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
return;
}
- const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
return;
}
@@ -186,14 +192,15 @@
});
}
-void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, const TracedEventArgs& args) {
+void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event,
+ const TracedEventMetadata& metadata) {
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
dataSource->initializeUidMap(mGetPackageUid);
if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
return;
}
- const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
return;
}
@@ -207,14 +214,14 @@
}
void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
- const TracedEventArgs& args) {
+ const TracedEventMetadata& metadata) {
InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
auto dataSource = ctx.GetDataSourceLocked();
dataSource->initializeUidMap(mGetPackageUid);
if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
return;
}
- const TraceLevel traceLevel = dataSource->resolveTraceLevel(args);
+ const TraceLevel traceLevel = dataSource->resolveTraceLevel(metadata);
if (traceLevel == TraceLevel::TRACE_LEVEL_NONE) {
return;
}
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
index af1c6b7..e945066 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.h
@@ -54,9 +54,9 @@
explicit PerfettoBackend(GetPackageUid);
~PerfettoBackend() override = default;
- void traceKeyEvent(const TracedKeyEvent&, const TracedEventArgs&) override;
- void traceMotionEvent(const TracedMotionEvent&, const TracedEventArgs&) override;
- void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventArgs&) override;
+ void traceKeyEvent(const TracedKeyEvent&, const TracedEventMetadata&) override;
+ void traceMotionEvent(const TracedMotionEvent&, const TracedEventMetadata&) override;
+ void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventMetadata&) override;
private:
// Implementation of the perfetto data source.
@@ -72,13 +72,13 @@
void initializeUidMap(GetPackageUid);
bool shouldIgnoreTracedInputEvent(const EventType&) const;
inline ftl::Flags<TraceFlag> getFlags() const { return mConfig.flags; }
- TraceLevel resolveTraceLevel(const TracedEventArgs&) const;
+ TraceLevel resolveTraceLevel(const TracedEventMetadata&) const;
private:
const int32_t mInstanceId;
TraceConfig mConfig;
- bool ruleMatches(const TraceRule&, const TracedEventArgs&) const;
+ bool ruleMatches(const TraceRule&, const TracedEventMetadata&) const;
std::optional<std::map<std::string, gui::Uid>> mUidMap;
};
diff --git a/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp b/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
index 1614789..77d09cb 100644
--- a/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/ThreadedBackend.cpp
@@ -54,25 +54,25 @@
template <typename Backend>
void ThreadedBackend<Backend>::traceMotionEvent(const TracedMotionEvent& event,
- const TracedEventArgs& traceArgs) {
+ const TracedEventMetadata& metadata) {
std::scoped_lock lock(mLock);
- mQueue.emplace_back(event, traceArgs);
+ mQueue.emplace_back(event, metadata);
mThreadWakeCondition.notify_all();
}
template <typename Backend>
void ThreadedBackend<Backend>::traceKeyEvent(const TracedKeyEvent& event,
- const TracedEventArgs& traceArgs) {
+ const TracedEventMetadata& metadata) {
std::scoped_lock lock(mLock);
- mQueue.emplace_back(event, traceArgs);
+ mQueue.emplace_back(event, metadata);
mThreadWakeCondition.notify_all();
}
template <typename Backend>
void ThreadedBackend<Backend>::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs,
- const TracedEventArgs& traceArgs) {
+ const TracedEventMetadata& metadata) {
std::scoped_lock lock(mLock);
- mQueue.emplace_back(dispatchArgs, traceArgs);
+ mQueue.emplace_back(dispatchArgs, metadata);
mThreadWakeCondition.notify_all();
}
diff --git a/services/inputflinger/dispatcher/trace/ThreadedBackend.h b/services/inputflinger/dispatcher/trace/ThreadedBackend.h
index 3bfc72b..650a87e 100644
--- a/services/inputflinger/dispatcher/trace/ThreadedBackend.h
+++ b/services/inputflinger/dispatcher/trace/ThreadedBackend.h
@@ -38,9 +38,9 @@
ThreadedBackend(Backend&& innerBackend);
~ThreadedBackend() override;
- void traceKeyEvent(const TracedKeyEvent&, const TracedEventArgs&) override;
- void traceMotionEvent(const TracedMotionEvent&, const TracedEventArgs&) override;
- void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventArgs&) override;
+ void traceKeyEvent(const TracedKeyEvent&, const TracedEventMetadata&) override;
+ void traceMotionEvent(const TracedMotionEvent&, const TracedEventMetadata&) override;
+ void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventMetadata&) override;
private:
std::mutex mLock;
@@ -49,7 +49,7 @@
Backend mBackend;
using TraceEntry =
std::pair<std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>,
- TracedEventArgs>;
+ TracedEventMetadata>;
std::vector<TraceEntry> mQueue GUARDED_BY(mLock);
// InputThread stops when its destructor is called. Initialize it last so that it is the
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4d8ffb6..782c84a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -507,10 +507,7 @@
}
// Touchscreens and touchpad devices.
- static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
- sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);
- if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
- classes.test(InputDeviceClass::TOUCH_MT)) {
+ if (classes.test(InputDeviceClass::TOUCHPAD) && classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(createInputMapper<MultiTouchInputMapper>(contextPtr, readerConfig));
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.cpp b/services/inputflinger/tests/FakeInputTracingBackend.cpp
index 069b50d..b46055e 100644
--- a/services/inputflinger/tests/FakeInputTracingBackend.cpp
+++ b/services/inputflinger/tests/FakeInputTracingBackend.cpp
@@ -162,7 +162,7 @@
// --- FakeInputTracingBackend ---
void FakeInputTracingBackend::traceKeyEvent(const trace::TracedKeyEvent& event,
- const trace::TracedEventArgs&) {
+ const trace::TracedEventMetadata&) {
{
std::scoped_lock lock(mTrace->mLock);
mTrace->mTracedEvents.emplace(event.id, event);
@@ -171,7 +171,7 @@
}
void FakeInputTracingBackend::traceMotionEvent(const trace::TracedMotionEvent& event,
- const trace::TracedEventArgs&) {
+ const trace::TracedEventMetadata&) {
{
std::scoped_lock lock(mTrace->mLock);
mTrace->mTracedEvents.emplace(event.id, event);
@@ -180,7 +180,7 @@
}
void FakeInputTracingBackend::traceWindowDispatch(const trace::WindowDispatchArgs& args,
- const trace::TracedEventArgs&) {
+ const trace::TracedEventMetadata&) {
{
std::scoped_lock lock(mTrace->mLock);
mTrace->mTracedWindowDispatches.push_back(args);
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.h b/services/inputflinger/tests/FakeInputTracingBackend.h
index ab05d6b..cd4b507 100644
--- a/services/inputflinger/tests/FakeInputTracingBackend.h
+++ b/services/inputflinger/tests/FakeInputTracingBackend.h
@@ -82,11 +82,12 @@
private:
std::shared_ptr<VerifyingTrace> mTrace;
- void traceKeyEvent(const trace::TracedKeyEvent& entry, const trace::TracedEventArgs&) override;
+ void traceKeyEvent(const trace::TracedKeyEvent& entry,
+ const trace::TracedEventMetadata&) override;
void traceMotionEvent(const trace::TracedMotionEvent& entry,
- const trace::TracedEventArgs&) override;
+ const trace::TracedEventMetadata&) override;
void traceWindowDispatch(const trace::WindowDispatchArgs& entry,
- const trace::TracedEventArgs&) override;
+ const trace::TracedEventMetadata&) override;
};
} // namespace android::inputdispatcher
diff --git a/services/surfaceflinger/LayerFE.cpp b/services/surfaceflinger/LayerFE.cpp
index 620edca..c2251a8 100644
--- a/services/surfaceflinger/LayerFE.cpp
+++ b/services/surfaceflinger/LayerFE.cpp
@@ -27,6 +27,7 @@
#include "LayerFE.h"
#include "SurfaceFlinger.h"
+#include "common/FlagManager.h"
#include "ui/FenceResult.h"
#include "ui/LayerStack.h"
@@ -80,6 +81,16 @@
LayerFE::LayerFE(const std::string& name) : mName(name) {}
+LayerFE::~LayerFE() {
+ // Ensures that no promise is left unfulfilled before the LayerFE is destroyed.
+ // An unfulfilled promise could occur when a screenshot is attempted, but the
+ // render area is invalid and there is no memory for the capture result.
+ if (FlagManager::getInstance().ce_fence_promise() &&
+ mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
+ setReleaseFence(Fence::NO_FENCE);
+ }
+}
+
const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
return mSnapshot.get();
}
diff --git a/services/surfaceflinger/LayerFE.h b/services/surfaceflinger/LayerFE.h
index 019fa22..658f949 100644
--- a/services/surfaceflinger/LayerFE.h
+++ b/services/surfaceflinger/LayerFE.h
@@ -36,6 +36,7 @@
class LayerFE : public virtual RefBase, public virtual compositionengine::LayerFE {
public:
LayerFE(const std::string& name);
+ virtual ~LayerFE();
// compositionengine::LayerFE overrides
const compositionengine::LayerFECompositionState* getCompositionState() const override;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 005ec05..c83d81f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -663,7 +663,13 @@
void Scheduler::recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime,
nsecs_t now, LayerHistory::LayerUpdateType updateType) {
- if (pacesetterSelectorPtr()->canSwitch()) {
+ const auto& selectorPtr = pacesetterSelectorPtr();
+ // Skip recording layer history on LayerUpdateType::SetFrameRate for MRR devices when the
+ // dVRR vote types are guarded (disabled) for MRR. This is to avoid activity when setting dVRR
+ // vote types.
+ if (selectorPtr->canSwitch() &&
+ (updateType != LayerHistory::LayerUpdateType::SetFrameRate ||
+ layerProps.setFrameRateVote.isVoteValidForMrr(selectorPtr->isVrrDevice()))) {
mLayerHistory.record(id, layerProps, presentTime, now, updateType);
}
}
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index b3c1f6b..0b47924 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -427,6 +427,7 @@
mRateMap[idealPeriod()] = {idealPeriod(), 0};
}
+ mTimelines.clear();
clearTimestamps();
}
@@ -553,10 +554,23 @@
mLastTimestampIndex = 0;
}
- mTimelines.clear();
- mLastCommittedVsync = TimePoint::fromNs(0);
mIdealPeriod = Period::fromNs(idealPeriod());
- mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt);
+ if (mTimelines.empty()) {
+ mLastCommittedVsync = TimePoint::fromNs(0);
+ mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt);
+ } else {
+ while (mTimelines.size() > 1) {
+ mTimelines.pop_front();
+ }
+ mTimelines.front().setRenderRate(mRenderRateOpt);
+ // set mLastCommittedVsync to a valid vsync but don't commit too much in the future
+ const auto vsyncOpt = mTimelines.front().nextAnticipatedVSyncTimeFrom(
+ getVSyncPredictionModelLocked(),
+ /* minFramePeriodOpt */ std::nullopt,
+ snapToVsync(mClock->now()), MissedVsync{},
+ /* lastVsyncOpt */ std::nullopt);
+ mLastCommittedVsync = *vsyncOpt;
+ }
}
bool VSyncPredictor::needsMoreSamples() const {
@@ -588,6 +602,7 @@
if (mRenderRateOpt &&
mLastCommittedVsync.ns() + mRenderRateOpt->getPeriodNsecs() * kEnoughFramesToBreakPhase <
mClock->now()) {
+ ATRACE_FORMAT_INSTANT("kEnoughFramesToBreakPhase");
mTimelines.clear();
mLastCommittedVsync = TimePoint::fromNs(0);
mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, mRenderRateOpt);
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 3ed1d41..a661292 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -83,7 +83,7 @@
};
struct MissedVsync {
- TimePoint vsync;
+ TimePoint vsync = TimePoint::fromNs(0);
Duration fixup = Duration::fromNs(0);
};
@@ -97,7 +97,7 @@
std::optional<TimePoint> validUntil() const { return mValidUntil; }
bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate);
void shiftVsyncSequence(Duration phase);
- void setRenderRate(Fps renderRate) { mRenderRateOpt = renderRate; }
+ void setRenderRate(std::optional<Fps> renderRateOpt) { mRenderRateOpt = renderRateOpt; }
private:
nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync);
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 0a5cde3..a8fd6b7 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -19,7 +19,7 @@
metadata {
purpose: PURPOSE_BUGFIX
}
-}
+ } # ce_fence_promise
flag {
name: "dont_skip_on_early_ro2"