• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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.base;
6 
7 import android.content.Context;
8 import android.content.Intent;
9 import android.content.IntentFilter;
10 import android.os.BatteryManager;
11 import android.os.Handler;
12 import android.os.Looper;
13 
14 import org.chromium.base.annotations.CalledByNative;
15 import org.chromium.base.annotations.JNINamespace;
16 
17 
18 /**
19  * Integrates native PowerMonitor with the java side.
20  */
21 @JNINamespace("base::android")
22 public class PowerMonitor implements ApplicationStatus.ApplicationStateListener {
23     private static final long SUSPEND_DELAY_MS = 1 * 60 * 1000;  // 1 minute.
24     private static class LazyHolder {
25         private static final PowerMonitor INSTANCE = new PowerMonitor();
26     }
27     private static PowerMonitor sInstance;
28 
29     private boolean mIsBatteryPower;
30     private final Handler mHandler = new Handler(Looper.getMainLooper());
31 
32     // Asynchronous task used to fire the "paused" event to the native side 1 minute after the main
33     // activity transitioned to the "paused" state. This event is not sent immediately because it
34     // would be too aggressive. An Android activity can be in the "paused" state quite often. This
35     // can happen when a dialog window shows up for instance.
36     private static final Runnable sSuspendTask = new Runnable() {
37         @Override
38         public void run() {
39             nativeOnMainActivitySuspended();
40         }
41     };
42 
createForTests(Context context)43     public static void createForTests(Context context) {
44         // Applications will create this once the JNI side has been fully wired up both sides. For
45         // tests, we just need native -> java, that is, we don't need to notify java -> native on
46         // creation.
47         sInstance = LazyHolder.INSTANCE;
48     }
49 
50     /**
51      * Create a PowerMonitor instance if none exists.
52      * @param context The context to register broadcast receivers for.  The application context
53      *                will be used from this parameter.
54      */
create(Context context)55     public static void create(Context context) {
56         context = context.getApplicationContext();
57         if (sInstance == null) {
58             sInstance = LazyHolder.INSTANCE;
59             ApplicationStatus.registerApplicationStateListener(sInstance);
60             IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
61             Intent batteryStatusIntent = context.registerReceiver(null, ifilter);
62             if (batteryStatusIntent != null) onBatteryChargingChanged(batteryStatusIntent);
63         }
64     }
65 
PowerMonitor()66     private PowerMonitor() {
67     }
68 
onBatteryChargingChanged(Intent intent)69     public static void onBatteryChargingChanged(Intent intent) {
70         if (sInstance == null) {
71             // We may be called by the framework intent-filter before being fully initialized. This
72             // is not a problem, since our constructor will check for the state later on.
73             return;
74         }
75         int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
76         // If we're not plugged, assume we're running on battery power.
77         sInstance.mIsBatteryPower = chargePlug != BatteryManager.BATTERY_PLUGGED_USB
78                 && chargePlug != BatteryManager.BATTERY_PLUGGED_AC;
79         nativeOnBatteryChargingChanged();
80     }
81 
82     @Override
onApplicationStateChange(int newState)83     public void onApplicationStateChange(int newState) {
84         if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES) {
85             // Remove the callback from the message loop in case it hasn't been executed yet.
86             mHandler.removeCallbacks(sSuspendTask);
87             nativeOnMainActivityResumed();
88         } else if (newState == ApplicationState.HAS_PAUSED_ACTIVITIES) {
89             mHandler.postDelayed(sSuspendTask, SUSPEND_DELAY_MS);
90         }
91     }
92 
93     @CalledByNative
isBatteryPower()94     private static boolean isBatteryPower() {
95         return sInstance.mIsBatteryPower;
96     }
97 
nativeOnBatteryChargingChanged()98     private static native void nativeOnBatteryChargingChanged();
nativeOnMainActivitySuspended()99     private static native void nativeOnMainActivitySuspended();
nativeOnMainActivityResumed()100     private static native void nativeOnMainActivityResumed();
101 }
102