-
Notifications
You must be signed in to change notification settings - Fork 18
Implement GPowerProfileMonitor for Android thermal and battery saver … #223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
0b3af06
0deb029
7cc324d
a0c83a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |
| #include "WKWebContext.h" | ||
| #include "WKWebView.h" | ||
| #include "WKWebsiteDataManager.h" | ||
| #include "WPEAndroidPowerProfileMonitor.h" | ||
|
|
||
| extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* javaVM, void* /*reserved*/) | ||
| { | ||
|
|
@@ -41,6 +42,8 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* javaVM, void* /*reserved*/) | |
| WKWebsiteDataManager::configureJNIMappings(); | ||
| WKWebView::configureJNIMappings(); | ||
| WKSettings::configureJNIMappings(); | ||
| WPEAndroidPowerProfileMonitor::configureJNIMappings(); | ||
| WPEAndroidPowerProfileMonitor::registerExtension(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the classes that may be registered using JNI we use the |
||
|
|
||
| return JNI::VERSION; | ||
| } catch (const std::exception& e) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,262 @@ | ||||||||||||||||
| /** | ||||||||||||||||
| * Copyright (C) 2025 maceip | ||||||||||||||||
| * | ||||||||||||||||
| * This library is free software; you can redistribute it and/or | ||||||||||||||||
| * modify it under the terms of the GNU Lesser General Public | ||||||||||||||||
| * License as published by the Free Software Foundation; either | ||||||||||||||||
| * version 2.1 of the License, or (at your option) any later version. | ||||||||||||||||
| * | ||||||||||||||||
| * This library is distributed in the hope that it will be useful, | ||||||||||||||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||||||||||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||||||||||||||
| * Lesser General Public License for more details. | ||||||||||||||||
| * | ||||||||||||||||
| * You should have received a copy of the GNU Lesser General Public | ||||||||||||||||
| * License along with this library; if not, write to the Free Software | ||||||||||||||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||||||||||||
| */ | ||||||||||||||||
|
|
||||||||||||||||
| #include "WPEAndroidPowerProfileMonitor.h" | ||||||||||||||||
|
|
||||||||||||||||
| #include "JNI/JNI.h" | ||||||||||||||||
| #include "Logging.h" | ||||||||||||||||
|
|
||||||||||||||||
| #include <atomic> | ||||||||||||||||
| #include <gio/gio.h> | ||||||||||||||||
|
|
||||||||||||||||
| // NDK Thermal API (API level 30+) - always include, use runtime detection | ||||||||||||||||
| #include <android/thermal.h> | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
| * WPEAndroidPowerProfileMonitor implements GPowerProfileMonitor for Android. | ||||||||||||||||
| * | ||||||||||||||||
| * Aggregates two signals to determine "Low Power Mode": | ||||||||||||||||
| * 1. Thermal Status (via NDK AThermalManager on API 30+) | ||||||||||||||||
| * 2. Battery Saver Mode (via Java PowerManager broadcast) | ||||||||||||||||
| * | ||||||||||||||||
| * When either thermal throttling is active (SEVERE or higher) or Battery Saver | ||||||||||||||||
| * mode is enabled, the monitor reports power-saver-enabled=TRUE to WebKit. | ||||||||||||||||
| */ | ||||||||||||||||
| struct _WPEAndroidPowerMonitor { | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be
Suggested change
|
||||||||||||||||
| GObject parentInstance; | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The convention when defining a subclass using GObject is to use the name
Suggested change
|
||||||||||||||||
|
|
||||||||||||||||
| AThermalManager* thermalManager; | ||||||||||||||||
|
|
||||||||||||||||
| // Thread-safe flags: NDK thermal callbacks occur on Binder threads, | ||||||||||||||||
| // JNI calls may be on UI thread | ||||||||||||||||
| std::atomic<bool> isBatterySaverActive; | ||||||||||||||||
| std::atomic<bool> isThermalThrottling; | ||||||||||||||||
|
Comment on lines
+47
to
+48
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using C++ types directly inside a struct allocated by GLib won't run constructors/destructors; the fact that this works in this case is by pure chance. Either use an inner struct that gets initialized using placement- |
||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| enum { PROP_0, PROP_POWER_SAVER_ENABLED, N_PROPERTIES }; | ||||||||||||||||
|
|
||||||||||||||||
| static WPEAndroidPowerMonitor* s_singleton = nullptr; | ||||||||||||||||
|
|
||||||||||||||||
| static void wpeAndroidPowerProfileMonitorIfaceInit(GPowerProfileMonitorInterface* iface); | ||||||||||||||||
|
|
||||||||||||||||
| G_DEFINE_FINAL_TYPE_WITH_CODE(WPEAndroidPowerMonitor, wpe_android_power_profile_monitor, G_TYPE_OBJECT, | ||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, GObject has strong conventions for the naming, and this does not build as-is, the type has to be named
Suggested change
|
||||||||||||||||
| G_IMPLEMENT_INTERFACE(G_TYPE_POWER_PROFILE_MONITOR, wpeAndroidPowerProfileMonitorIfaceInit)) | ||||||||||||||||
|
|
||||||||||||||||
| static void updatePowerStateOnMainThread(WPEAndroidPowerMonitor* self) | ||||||||||||||||
| { | ||||||||||||||||
| bool isPowerSaverEnabled = self->isBatterySaverActive.load() || self->isThermalThrottling.load(); | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: power-saver-enabled=%s (battery=%s, thermal=%s)", | ||||||||||||||||
| isPowerSaverEnabled ? "true" : "false", self->isBatterySaverActive.load() ? "true" : "false", | ||||||||||||||||
| self->isThermalThrottling.load() ? "true" : "false"); | ||||||||||||||||
|
|
||||||||||||||||
| g_object_notify(G_OBJECT(self), "power-saver-enabled"); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // AThermalStatus values: | ||||||||||||||||
| // ATHERMAL_STATUS_NONE = 0, LIGHT = 1, MODERATE = 2, SEVERE = 3, | ||||||||||||||||
| // CRITICAL = 4, EMERGENCY = 5, SHUTDOWN = 6 | ||||||||||||||||
|
Comment on lines
+70
to
+72
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment does not really add any interesting information, IMO it could be removed. |
||||||||||||||||
| static void onThermalStatusChanged(void* data, AThermalStatus status) | ||||||||||||||||
| { | ||||||||||||||||
| auto* self = WPE_ANDROID_POWER_PROFILE_MONITOR(data); | ||||||||||||||||
| bool throttling = (status >= ATHERMAL_STATUS_SEVERE); | ||||||||||||||||
|
|
||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::onThermalStatusChanged(%d, throttling=%s)", | ||||||||||||||||
| static_cast<int>(status), throttling ? "true" : "false"); | ||||||||||||||||
|
|
||||||||||||||||
| if (self->isThermalThrottling.load() != throttling) { | ||||||||||||||||
| self->isThermalThrottling.store(throttling); | ||||||||||||||||
| g_main_context_invoke( | ||||||||||||||||
| nullptr, | ||||||||||||||||
| +[](gpointer userData) -> gboolean { | ||||||||||||||||
| updatePowerStateOnMainThread(WPE_ANDROID_POWER_PROFILE_MONITOR(userData)); | ||||||||||||||||
| return G_SOURCE_REMOVE; | ||||||||||||||||
| }, | ||||||||||||||||
| self); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| DECLARE_JNI_CLASS_SIGNATURE(JNIWPEPowerMonitor, "org/wpewebkit/wpe/WPEPowerMonitor"); | ||||||||||||||||
|
|
||||||||||||||||
| class JNIWPEPowerMonitorCache final : public JNI::TypedClass<JNIWPEPowerMonitor> { | ||||||||||||||||
| public: | ||||||||||||||||
| JNIWPEPowerMonitorCache() | ||||||||||||||||
| : JNI::TypedClass<JNIWPEPowerMonitor>(true) | ||||||||||||||||
| { | ||||||||||||||||
| registerNativeMethods( | ||||||||||||||||
| JNI::StaticNativeMethod<void(jboolean)>("nativeOnPowerSaveModeChanged", nativeOnPowerSaveModeChanged)); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| private: | ||||||||||||||||
| static void nativeOnPowerSaveModeChanged(JNIEnv*, jclass, jboolean isPowerSave) | ||||||||||||||||
| { | ||||||||||||||||
| bool newVal = (isPowerSave != JNI_FALSE); | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::nativeOnPowerSaveModeChanged(%s)", newVal ? "true" : "false"); | ||||||||||||||||
| wpe_android_power_profile_monitor_set_battery_saver(newVal ? TRUE : FALSE); | ||||||||||||||||
| } | ||||||||||||||||
| }; | ||||||||||||||||
|
|
||||||||||||||||
| static const JNIWPEPowerMonitorCache& getJNIWPEPowerMonitorCache() | ||||||||||||||||
| { | ||||||||||||||||
| static const JNIWPEPowerMonitorCache s_singleton; | ||||||||||||||||
| return s_singleton; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| static void wpeAndroidPowerProfileMonitorIfaceInit(GPowerProfileMonitorInterface* iface) | ||||||||||||||||
| { | ||||||||||||||||
| // Interface implemented via "power-saver-enabled" property override | ||||||||||||||||
| (void)iface; | ||||||||||||||||
|
Comment on lines
+119
to
+122
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. C++ allows omitting the argument variable name, so we can do this:
Suggested change
|
||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| static void wpeAndroidPowerProfileMonitorGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* pspec) | ||||||||||||||||
| { | ||||||||||||||||
| auto* self = WPE_ANDROID_POWER_PROFILE_MONITOR(object); | ||||||||||||||||
|
|
||||||||||||||||
| switch (propId) { | ||||||||||||||||
| case PROP_POWER_SAVER_ENABLED: | ||||||||||||||||
| g_value_set_boolean( | ||||||||||||||||
| value, static_cast<gboolean>(self->isBatterySaverActive.load() || self->isThermalThrottling.load())); | ||||||||||||||||
| break; | ||||||||||||||||
| default: | ||||||||||||||||
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); | ||||||||||||||||
| break; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| static void wpe_android_power_profile_monitor_init(WPEAndroidPowerMonitor* self) | ||||||||||||||||
| { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::init(%p)", static_cast<void*>(self)); | ||||||||||||||||
|
|
||||||||||||||||
| s_singleton = self; | ||||||||||||||||
| self->thermalManager = nullptr; | ||||||||||||||||
| self->isBatterySaverActive.store(false); | ||||||||||||||||
| self->isThermalThrottling.store(false); | ||||||||||||||||
|
|
||||||||||||||||
| if (__builtin_available(android 30, *)) { | ||||||||||||||||
| self->thermalManager = AThermal_acquireManager(); | ||||||||||||||||
| if (self->thermalManager != nullptr) { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Thermal manager acquired"); | ||||||||||||||||
|
|
||||||||||||||||
| int result = AThermal_registerThermalStatusListener(self->thermalManager, onThermalStatusChanged, self); | ||||||||||||||||
| if (result == 0) { | ||||||||||||||||
| AThermalStatus status = AThermal_getCurrentThermalStatus(self->thermalManager); | ||||||||||||||||
| self->isThermalThrottling.store(status >= ATHERMAL_STATUS_SEVERE); | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Initial thermal status=%d, throttling=%s", | ||||||||||||||||
| static_cast<int>(status), self->isThermalThrottling.load() ? "true" : "false"); | ||||||||||||||||
| } else { | ||||||||||||||||
| Logging::logError("WPEAndroidPowerProfileMonitor: Failed to register thermal listener: %d", result); | ||||||||||||||||
| } | ||||||||||||||||
| } else { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Thermal manager not available"); | ||||||||||||||||
| } | ||||||||||||||||
| } else { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Thermal API not available (requires Android 11+)"); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| static void wpeAndroidPowerProfileMonitorDispose(GObject* object) | ||||||||||||||||
| { | ||||||||||||||||
| auto* self = WPE_ANDROID_POWER_PROFILE_MONITOR(object); | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::dispose(%p)", static_cast<void*>(object)); | ||||||||||||||||
|
|
||||||||||||||||
| if (__builtin_available(android 30, *)) { | ||||||||||||||||
| if (self->thermalManager != nullptr) { | ||||||||||||||||
| AThermal_unregisterThermalStatusListener(self->thermalManager, onThermalStatusChanged, self); | ||||||||||||||||
| AThermal_releaseManager(self->thermalManager); | ||||||||||||||||
| self->thermalManager = nullptr; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if (s_singleton == self) | ||||||||||||||||
| s_singleton = nullptr; | ||||||||||||||||
|
|
||||||||||||||||
| G_OBJECT_CLASS(wpe_android_power_profile_monitor_parent_class)->dispose(object); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| static void wpe_android_power_profile_monitor_class_init(WPEAndroidPowerMonitorClass* klass) | ||||||||||||||||
| { | ||||||||||||||||
| GObjectClass* objectClass = G_OBJECT_CLASS(klass); | ||||||||||||||||
| objectClass->dispose = wpeAndroidPowerProfileMonitorDispose; | ||||||||||||||||
| objectClass->get_property = wpeAndroidPowerProfileMonitorGetProperty; | ||||||||||||||||
|
|
||||||||||||||||
| g_object_class_override_property(objectClass, PROP_POWER_SAVER_ENABLED, "power-saver-enabled"); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void wpe_android_power_profile_monitor_set_battery_saver(gboolean isPowerSaveMode) | ||||||||||||||||
| { | ||||||||||||||||
| if (s_singleton == nullptr) { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::set_battery_saver called before init, ignoring"); | ||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| bool newValue = (isPowerSaveMode != FALSE); | ||||||||||||||||
| if (s_singleton->isBatterySaverActive.load() != newValue) { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Battery saver changed to %s", newValue ? "true" : "false"); | ||||||||||||||||
| s_singleton->isBatterySaverActive.store(newValue); | ||||||||||||||||
| g_main_context_invoke( | ||||||||||||||||
| nullptr, | ||||||||||||||||
| +[](gpointer userData) -> gboolean { | ||||||||||||||||
| updatePowerStateOnMainThread(WPE_ANDROID_POWER_PROFILE_MONITOR(userData)); | ||||||||||||||||
| return G_SOURCE_REMOVE; | ||||||||||||||||
| }, | ||||||||||||||||
| s_singleton); | ||||||||||||||||
|
Comment on lines
+210
to
+216
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This piece of code is repeated in three different places. I would put the call to Then probably |
||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void wpe_android_power_profile_monitor_set_thermal_throttling(gboolean isThermalThrottling) | ||||||||||||||||
| { | ||||||||||||||||
| if (s_singleton == nullptr) { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::set_thermal_throttling called before init, ignoring"); | ||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| bool newValue = (isThermalThrottling != FALSE); | ||||||||||||||||
| if (s_singleton->isThermalThrottling.load() != newValue) { | ||||||||||||||||
| Logging::logDebug( | ||||||||||||||||
| "WPEAndroidPowerProfileMonitor: Thermal throttling changed to %s", newValue ? "true" : "false"); | ||||||||||||||||
| s_singleton->isThermalThrottling.store(newValue); | ||||||||||||||||
| g_main_context_invoke( | ||||||||||||||||
| nullptr, | ||||||||||||||||
| +[](gpointer userData) -> gboolean { | ||||||||||||||||
| updatePowerStateOnMainThread(WPE_ANDROID_POWER_PROFILE_MONITOR(userData)); | ||||||||||||||||
| return G_SOURCE_REMOVE; | ||||||||||||||||
| }, | ||||||||||||||||
| s_singleton); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
Comment on lines
+220
to
+240
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is not used anywhere and should be removed. |
||||||||||||||||
|
|
||||||||||||||||
| void WPEAndroidPowerProfileMonitor::configureJNIMappings() | ||||||||||||||||
| { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::configureJNIMappings()"); | ||||||||||||||||
| getJNIWPEPowerMonitorCache(); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| void WPEAndroidPowerProfileMonitor::registerExtension() | ||||||||||||||||
| { | ||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor::registerExtension()"); | ||||||||||||||||
|
|
||||||||||||||||
| g_type_ensure(WPE_TYPE_ANDROID_POWER_PROFILE_MONITOR); | ||||||||||||||||
|
|
||||||||||||||||
| GIOExtensionPoint* extensionPoint = g_io_extension_point_lookup(G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME); | ||||||||||||||||
| if (extensionPoint == nullptr) | ||||||||||||||||
| extensionPoint = g_io_extension_point_register(G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME); | ||||||||||||||||
|
|
||||||||||||||||
| g_io_extension_point_implement( | ||||||||||||||||
| G_POWER_PROFILE_MONITOR_EXTENSION_POINT_NAME, WPE_TYPE_ANDROID_POWER_PROFILE_MONITOR, "android", 10); | ||||||||||||||||
|
|
||||||||||||||||
| Logging::logDebug("WPEAndroidPowerProfileMonitor: Registered as GPowerProfileMonitor extension"); | ||||||||||||||||
| } | ||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,59 @@ | ||||||
| /** | ||||||
| * Copyright (C) 2025 maceip | ||||||
| * | ||||||
| * This library is free software; you can redistribute it and/or | ||||||
| * modify it under the terms of the GNU Lesser General Public | ||||||
| * License as published by the Free Software Foundation; either | ||||||
| * version 2.1 of the License, or (at your option) any later version. | ||||||
| * | ||||||
| * This library is distributed in the hope that it will be useful, | ||||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||||
| * Lesser General Public License for more details. | ||||||
| * | ||||||
| * You should have received a copy of the GNU Lesser General Public | ||||||
| * License along with this library; if not, write to the Free Software | ||||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||||
| */ | ||||||
|
|
||||||
| #pragma once | ||||||
|
|
||||||
| #include <glib.h> | ||||||
|
|
||||||
| G_BEGIN_DECLS | ||||||
|
|
||||||
| #define WPE_TYPE_ANDROID_POWER_PROFILE_MONITOR (wpe_android_power_profile_monitor_get_type()) | ||||||
| G_DECLARE_FINAL_TYPE( | ||||||
| WPEAndroidPowerMonitor, wpe_android_power_profile_monitor, WPE, ANDROID_POWER_PROFILE_MONITOR, GObject) | ||||||
|
|
||||||
| /** | ||||||
| * Updates the battery saver state from Java layer. | ||||||
| * Called via JNI when the battery saver mode changes. | ||||||
| */ | ||||||
| void wpe_android_power_profile_monitor_set_battery_saver(gboolean isPowerSaveMode); | ||||||
|
|
||||||
| /** | ||||||
| * Updates the thermal throttling state. | ||||||
| * Can be called from native code, though thermal status is typically | ||||||
| * monitored internally via AThermalManager. | ||||||
| */ | ||||||
| void wpe_android_power_profile_monitor_set_thermal_throttling(gboolean isThermalThrottling); | ||||||
|
Comment on lines
+25
to
+40
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is all implementation details of the power profile monitor and do not need to be in the header. |
||||||
|
|
||||||
| G_END_DECLS | ||||||
|
|
||||||
| /** | ||||||
| * WPEAndroidPowerProfileMonitor implements GPowerProfileMonitor for Android. | ||||||
| * | ||||||
| * Aggregates two signals to determine "Low Power Mode": | ||||||
| * 1. Thermal Status (via NDK AThermalManager, API 30+) | ||||||
| * 2. Battery Saver Mode (via Java PowerManager broadcast) | ||||||
| * | ||||||
| * When either condition indicates power constraints, WebKit's LowPowerModeNotifierGLib | ||||||
| * sees "power-saver-enabled" as TRUE, causing reduced timer precision, stopped | ||||||
| * smooth animations, and throttled background tabs. | ||||||
| */ | ||||||
| class WPEAndroidPowerProfileMonitor { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| public: | ||||||
| static void configureJNIMappings(); | ||||||
| static void registerExtension(); | ||||||
| }; | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.