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