| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 package org.chromium.content.browser; | |
| 6 | |
| 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; | |
| 14 | |
| 15 import org.chromium.base.CalledByNative; | |
| 16 import org.chromium.base.JNINamespace; | |
| 17 import org.chromium.base.VisibleForTesting; | |
| 18 | |
| 19 /** | |
| 20 * Android implementation of the battery status APIs. | |
| 21 */ | |
| 22 @JNINamespace("content") | |
| 23 class BatteryStatusManager { | |
| 24 | |
| 25 private static final String TAG = "BatteryStatusManager"; | |
| 26 | |
| 27 // A reference to the application context in order to acquire the SensorServ
ice. | |
| 28 private final Context mAppContext; | |
| 29 private final IntentFilter mFilter = new IntentFilter(Intent.ACTION_BATTERY_
CHANGED); | |
| 30 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { | |
| 31 @Override | |
| 32 public void onReceive(Context context, Intent intent) { | |
| 33 BatteryStatusManager.this.onReceive(intent); | |
| 34 } | |
| 35 }; | |
| 36 | |
| 37 // Non-zero if and only if we're listening for events. | |
| 38 // To avoid race conditions on the C++ side, access must be synchronized. | |
| 39 private long mNativePtr; | |
| 40 // The lock to access the mNativePtr. | |
| 41 private final Object mNativePtrLock = new Object(); | |
| 42 | |
| 43 private boolean mEnabled = false; | |
| 44 | |
| 45 protected BatteryStatusManager(Context context) { | |
| 46 mAppContext = context.getApplicationContext(); | |
| 47 } | |
| 48 | |
| 49 @CalledByNative | |
| 50 static BatteryStatusManager getInstance(Context appContext) { | |
| 51 return new BatteryStatusManager(appContext); | |
| 52 } | |
| 53 | |
| 54 /** | |
| 55 * Start listening for intents | |
| 56 * @return True on success. | |
| 57 */ | |
| 58 @CalledByNative | |
| 59 boolean start(long nativePtr) { | |
| 60 synchronized (mNativePtrLock) { | |
| 61 if (!mEnabled && mAppContext.registerReceiver(mReceiver, mFilter) !=
null) { | |
| 62 // success | |
| 63 mNativePtr = nativePtr; | |
| 64 mEnabled = true; | |
| 65 } | |
| 66 } | |
| 67 return mEnabled; | |
| 68 } | |
| 69 | |
| 70 /** | |
| 71 * Stop listening to intents. | |
| 72 */ | |
| 73 @CalledByNative | |
| 74 void stop() { | |
| 75 synchronized (mNativePtrLock) { | |
| 76 if (mEnabled) { | |
| 77 mAppContext.unregisterReceiver(mReceiver); | |
| 78 mNativePtr = 0; | |
| 79 mEnabled = false; | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 | |
| 84 @VisibleForTesting | |
| 85 void onReceive(Intent intent) { | |
| 86 if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { | |
| 87 Log.e(TAG, "Unexpected intent."); | |
| 88 return; | |
| 89 } | |
| 90 | |
| 91 boolean present = ignoreBatteryPresentState() ? | |
| 92 true : intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, fals
e); | |
| 93 int pluggedStatus = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
; | |
| 94 | |
| 95 if (!present || pluggedStatus == -1) { | |
| 96 // No battery or no plugged status: return default values. | |
| 97 gotBatteryStatus(true, 0, Double.POSITIVE_INFINITY, 1); | |
| 98 return; | |
| 99 } | |
| 100 | |
| 101 boolean charging = pluggedStatus != 0; | |
| 102 int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); | |
| 103 boolean batteryFull = status == BatteryManager.BATTERY_STATUS_FULL; | |
| 104 | |
| 105 int current = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); | |
| 106 int max = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); | |
| 107 double level = (double) current / (double) max; | |
| 108 if (level < 0 || level > 1) { | |
| 109 // Sanity check, assume default value in this case. | |
| 110 level = 1.0; | |
| 111 } | |
| 112 | |
| 113 // Currently Android does not provide charging/discharging time, as a wo
rk-around | |
| 114 // we could compute it manually based on level delta. | |
| 115 // TODO(timvolodine): add proper projection for chargingTime, dischargin
gTime | |
| 116 // (see crbug.com/401553). | |
| 117 double chargingTime = (charging & batteryFull) ? 0 : Double.POSITIVE_INF
INITY; | |
| 118 double dischargingTime = Double.POSITIVE_INFINITY; | |
| 119 | |
| 120 gotBatteryStatus(charging, chargingTime, dischargingTime, level); | |
| 121 } | |
| 122 | |
| 123 /** | |
| 124 * Returns whether the BatteryStatusManager should ignore the battery presen
t state. | |
| 125 * It is required for some devices that incorrectly set the EXTRA_PRESENT pr
operty. | |
| 126 */ | |
| 127 protected boolean ignoreBatteryPresentState() { | |
| 128 // BatteryManager.EXTRA_PRESENT appears to be unreliable on Galaxy Nexus
, | |
| 129 // Android 4.2.1, it always reports false. See crbug.com/384348. | |
| 130 return Build.MODEL.equals("Galaxy Nexus"); | |
| 131 } | |
| 132 | |
| 133 protected void gotBatteryStatus(boolean charging, double chargingTime, | |
| 134 double dischargingTime, double level) { | |
| 135 synchronized (mNativePtrLock) { | |
| 136 if (mNativePtr != 0) { | |
| 137 nativeGotBatteryStatus(mNativePtr, charging, chargingTime, disch
argingTime, level); | |
| 138 } | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 /** | |
| 143 * Native JNI call | |
| 144 * see content/browser/battery_status/battery_status_manager.cc | |
| 145 */ | |
| 146 private native void nativeGotBatteryStatus(long nativeBatteryStatusManagerAn
droid, | |
| 147 boolean charging, double chargingTime, double dischargingTime, doubl
e level); | |
| 148 } | |
| OLD | NEW |