Merge changes I13283720,Iddd8f902 into main

* changes:
  BufferItemConsumer: Add/expose methods
  BufferQueue: Fix deadlock in setMaxAcquiredBufferCount
diff --git a/cmds/installd/TEST_MAPPING b/cmds/installd/TEST_MAPPING
index fc4cfc9..d53c94b 100644
--- a/cmds/installd/TEST_MAPPING
+++ b/cmds/installd/TEST_MAPPING
@@ -18,10 +18,6 @@
     {
       "name": "run_dex2oat_test"
     },
-    // AdoptableHostTest moves packages, part of which is handled by installd
-    {
-      "name": "AdoptableHostTest"
-    },
     {
       "name": "CtsUsesLibraryHostTestCases"
     },
diff --git a/include/input/DisplayTopologyGraph.h b/include/input/DisplayTopologyGraph.h
index 3ae865a..ce7259e 100644
--- a/include/input/DisplayTopologyGraph.h
+++ b/include/input/DisplayTopologyGraph.h
@@ -55,6 +55,8 @@
     ui::LogicalDisplayId primaryDisplayId = ui::LogicalDisplayId::INVALID;
     std::unordered_map<ui::LogicalDisplayId, std::vector<DisplayTopologyAdjacentDisplay>> graph;
     std::unordered_map<ui::LogicalDisplayId, int> displaysDensity;
+
+    bool isValid() const;
 };
 
 } // namespace android
diff --git a/include/input/InputFlags.h b/include/input/InputFlags.h
index 4b42f77..16e754e 100644
--- a/include/input/InputFlags.h
+++ b/include/input/InputFlags.h
@@ -22,7 +22,21 @@
 public:
     /**
      * Check if connected displays feature is enabled, either via the feature flag or settings
-     * override.
+     * override. Developer setting override allows enabling all the "desktop experiences" features
+     * including input related connected_displays_cursor flag.
+     *
+     * The developer settings override is prioritised over aconfig flags. Any tests that require
+     * applicable aconfig flags to be disabled with SCOPED_FLAG_OVERRIDE also need this developer
+     * option to be reset locally.
+     *
+     * Also note the developer setting override is only applicable to the desktop experiences
+     * related features.
+     *
+     * To enable only the input flag run:
+     *      adb shell aflags enable com.android.input.flags.connected_displays_cursor
+     * To override this flag and enable all "desktop experiences" features run:
+     *      adb shell aflags enable com.android.window.flags.enable_desktop_mode_through_dev_option
+     *      adb shell setprop persist.wm.debug.desktop_experience_devopts 1
      */
     static bool connectedDisplaysCursorEnabled();
 
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index 7c0319a..b1c8994 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -130,7 +130,13 @@
 
 bool BinderCacheWithInvalidation::isClientSideCachingEnabled(const std::string& serviceName) {
     sp<ProcessState> self = ProcessState::selfOrNull();
-    if (!self || self->getThreadPoolMaxTotalThreadCount() <= 0) {
+    // Should not cache if process state could not be found, or if thread pool
+    // max could is not greater than zero.
+    if (!self) {
+        ALOGW("Service retrieved before binder threads started. If they are to be started, "
+              "consider starting binder threads earlier.");
+        return false;
+    } else if (self->getThreadPoolMaxTotalThreadCount() <= 0) {
         ALOGW("Thread Pool max thread count is 0. Cannot cache binder as linkToDeath cannot be "
               "implemented. serviceName: %s",
               serviceName.c_str());
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index fa97142..1aae13c 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -937,15 +937,22 @@
           : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {}
 
     void allocateBuffers() override {
+        ATRACE_CALL();
         uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
         auto gbp = getIGraphicBufferProducer();
-        std::thread ([reqWidth, reqHeight, gbp=getIGraphicBufferProducer(),
-                      reqFormat=mReqFormat, reqUsage=mReqUsage] () {
+        std::thread allocateThread([reqWidth, reqHeight, gbp = getIGraphicBufferProducer(),
+                                    reqFormat = mReqFormat, reqUsage = mReqUsage]() {
+            if (com_android_graphics_libgui_flags_allocate_buffer_priority()) {
+                androidSetThreadName("allocateBuffers");
+                pid_t tid = gettid();
+                androidSetThreadPriority(tid, ANDROID_PRIORITY_DISPLAY);
+            }
+
             gbp->allocateBuffers(reqWidth, reqHeight,
                                  reqFormat, reqUsage);
-
-        }).detach();
+        });
+        allocateThread.detach();
     }
 
     status_t setFrameRate(float frameRate, int8_t compatibility,
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index 534f05e..2c3222d 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -142,3 +142,14 @@
   bug: "340934031"
   is_fixed_read_only: true
 } # wb_media_migration
+
+flag {
+  name: "allocate_buffer_priority"
+  namespace: "wear_system_health"
+  description: "Boost priority for buffer allocation"
+  bug: "399701430"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+  is_fixed_read_only: true
+} # allocate_buffer_priority
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index ff26184..52e0276 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -225,6 +225,7 @@
     srcs: [
         "AccelerationCurve.cpp",
         "CoordinateFilter.cpp",
+        "DisplayTopologyGraph.cpp",
         "Input.cpp",
         "InputConsumer.cpp",
         "InputConsumerNoResampling.cpp",
@@ -270,6 +271,7 @@
 
     shared_libs: [
         "android.companion.virtualdevice.flags-aconfig-cc",
+        "com.android.window.flags.window-aconfig_flags_c_lib",
         "libPlatformProperties",
         "libaconfig_storage_read_api_cc",
         "libbase",
diff --git a/libs/input/DisplayTopologyGraph.cpp b/libs/input/DisplayTopologyGraph.cpp
new file mode 100644
index 0000000..7ad9f16
--- /dev/null
+++ b/libs/input/DisplayTopologyGraph.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2025 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 LOG_TAG "DisplayTopologyValidator"
+
+#include <android-base/logging.h>
+#include <ftl/enum.h>
+#include <input/DisplayTopologyGraph.h>
+#include <ui/LogicalDisplayId.h>
+
+#include <algorithm>
+
+namespace android {
+
+namespace {
+DisplayTopologyPosition getOppositePosition(DisplayTopologyPosition position) {
+    switch (position) {
+        case DisplayTopologyPosition::LEFT:
+            return DisplayTopologyPosition::RIGHT;
+        case DisplayTopologyPosition::TOP:
+            return DisplayTopologyPosition::BOTTOM;
+        case DisplayTopologyPosition::RIGHT:
+            return DisplayTopologyPosition::LEFT;
+        case DisplayTopologyPosition::BOTTOM:
+            return DisplayTopologyPosition::TOP;
+    }
+}
+
+bool validatePrimaryDisplay(const android::DisplayTopologyGraph& displayTopologyGraph) {
+    return displayTopologyGraph.primaryDisplayId != ui::LogicalDisplayId::INVALID &&
+            displayTopologyGraph.graph.contains(displayTopologyGraph.primaryDisplayId);
+}
+
+bool validateTopologyGraph(const android::DisplayTopologyGraph& displayTopologyGraph) {
+    for (const auto& [sourceDisplay, adjacentDisplays] : displayTopologyGraph.graph) {
+        for (const DisplayTopologyAdjacentDisplay& adjacentDisplay : adjacentDisplays) {
+            const auto adjacentGraphIt = displayTopologyGraph.graph.find(adjacentDisplay.displayId);
+            if (adjacentGraphIt == displayTopologyGraph.graph.end()) {
+                LOG(ERROR) << "Missing adjacent display in topology graph: "
+                           << adjacentDisplay.displayId << " for source " << sourceDisplay;
+                return false;
+            }
+            const auto reverseEdgeIt =
+                    std::find_if(adjacentGraphIt->second.begin(), adjacentGraphIt->second.end(),
+                                 [sourceDisplay](const DisplayTopologyAdjacentDisplay&
+                                                         reverseAdjacentDisplay) {
+                                     return sourceDisplay == reverseAdjacentDisplay.displayId;
+                                 });
+            if (reverseEdgeIt == adjacentGraphIt->second.end()) {
+                LOG(ERROR) << "Missing reverse edge in topology graph for: " << sourceDisplay
+                           << " -> " << adjacentDisplay.displayId;
+                return false;
+            }
+            DisplayTopologyPosition expectedPosition =
+                    getOppositePosition(adjacentDisplay.position);
+            if (reverseEdgeIt->position != expectedPosition) {
+                LOG(ERROR) << "Unexpected reverse edge for: " << sourceDisplay << " -> "
+                           << adjacentDisplay.displayId
+                           << " expected position: " << ftl::enum_string(expectedPosition)
+                           << " actual " << ftl::enum_string(reverseEdgeIt->position);
+                return false;
+            }
+            if (reverseEdgeIt->offsetDp != -adjacentDisplay.offsetDp) {
+                LOG(ERROR) << "Unexpected reverse edge offset: " << sourceDisplay << " -> "
+                           << adjacentDisplay.displayId
+                           << " expected offset: " << -adjacentDisplay.offsetDp << " actual "
+                           << reverseEdgeIt->offsetDp;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool validateDensities(const android::DisplayTopologyGraph& displayTopologyGraph) {
+    for (const auto& [sourceDisplay, adjacentDisplays] : displayTopologyGraph.graph) {
+        if (!displayTopologyGraph.displaysDensity.contains(sourceDisplay)) {
+            LOG(ERROR) << "Missing density value in topology graph for display: " << sourceDisplay;
+            return false;
+        }
+    }
+    return true;
+}
+
+} // namespace
+
+bool DisplayTopologyGraph::isValid() const {
+    return validatePrimaryDisplay(*this) && validateTopologyGraph(*this) &&
+            validateDensities(*this);
+}
+
+} // namespace android
diff --git a/libs/input/InputFlags.cpp b/libs/input/InputFlags.cpp
index f866f9b..6aa9ae6 100644
--- a/libs/input/InputFlags.cpp
+++ b/libs/input/InputFlags.cpp
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 #include <com_android_input_flags.h>
+#include <com_android_window_flags.h>
 #include <cutils/properties.h>
 
 #include <string>
@@ -25,6 +26,9 @@
 namespace android {
 
 bool InputFlags::connectedDisplaysCursorEnabled() {
+    if (!com::android::window::flags::enable_desktop_mode_through_dev_option()) {
+        return com::android::input::flags::connected_displays_cursor();
+    }
     static std::optional<bool> cachedDevOption;
     if (!cachedDevOption.has_value()) {
         char value[PROPERTY_VALUE_MAX];
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 1c0c9e7..983bbde 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -239,3 +239,13 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "enable_display_topology_validation"
+  namespace: "input"
+  description: "Set to true to enable display topology validation"
+  bug: "401219231"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 18d47f6..677cf1e 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -52,6 +52,7 @@
         "AnrTracker_test.cpp",
         "CapturedTouchpadEventConverter_test.cpp",
         "CursorInputMapper_test.cpp",
+        "DisplayTopologyGraph_test.cpp",
         "EventHub_test.cpp",
         "FakeEventHub.cpp",
         "FakeInputReaderPolicy.cpp",
diff --git a/services/inputflinger/tests/DisplayTopologyGraph_test.cpp b/services/inputflinger/tests/DisplayTopologyGraph_test.cpp
new file mode 100644
index 0000000..fd2f21c
--- /dev/null
+++ b/services/inputflinger/tests/DisplayTopologyGraph_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <input/DisplayTopologyGraph.h>
+
+#include <string>
+#include <string_view>
+#include <tuple>
+
+namespace android {
+
+namespace {
+
+constexpr ui::LogicalDisplayId DISPLAY_ID_1{1};
+constexpr ui::LogicalDisplayId DISPLAY_ID_2{2};
+constexpr int DENSITY_MEDIUM = 160;
+
+} // namespace
+
+using DisplayTopologyGraphTestFixtureParam =
+        std::tuple<std::string_view /*name*/, DisplayTopologyGraph, bool /*isValid*/>;
+
+class DisplayTopologyGraphTestFixture
+      : public testing::Test,
+        public testing::WithParamInterface<DisplayTopologyGraphTestFixtureParam> {};
+
+TEST_P(DisplayTopologyGraphTestFixture, DisplayTopologyGraphTest) {
+    const auto& [_, displayTopology, isValid] = GetParam();
+    EXPECT_EQ(isValid, displayTopology.isValid());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        DisplayTopologyGraphTest, DisplayTopologyGraphTestFixture,
+        testing::Values(
+                std::make_tuple(
+                        "InvalidPrimaryDisplay",
+                        DisplayTopologyGraph{.primaryDisplayId = ui::LogicalDisplayId::INVALID,
+                                             .graph = {},
+                                             .displaysDensity = {}},
+                        false),
+                std::make_tuple("PrimaryDisplayNotInGraph",
+                                DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                                     .graph = {},
+                                                     .displaysDensity = {}},
+                                false),
+                std::make_tuple("DisplayDensityMissing",
+                                DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                                     .graph = {{DISPLAY_ID_1, {}}},
+                                                     .displaysDensity = {}},
+                                false),
+                std::make_tuple("ValidSingleDisplayTopology",
+                                DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                                     .graph = {{DISPLAY_ID_1, {}}},
+                                                     .displaysDensity = {{DISPLAY_ID_1,
+                                                                          DENSITY_MEDIUM}}},
+                                true),
+                std::make_tuple(
+                        "MissingReverseEdge",
+                        DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                             .graph = {{DISPLAY_ID_1,
+                                                        {{DISPLAY_ID_2,
+                                                          DisplayTopologyPosition::TOP, 0}}}},
+                                             .displaysDensity = {{DISPLAY_ID_1, DENSITY_MEDIUM},
+                                                                 {DISPLAY_ID_2, DENSITY_MEDIUM}}},
+                        false),
+                std::make_tuple(
+                        "IncorrectReverseEdgeDirection",
+                        DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                             .graph = {{DISPLAY_ID_1,
+                                                        {{DISPLAY_ID_2,
+                                                          DisplayTopologyPosition::TOP, 0}}},
+                                                       {DISPLAY_ID_2,
+                                                        {{DISPLAY_ID_1,
+                                                          DisplayTopologyPosition::TOP, 0}}}},
+                                             .displaysDensity = {{DISPLAY_ID_1, DENSITY_MEDIUM},
+                                                                 {DISPLAY_ID_2, DENSITY_MEDIUM}}},
+                        false),
+                std::make_tuple(
+                        "IncorrectReverseEdgeOffset",
+                        DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                             .graph = {{DISPLAY_ID_1,
+                                                        {{DISPLAY_ID_2,
+                                                          DisplayTopologyPosition::TOP, 10}}},
+                                                       {DISPLAY_ID_2,
+                                                        {{DISPLAY_ID_1,
+                                                          DisplayTopologyPosition::BOTTOM, 20}}}},
+                                             .displaysDensity = {{DISPLAY_ID_1, DENSITY_MEDIUM},
+                                                                 {DISPLAY_ID_2, DENSITY_MEDIUM}}},
+                        false),
+                std::make_tuple(
+                        "ValidMultiDisplayTopology",
+                        DisplayTopologyGraph{.primaryDisplayId = DISPLAY_ID_1,
+                                             .graph = {{DISPLAY_ID_1,
+                                                        {{DISPLAY_ID_2,
+                                                          DisplayTopologyPosition::TOP, 10}}},
+                                                       {DISPLAY_ID_2,
+                                                        {{DISPLAY_ID_1,
+                                                          DisplayTopologyPosition::BOTTOM, -10}}}},
+                                             .displaysDensity = {{DISPLAY_ID_1, DENSITY_MEDIUM},
+                                                                 {DISPLAY_ID_2, DENSITY_MEDIUM}}},
+                        true)),
+        [](const testing::TestParamInfo<DisplayTopologyGraphTestFixtureParam>& p) {
+            return std::string{std::get<0>(p.param)};
+        });
+
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index de1d13a..b30cf20 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1389,7 +1389,8 @@
     // or complex GPU shaders and it's expensive. We boost the GPU frequency so that
     // GPU composition can finish in time. We must reset GPU frequency afterwards,
     // because high frequency consumes extra battery.
-    const bool expensiveRenderingExpected =
+    const bool expensiveBlurs = mLayerRequestingBackgroundBlur != nullptr;
+    const bool expensiveRenderingExpected = expensiveBlurs ||
             std::any_of(clientCompositionLayers.begin(), clientCompositionLayers.end(),
                         [outputDataspace =
                                  clientCompositionDisplay.outputDataspace](const auto& layer) {