diff options
author | timvolodine <timvolodine@chromium.org> | 2015-02-20 11:31:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-20 19:32:11 +0000 |
commit | 13e397e55501bee3903bfe46edfd56f2442c1f11 (patch) | |
tree | 189d04e6f8b8d26a1e6b8cd25b6dd00a48375011 /device | |
parent | 1b5ccef52b9410ab6efeecdc9a2dc156acdbbbfe (diff) | |
download | chromium_src-13e397e55501bee3903bfe46edfd56f2442c1f11.zip chromium_src-13e397e55501bee3903bfe46edfd56f2442c1f11.tar.gz chromium_src-13e397e55501bee3903bfe46edfd56f2442c1f11.tar.bz2 |
[Android L] Add (dis)chargingTime support for the Battery Status API.
This patch implements the estimation of (dis)chargingTime on devices
running Android L (and above). Android L supports new properties in
BatteryManager which can be used to provide such estimates.
BUG=401553
TEST=http://jsbin.com/battery-status-test
Review URL: https://codereview.chromium.org/874713003
Cr-Commit-Position: refs/heads/master@{#317372}
Diffstat (limited to 'device')
2 files changed, 153 insertions, 12 deletions
diff --git a/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java b/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java index 0601be1..b94c7f0 100644 --- a/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java +++ b/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java @@ -42,19 +42,26 @@ class BatteryStatusManager { // This is to workaround a Galaxy Nexus bug, see the comment in the constructor. private final boolean mIgnoreBatteryPresentState; + // Only used in L (API level 21 and higher). + private BatteryManager mLollipopBatteryManager; + private boolean mEnabled = false; private BatteryStatusManager( - Context context, BatteryStatusCallback callback, boolean ignoreBatteryPresentState) { + Context context, BatteryStatusCallback callback, boolean ignoreBatteryPresentState, + BatteryManager batteryManager) { mAppContext = context.getApplicationContext(); mCallback = callback; mIgnoreBatteryPresentState = ignoreBatteryPresentState; + mLollipopBatteryManager = batteryManager; } BatteryStatusManager(Context context, BatteryStatusCallback callback) { // BatteryManager.EXTRA_PRESENT appears to be unreliable on Galaxy Nexus, // Android 4.2.1, it always reports false. See http://crbug.com/384348. - this(context, callback, Build.MODEL.equals("Galaxy Nexus")); + this(context, callback, Build.MODEL.equals("Galaxy Nexus"), + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? new BatteryManager() + : null); } /** @@ -62,8 +69,10 @@ class BatteryStatusManager { * testing. */ static BatteryStatusManager createBatteryStatusManagerForTesting( - Context context, BatteryStatusCallback callback) { - return new BatteryStatusManager(context, callback, false); + Context context, + BatteryStatusCallback callback, + BatteryManager batteryManager) { + return new BatteryStatusManager(context, callback, false, batteryManager); } /** @@ -114,20 +123,44 @@ class BatteryStatusManager { level = 1.0; } - // Currently Android does not provide charging/discharging time, as a work-around - // we could compute it manually based on level delta. + // Currently Android (below L) does not provide charging/discharging time, as a work-around + // we could compute it manually based on the evolution of level delta. // TODO(timvolodine): add proper projection for chargingTime, dischargingTime // (see crbug.com/401553). boolean charging = pluggedStatus != 0; int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); boolean batteryFull = status == BatteryManager.BATTERY_STATUS_FULL; - double chargingTime = (charging & batteryFull) ? 0 : Double.POSITIVE_INFINITY; - double dischargingTime = Double.POSITIVE_INFINITY; + double chargingTimeSeconds = (charging && batteryFull) ? 0 : Double.POSITIVE_INFINITY; + double dischargingTimeSeconds = Double.POSITIVE_INFINITY; + + if (mLollipopBatteryManager != null) { + // On Lollipop we can provide a better estimate for chargingTime and dischargingTime. + double remainingCapacityRatio = mLollipopBatteryManager.getIntProperty( + BatteryManager.BATTERY_PROPERTY_CAPACITY) / 100.0; + double batteryCapacityMicroAh = mLollipopBatteryManager.getIntProperty( + BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER); + double averageCurrentMicroA = mLollipopBatteryManager.getIntProperty( + BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE); + + if (charging) { + if (chargingTimeSeconds == Double.POSITIVE_INFINITY && averageCurrentMicroA > 0) { + double chargeFromEmptyHours = batteryCapacityMicroAh / averageCurrentMicroA; + chargingTimeSeconds = + Math.ceil((1 - remainingCapacityRatio) * chargeFromEmptyHours * 3600.0); + } + } else { + if (averageCurrentMicroA < 0) { + double dischargeFromFullHours = batteryCapacityMicroAh / -averageCurrentMicroA; + dischargingTimeSeconds = + Math.floor(remainingCapacityRatio * dischargeFromFullHours * 3600.0); + } + } + } BatteryStatus batteryStatus = new BatteryStatus(); batteryStatus.charging = charging; - batteryStatus.chargingTime = chargingTime; - batteryStatus.dischargingTime = dischargingTime; + batteryStatus.chargingTime = chargingTimeSeconds; + batteryStatus.dischargingTime = dischargingTimeSeconds; batteryStatus.level = level; mCallback.onBatteryStatusChanged(batteryStatus); } diff --git a/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java b/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java index addcdde..536e31b 100644 --- a/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java +++ b/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java @@ -6,6 +6,7 @@ package org.chromium.device.battery; import android.content.Intent; import android.os.BatteryManager; +import android.os.Build; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; @@ -42,11 +43,50 @@ public class BatteryStatusManagerTest extends AndroidTestCase { assertEquals(level, mLevel); } + private static class BatteryManagerForTesting extends BatteryManager { + private int mChargeCounter; + private int mCapacity; + private int mAverageCurrent; + + @Override + public int getIntProperty(int id) { + switch(id) { + case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER : + return mChargeCounter; + case BatteryManager.BATTERY_PROPERTY_CAPACITY: + return mCapacity; + case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE: + return mAverageCurrent; + } + fail(); + return 0; + } + + public void setIntProperty(int id, int value) { + switch(id) { + case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER : + mChargeCounter = value; + return; + case BatteryManager.BATTERY_PROPERTY_CAPACITY: + mCapacity = value; + return; + case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE: + mAverageCurrent = value; + return; + } + fail(); + } + } + @Override protected void setUp() throws Exception { super.setUp(); - mManager = - BatteryStatusManager.createBatteryStatusManagerForTesting(getContext(), mCallback); + initializeManager(null); + } + + public void initializeManager(BatteryManagerForTesting managerForTesting) { + mManager = BatteryStatusManager.createBatteryStatusManagerForTesting( + getContext(), mCallback, managerForTesting); } @SmallTest @@ -125,4 +165,72 @@ public class BatteryStatusManagerTest extends AndroidTestCase { assertTrue(mManager.start()); mManager.stop(); } + + @SmallTest + public void testLollipopChargingTimeEstimate() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + return; + + BatteryManagerForTesting testManager = new BatteryManagerForTesting(); + initializeManager(testManager); + + Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); + intent.putExtra(BatteryManager.EXTRA_PRESENT, true); + intent.putExtra(BatteryManager.EXTRA_PLUGGED, BatteryManager.BATTERY_PLUGGED_USB); + intent.putExtra(BatteryManager.EXTRA_LEVEL, 50); + intent.putExtra(BatteryManager.EXTRA_SCALE, 100); + + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 50); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, 100); + + mManager.onReceive(intent); + verifyValues(true, 0.5 * 10 * 3600, Double.POSITIVE_INFINITY, 0.5); + } + + @SmallTest + public void testLollipopDischargingTimeEstimate() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + return; + + BatteryManagerForTesting testManager = new BatteryManagerForTesting(); + initializeManager(testManager); + + Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); + intent.putExtra(BatteryManager.EXTRA_PRESENT, true); + intent.putExtra(BatteryManager.EXTRA_PLUGGED, 0); + intent.putExtra(BatteryManager.EXTRA_LEVEL, 60); + intent.putExtra(BatteryManager.EXTRA_SCALE, 100); + intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_NOT_CHARGING); + + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1000); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 60); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -100); + + mManager.onReceive(intent); + verifyValues(false, Double.POSITIVE_INFINITY, 0.6 * 10 * 3600, 0.6); + } + + @SmallTest + public void testLollipopDischargingTimeEstimateRounding() { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) + return; + + BatteryManagerForTesting testManager = new BatteryManagerForTesting(); + initializeManager(testManager); + + Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED); + intent.putExtra(BatteryManager.EXTRA_PRESENT, true); + intent.putExtra(BatteryManager.EXTRA_PLUGGED, 0); + intent.putExtra(BatteryManager.EXTRA_LEVEL, 90); + intent.putExtra(BatteryManager.EXTRA_SCALE, 100); + intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_NOT_CHARGING); + + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, 1999); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY, 90); + testManager.setIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE, -1000); + + mManager.onReceive(intent); + verifyValues(false, Double.POSITIVE_INFINITY, Math.floor(0.9 * 1.999 * 3600), 0.9); + } } |