Home | History | Annotate | Download | only in base
      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 
     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      */
     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 
     66     private PowerMonitor() {
     67     }
     68 
     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
     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
     94     private static boolean isBatteryPower() {
     95         return sInstance.mIsBatteryPower;
     96     }
     97 
     98     private static native void nativeOnBatteryChargingChanged();
     99     private static native void nativeOnMainActivitySuspended();
    100     private static native void nativeOnMainActivityResumed();
    101 }
    102