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, false
); | |
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 wor
k-around | |
114 // we could compute it manually based on level delta. | |
115 // TODO(timvolodine): add proper projection for chargingTime, discharging
Time | |
116 // (see crbug.com/401553). | |
117 double chargingTime = (charging & batteryFull) ? 0 : Double.POSITIVE_INFI
NITY; | |
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 |