diff --git a/embedding/android/GeckoApp.java b/embedding/android/GeckoApp.java index a35e7e1fa6b..58b46bbe09f 100644 --- a/embedding/android/GeckoApp.java +++ b/embedding/android/GeckoApp.java @@ -87,6 +87,8 @@ abstract public class GeckoApp public Handler mMainHandler; private IntentFilter mConnectivityFilter; private BroadcastReceiver mConnectivityReceiver; + private IntentFilter mBatteryFilter; + private BroadcastReceiver mBatteryReceiver; enum LaunchState {PreLaunch, Launching, WaitForDebugger, Launched, GeckoRunning, GeckoExiting}; @@ -408,6 +410,10 @@ abstract public class GeckoApp mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); mConnectivityReceiver = new GeckoConnectivityReceiver(); + mBatteryFilter = new IntentFilter(); + mBatteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED); + mBatteryReceiver = new GeckoBatteryManager(); + if (!checkAndSetLaunchState(LaunchState.PreLaunch, LaunchState.Launching)) return; @@ -491,6 +497,7 @@ abstract public class GeckoApp super.onPause(); unregisterReceiver(mConnectivityReceiver); + unregisterReceiver(mBatteryReceiver); } @Override @@ -509,6 +516,7 @@ abstract public class GeckoApp onNewIntent(getIntent()); registerReceiver(mConnectivityReceiver, mConnectivityFilter); + registerReceiver(mBatteryReceiver, mBatteryFilter); } @Override @@ -526,7 +534,6 @@ abstract public class GeckoApp // etc., and generally mark the profile as 'clean', and then // dirty it again if we get an onResume. - GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_STOPPING)); super.onStop(); GeckoAppShell.putChildInBackground(); diff --git a/embedding/android/GeckoBatteryManager.java b/embedding/android/GeckoBatteryManager.java index 3f7867f166c..5f9eeba602d 100644 --- a/embedding/android/GeckoBatteryManager.java +++ b/embedding/android/GeckoBatteryManager.java @@ -37,15 +37,93 @@ package org.mozilla.gecko; +import java.lang.Math; + +import android.util.Log; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import android.os.BatteryManager; + public class GeckoBatteryManager + extends BroadcastReceiver { + private final static float kDefaultLevel = 1.0f; + private final static boolean kDefaultCharging = true; + private final static float kMinimumLevelChange = 0.01f; + + private static boolean sNotificationsEnabled = false; + private static float sLevel = kDefaultLevel; + private static boolean sCharging = kDefaultCharging; + + @Override + public void onReceive(Context context, Intent intent) { + if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { + Log.e("GeckoBatteryManager", "Got an unexpected intent!"); + return; + } + + boolean previousCharging = isCharging(); + float previousLevel = getLevel(); + + if (intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false)) { + int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1); + if (plugged == -1) { + sCharging = kDefaultCharging; + Log.e("GeckoBatteryManager", "Failed to get the plugged status!"); + } else { + // Likely, if plugged > 0, it's likely plugged and charging but the doc + // isn't clear about that. + sCharging = plugged != 0; + } + + // We need two floats because sLevel is a float. + float current = (float)intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + float max = (float)intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + if (current == -1 || max == -1) { + Log.e("GeckoBatteryManager", "Failed to get battery level!"); + sLevel = kDefaultLevel; + } else { + sLevel = current / max; + } + } else { + sLevel = kDefaultLevel; + sCharging = kDefaultCharging; + } + + /* + * We want to inform listeners if the following conditions are fulfilled: + * - we have at least one observer; + * - the charging state has changed + * OR + * the level has changed of at least kMinimumLevelChange + */ + if (sNotificationsEnabled && + (previousCharging != isCharging() || + Math.abs(previousLevel - getLevel()) >= kMinimumLevelChange)) { + GeckoAppShell.notifyBatteryChange(sLevel, sCharging); + } + } + + public static boolean isCharging() { + return sCharging; + } + + public static float getLevel() { + return sLevel; + } + public static void enableNotifications() { + sNotificationsEnabled = true; } public static void disableNotifications() { + sNotificationsEnabled = false; } public static float[] getCurrentInformation() { - return new float[] { 1.0f, 1.0f }; + return new float[] { getLevel(), isCharging() ? 1.0f : 0.0f }; } }