BatteryStatusManager.java revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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 5package org.chromium.content.browser; 6 7import android.content.BroadcastReceiver; 8import android.content.Context; 9import android.content.Intent; 10import android.content.IntentFilter; 11import android.os.BatteryManager; 12import android.util.Log; 13 14import com.google.common.annotations.VisibleForTesting; 15 16import org.chromium.base.CalledByNative; 17import org.chromium.base.JNINamespace; 18 19/** 20 * Android implementation of the battery status APIs. 21 */ 22@JNINamespace("content") 23class BatteryStatusManager { 24 25 private static final String TAG = "BatteryStatusManager"; 26 27 // A reference to the application context in order to acquire the SensorService. 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 int current = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 92 int max = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 93 double level = (double)current / (double)max; 94 95 int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); 96 // by default assume a battery is present 97 boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true); 98 boolean charging = (present && status == BatteryManager.BATTERY_STATUS_DISCHARGING) 99 ? false : true; 100 101 //TODO(timvolodine) : add proper projection for chargingTime, dischargingTime. 102 double chargingTime = (!present || status == BatteryManager.BATTERY_STATUS_FULL) 103 ? 0 : Double.POSITIVE_INFINITY; 104 double dischargingTime = Double.POSITIVE_INFINITY; 105 106 gotBatteryStatus(charging, chargingTime, dischargingTime, level); 107 } 108 109 protected void gotBatteryStatus(boolean charging, double chargingTime, 110 double dischargingTime, double level) { 111 synchronized (mNativePtrLock) { 112 if (mNativePtr != 0) { 113 nativeGotBatteryStatus(mNativePtr, charging, chargingTime, dischargingTime, level); 114 } 115 } 116 } 117 118 /** 119 * Native JNI call 120 * see content/browser/battery_status/battery_status_manager_android.cc 121 */ 122 private native void nativeGotBatteryStatus(long nativeBatteryStatusManagerAndroid, 123 boolean charging, double chargingTime, double dischargingTime, double level); 124} 125