1 /*
2  * Copyright (C) 2016 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.googlecode.android_scripting.facade;
18 
19 import android.app.Service;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.os.BatteryManager;
25 import android.os.Bundle;
26 
27 import com.googlecode.android_scripting.Log;
28 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
29 import com.googlecode.android_scripting.rpc.Rpc;
30 import com.googlecode.android_scripting.rpc.RpcStartEvent;
31 import com.googlecode.android_scripting.rpc.RpcStopEvent;
32 
33 import java.lang.reflect.Field;
34 
35 /**
36  * Exposes Batterymanager API. Note that in order to use any of the batteryGet* functions, you need
37  * to batteryStartMonitoring, and then wait for a "battery" event. Sleeping for a second will
38  * usually work just as well.
39  *
40  * @author Alexey Reznichenko (alexey.reznichenko@gmail.com)
41  * @author Robbie Matthews (rjmatthews62@gmail.com)
42  */
43 public class BatteryManagerFacade extends RpcReceiver {
44 
45   private final Service mService;
46   private final EventFacade mEventFacade;
47   private final int mSdkVersion;
48 
49   private BatteryStateListener mReceiver;
50 
51   private volatile Bundle mBatteryData = null;
52   private volatile Integer mBatteryStatus = null;
53   private volatile Integer mBatteryHealth = null;
54   private volatile Integer mPlugType = null;
55 
56   private volatile Boolean mBatteryPresent = null;
57   private volatile Integer mBatteryLevel = null;
58   private volatile Integer mBatteryMaxLevel = null;
59   private volatile Integer mBatteryVoltage = null;
60   private volatile Integer mBatteryTemperature = null;
61   private volatile String mBatteryTechnology = null;
62 
BatteryManagerFacade(FacadeManager manager)63   public BatteryManagerFacade(FacadeManager manager) {
64     super(manager);
65     mService = manager.getService();
66     mSdkVersion = manager.getSdkLevel();
67     mEventFacade = manager.getReceiver(EventFacade.class);
68     mReceiver = null;
69     mBatteryData = null;
70   }
71 
72   private class BatteryStateListener extends BroadcastReceiver {
73 
74     private final EventFacade mmEventFacade;
75 
BatteryStateListener(EventFacade facade)76     private BatteryStateListener(EventFacade facade) {
77       mmEventFacade = facade;
78     }
79 
80     @Override
onReceive(Context context, Intent intent)81     public void onReceive(Context context, Intent intent) {
82       mBatteryStatus = intent.getIntExtra("status", 1);
83       mBatteryHealth = intent.getIntExtra("health", 1);
84       mPlugType = intent.getIntExtra("plugged", -1);
85       if (mSdkVersion >= 5) {
86         mBatteryPresent =
87             intent.getBooleanExtra(getBatteryManagerFieldValue("EXTRA_PRESENT"), false);
88         mBatteryLevel = intent.getIntExtra(getBatteryManagerFieldValue("EXTRA_LEVEL"), -1);
89         mBatteryMaxLevel = intent.getIntExtra(getBatteryManagerFieldValue("EXTRA_SCALE"), 0);
90         mBatteryVoltage = intent.getIntExtra(getBatteryManagerFieldValue("EXTRA_VOLTAGE"), -1);
91         mBatteryTemperature =
92             intent.getIntExtra(getBatteryManagerFieldValue("EXTRA_TEMPERATURE"), -1);
93         mBatteryTechnology = intent.getStringExtra(getBatteryManagerFieldValue("EXTRA_TECHNOLOGY"));
94       }
95       Bundle data = new Bundle();
96       data.putInt("status", mBatteryStatus);
97       data.putInt("health", mBatteryHealth);
98       data.putInt("plugged", mPlugType);
99       if (mSdkVersion >= 5) {
100         data.putBoolean("battery_present", mBatteryPresent);
101         if (mBatteryMaxLevel == null || mBatteryMaxLevel == 100 || mBatteryMaxLevel == 0) {
102           data.putInt("level", mBatteryLevel);
103         } else {
104           data.putInt("level", (int) (mBatteryLevel * 100.0 / mBatteryMaxLevel));
105         }
106         data.putInt("voltage", mBatteryVoltage);
107         data.putInt("temperature", mBatteryTemperature);
108         data.putString("technology", mBatteryTechnology);
109       }
110       mBatteryData = data;
111       mmEventFacade.postEvent("battery", mBatteryData.clone());
112     }
113   }
114 
getBatteryManagerFieldValue(String name)115   private String getBatteryManagerFieldValue(String name) {
116     try {
117       Field f = BatteryManager.class.getField(name);
118       return f.get(null).toString();
119     } catch (Exception e) {
120       Log.e(e);
121     }
122     return null;
123   }
124 
125   @Rpc(description = "Returns the most recently recorded battery data.")
readBatteryData()126   public Bundle readBatteryData() {
127     return mBatteryData;
128   }
129 
130   /**
131    * throws "battery" events
132    */
133   @Rpc(description = "Starts tracking battery state.")
134   @RpcStartEvent("battery")
batteryStartMonitoring()135   public void batteryStartMonitoring() {
136     if (mReceiver == null) {
137       IntentFilter filter = new IntentFilter();
138       filter.addAction(Intent.ACTION_BATTERY_CHANGED);
139       mReceiver = new BatteryStateListener(mEventFacade);
140       mService.registerReceiver(mReceiver, filter);
141     }
142   }
143 
144   @Rpc(description = "Stops tracking battery state.")
145   @RpcStopEvent("battery")
batteryStopMonitoring()146   public void batteryStopMonitoring() {
147     if (mReceiver != null) {
148       mService.unregisterReceiver(mReceiver);
149       mReceiver = null;
150     }
151     mBatteryData = null;
152   }
153 
154   @Override
shutdown()155   public void shutdown() {
156     batteryStopMonitoring();
157   }
158 
159   @Rpc(description = "Returns  the most recently received battery status data:" + "\n1 - unknown;"
160       + "\n2 - charging;" + "\n3 - discharging;" + "\n4 - not charging;" + "\n5 - full;")
batteryGetStatus()161   public Integer batteryGetStatus() {
162     return mBatteryStatus;
163   }
164 
165   @Rpc(description = "Returns the most recently received battery health data:" + "\n1 - unknown;"
166       + "\n2 - good;" + "\n3 - overheat;" + "\n4 - dead;" + "\n5 - over voltage;"
167       + "\n6 - unspecified failure;")
batteryGetHealth()168   public Integer batteryGetHealth() {
169     return mBatteryHealth;
170   }
171 
172   /** Power source is an AC charger. */
173   public static final int BATTERY_PLUGGED_AC = 1;
174   /** Power source is a USB port. */
175   public static final int BATTERY_PLUGGED_USB = 2;
176 
177   @Rpc(description = "Returns the most recently received plug type data:" + "\n-1 - unknown"
178       + "\n0 - unplugged;" + "\n1 - power source is an AC charger"
179       + "\n2 - power source is a USB port")
batteryGetPlugType()180   public Integer batteryGetPlugType() {
181     return mPlugType;
182   }
183 
184   @Rpc(description = "Returns the most recently received battery presence data.")
batteryCheckPresent()185   public Boolean batteryCheckPresent() {
186     return mBatteryPresent;
187   }
188 
189   @Rpc(description = "Returns the most recently received battery level (percentage).")
batteryGetLevel()190   public Integer batteryGetLevel() {
191     if (mBatteryMaxLevel == null || mBatteryMaxLevel == 100 || mBatteryMaxLevel == 0) {
192       return mBatteryLevel;
193     } else {
194       return (int) (mBatteryLevel * 100.0 / mBatteryMaxLevel);
195     }
196   }
197 
198   @Rpc(description = "Returns the most recently received battery voltage.")
batteryGetVoltage()199   public Integer batteryGetVoltage() {
200     return mBatteryVoltage;
201   }
202 
203   @Rpc(description = "Returns the most recently received battery temperature.")
batteryGetTemperature()204   public Integer batteryGetTemperature() {
205     return mBatteryTemperature;
206   }
207 
208   @Rpc(description = "Returns the most recently received battery technology data.")
batteryGetTechnology()209   public String batteryGetTechnology() {
210     return mBatteryTechnology;
211   }
212 
213 }
214