summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Williams <pdwilliams@google.com>2023-04-03 15:27:38 -0500
committerPatrick Williams <pdwilliams@google.com>2023-04-04 18:26:48 -0500
commit243e2e9af82700c76f743ee71e0f27fe1a3f4383 (patch)
tree0835d4558401c9cad5592620dc7121ff9f80d289
parentb218143d95d241509954a82050c747ee18bdffc8 (diff)
downloadnative-243e2e9af82700c76f743ee71e0f27fe1a3f4383.tar.gz
DO NOT MERGE: Force input window updates when layer visibility changes
This should fix a latency regression introduced by delaying input window visibility changes. See ag/22210759. Bug: 270894765 Bug: 275562923 Test: v2/android-crystalball-eng/health/microbench/instr_metric/input_method Change-Id: I0f64fa148eb4b02600eac9578d3d23ac00c78fa3
-rw-r--r--services/surfaceflinger/Layer.cpp11
-rw-r--r--services/surfaceflinger/Layer.h15
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp19
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h5
4 files changed, 38 insertions, 12 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index aff94d132e..4593b40b7d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2391,16 +2391,7 @@ WindowInfo Layer::fillInputInfo(const InputDisplayArgs& displayArgs) {
info.inputConfig |= WindowInfo::InputConfig::NOT_TOUCHABLE;
}
- // For compatibility reasons we let layers which can receive input
- // receive input before they have actually submitted a buffer. Because
- // of this we use canReceiveInput instead of isVisible to check the
- // policy-visibility, ignoring the buffer state. However for layers with
- // hasInputInfo()==false we can use the real visibility state.
- // We are just using these layers for occlusion detection in
- // InputDispatcher, and obviously if they aren't visible they can't occlude
- // anything.
- const bool visible = hasInputInfo() ? canReceiveInput() : isVisible();
- info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !visible);
+ info.setInputConfig(WindowInfo::InputConfig::NOT_VISIBLE, !isVisibleForInput());
info.alpha = getAlpha();
fillTouchOcclusionMode(info);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 200baf0ba1..1724c150ad 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -471,6 +471,21 @@ public:
virtual bool canReceiveInput() const;
/*
+ * Whether or not the layer should be considered visible for input calculations.
+ */
+ virtual bool isVisibleForInput() const {
+ // For compatibility reasons we let layers which can receive input
+ // receive input before they have actually submitted a buffer. Because
+ // of this we use canReceiveInput instead of isVisible to check the
+ // policy-visibility, ignoring the buffer state. However for layers with
+ // hasInputInfo()==false we can use the real visibility state.
+ // We are just using these layers for occlusion detection in
+ // InputDispatcher, and obviously if they aren't visible they can't occlude
+ // anything.
+ return hasInputInfo() ? canReceiveInput() : isVisible();
+ }
+
+ /*
* isProtected - true if the layer may contain protected contents in the
* GRALLOC_USAGE_PROTECTED sense.
*/
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5db79999c8..1dfb1d3e9b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3249,19 +3249,34 @@ void SurfaceFlinger::updateInputFlinger() {
if (!updateWindowInfo && mInputWindowCommands.empty()) {
return;
}
+
+ std::unordered_set<Layer*> visibleLayers;
+ mDrawingState.traverse([&visibleLayers](Layer* layer) {
+ if (layer->isVisibleForInput()) {
+ visibleLayers.insert(layer);
+ }
+ });
+ bool visibleLayersChanged = false;
+ if (visibleLayers != mVisibleLayers) {
+ visibleLayersChanged = true;
+ mVisibleLayers = std::move(visibleLayers);
+ }
+
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
inputWindowCommands =
std::move(mInputWindowCommands),
- inputFlinger = mInputFlinger, this]() {
+ inputFlinger = mInputFlinger, this,
+ visibleLayersChanged]() {
ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
mWindowInfosListenerInvoker
->windowInfosChanged(std::move(windowInfos), std::move(displayInfos),
/* shouldSync= */ inputWindowCommands.syncInputWindows,
/* forceImmediateCall= */
- !inputWindowCommands.focusRequests.empty());
+ visibleLayersChanged ||
+ !inputWindowCommands.focusRequests.empty());
} else if (inputWindowCommands.syncInputWindows) {
// If the caller requested to sync input windows, but there are no
// changes to input windows, notify immediately.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3a45229ed3..a78144dea2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1449,6 +1449,11 @@ private:
nsecs_t mAnimationTransactionTimeout = s2ns(5);
friend class SurfaceComposerAIDL;
+
+ // Layers visible during the last commit. This set should only be used for testing set equality
+ // and membership. The pointers should not be dereferenced as it's possible the set contains
+ // pointers to freed layers.
+ std::unordered_set<Layer*> mVisibleLayers;
};
class SurfaceComposerAIDL : public gui::BnSurfaceComposer {