Merge "FrameRateCategory::NoPreference votes Min" into main
diff --git a/include/input/TraceTools.h b/include/input/TraceTools.h
index 70b23c5..81fc7af 100644
--- a/include/input/TraceTools.h
+++ b/include/input/TraceTools.h
@@ -19,7 +19,11 @@
 #include <utils/Trace.h>
 #include <optional>
 
-#define ATRACE_NAME_IF(condition, messageProvider)                                            \
-    const auto _trace_token = condition                                                       \
-            ? std::make_optional<android::ScopedTrace>(ATRACE_TAG, messageProvider().c_str()) \
+// A macro for tracing when the given condition is true.
+// This macro relies on the fact that only one branch of the ternary operator is evaluated. That
+// means if `message` is an expression that evaluates to a std::string value, the value will
+// not be computed unless the condition is true.
+#define ATRACE_NAME_IF(condition, message)                                            \
+    const auto _trace_token = condition                                               \
+            ? std::make_optional<android::ScopedTrace>(ATRACE_TAG, (message).c_str()) \
             : std::nullopt
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 2cf5123..8c36058 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -267,8 +267,8 @@
             layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
             layer_state_t::eColorTransformChanged | layer_state_t::eCornerRadiusChanged |
             layer_state_t::eFlagsChanged | layer_state_t::eTrustedOverlayChanged |
-            layer_state_t::eFrameRateChanged | layer_state_t::eFrameRateSelectionPriority |
-            layer_state_t::eFixedTransformHintChanged;
+            layer_state_t::eFrameRateChanged | layer_state_t::eFrameRateCategoryChanged |
+            layer_state_t::eFrameRateSelectionPriority | layer_state_t::eFixedTransformHintChanged;
 
     // Changes affecting data sent to input.
     static constexpr uint64_t INPUT_CHANGES = layer_state_t::eInputInfoChanged |
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 8656b26..36a01d3 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -33,6 +33,21 @@
     ],
 }
 
+/////////////////////////////////////////////////
+// flags
+/////////////////////////////////////////////////
+aconfig_declarations {
+    name: "aconfig_input_flags",
+    package: "com.android.input.flags",
+    srcs: ["input_flags.aconfig"],
+}
+
+cc_aconfig_library {
+    name: "aconfig_input_flags_c_lib",
+    aconfig_declarations: "aconfig_input_flags",
+    host_supported: true,
+}
+
 aidl_interface {
     name: "inputconstants",
     host_supported: true,
@@ -176,6 +191,7 @@
         "libtinyxml2",
         "libutils",
         "libvintf",
+        "server_configurable_flags",
     ],
 
     ldflags: [
@@ -196,6 +212,7 @@
     ],
 
     whole_static_libs: [
+        "aconfig_input_flags_c_lib",
         "libinput_rust_ffi",
     ],
 
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 5fec1a9..1f14396 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -23,9 +23,12 @@
 #include <log/log.h>
 #include <utils/Trace.h>
 
+#include <com_android_input_flags.h>
 #include <input/InputTransport.h>
 #include <input/TraceTools.h>
 
+namespace input_flags = com::android::input::flags;
+
 namespace {
 
 /**
@@ -139,7 +142,8 @@
  * Enable this via "adb shell setprop log.tag.InputTransportVerifyEvents DEBUG"
  */
 static bool verifyEvents() {
-    return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "VerifyEvents", ANDROID_LOG_INFO);
+    return input_flags::enable_outbound_event_verification() ||
+            __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "VerifyEvents", ANDROID_LOG_INFO);
 }
 
 template<typename T>
@@ -433,10 +437,10 @@
 }
 
 status_t InputChannel::sendMessage(const InputMessage* msg) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("sendMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32 ")",
-                            mName.c_str(), msg->header.seq, msg->header.type);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("sendMessage(inputChannel=%s, seq=0x%" PRIx32 ", type=0x%" PRIx32
+                                ")",
+                                mName.c_str(), msg->header.seq, msg->header.type));
     const size_t msgLength = msg->size();
     InputMessage cleanMsg;
     msg->getSanitizedCopy(&cleanMsg);
@@ -472,9 +476,8 @@
 }
 
 status_t InputChannel::receiveMessage(InputMessage* msg) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("receiveMessage(inputChannel=%s)", mName.c_str());
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("receiveMessage(inputChannel=%s)", mName.c_str()));
     ssize_t nRead;
     do {
         nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
@@ -580,11 +583,10 @@
                                          int32_t flags, int32_t keyCode, int32_t scanCode,
                                          int32_t metaState, int32_t repeatCount, nsecs_t downTime,
                                          nsecs_t eventTime) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishKeyEvent(inputChannel=%s, action=%s, keyCode=%s)",
-                            mChannel->getName().c_str(), KeyEvent::actionToString(action),
-                            KeyEvent::getLabel(keyCode));
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishKeyEvent(inputChannel=%s, action=%s, keyCode=%s)",
+                                mChannel->getName().c_str(), KeyEvent::actionToString(action),
+                                KeyEvent::getLabel(keyCode)));
     ALOGD_IF(debugTransportPublisher(),
              "channel '%s' publisher ~ %s: seq=%u, id=%d, deviceId=%d, source=%s, "
              "action=%s, flags=0x%x, keyCode=%s, scanCode=%d, metaState=0x%x, repeatCount=%d,"
@@ -626,11 +628,10 @@
         const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
         uint32_t pointerCount, const PointerProperties* pointerProperties,
         const PointerCoords* pointerCoords) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishMotionEvent(inputChannel=%s, action=%s)",
-                            mChannel->getName().c_str(),
-                            MotionEvent::actionToString(action).c_str());
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishMotionEvent(inputChannel=%s, action=%s)",
+                                mChannel->getName().c_str(),
+                                MotionEvent::actionToString(action).c_str()));
     if (verifyEvents()) {
         Result<void> result =
                 mInputVerifier.processMovement(deviceId, action, pointerCount, pointerProperties,
@@ -709,10 +710,9 @@
 }
 
 status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s)",
-                            mChannel->getName().c_str(), toString(hasFocus));
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s)",
+                                mChannel->getName().c_str(), toString(hasFocus)));
     ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: seq=%u, id=%d, hasFocus=%s",
              mChannel->getName().c_str(), __func__, seq, eventId, toString(hasFocus));
 
@@ -726,10 +726,9 @@
 
 status_t InputPublisher::publishCaptureEvent(uint32_t seq, int32_t eventId,
                                              bool pointerCaptureEnabled) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishCaptureEvent(inputChannel=%s, pointerCaptureEnabled=%s)",
-                            mChannel->getName().c_str(), toString(pointerCaptureEnabled));
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishCaptureEvent(inputChannel=%s, pointerCaptureEnabled=%s)",
+                                mChannel->getName().c_str(), toString(pointerCaptureEnabled)));
     ALOGD_IF(debugTransportPublisher(),
              "channel '%s' publisher ~ %s: seq=%u, id=%d, pointerCaptureEnabled=%s",
              mChannel->getName().c_str(), __func__, seq, eventId, toString(pointerCaptureEnabled));
@@ -744,10 +743,9 @@
 
 status_t InputPublisher::publishDragEvent(uint32_t seq, int32_t eventId, float x, float y,
                                           bool isExiting) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishDragEvent(inputChannel=%s, x=%f, y=%f, isExiting=%s)",
-                            mChannel->getName().c_str(), x, y, toString(isExiting));
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishDragEvent(inputChannel=%s, x=%f, y=%f, isExiting=%s)",
+                                mChannel->getName().c_str(), x, y, toString(isExiting)));
     ALOGD_IF(debugTransportPublisher(),
              "channel '%s' publisher ~ %s: seq=%u, id=%d, x=%f, y=%f, isExiting=%s",
              mChannel->getName().c_str(), __func__, seq, eventId, x, y, toString(isExiting));
@@ -763,10 +761,9 @@
 }
 
 status_t InputPublisher::publishTouchModeEvent(uint32_t seq, int32_t eventId, bool isInTouchMode) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("publishTouchModeEvent(inputChannel=%s, isInTouchMode=%s)",
-                            mChannel->getName().c_str(), toString(isInTouchMode));
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("publishTouchModeEvent(inputChannel=%s, isInTouchMode=%s)",
+                                mChannel->getName().c_str(), toString(isInTouchMode)));
     ALOGD_IF(debugTransportPublisher(),
              "channel '%s' publisher ~ %s: seq=%u, id=%d, isInTouchMode=%s",
              mChannel->getName().c_str(), __func__, seq, eventId, toString(isInTouchMode));
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
new file mode 100644
index 0000000..1f29a00
--- /dev/null
+++ b/libs/input/input_flags.aconfig
@@ -0,0 +1,15 @@
+package: "com.android.input.flags"
+
+flag {
+  name: "enable_outbound_event_verification"
+  namespace: "input"
+  description: "Set to true to enable crashing whenever bad outbound events are detected inside InputTransport"
+  bug: "271455682"
+}
+
+flag {
+  name: "enable_inbound_event_verification"
+  namespace: "input"
+  description: "Set to true to enable crashing whenever bad inbound events are going into InputDispatcher"
+  bug: "271455682"
+}
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index e7224ff..138898f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -62,6 +62,7 @@
         "libtinyxml2",
         "libutils",
         "libvintf",
+        "server_configurable_flags",
     ],
     data: [
         "data/*",
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index d319d6d..1f17c16 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -114,73 +114,64 @@
 
 void TracedInputListener::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyKey(const NotifyKeyArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyMotion(const NotifyMotionArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifySwitch(const NotifySwitchArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifySensor(const NotifySensorArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyVibratorState(const NotifyVibratorStateArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
 void TracedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
     constexpr static auto& fnName = __func__;
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("%s::%s(id=0x%" PRIx32 ")", mName, fnName, args.id));
     mInnerListener.notify(args);
 }
 
diff --git a/services/inputflinger/dispatcher/DebugConfig.h b/services/inputflinger/dispatcher/DebugConfig.h
index 7a41d68..c7d98ab 100644
--- a/services/inputflinger/dispatcher/DebugConfig.h
+++ b/services/inputflinger/dispatcher/DebugConfig.h
@@ -19,6 +19,9 @@
 #define LOG_TAG "InputDispatcher"
 
 #include <android-base/logging.h>
+#include <com_android_input_flags.h>
+
+namespace input_flags = com::android::input::flags;
 
 namespace android::inputdispatcher {
 
@@ -102,7 +105,7 @@
  * Crash if a bad stream from InputListener is detected.
  * Enable this via "adb shell setprop log.tag.InputDispatcherVerifyEvents DEBUG" (requires restart)
  */
-const bool DEBUG_VERIFY_EVENTS =
+const bool DEBUG_VERIFY_EVENTS = input_flags::enable_inbound_event_verification() ||
         android::base::ShouldLog(android::base::LogSeverity::DEBUG, LOG_TAG "VerifyEvents");
 
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 8b7a99b..d98641e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -3183,10 +3183,9 @@
                                                  const std::shared_ptr<Connection>& connection,
                                                  std::shared_ptr<EventEntry> eventEntry,
                                                  const InputTarget& inputTarget) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
-                            connection->getInputChannelName().c_str(), eventEntry->id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+                                connection->getInputChannelName().c_str(), eventEntry->id));
     if (DEBUG_DISPATCH_CYCLE) {
         ALOGD("channel '%s' ~ prepareDispatchCycle - flags=%s, "
               "globalScaleFactor=%f, pointerIds=%s %s",
@@ -3251,10 +3250,9 @@
                                                    const std::shared_ptr<Connection>& connection,
                                                    std::shared_ptr<EventEntry> eventEntry,
                                                    const InputTarget& inputTarget) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
-                            connection->getInputChannelName().c_str(), eventEntry->id);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+                                connection->getInputChannelName().c_str(), eventEntry->id));
     LOG_ALWAYS_FATAL_IF(!inputTarget.flags.any(InputTarget::DISPATCH_MASK),
                         "No dispatch flags are set for %s", eventEntry->getDescription().c_str());
 
@@ -3570,10 +3568,9 @@
 
 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
                                                const std::shared_ptr<Connection>& connection) {
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
-                            connection->getInputChannelName().c_str());
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
+                                connection->getInputChannelName().c_str()));
     if (DEBUG_DISPATCH_CYCLE) {
         ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
     }
@@ -4147,10 +4144,10 @@
     }
 
     int32_t newId = mIdGenerator.nextId();
-    ATRACE_NAME_IF(ATRACE_ENABLED(), [&]() {
-        return StringPrintf("Split MotionEvent(id=0x%" PRIx32 ") to MotionEvent(id=0x%" PRIx32 ").",
-                            originalMotionEntry.id, newId);
-    });
+    ATRACE_NAME_IF(ATRACE_ENABLED(),
+                   StringPrintf("Split MotionEvent(id=0x%" PRIx32 ") to MotionEvent(id=0x%" PRIx32
+                                ").",
+                                originalMotionEntry.id, newId));
     std::unique_ptr<MotionEntry> splitMotionEntry =
             std::make_unique<MotionEntry>(newId, originalMotionEntry.eventTime,
                                           originalMotionEntry.deviceId, originalMotionEntry.source,
diff --git a/services/inputflinger/dispatcher/LatencyAggregator.cpp b/services/inputflinger/dispatcher/LatencyAggregator.cpp
index 96d78c3..e09d97a 100644
--- a/services/inputflinger/dispatcher/LatencyAggregator.cpp
+++ b/services/inputflinger/dispatcher/LatencyAggregator.cpp
@@ -126,6 +126,7 @@
 }
 
 void LatencyAggregator::processStatistics(const InputEventTimeline& timeline) {
+    std::scoped_lock lock(mLock);
     // Before we do any processing, check that we have not yet exceeded MAX_SIZE
     if (mNumSketchEventsProcessed >= MAX_EVENTS_FOR_STATISTICS) {
         return;
@@ -167,6 +168,7 @@
 }
 
 AStatsManager_PullAtomCallbackReturn LatencyAggregator::pullData(AStatsEventList* data) {
+    std::scoped_lock lock(mLock);
     std::array<std::unique_ptr<SafeBytesField>, SketchIndex::SIZE> serializedDownData;
     std::array<std::unique_ptr<SafeBytesField>, SketchIndex::SIZE> serializedMoveData;
     for (size_t i = 0; i < SketchIndex::SIZE; i++) {
@@ -257,6 +259,7 @@
 }
 
 std::string LatencyAggregator::dump(const char* prefix) const {
+    std::scoped_lock lock(mLock);
     std::string sketchDump = StringPrintf("%s  Sketches:\n", prefix);
     for (size_t i = 0; i < SketchIndex::SIZE; i++) {
         const int64_t numDown = mDownSketches[i]->num_values();
diff --git a/services/inputflinger/dispatcher/LatencyAggregator.h b/services/inputflinger/dispatcher/LatencyAggregator.h
index 60b6813..d6d1686 100644
--- a/services/inputflinger/dispatcher/LatencyAggregator.h
+++ b/services/inputflinger/dispatcher/LatencyAggregator.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <android-base/thread_annotations.h>
 #include <kll.h>
 #include <statslog.h>
 #include <utils/Timers.h>
@@ -61,10 +62,13 @@
     ~LatencyAggregator();
 
 private:
+    // Binder call -- called on a binder thread. This is different from the thread where the rest of
+    // the public API is called.
     static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atom_tag,
                                                                  AStatsEventList* data,
                                                                  void* cookie);
     AStatsManager_PullAtomCallbackReturn pullData(AStatsEventList* data);
+
     // ---------- Slow event handling ----------
     void processSlowEvent(const InputEventTimeline& timeline);
     nsecs_t mLastSlowEventTime = 0;
@@ -74,14 +78,17 @@
     size_t mNumEventsSinceLastSlowEventReport = 0;
 
     // ---------- Statistics handling ----------
+    // Statistics is pulled rather than pushed. It's pulled on a binder thread, and therefore will
+    // be accessed by two different threads. The lock is needed to protect the pulled data.
+    mutable std::mutex mLock;
     void processStatistics(const InputEventTimeline& timeline);
     // Sketches
     std::array<std::unique_ptr<dist_proc::aggregation::KllQuantile>, SketchIndex::SIZE>
-            mDownSketches;
+            mDownSketches GUARDED_BY(mLock);
     std::array<std::unique_ptr<dist_proc::aggregation::KllQuantile>, SketchIndex::SIZE>
-            mMoveSketches;
+            mMoveSketches GUARDED_BY(mLock);
     // How many events have been processed so far
-    size_t mNumSketchEventsProcessed = 0;
+    size_t mNumSketchEventsProcessed GUARDED_BY(mLock) = 0;
 };
 
 } // namespace android::inputdispatcher
diff --git a/services/sensorservice/aidl/SensorManager.cpp b/services/sensorservice/aidl/SensorManager.cpp
index 08e00b4..2b6ea7c 100644
--- a/services/sensorservice/aidl/SensorManager.cpp
+++ b/services/sensorservice/aidl/SensorManager.cpp
@@ -196,6 +196,11 @@
 sp<Looper> SensorManagerAidl::getLooper() {
     std::lock_guard<std::mutex> lock(mThreadMutex);
 
+    if (!mJavaVm) {
+        LOG(ERROR) << "No Java VM. This must be running in a test or fuzzer.";
+        return mLooper;
+    }
+
     if (!mPollThread.joinable()) {
         // if thread not initialized, start thread
         mStopThread = false;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 1718e0b..71c75f9 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -7,6 +7,17 @@
     default_applicable_licenses: ["frameworks_native_license"],
 }
 
+aconfig_declarations {
+    name: "surfaceflinger_flags",
+    package: "com.android.graphics.surfaceflinger.flags",
+    srcs: ["surfaceflinger_flags.aconfig"],
+}
+
+cc_aconfig_library {
+    name: "libsurfaceflingerflags",
+    aconfig_declarations: "surfaceflinger_flags",
+}
+
 cc_defaults {
     name: "surfaceflinger_defaults",
     cflags: [
@@ -20,6 +31,9 @@
         "-Wconversion",
         "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
+    static_libs: [
+        "libsurfaceflingerflags",
+    ],
 }
 
 cc_defaults {
@@ -84,6 +98,7 @@
         "libshaders",
         "libtimestats",
         "libtonemap",
+        "libsurfaceflingerflags",
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 38dc435..517dc96 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -161,6 +161,8 @@
 #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
 #include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
 
+#include <com_android_graphics_surfaceflinger_flags.h>
+
 #undef NO_THREAD_SAFETY_ANALYSIS
 #define NO_THREAD_SAFETY_ANALYSIS \
     _Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"")
@@ -170,6 +172,7 @@
 #define DOES_CONTAIN_BORDER false
 
 namespace android {
+using namespace com::android::graphics::surfaceflinger;
 
 using namespace std::chrono_literals;
 using namespace std::string_literals;
@@ -490,6 +493,10 @@
             base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, true);
     mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled ||
             base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false);
+
+    // Trunk-Stable flags
+    mMiscFlagValue = flags::misc1();
+    mConnectedDisplayFlagValue = flags::connected_display();
 }
 
 LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() {
@@ -731,6 +738,8 @@
             enableRefreshRateOverlay(true);
         }
     }));
+
+    LOG_ALWAYS_FATAL_IF(flags::misc1() != mMiscFlagValue, "misc1 flag is not boot stable!");
 }
 
 static std::optional<renderengine::RenderEngine::RenderEngineType>
@@ -5912,6 +5921,7 @@
             }
         }
     }
+
     write(fd, result.c_str(), result.size());
     return NO_ERROR;
 }
@@ -6333,6 +6343,10 @@
     result.append("SurfaceFlinger global state:\n");
     colorizer.reset(result);
 
+    StringAppendF(&result, "MiscFlagValue: %s\n", mMiscFlagValue ? "true" : "false");
+    StringAppendF(&result, "ConnectedDisplayFlagValue: %s\n",
+                  mConnectedDisplayFlagValue ? "true" : "false");
+
     getRenderEngine().dump(result);
 
     result.append("ClientCache state:\n");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index dc4e7cf..59b1172 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1450,6 +1450,10 @@
     void sfdo_setDebugFlash(int delay);
     void sfdo_scheduleComposite();
     void sfdo_scheduleCommit();
+
+    // Trunk-Stable flags
+    bool mMiscFlagValue;
+    bool mConnectedDisplayFlagValue;
 };
 
 class SurfaceComposerAIDL : public gui::BnSurfaceComposer {
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
new file mode 100644
index 0000000..f47ed45
--- /dev/null
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -0,0 +1,17 @@
+package: "com.android.graphics.surfaceflinger.flags"
+
+flag {
+  name: "misc1"
+  namespace: "core_graphics"
+  description: "This flag controls minor miscellaneous SurfaceFlinger changes"
+  bug: "297389311"
+  is_fixed_read_only: true
+}
+
+flag {
+  name: "connected_display"
+  namespace: "core_graphics"
+  description: "Controls SurfaceFlinger support for Connected Displays"
+  bug: "278199093"
+  is_fixed_read_only: true
+}
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 72ed4c8..2353480 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -667,6 +667,8 @@
               scheduler::LayerInfo::FrameRateCompatibility::Default);
     EXPECT_EQ(getSnapshot({.id = 122})->frameRate.category, FrameRateCategory::Normal);
     EXPECT_TRUE(getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::FrameRate));
+    EXPECT_TRUE(
+            getSnapshot({.id = 122})->changes.test(RequestedLayerState::Changes::AffectsChildren));
 
     EXPECT_FALSE(getSnapshot({.id = 1221})->frameRate.vote.rate.isValid());
     EXPECT_TRUE(getSnapshot({.id = 1221})->frameRate.isValid());
@@ -674,6 +676,8 @@
               scheduler::LayerInfo::FrameRateCompatibility::Default);
     EXPECT_EQ(getSnapshot({.id = 1221})->frameRate.category, FrameRateCategory::Normal);
     EXPECT_TRUE(getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::FrameRate));
+    EXPECT_TRUE(
+            getSnapshot({.id = 1221})->changes.test(RequestedLayerState::Changes::AffectsChildren));
 
     // reparent and verify the child does NOT get the new parent's framerate because it already has
     // the frame rate category specified.