• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 The Chromium Authors
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.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.os.PowerManager;
14 
15 import org.jni_zero.CalledByNative;
16 import org.jni_zero.JNINamespace;
17 import org.jni_zero.NativeMethods;
18 
19 import org.chromium.base.compat.ApiHelperForQ;
20 
21 /** Integrates native PowerMonitor with the java side. */
22 @JNINamespace("base::android")
23 public class PowerMonitor {
24     private static PowerMonitor sInstance;
25 
26     private boolean mIsBatteryPower;
27 
createForTests()28     public static void createForTests() {
29         // Applications will create this once the JNI side has been fully wired up both sides. For
30         // tests, we just need native -> java, that is, we don't need to notify java -> native on
31         // creation.
32         sInstance = new PowerMonitor();
33     }
34 
35     /** Create a PowerMonitor instance if none exists. */
create()36     public static void create() {
37         ThreadUtils.assertOnUiThread();
38 
39         if (sInstance != null) return;
40 
41         Context context = ContextUtils.getApplicationContext();
42         sInstance = new PowerMonitor();
43         IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
44         Intent batteryStatusIntent =
45                 ContextUtils.registerProtectedBroadcastReceiver(context, null, ifilter);
46         if (batteryStatusIntent != null) {
47             // Default to 0, which the EXTRA_PLUGGED docs indicate means "on battery power".  There
48             // is no symbolic constant.  Nonzero values indicate we have some external power source.
49             int chargePlug = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
50             // If we're not plugged, assume we're running on battery power.
51             onBatteryChargingChanged(chargePlug == 0);
52         }
53 
54         IntentFilter powerConnectedFilter = new IntentFilter();
55         powerConnectedFilter.addAction(Intent.ACTION_POWER_CONNECTED);
56         powerConnectedFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
57         ContextUtils.registerProtectedBroadcastReceiver(
58                 context,
59                 new BroadcastReceiver() {
60                     @Override
61                     public void onReceive(Context context, Intent intent) {
62                         PowerMonitor.onBatteryChargingChanged(
63                                 intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED));
64                     }
65                 },
66                 powerConnectedFilter);
67 
68         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
69             PowerManager powerManager =
70                     (PowerManager) context.getSystemService(Context.POWER_SERVICE);
71             if (powerManager != null) {
72                 PowerMonitorForQ.addThermalStatusListener(powerManager);
73             }
74         }
75     }
76 
PowerMonitor()77     private PowerMonitor() {}
78 
onBatteryChargingChanged(boolean isBatteryPower)79     private static void onBatteryChargingChanged(boolean isBatteryPower) {
80         assert sInstance != null;
81         sInstance.mIsBatteryPower = isBatteryPower;
82         PowerMonitorJni.get().onBatteryChargingChanged();
83     }
84 
85     @CalledByNative
isBatteryPower()86     private static boolean isBatteryPower() {
87         // Creation of the PowerMonitor can be deferred based on the browser startup path.  If the
88         // battery power is requested prior to the browser triggering the creation, force it to be
89         // created now.
90         if (sInstance == null) create();
91 
92         return sInstance.mIsBatteryPower;
93     }
94 
95     @CalledByNative
getRemainingBatteryCapacity()96     private static int getRemainingBatteryCapacity() {
97         // Creation of the PowerMonitor can be deferred based on the browser startup path.  If the
98         // battery power is requested prior to the browser triggering the creation, force it to be
99         // created now.
100         if (sInstance == null) create();
101 
102         return getRemainingBatteryCapacityImpl();
103     }
104 
getRemainingBatteryCapacityImpl()105     private static int getRemainingBatteryCapacityImpl() {
106         return ((BatteryManager)
107                         ContextUtils.getApplicationContext()
108                                 .getSystemService(Context.BATTERY_SERVICE))
109                 .getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER);
110     }
111 
112     @CalledByNative
getCurrentThermalStatus()113     private static int getCurrentThermalStatus() {
114         // Return invalid code that will get mapped to unknown in the native library.
115         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return -1;
116 
117         // Creation of the PowerMonitor can be deferred based on the browser startup path.  If the
118         // battery power is requested prior to the browser triggering the creation, force it to be
119         // created now.
120         if (sInstance == null) create();
121 
122         PowerManager powerManager =
123                 (PowerManager)
124                         ContextUtils.getApplicationContext()
125                                 .getSystemService(Context.POWER_SERVICE);
126         if (powerManager == null) return -1;
127         return ApiHelperForQ.getCurrentThermalStatus(powerManager);
128     }
129 
130     @NativeMethods
131     interface Natives {
onBatteryChargingChanged()132         void onBatteryChargingChanged();
133 
onThermalStatusChanged(int thermalStatus)134         void onThermalStatusChanged(int thermalStatus);
135     }
136 }
137