summaryrefslogtreecommitdiff
path: root/Source/Android/jni/HotkeyScheduler.cpp
diff options
context:
space:
mode:
authorvisarhoxha <vhoxha08@gmail.com>2026-09-24 00:30:54 +0200
committervisarhoxha <vhoxha08@gmail.com>2026-10-19 12:22:32 +0200
commitf0ef80016182ef0a79fd8b100b35ed906f954044 (patch)
tree7f2f1cca208245bc270bd4abfb72e84ca0ca1b3e /Source/Android/jni/HotkeyScheduler.cpp
parent301182532074dae57a4b23ff508308485c122ea8 (diff)
Android: Avoid constant hotkey polling to save battery
Only poll for hotkeys while EmulationActivity is resumed and at least one supported hotkey is mapped. Otherwise the scheduler thread waits on an event instead of polling.
Diffstat (limited to 'Source/Android/jni/HotkeyScheduler.cpp')
-rw-r--r--Source/Android/jni/HotkeyScheduler.cpp84
1 files changed, 75 insertions, 9 deletions
diff --git a/Source/Android/jni/HotkeyScheduler.cpp b/Source/Android/jni/HotkeyScheduler.cpp
index bb360d1e2a..85d981f755 100644
--- a/Source/Android/jni/HotkeyScheduler.cpp
+++ b/Source/Android/jni/HotkeyScheduler.cpp
@@ -3,6 +3,7 @@
#include "jni/HotkeyScheduler.h"
+#include <chrono>
#include <cmath>
#include <jni.h>
#include <thread>
@@ -13,6 +14,7 @@
#include "AudioCommon/AudioCommon.h"
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
+#include "Common/Event.h"
#include "Common/Flag.h"
#include "Common/Thread.h"
#include "Core/Config/GraphicsSettings.h"
@@ -22,6 +24,8 @@
#include "Core/State.h"
#include "Core/System.h"
#include "InputCommon/ControlReference/ControlReference.h"
+#include "InputCommon/ControllerEmu/Control/Control.h"
+#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoConfig.h"
@@ -34,6 +38,8 @@ constexpr int POLL_INTERVAL_MS = 5;
std::thread s_thread;
Common::Flag s_stop_requested;
+Common::Flag s_any_hotkey_set;
+Common::Event s_wakeup;
int s_state_slot = 1;
@@ -42,6 +48,43 @@ bool IsHotkey(int id, bool held = false)
return HotkeyManagerEmu::IsPressed(id, held);
}
+bool IsAnyHotkeySet()
+{
+ InputConfig* const config = HotkeyManagerEmu::GetConfig();
+ if (config == nullptr || config->ControllersNeedToBeCreated())
+ return false;
+
+ auto* const hotkeys = static_cast<HotkeyManager*>(config->GetController(0));
+
+ for (const int hotkey : GetSupportedHotkeys())
+ {
+ const int group = hotkeys->FindGroupByID(hotkey);
+ const int index = hotkeys->GetIndexForGroup(group, hotkey);
+ const auto* const control_group =
+ HotkeyManagerEmu::GetHotkeyGroup(static_cast<HotkeyGroup>(group));
+
+ if (!control_group->controls[index]->control_ref->GetExpression().empty())
+ return true;
+ }
+
+ return false;
+}
+
+bool ShouldPoll()
+{
+ if (!s_any_hotkey_set.IsSet() || !HotkeyManagerEmu::IsEnabled())
+ return false;
+
+ return Core::GetState(Core::System::GetInstance()) != Core::State::Stopping;
+}
+
+// Buttons already held when polling resumes must not count as new presses
+void ConsumePendingPresses()
+{
+ for (const int hotkey : GetSupportedHotkeys())
+ IsHotkey(hotkey);
+}
+
void ShowVolumeOSD()
{
OSD::AddMessage(
@@ -196,19 +239,24 @@ void Run()
{
Common::SetCurrentThreadName("HotkeyScheduler");
+ bool was_polling = false;
+
while (!s_stop_requested.IsSet())
{
- Common::SleepCurrentThread(POLL_INTERVAL_MS);
+ if (!ShouldPoll())
+ {
+ was_polling = false;
+ s_wakeup.Wait();
+ continue;
+ }
- ControllerInterface::SetCurrentInputChannel(ciface::InputChannel::Host);
- g_controller_interface.UpdateInput();
+ s_wakeup.WaitFor(std::chrono::milliseconds(POLL_INTERVAL_MS));
- if (!HotkeyManagerEmu::IsEnabled())
- continue;
+ if (s_stop_requested.IsSet())
+ break;
- Core::System& system = Core::System::GetInstance();
- if (Core::GetState(system) == Core::State::Stopping)
- continue;
+ ControllerInterface::SetCurrentInputChannel(ciface::InputChannel::Host);
+ g_controller_interface.UpdateInput();
ControlReference::SetInputGate(true);
@@ -217,6 +265,15 @@ void Run()
HotkeyManagerEmu::GetStatus(false);
HotkeyManagerEmu::GetStatus(true);
+ if (!was_polling)
+ {
+ ConsumePendingPresses();
+ was_polling = true;
+ continue;
+ }
+
+ Core::System& system = Core::System::GetInstance();
+
HandleGeneralHotkeys();
HandleEmulationSpeedHotkeys();
HandleVolumeHotkeys(system);
@@ -231,9 +288,10 @@ void Start()
if (s_thread.joinable())
return;
- HotkeyManagerEmu::Enable(true);
s_state_slot = 1;
+ s_any_hotkey_set.Set(IsAnyHotkeySet());
s_stop_requested.Clear();
+ s_wakeup.Reset();
s_thread = std::thread(Run);
}
@@ -243,11 +301,18 @@ void Stop()
return;
s_stop_requested.Set();
+ s_wakeup.Set();
s_thread.join();
Core::SetIsThrottlerTempDisabled(false);
}
+void RefreshActiveHotkeys()
+{
+ s_any_hotkey_set.Set(IsAnyHotkeySet());
+ s_wakeup.Set();
+}
+
const std::vector<int>& GetSupportedHotkeys()
{
static const std::vector<int> supported = [] {
@@ -294,5 +359,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_Hotke
JNIEnv*, jclass, jboolean enabled)
{
HotkeyManagerEmu::Enable(enabled == JNI_TRUE);
+ HotkeyScheduler::RefreshActiveHotkeys();
}
}