diff --git a/Core/Core.cpp b/Core/Core.cpp index 8beaecd685d5..87d3d40fd7cf 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -56,9 +56,10 @@ static bool windowHidden = false; static double lastActivity = 0.0; static double lastKeepAwake = 0.0; static GraphicsContext *graphicsContext; +static bool powerSaving = false; void Core_SetGraphicsContext(GraphicsContext *ctx) { - graphicsContext = ctx; + graphicsContext = ctx; } void Core_NotifyWindowHidden(bool hidden) { @@ -120,6 +121,14 @@ void Core_WaitInactive(int milliseconds) { } } +void Core_SetPowerSaving(bool mode) { + powerSaving = mode; +} + +bool Core_GetPowerSaving() { + return powerSaving; +} + bool UpdateScreenScale(int width, int height, bool smallWindow) { g_dpi = 72; g_dpi_scale = 1.0f; diff --git a/Core/Core.h b/Core/Core.h index 3cf96c8575f6..d21ec4847adb 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -52,3 +52,6 @@ bool UpdateScreenScale(int width, int height, bool smallWindow); // Don't run the core when minimized etc. void Core_NotifyWindowHidden(bool hidden); void Core_NotifyActivity(); + +void Core_SetPowerSaving(bool mode); +bool Core_GetPowerSaving(); diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 9b6012b07b29..e0a7ebaaf1c7 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -18,6 +18,7 @@ #include "Core/Reporting.h" #include "Common/CPUDetect.h" +#include "Core/Core.h" #include "Core/CoreTiming.h" #include "Core/Config.h" #include "Core/CwCheat.h" @@ -427,7 +428,7 @@ namespace Reporting postdata.Add("graphics", StringFromFormat("%d", payload.int1)); postdata.Add("speed", StringFromFormat("%d", payload.int2)); postdata.Add("gameplay", StringFromFormat("%d", payload.int3)); - postdata.Add("crc", StringFromFormat("%08x", RetrieveCRC())); + postdata.Add("crc", StringFromFormat("%08x", Core_GetPowerSaving() ? 0 : RetrieveCRC())); AddScreenshotData(postdata, payload.string2); payload.string1.clear(); payload.string2.clear(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 81669500d58f..fdf78a3d5d8f 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -196,6 +196,11 @@ void EmuScreen::bootComplete() { } } + if (Core_GetPowerSaving()) { + I18NCategory *sy = GetI18NCategory("System"); + osm.Show(sy->T("WARNING: Battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); + } + System_SendMessage("event", "startgame"); } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ba3401d71ac2..048a235c8a66 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -784,6 +784,14 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) { // Show for the same duration as the preview. osm.Show(msg, 2.0f, 0xFFFFFF, -1, true, "savestate_slot"); } + if (msg == "core_powerSaving") { + if (value != "false") { + I18NCategory *sy = GetI18NCategory("System"); + osm.Show(sy->T("WARNING: Battery save mode is on"), 2.0f, 0xFFFFFF, -1, true, "core_powerSaving"); + } + + Core_SetPowerSaving(value != "false"); + } } void NativeUpdate(InputState &input) { diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 3e3e5994af11..fcd7277e33ff 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -23,6 +23,7 @@ #include "UI/PauseScreen.h" #include "UI/ReportScreen.h" +#include "Core/Core.h" #include "Core/Reporting.h" #include "Core/Screenshot.h" #include "Core/System.h" @@ -224,7 +225,9 @@ void ReportScreen::CreateViews() { } #ifdef MOBILE_DEVICE - leftColumnItems->Add(new TextView(rp->T("FeedbackIncludeCRC", "Note: Battery will be used to send a disc CRC"), new LinearLayoutParams(Margins(12, 5, 0, 5))))->SetEnabledPtr(&enableReporting_); + if (!Core_GetPowerSaving()) { + leftColumnItems->Add(new TextView(rp->T("FeedbackIncludeCRC", "Note: Battery will be used to send a disc CRC"), new LinearLayoutParams(Margins(12, 5, 0, 5))))->SetEnabledPtr(&enableReporting_); + } #endif std::string path = GetSysDirectory(DIRECTORY_SCREENSHOT); diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index aeb77b7acdec..6bbf4bf570d0 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -96,6 +96,14 @@ + + + + + + + + diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 7213323bb3e6..99899c821d38 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -28,6 +28,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.PowerManager; import android.os.Vibrator; import android.text.InputType; import android.util.DisplayMetrics; @@ -272,6 +273,7 @@ public void Initialize() { javaGL = "true".equalsIgnoreCase(NativeApp.queryConfig("androidJavaGL")); sendInitialGrants(); + PowerSaveModeReceiver.initAndSend(this); // OK, config should be initialized, we can query for screen rotation. if (Build.VERSION.SDK_INT >= 9) { diff --git a/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java b/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java new file mode 100644 index 000000000000..1a016910d035 --- /dev/null +++ b/android/src/org/ppsspp/ppsspp/PowerSaveModeReceiver.java @@ -0,0 +1,81 @@ +package org.ppsspp.ppsspp; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Build; +import android.os.PowerManager; +import android.provider.Settings; + +public class PowerSaveModeReceiver extends BroadcastReceiver { + private static boolean isPowerSaving = false; + private static boolean isBatteryLow = false; + + @Override + public void onReceive(final Context context, final Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_LOW)) { + isBatteryLow = true; + } else if (action.equals(Intent.ACTION_BATTERY_OKAY)) { + isBatteryLow = false; + } + + sendPowerSaving(context); + } + + public static void initAndSend(final Activity activity) { + sendPowerSaving(activity); + + activity.getContentResolver().registerContentObserver(Settings.System.CONTENT_URI, true, new ContentObserver(null) { + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + + String key = uri.getPath(); + key = key.substring(key.lastIndexOf("/") + 1, key.length()); + if (key != null && (key.equals("user_powersaver_enable") || key.equals("psm_switch"))) { + PowerSaveModeReceiver.sendPowerSaving(activity); + } + } + }); + } + + @TargetApi(21) + private static boolean getNativePowerSaving(final Context context) { + final PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + return pm.isPowerSaveMode(); + } + + private static boolean getExtraPowerSaving(final Context context) { + // http://stackoverflow.com/questions/25065635/checking-for-power-saver-mode-programically + // HTC (Sense) + String htcValue = Settings.System.getString(context.getContentResolver(), "user_powersaver_enable"); + if (htcValue != null && htcValue.equals("1")) { + return true; + } + // Samsung (Touchwiz) + String samsungValue = Settings.System.getString(context.getContentResolver(), "psm_switch"); + if (samsungValue != null && samsungValue.equals("1")) { + return true; + } + return false; + } + + private static void sendPowerSaving(final Context context) { + if (Build.VERSION.SDK_INT >= 21) { + isPowerSaving = getNativePowerSaving(context) || getExtraPowerSaving(context); + } else { + isPowerSaving = getExtraPowerSaving(context); + } + + if (isBatteryLow || isPowerSaving) { + NativeApp.sendMessage("core_powerSaving", "true"); + } else { + NativeApp.sendMessage("core_powerSaving", "false"); + } + } +}