diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java index c197c002b0..e0816e408b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/DolphinApplication.java @@ -6,6 +6,7 @@ import android.app.Application; import android.content.Context; import android.hardware.usb.UsbManager; +import org.dolphinemu.dolphinemu.utils.ActivityTracker; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.Java_GCAdapter; import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter; @@ -20,6 +21,7 @@ public class DolphinApplication extends Application { super.onCreate(); application = this; + registerActivityLifecycleCallbacks(new ActivityTracker()); VolleyUtil.init(getApplicationContext()); System.loadLibrary("main"); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt new file mode 100644 index 0000000000..b3a6a5d91a --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ActivityTracker.kt @@ -0,0 +1,41 @@ +package org.dolphinemu.dolphinemu.utils + +import android.app.Activity +import android.app.Application.ActivityLifecycleCallbacks +import android.os.Bundle + +class ActivityTracker : ActivityLifecycleCallbacks { + val resumedActivities = HashSet() + var backgroundExecutionAllowed = false + + override fun onActivityCreated(activity: Activity, bundle: Bundle?) {} + + override fun onActivityStarted(activity: Activity) {} + + override fun onActivityResumed(activity: Activity) { + resumedActivities.add(activity) + if (!backgroundExecutionAllowed && !resumedActivities.isEmpty()) { + backgroundExecutionAllowed = true + setBackgroundExecutionAllowedNative(true) + } + } + + override fun onActivityPaused(activity: Activity) { + resumedActivities.remove(activity) + if (backgroundExecutionAllowed && resumedActivities.isEmpty()) { + backgroundExecutionAllowed = false + setBackgroundExecutionAllowedNative(false) + } + } + + override fun onActivityStopped(activity: Activity) {} + + override fun onActivitySaveInstanceState(activity: Activity, bundle: Bundle) {} + + override fun onActivityDestroyed(activity: Activity) {} + + companion object { + @JvmStatic + external fun setBackgroundExecutionAllowedNative(allowed: Boolean) + } +} diff --git a/Source/Android/jni/ActivityTracker.cpp b/Source/Android/jni/ActivityTracker.cpp new file mode 100644 index 0000000000..b871890576 --- /dev/null +++ b/Source/Android/jni/ActivityTracker.cpp @@ -0,0 +1,21 @@ +// Copyright 2024 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include + +#include "Common/Logging/Log.h" +#include "Core/AchievementManager.h" + +extern "C" { + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_utils_ActivityTracker_setBackgroundExecutionAllowedNative( + JNIEnv*, jclass, jboolean allowed) +{ + // This is called with allowed == false when the app goes into the background. + // We use this to stop continuously running background threads so we don't waste battery. + + INFO_LOG_FMT(CORE, "SetBackgroundExecutionAllowed {}", allowed); + AchievementManager::GetInstance().SetBackgroundExecutionAllowed(allowed); +} +} diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index ab2acc7063..7ddae94c07 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -1,4 +1,5 @@ add_library(main SHARED + ActivityTracker.cpp Cheats/ARCheat.cpp Cheats/Cheats.h Cheats/GeckoCheat.cpp @@ -11,6 +12,7 @@ add_library(main SHARED GameList/GameFile.cpp GameList/GameFile.h GameList/GameFileCache.cpp + GpuDriver.cpp Host.cpp Host.h InfinityConfig.cpp @@ -32,7 +34,6 @@ add_library(main SHARED RiivolutionPatches.cpp SkylanderConfig.cpp WiiUtils.cpp - GpuDriver.cpp ) target_link_libraries(main diff --git a/Source/Core/Core/AchievementManager.cpp b/Source/Core/Core/AchievementManager.cpp index c85f6f0f59..8227df450b 100644 --- a/Source/Core/Core/AchievementManager.cpp +++ b/Source/Core/Core/AchievementManager.cpp @@ -158,6 +158,10 @@ bool AchievementManager::IsGameLoaded() const return game_info && game_info->id != 0; } +void AchievementManager::SetBackgroundExecutionAllowed(bool allowed) +{ +} + void AchievementManager::FetchPlayerBadge() { FetchBadge(&m_player_badge, RC_IMAGE_TYPE_USER, diff --git a/Source/Core/Core/AchievementManager.h b/Source/Core/Core/AchievementManager.h index c26d3bcf96..935b4c0948 100644 --- a/Source/Core/Core/AchievementManager.h +++ b/Source/Core/Core/AchievementManager.h @@ -96,6 +96,7 @@ public: bool HasAPIToken() const; void LoadGame(const std::string& file_path, const DiscIO::Volume* volume); bool IsGameLoaded() const; + void SetBackgroundExecutionAllowed(bool allowed); void FetchPlayerBadge(); void FetchGameBadges(); @@ -239,6 +240,8 @@ public: constexpr void LoadGame(const std::string&, const DiscIO::Volume*) {} + constexpr void SetBackgroundExecutionAllowed(bool allowed) {} + constexpr void DoFrame() {} constexpr void CloseGame() {}