Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / content / public / android / java / src / org / chromium / content / browser / BatteryStatusManager.java
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 com.google.common.annotations.VisibleForTesting;
16
17 import org.chromium.base.CalledByNative;
18 import org.chromium.base.JNINamespace;
19
20 /**
21  * Android implementation of the battery status APIs.
22  */
23 @JNINamespace("content")
24 class BatteryStatusManager {
25
26     private static final String TAG = "BatteryStatusManager";
27
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() {
32         @Override
33         public void onReceive(Context context, Intent intent) {
34             BatteryStatusManager.this.onReceive(intent);
35         }
36     };
37
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();
43
44     private boolean mEnabled = false;
45
46     protected BatteryStatusManager(Context context) {
47         mAppContext = context.getApplicationContext();
48     }
49
50     @CalledByNative
51     static BatteryStatusManager getInstance(Context appContext) {
52         return new BatteryStatusManager(appContext);
53     }
54
55     /**
56      * Start listening for intents
57      * @return True on success.
58      */
59     @CalledByNative
60     boolean start(long nativePtr) {
61         synchronized (mNativePtrLock) {
62             if (!mEnabled && mAppContext.registerReceiver(mReceiver, mFilter) != null) {
63                 // success
64                 mNativePtr = nativePtr;
65                 mEnabled = true;
66             }
67         }
68         return mEnabled;
69     }
70
71     /**
72      * Stop listening to intents.
73      */
74     @CalledByNative
75     void stop() {
76         synchronized (mNativePtrLock) {
77             if (mEnabled) {
78                 mAppContext.unregisterReceiver(mReceiver);
79                 mNativePtr = 0;
80                 mEnabled = false;
81             }
82         }
83     }
84
85     @VisibleForTesting
86     void onReceive(Intent intent) {
87        if (!intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) {
88            Log.e(TAG, "Unexpected intent.");
89            return;
90        }
91
92        boolean present = ignoreBatteryPresentState() ?
93                true : intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
94
95        if (!present) {
96            // No battery, return default values.
97            gotBatteryStatus(true, 0, Double.POSITIVE_INFINITY, 1);
98            return;
99        }
100
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.
106            level = 1.0;
107        }
108
109        int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
110        boolean charging = !(status == BatteryManager.BATTERY_STATUS_DISCHARGING);
111
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;
116
117        gotBatteryStatus(charging, chargingTime, dischargingTime, level);
118     }
119
120     /**
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.
123      */
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");
128     }
129
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);
135             }
136         }
137     }
138
139     /**
140      * Native JNI call
141      * see content/browser/battery_status/battery_status_manager.cc
142      */
143     private native void nativeGotBatteryStatus(long nativeBatteryStatusManager,
144             boolean charging, double chargingTime, double dischargingTime, double level);
145 }