refactor(events): Simplify ScopedCallback creation with type deduction

Introduce a new template overload for `makeScopedCallback` that
automatically deduces the event type from the provided callback's
signature. This is achieved using a `function_traits` helper to inspect
the lambda's arguments.

Previously, creating a scoped callback was verbose:
auto handle = android::base::makeScopedCallback<
    SomeCallbackSource<MyEvent>, MyEvent>
    (source, [](const MyEvent& event) {});

Now, the compiler can deduce the template arguments automatically:
auto handle = android::base::makeScopedCallback(
    source, [](const MyEvent& event) {});

Change-Id: I4a95ba8715ea331d964c7a302afd65b31adcae55
diff --git a/base/include/aemu/base/events/CallbackEventSupport.h b/base/include/aemu/base/events/CallbackEventSupport.h
index 704e0cf..8acea21 100644
--- a/base/include/aemu/base/events/CallbackEventSupport.h
+++ b/base/include/aemu/base/events/CallbackEventSupport.h
@@ -439,5 +439,24 @@
                         typename ScopedEventCallback<EventSystem, T>::EventCallback callback) {
     return std::make_unique<ScopedEventCallback<EventSystem, T>>(system, std::move(callback));
 }
+
+// Helper to deduce the event type from a lambda's signature
+template <typename T> struct function_traits;
+template <typename ClassType, typename ReturnType, typename Arg>
+struct function_traits<ReturnType (ClassType::*)(Arg) const> { using event_type = std::decay_t<Arg>; };
+template <typename ClassType, typename ReturnType>
+struct function_traits<ReturnType (ClassType::*)() const> { using event_type = void; };
+
+/**
+ * @brief Helper function to create a ScopedEventCallback with automatic type deduction.
+ * @param system Reference to the event system
+ * @param callback The callback function
+ * @return A new ScopedEventCallback instance
+ */
+template <typename EventSystem, typename F>
+auto makeScopedCallback(EventSystem& system, F&& callback) {
+    using T = typename function_traits<decltype(&F::operator())>::event_type;
+    return std::make_unique<ScopedEventCallback<EventSystem, T>>(system, std::forward<F>(callback));
+}
 }  // namespace base
 }  // namespace android
\ No newline at end of file
diff --git a/base/tests/CallbackEvent_unittest.cpp b/base/tests/CallbackEvent_unittest.cpp
index 3a28900..537cbf6 100644
--- a/base/tests/CallbackEvent_unittest.cpp
+++ b/base/tests/CallbackEvent_unittest.cpp
@@ -86,7 +86,7 @@
     int count = 0;
     {
         auto scoped =
-            makeScopedCallback<TestEventSystem, int>(events, [&count](const int&) { count++; });
+            makeScopedCallback(events, [&count](const int&) { count++; });
 
         EXPECT_EQ(events.callbackCount(), 1);
         events.triggerEvent(42);
@@ -101,7 +101,7 @@
 TEST_F(CallbackTests, ScopedCallbackMove) {
     int count = 0;
     auto scoped =
-        makeScopedCallback<TestEventSystem, int>(events, [&count](const int&) { count++; });
+        makeScopedCallback(events, [&count](const int&) { count++; });
 
     // Move the callback
     auto moved = std::move(scoped);
@@ -197,7 +197,7 @@
 // Memory leak tests (requires running with sanitizers)
 TEST_F(CallbackTests, NoMemoryLeaks) {
     for (int i = 0; i < 1000; ++i) {
-        auto scoped = makeScopedCallback<TestEventSystem, int>(events, [](const int&) {});
+        auto scoped = makeScopedCallback(events, [](const int&) {});
         events.triggerEvent(42);
     }
     EXPECT_EQ(events.callbackCount(), 0);