1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.content.browser;
7 import android.content.BroadcastReceiver;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.content.IntentFilter;
11 import android.os.BatteryManager;
12 import android.os.Build;
13 import android.util.Log;
15 import com.google.common.annotations.VisibleForTesting;
17 import org.chromium.base.CalledByNative;
18 import org.chromium.base.JNINamespace;
21 * Android implementation of the battery status APIs.
23 @JNINamespace("content")
24 class BatteryStatusManager {
26 private static final String TAG = "BatteryStatusManager";
28 // A reference to the application context in order to acquire the SensorService.
29 private final Context mAppContext;
30 private final IntentFilter mFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
31 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
33 public void onReceive(Context context, Intent intent) {
34 BatteryStatusManager.this.onReceive(intent);
38 // Non-zero if and only if we're listening for events.
39 // To avoid race conditions on the C++ side, access must be synchronized.
40 private long mNativePtr;
41 // The lock to access the mNativePtr.
42 private final Object mNativePtrLock = new Object();
44 private boolean mEnabled = false;
46 protected BatteryStatusManager(Context context) {
47 mAppContext = context.getApplicationContext();
51 static BatteryStatusManager getInstance(Context appContext) {
52 return new BatteryStatusManager(appContext);
56 * Start listening for intents
57 * @return True on success.
60 boolean start(long nativePtr) {
61 synchronized (mNativePtrLock) {
62 if (!mEnabled && mAppContext.registerReceiver(mReceiver, mFilter) != null) {
64 mNativePtr = nativePtr;
72 * Stop listening to intents.
76 synchronized (mNativePtrLock) {
78 mAppContext.unregisterReceiver(mReceiver);
86 void onReceive(Intent intent) {
87 if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
88 Log.e(TAG, "Unexpected intent.");
92 boolean present = ignoreBatteryPresentState() ?
93 true : intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
96 // No battery, return default values.
97 gotBatteryStatus(true, 0, Double.POSITIVE_INFINITY, 1);
101 int current = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
102 int max = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
103 double level = (double)current / (double)max;
104 if (level < 0 || level > 1) {
105 // Sanity check, assume default value in this case.
109 int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
110 boolean charging = !(status == BatteryManager.BATTERY_STATUS_DISCHARGING);
112 // TODO(timvolodine) : add proper projection for chargingTime, dischargingTime.
113 double chargingTime = (status == BatteryManager.BATTERY_STATUS_FULL) ?
114 0 : Double.POSITIVE_INFINITY;
115 double dischargingTime = Double.POSITIVE_INFINITY;
117 gotBatteryStatus(charging, chargingTime, dischargingTime, level);
121 * Returns whether the BatteryStatusManager should ignore the battery present state.
122 * It is required for some devices that incorrectly set the EXTRA_PRESENT property.
124 protected boolean ignoreBatteryPresentState() {
125 // BatteryManager.EXTRA_PRESENT appears to be unreliable on Galaxy Nexus,
126 // Android 4.2.1, it always reports false. See crbug.com/384348.
127 return Build.MODEL.equals("Galaxy Nexus");
130 protected void gotBatteryStatus(boolean charging, double chargingTime,
131 double dischargingTime, double level) {
132 synchronized (mNativePtrLock) {
133 if (mNativePtr != 0) {
134 nativeGotBatteryStatus(mNativePtr, charging, chargingTime, dischargingTime, level);
141 * see content/browser/battery_status/battery_status_manager.cc
143 private native void nativeGotBatteryStatus(long nativeBatteryStatusManager,
144 boolean charging, double chargingTime, double dischargingTime, double level);