Merge "SF: Enforce thread safety for SurfaceFlinger class" into rvc-dev
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2832bc9..db4aba8 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -74,6 +74,9 @@
     // or dessert updates. Instead, apex users should use libbinder_ndk.
     apex_available: [
         "//apex_available:platform",
+        // TODO(b/139016109) remove these three
+        "com.android.media.swcodec",
+        "test_com.android.media.swcodec",
     ],
 
     srcs: [
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 3997134..e8d3684 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -100,6 +100,7 @@
         "libgraphicsenv",
         "libnativewindow",
         "libbacktrace",
+        "libbase",
     ],
     target: {
         vendor: {
diff --git a/opengl/libs/EGL/BlobCache.cpp b/opengl/libs/EGL/BlobCache.cpp
index 74c4d7d..74fb019 100644
--- a/opengl/libs/EGL/BlobCache.cpp
+++ b/opengl/libs/EGL/BlobCache.cpp
@@ -21,7 +21,7 @@
 #include <errno.h>
 #include <inttypes.h>
 
-#include <cutils/properties.h>
+#include <android-base/properties.h>
 #include <log/log.h>
 #include <chrono>
 
@@ -165,7 +165,8 @@
 }
 
 size_t BlobCache::getFlattenedSize() const {
-    size_t size = align4(sizeof(Header) + PROPERTY_VALUE_MAX);
+    auto buildId = base::GetProperty("ro.build.id", "");
+    size_t size = align4(sizeof(Header) + buildId.size());
     for (const CacheEntry& e :  mCacheEntries) {
         std::shared_ptr<Blob> const& keyBlob = e.getKey();
         std::shared_ptr<Blob> const& valueBlob = e.getValue();
@@ -185,9 +186,9 @@
     header->mBlobCacheVersion = blobCacheVersion;
     header->mDeviceVersion = blobCacheDeviceVersion;
     header->mNumEntries = mCacheEntries.size();
-    char buildId[PROPERTY_VALUE_MAX];
-    header->mBuildIdLength = property_get("ro.build.id", buildId, "");
-    memcpy(header->mBuildId, buildId, header->mBuildIdLength);
+    auto buildId = base::GetProperty("ro.build.id", "");
+    header->mBuildIdLength = buildId.size();
+    memcpy(header->mBuildId, buildId.c_str(), header->mBuildIdLength);
 
     // Write cache entries
     uint8_t* byteBuffer = reinterpret_cast<uint8_t*>(buffer);
@@ -238,12 +239,11 @@
         ALOGE("unflatten: bad magic number: %" PRIu32, header->mMagicNumber);
         return -EINVAL;
     }
-    char buildId[PROPERTY_VALUE_MAX];
-    int len = property_get("ro.build.id", buildId, "");
+    auto buildId = base::GetProperty("ro.build.id", "");
     if (header->mBlobCacheVersion != blobCacheVersion ||
-            header->mDeviceVersion != blobCacheDeviceVersion ||
-            len != header->mBuildIdLength ||
-            strncmp(buildId, header->mBuildId, len)) {
+        header->mDeviceVersion != blobCacheDeviceVersion ||
+        buildId.size() != header->mBuildIdLength ||
+        strncmp(buildId.c_str(), header->mBuildId, buildId.size())) {
         // We treat version mismatches as an empty cache.
         return 0;
     }
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index d664e4d..d66ef2b 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -24,8 +24,8 @@
 #include <dirent.h>
 #include <dlfcn.h>
 
+#include <android-base/properties.h>
 #include <android/dlext.h>
-#include <cutils/properties.h>
 #include <log/log.h>
 #include <utils/Timers.h>
 
@@ -241,12 +241,12 @@
         // i.e.:
         //      libGLES_${prop}.so, or:
         //      libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
-        char prop[PROPERTY_VALUE_MAX + 1];
         for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
-            if (property_get(key, prop, nullptr) <= 0) {
+            auto prop = base::GetProperty(key, "");
+            if (prop.empty()) {
                 continue;
             }
-            hnd = attempt_to_load_system_driver(cnx, prop, true);
+            hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
             if (hnd) {
                 break;
             } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
@@ -510,9 +510,9 @@
         .library_namespace = ns,
     };
     void* so = nullptr;
-    char prop[PROPERTY_VALUE_MAX + 1];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
-        if (property_get(key, prop, nullptr) <= 0) {
+        auto prop = base::GetProperty(key, "");
+        if (prop.empty()) {
             continue;
         }
         std::string name = std::string("lib") + kind + "_" + prop + ".so";
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index d5d57d7..43f7a07 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -18,7 +18,7 @@
 
 #include <EGL/egl.h>
 
-#include <cutils/properties.h>
+#include <android-base/properties.h>
 
 #include <log/log.h>
 
@@ -58,9 +58,7 @@
         } else {
             LOG_ALWAYS_FATAL(error);
         }
-        char value[PROPERTY_VALUE_MAX];
-        property_get("debug.egl.callstack", value, "0");
-        if (atoi(value)) {
+        if (base::GetBoolProperty("debug.egl.callstack", false)) {
             CallStack::log(LOG_TAG);
         }
     }
@@ -224,9 +222,7 @@
     pthread_mutex_unlock(&sLogPrintMutex);
     if (printLog) {
         ALOGE("called unimplemented OpenGL ES API");
-        char value[PROPERTY_VALUE_MAX];
-        property_get("debug.egl.callstack", value, "0");
-        if (atoi(value)) {
+        if (base::GetBoolProperty("debug.egl.callstack", false)) {
             CallStack::log(LOG_TAG);
         }
     }
diff --git a/opengl/libs/EGL/egl_angle_platform.cpp b/opengl/libs/EGL/egl_angle_platform.cpp
index 00caff2..97dc0f1 100644
--- a/opengl/libs/EGL/egl_angle_platform.cpp
+++ b/opengl/libs/EGL/egl_angle_platform.cpp
@@ -16,7 +16,6 @@
 
 #if defined(__ANDROID__)
 
-#include <cutils/properties.h>
 #include "Loader.h"
 #include "egl_angle_platform.h"
 
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 6af7cd2..3b1cf71 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -24,7 +24,6 @@
 #include <EGL/eglext_angle.h>
 #include <private/EGL/display.h>
 
-#include <cutils/properties.h>
 #include "Loader.h"
 #include "egl_angle_platform.h"
 #include "egl_cache.h"
@@ -32,6 +31,7 @@
 #include "egl_tls.h"
 
 #include <SurfaceFlingerProperties.h>
+#include <android-base/properties.h>
 #include <android/dlext.h>
 #include <dlfcn.h>
 #include <graphicsenv/GraphicsEnv.h>
@@ -73,7 +73,7 @@
 }
 
 bool needsAndroidPEglMitigation() {
-    static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
+    static const int32_t vndk_version = base::GetIntProperty("ro.vndk.version", -1);
     return vndk_version <= 28;
 }
 
@@ -151,10 +151,8 @@
         attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
         attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
 
-        char prop[PROPERTY_VALUE_MAX];
-        property_get("debug.angle.validation", prop, "0");
         attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
-        attrs.push_back(atoi(prop));
+        attrs.push_back(base::GetBoolProperty("debug.angle.validation", false));
 
         attrs.push_back(EGL_NONE);
 
@@ -372,16 +370,8 @@
 
         egl_cache_t::get()->initialize(this);
 
-        char value[PROPERTY_VALUE_MAX];
-        property_get("debug.egl.finish", value, "0");
-        if (atoi(value)) {
-            finishOnSwap = true;
-        }
-
-        property_get("debug.egl.traceGpuCompletion", value, "0");
-        if (atoi(value)) {
-            traceGpuCompletion = true;
-        }
+        finishOnSwap = base::GetBoolProperty("debug.egl.finish", false);
+        traceGpuCompletion = base::GetBoolProperty("debug.egl.traceGpuCompletion", false);
 
         // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
         // changing the behavior from the past where we always advertise
diff --git a/opengl/libs/EGL/egl_layers.cpp b/opengl/libs/EGL/egl_layers.cpp
index 44a1c0b..ea86c9a 100644
--- a/opengl/libs/EGL/egl_layers.cpp
+++ b/opengl/libs/EGL/egl_layers.cpp
@@ -18,9 +18,9 @@
 
 #include <EGL/egl.h>
 #include <android-base/file.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <android/dlext.h>
-#include <cutils/properties.h>
 #include <dlfcn.h>
 #include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
@@ -157,9 +157,7 @@
 
     if (debug_layers.empty()) {
         // Only check system properties if Java settings are empty
-        char prop[PROPERTY_VALUE_MAX];
-        property_get("debug.gles.layers", prop, "");
-        debug_layers = prop;
+        debug_layers = base::GetProperty("debug.gles.layers", "");
     }
 
     return debug_layers;
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index c976c60..99283be 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -27,13 +27,13 @@
 #include <EGL/eglext.h>
 #include <EGL/eglext_angle.h>
 
-#include <android/hardware_buffer.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
+#include <android/hardware_buffer.h>
 #include <graphicsenv/GraphicsEnv.h>
 #include <private/android/AHardwareBufferHelpers.h>
 
 #include <cutils/compiler.h>
-#include <cutils/properties.h>
 #include <log/log.h>
 
 #include <condition_variable>
@@ -381,10 +381,7 @@
     egl_connection_t* const cnx = &gEGLImpl;
     if (cnx->dso) {
         if (attrib_list) {
-            char value[PROPERTY_VALUE_MAX];
-            property_get("debug.egl.force_msaa", value, "false");
-
-            if (!strcmp(value, "true")) {
+            if (base::GetBoolProperty("debug.egl.force_msaa", false)) {
                 size_t attribCount = 0;
                 EGLint attrib = attrib_list[0];
 
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index aaecb62..8d118e0 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -18,7 +18,7 @@
 
 #include <stdlib.h>
 
-#include <cutils/properties.h>
+#include <android-base/properties.h>
 #include <log/log.h>
 #include "CallStack.h"
 #include "egl_platform_entries.h"
@@ -96,9 +96,7 @@
         if (!quiet) {
             ALOGE("%s:%d error %x (%s)",
                     caller, line, error, egl_strerror(error));
-            char value[PROPERTY_VALUE_MAX];
-            property_get("debug.egl.callstack", value, "0");
-            if (atoi(value)) {
+            if (base::GetBoolProperty("debug.egl.callstack", false)) {
                 CallStack::log(LOG_TAG);
             }
         }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 1dbcf98..a239723 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1152,14 +1152,16 @@
     }
 
     setInjectionResult(entry, injectionResult);
+    if (injectionResult == INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
+        ALOGW("Permission denied, dropping the motion (isPointer=%s)", toString(isPointerEvent));
+        return true;
+    }
     if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
-        if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
-            CancelationOptions::Mode mode(isPointerEvent
-                                                  ? CancelationOptions::CANCEL_POINTER_EVENTS
-                                                  : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
-            CancelationOptions options(mode, "input event injection failed");
-            synthesizeCancelationEventsForMonitorsLocked(options);
-        }
+        CancelationOptions::Mode mode(isPointerEvent
+                                              ? CancelationOptions::CANCEL_POINTER_EVENTS
+                                              : CancelationOptions::CANCEL_NON_POINTER_EVENTS);
+        CancelationOptions options(mode, "input event injection failed");
+        synthesizeCancelationEventsForMonitorsLocked(options);
         return true;
     }
 
@@ -1345,13 +1347,6 @@
     }
 }
 
-nsecs_t InputDispatcher::getTimeSpentWaitingForApplicationLocked(nsecs_t currentTime) {
-    if (mInputTargetWaitCause == INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
-        return currentTime - mInputTargetWaitStartTime;
-    }
-    return 0;
-}
-
 void InputDispatcher::resetAnrTimeoutsLocked() {
     if (DEBUG_FOCUS) {
         ALOGD("Resetting ANR timeouts.");
@@ -1394,7 +1389,6 @@
                                                         const EventEntry& entry,
                                                         std::vector<InputTarget>& inputTargets,
                                                         nsecs_t* nextWakeupTime) {
-    int32_t injectionResult;
     std::string reason;
 
     int32_t displayId = getTargetDisplayId(entry);
@@ -1407,54 +1401,38 @@
     // then drop the event.
     if (focusedWindowHandle == nullptr) {
         if (focusedApplicationHandle != nullptr) {
-            injectionResult =
-                    handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
-                                                nullptr, nextWakeupTime,
-                                                "Waiting because no window has focus but there is "
-                                                "a focused application that may eventually add a "
-                                                "window when it finishes starting up.");
-            goto Unresponsive;
+            return handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
+                                               nullptr, nextWakeupTime,
+                                               "Waiting because no window has focus but there is "
+                                               "a focused application that may eventually add a "
+                                               "window when it finishes starting up.");
         }
 
         ALOGI("Dropping event because there is no focused window or focused application in display "
               "%" PRId32 ".",
               displayId);
-        injectionResult = INPUT_EVENT_INJECTION_FAILED;
-        goto Failed;
+        return INPUT_EVENT_INJECTION_FAILED;
     }
 
     // Check permissions.
     if (!checkInjectionPermission(focusedWindowHandle, entry.injectionState)) {
-        injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
-        goto Failed;
+        return INPUT_EVENT_INJECTION_PERMISSION_DENIED;
     }
 
     // Check whether the window is ready for more input.
     reason = checkWindowReadyForMoreInputLocked(currentTime, focusedWindowHandle, entry, "focused");
     if (!reason.empty()) {
-        injectionResult =
-                handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
-                                            focusedWindowHandle, nextWakeupTime, reason.c_str());
-        goto Unresponsive;
+        return handleTargetsNotReadyLocked(currentTime, entry, focusedApplicationHandle,
+                                           focusedWindowHandle, nextWakeupTime, reason.c_str());
     }
 
     // Success!  Output targets.
-    injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
     addWindowTargetLocked(focusedWindowHandle,
                           InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
                           BitSet32(0), inputTargets);
 
     // Done.
-Failed:
-Unresponsive:
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
-    if (DEBUG_FOCUS) {
-        ALOGD("findFocusedWindow finished: injectionResult=%d, "
-              "timeSpentWaitingForApplication=%0.1fms",
-              injectionResult, timeSpentWaitingForApplication / 1000000.0);
-    }
-    return injectionResult;
+    return INPUT_EVENT_INJECTION_SUCCEEDED;
 }
 
 int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
@@ -1751,10 +1729,9 @@
                     checkWindowReadyForMoreInputLocked(currentTime, touchedWindow.windowHandle,
                                                        entry, "touched");
             if (!reason.empty()) {
-                injectionResult = handleTargetsNotReadyLocked(currentTime, entry, nullptr,
-                                                              touchedWindow.windowHandle,
-                                                              nextWakeupTime, reason.c_str());
-                goto Unresponsive;
+                return handleTargetsNotReadyLocked(currentTime, entry, nullptr,
+                                                   touchedWindow.windowHandle, nextWakeupTime,
+                                                   reason.c_str());
             }
         }
     }
@@ -1814,98 +1791,85 @@
         }
     }
 
+    if (injectionPermission != INJECTION_PERMISSION_GRANTED) {
+        return injectionResult;
+    }
+
     // Update final pieces of touch state if the injector had permission.
-    if (injectionPermission == INJECTION_PERMISSION_GRANTED) {
-        if (!wrongDevice) {
-            if (switchedDevice) {
+    if (!wrongDevice) {
+        if (switchedDevice) {
+            if (DEBUG_FOCUS) {
+                ALOGD("Conflicting pointer actions: Switched to a different device.");
+            }
+            *outConflictingPointerActions = true;
+        }
+
+        if (isHoverAction) {
+            // Started hovering, therefore no longer down.
+            if (oldState && oldState->down) {
                 if (DEBUG_FOCUS) {
-                    ALOGD("Conflicting pointer actions: Switched to a different device.");
+                    ALOGD("Conflicting pointer actions: Hover received while pointer was "
+                          "down.");
                 }
                 *outConflictingPointerActions = true;
             }
+            mTempTouchState.reset();
+            if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
+                maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
+                mTempTouchState.deviceId = entry.deviceId;
+                mTempTouchState.source = entry.source;
+                mTempTouchState.displayId = displayId;
+            }
+        } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
+                   maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
+            // All pointers up or canceled.
+            mTempTouchState.reset();
+        } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
+            // First pointer went down.
+            if (oldState && oldState->down) {
+                if (DEBUG_FOCUS) {
+                    ALOGD("Conflicting pointer actions: Down received while already down.");
+                }
+                *outConflictingPointerActions = true;
+            }
+        } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
+            // One pointer went up.
+            if (isSplit) {
+                int32_t pointerIndex = getMotionEventActionPointerIndex(action);
+                uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
 
-            if (isHoverAction) {
-                // Started hovering, therefore no longer down.
-                if (oldState && oldState->down) {
-                    if (DEBUG_FOCUS) {
-                        ALOGD("Conflicting pointer actions: Hover received while pointer was "
-                              "down.");
-                    }
-                    *outConflictingPointerActions = true;
-                }
-                mTempTouchState.reset();
-                if (maskedAction == AMOTION_EVENT_ACTION_HOVER_ENTER ||
-                    maskedAction == AMOTION_EVENT_ACTION_HOVER_MOVE) {
-                    mTempTouchState.deviceId = entry.deviceId;
-                    mTempTouchState.source = entry.source;
-                    mTempTouchState.displayId = displayId;
-                }
-            } else if (maskedAction == AMOTION_EVENT_ACTION_UP ||
-                       maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
-                // All pointers up or canceled.
-                mTempTouchState.reset();
-            } else if (maskedAction == AMOTION_EVENT_ACTION_DOWN) {
-                // First pointer went down.
-                if (oldState && oldState->down) {
-                    if (DEBUG_FOCUS) {
-                        ALOGD("Conflicting pointer actions: Down received while already down.");
-                    }
-                    *outConflictingPointerActions = true;
-                }
-            } else if (maskedAction == AMOTION_EVENT_ACTION_POINTER_UP) {
-                // One pointer went up.
-                if (isSplit) {
-                    int32_t pointerIndex = getMotionEventActionPointerIndex(action);
-                    uint32_t pointerId = entry.pointerProperties[pointerIndex].id;
-
-                    for (size_t i = 0; i < mTempTouchState.windows.size();) {
-                        TouchedWindow& touchedWindow = mTempTouchState.windows[i];
-                        if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
-                            touchedWindow.pointerIds.clearBit(pointerId);
-                            if (touchedWindow.pointerIds.isEmpty()) {
-                                mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
-                                continue;
-                            }
+                for (size_t i = 0; i < mTempTouchState.windows.size();) {
+                    TouchedWindow& touchedWindow = mTempTouchState.windows[i];
+                    if (touchedWindow.targetFlags & InputTarget::FLAG_SPLIT) {
+                        touchedWindow.pointerIds.clearBit(pointerId);
+                        if (touchedWindow.pointerIds.isEmpty()) {
+                            mTempTouchState.windows.erase(mTempTouchState.windows.begin() + i);
+                            continue;
                         }
-                        i += 1;
                     }
+                    i += 1;
                 }
             }
+        }
 
-            // Save changes unless the action was scroll in which case the temporary touch
-            // state was only valid for this one action.
-            if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
-                if (mTempTouchState.displayId >= 0) {
-                    if (oldStateIndex >= 0) {
-                        mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
-                    } else {
-                        mTouchStatesByDisplay.add(displayId, mTempTouchState);
-                    }
-                } else if (oldStateIndex >= 0) {
-                    mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
+        // Save changes unless the action was scroll in which case the temporary touch
+        // state was only valid for this one action.
+        if (maskedAction != AMOTION_EVENT_ACTION_SCROLL) {
+            if (mTempTouchState.displayId >= 0) {
+                if (oldStateIndex >= 0) {
+                    mTouchStatesByDisplay.editValueAt(oldStateIndex).copyFrom(mTempTouchState);
+                } else {
+                    mTouchStatesByDisplay.add(displayId, mTempTouchState);
                 }
+            } else if (oldStateIndex >= 0) {
+                mTouchStatesByDisplay.removeItemsAt(oldStateIndex);
             }
+        }
 
-            // Update hover state.
-            mLastHoverWindowHandle = newHoverWindowHandle;
-        }
-    } else {
-        if (DEBUG_FOCUS) {
-            ALOGD("Not updating touch focus because injection was denied.");
-        }
+        // Update hover state.
+        mLastHoverWindowHandle = newHoverWindowHandle;
     }
 
-Unresponsive:
-    // Reset temporary touch state to ensure we release unnecessary references to input channels.
-    mTempTouchState.reset();
-
-    nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
-    updateDispatchStatistics(currentTime, entry, injectionResult, timeSpentWaitingForApplication);
-    if (DEBUG_FOCUS) {
-        ALOGD("findTouchedWindow finished: injectionResult=%d, injectionPermission=%d, "
-              "timeSpentWaitingForApplication=%0.1fms",
-              injectionResult, injectionPermission, timeSpentWaitingForApplication / 1000000.0);
-    }
     return injectionResult;
 }
 
@@ -4664,6 +4628,7 @@
         dispatchEntry->eventEntry->appendDescription(msg);
         ALOGI("%s", msg.c_str());
     }
+    reportDispatchStatistics(std::chrono::nanoseconds(eventDuration), *connection, handled);
 
     bool restartEvent;
     if (dispatchEntry->eventEntry->type == EventEntry::Type::KEY) {
@@ -4898,9 +4863,8 @@
     return event;
 }
 
-void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventEntry& entry,
-                                               int32_t injectionResult,
-                                               nsecs_t timeSpentWaitingForApplication) {
+void InputDispatcher::reportDispatchStatistics(std::chrono::nanoseconds eventDuration,
+                                               const Connection& connection, bool handled) {
     // TODO Write some statistics about how long we spend waiting.
 }
 
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 670d0e1..d122282 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -497,8 +497,8 @@
     LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD};
 
     void reportTouchEventForStatistics(const MotionEntry& entry);
-    void updateDispatchStatistics(nsecs_t currentTime, const EventEntry& entry,
-                                  int32_t injectionResult, nsecs_t timeSpentWaitingForApplication);
+    void reportDispatchStatistics(std::chrono::nanoseconds eventDuration,
+                                  const Connection& connection, bool handled);
     void traceInboundQueueLengthLocked() REQUIRES(mLock);
     void traceOutboundQueueLength(const sp<Connection>& connection);
     void traceWaitQueueLength(const sp<Connection>& connection);
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 81f2dd1..1faf775 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -149,9 +149,9 @@
         // a modification of the axes of rotation. To account for this we
         // need to reorient the inverse rotation in terms of the current
         // axes of rotation.
-        bool is_h_flipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
-        bool is_v_flipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
-        if (is_h_flipped == is_v_flipped) {
+        bool isHFlipped = (invTransform & HAL_TRANSFORM_FLIP_H) != 0;
+        bool isVFlipped = (invTransform & HAL_TRANSFORM_FLIP_V) != 0;
+        if (isHFlipped == isVFlipped) {
             invTransform ^= HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_FLIP_H;
         }
         std::swap(winWidth, winHeight);
@@ -160,18 +160,18 @@
             activeCrop.transform(invTransform, bufferSize.getWidth(), bufferSize.getHeight());
 
     // below, crop is intersected with winCrop expressed in crop's coordinate space
-    float xScale = crop.getWidth() / float(winWidth);
-    float yScale = crop.getHeight() / float(winHeight);
+    const float xScale = crop.getWidth() / float(winWidth);
+    const float yScale = crop.getHeight() / float(winHeight);
 
-    float insetL = winCrop.left * xScale;
-    float insetT = winCrop.top * yScale;
-    float insetR = (winWidth - winCrop.right) * xScale;
-    float insetB = (winHeight - winCrop.bottom) * yScale;
+    const float insetLeft = winCrop.left * xScale;
+    const float insetTop = winCrop.top * yScale;
+    const float insetRight = (winWidth - winCrop.right) * xScale;
+    const float insetBottom = (winHeight - winCrop.bottom) * yScale;
 
-    crop.left += insetL;
-    crop.top += insetT;
-    crop.right -= insetR;
-    crop.bottom -= insetB;
+    crop.left += insetLeft;
+    crop.top += insetTop;
+    crop.right -= insetRight;
+    crop.bottom -= insetBottom;
 
     return crop;
 }
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 9af9cad..0c8aafc 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -158,19 +158,19 @@
     mOrientation = orientation;
 
     const Rect& displayBounds = getCompositionDisplay()->getState().bounds;
-    const int w = displayBounds.width();
-    const int h = displayBounds.height();
+    const int displayWidth = displayBounds.width();
+    const int displayHeight = displayBounds.height();
 
-    ui::Transform R;
+    ui::Transform rotation;
     if (const auto flags = ui::Transform::toRotationFlags(orientation);
         flags != ui::Transform::ROT_INVALID) {
-        R.set(flags, w, h);
+        rotation.set(flags, displayWidth, displayHeight);
     }
 
     if (!frame.isValid()) {
         // the destination frame can be invalid if it has never been set,
         // in that case we assume the whole display frame.
-        frame = Rect(w, h);
+        frame = Rect(displayWidth, displayHeight);
     }
 
     if (viewport.isEmpty()) {
@@ -178,45 +178,45 @@
         // we assume the whole display size.
         // it's also invalid to have an empty viewport, so we handle that
         // case in the same way.
-        viewport = Rect(w, h);
-        if (R.getOrientation() & ui::Transform::ROT_90) {
+        viewport = Rect(displayWidth, displayHeight);
+        if (rotation.getOrientation() & ui::Transform::ROT_90) {
             // viewport is always specified in the logical orientation
             // of the display (ie: post-rotation).
             std::swap(viewport.right, viewport.bottom);
         }
     }
 
-    ui::Transform TL, TP, S;
-    float src_width  = viewport.width();
-    float src_height = viewport.height();
-    float dst_width  = frame.width();
-    float dst_height = frame.height();
-    if (src_width != dst_width || src_height != dst_height) {
-        float sx = dst_width  / src_width;
-        float sy = dst_height / src_height;
-        S.set(sx, 0, 0, sy);
+    ui::Transform logicalTranslation, physicalTranslation, scale;
+    const float sourceWidth = viewport.width();
+    const float sourceHeight = viewport.height();
+    const float destWidth = frame.width();
+    const float destHeight = frame.height();
+    if (sourceWidth != destWidth || sourceHeight != destHeight) {
+        const float scaleX = destWidth / sourceWidth;
+        const float scaleY = destHeight / sourceHeight;
+        scale.set(scaleX, 0, 0, scaleY);
     }
 
-    float src_x = viewport.left;
-    float src_y = viewport.top;
-    float dst_x = frame.left;
-    float dst_y = frame.top;
-    TL.set(-src_x, -src_y);
-    TP.set(dst_x, dst_y);
+    const float sourceX = viewport.left;
+    const float sourceY = viewport.top;
+    const float destX = frame.left;
+    const float destY = frame.top;
+    logicalTranslation.set(-sourceX, -sourceY);
+    physicalTranslation.set(destX, destY);
 
     // need to take care of primary display rotation for globalTransform
     // for case if the panel is not installed aligned with device orientation
     if (isPrimary()) {
         if (const auto flags = ui::Transform::toRotationFlags(orientation + mPhysicalOrientation);
             flags != ui::Transform::ROT_INVALID) {
-            R.set(flags, w, h);
+            rotation.set(flags, displayWidth, displayHeight);
         }
     }
 
     // The viewport and frame are both in the logical orientation.
     // Apply the logical translation, scale to physical size, apply the
     // physical translation and finally rotate to the physical orientation.
-    ui::Transform globalTransform = R * TP * S * TL;
+    ui::Transform globalTransform = rotation * physicalTranslation * scale * logicalTranslation;
 
     const uint8_t type = globalTransform.getType();
     const bool needsFiltering =
diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
index b067466..e6c5cc9 100644
--- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp
@@ -174,8 +174,10 @@
                         return LayerVoteType::NoVote;
                 }
             }();
-            if (layer->isVisible() && (frameRate.rate > 0 || voteType == LayerVoteType::NoVote)) {
-                info->setLayerVote(voteType, frameRate.rate);
+
+            if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) {
+                const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote;
+                info->setLayerVote(type, frameRate.rate);
             } else {
                 info->resetLayerVote();
             }
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index d73fd8b..f87c1f8 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -66,15 +66,15 @@
     // TODO (140302863) remove this and use the vsync_reactor system.
     if (property_get_bool("debug.sf.vsync_reactor", true)) {
         // TODO (144707443) tune Predictor tunables.
-        static constexpr int default_rate = 60;
-        static constexpr auto initial_period =
-                std::chrono::duration<nsecs_t, std::ratio<1, default_rate>>(1);
+        static constexpr int defaultRate = 60;
+        static constexpr auto initialPeriod =
+                std::chrono::duration<nsecs_t, std::ratio<1, defaultRate>>(1);
         static constexpr size_t vsyncTimestampHistorySize = 20;
         static constexpr size_t minimumSamplesForPrediction = 6;
         static constexpr uint32_t discardOutlierPercent = 20;
         auto tracker = std::make_unique<
                 scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
-                                                   initial_period)
+                                                   initialPeriod)
                                                    .count(),
                                            vsyncTimestampHistorySize, minimumSamplesForPrediction,
                                            discardOutlierPercent);
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
index 6fca673..431cf0f 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp
@@ -512,5 +512,34 @@
     EXPECT_EQ(1, frequentLayerCount(time));
 }
 
+TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) {
+    auto explicitVisiblelayer = createLayer();
+    auto explicitInvisiblelayer = createLayer();
+
+    EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true));
+    EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false));
+    EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree())
+            .WillRepeatedly(Return(
+                    Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple)));
+
+    nsecs_t time = systemTime();
+
+    // Post a buffer to the layers to make them active
+    history().record(explicitVisiblelayer.get(), time, time);
+    history().record(explicitInvisiblelayer.get(), time, time);
+
+    EXPECT_EQ(2, layerCount());
+    ASSERT_EQ(1, history().summarize(time).size());
+    EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
+              history().summarize(time)[0].vote);
+    EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate);
+    EXPECT_EQ(2, activeLayerCount());
+    EXPECT_EQ(2, frequentLayerCount(time));
+}
+
 } // namespace
 } // namespace android::scheduler