今天讲讲mtk Android平台如何获取电池相关信息。
获取电池信息最常用的方法-注册广播(被动接受)
IntentFilter filter2 = new IntentFilter();
filter2.addAction(Intent.ACTION_BATTERY_CHANGED);registerReceiver(filter2,receiver);
接收到广播后,用getIntExtra("level")和getIntExtra("scale")获得相应值
intent.getIntExtra("level", 0); ///电池剩余电量
intent.getIntExtra("scale", 0); ///获取电池满电量数值
intent.getStringExtra("technology"); ///获取电池技术支持
intent.getIntExtra("status",BatteryManager.BATTERY_STATUS_UNKNOWN); ///获取电池状态
intent.getIntExtra("plugged", 0); ///获取电源信息
intent.getIntExtra("health",BatteryManager.BATTERY_HEALTH_UNKNOWN); ///获取电池健康度
intent.getIntExtra("voltage", 0); ///获取电池电压
intent.getIntExtra("temperature", 0); ///获取电池温度
如果是调试,也可以adb 查看
C:\Users\ShawnXia>adb shell dumpsys battery Current Battery Service state: AC powered: false ///有线充电器状态 USB powered: true ///USB连接状态 Wireless powered: false ///无线充电状态 Max charging current: 500000 ///最大充电电流,单位微安(uA) Max charging voltage: 5000000 ///最大充电电压,单位微伏(uV) Charge counter: 4149000 /// status: 2 ///充电状态,UNKNOWN=1,CHARGING=2,DISCHARGING=3,NOT_CHARGING=4,FULL=5 health: 2 ///电池健康状态 present: true /// level: 95 ///当前95% scale: 100 ///满电100% voltage: 4244 ///电压 temperature: 250 ///温度 technology: Li-ion
那电池广播 Intent.ACTION_BATTERY_CHANGED是从哪里发来的呢。
从BatteryService.java的sendIntentLocked里面发的
// Pack up the values and broadcast them to everyone
final Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_REPLACE_PENDING);
....
mHandler.post(new Runnable() {
@Override
public void run() {
ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);这里发出的。
}
});
那这个广播又是什么时候发的呢。
我们继续找sendIntentLocked。
流程是这样的onStart()-BatteryListener()-update()-processValuesLocked()-sendIntentLocked()。
在onStart注册监听器。当电池信息有变化时,发送ACTION_BATTERY_CHANGED出去。
那BatteryListener监听的是什么呢。我们继续看。
这里是注册地方。
void BatteryPropertiesRegistrar::registerListener(const sp<IBatteryPropertiesListener>& listener) {
{
if (listener == NULL)
return;
Mutex::Autolock _l(mRegistrationLock);
// check whether this is a duplicate
for (size_t i = 0; i < mListeners.size(); i++) {
if (IInterface::asBinder(mListeners[i]) == IInterface::asBinder(listener)) {
return;
}
}mListeners.add(listener);
IInterface::asBinder(listener)->linkToDeath(this);
}
healthd_battery_update();-
}
void healthd_battery_update(void) {
// Fast wake interval when on charger (watch for overheat);
// slow wake interval when on battery (watch for drained battery).int new_wake_interval = gBatteryMonitor->update() --最终走这里
healthd_config.periodic_chores_interval_fast :
healthd_config.periodic_chores_interval_slow;if (new_wake_interval != wakealarm_wake_interval)
wakealarm_set_interval(new_wake_interval);// During awake periods poll at fast rate. If wake alarm is set at fast
// rate then just use the alarm; if wake alarm is set at slow rate then
// poll at fast rate while awake and let alarm wake up at slow rate when
// asleep.if (healthd_config.periodic_chores_interval_fast == -1)
awake_poll_interval = -1;
else
awake_poll_interval =
new_wake_interval == healthd_config.periodic_chores_interval_fast ?
-1 : healthd_config.periodic_chores_interval_fast * 1000;
}
int new_wake_interval = gBatteryMonitor->update() 最终走的是这里。
这个代码在BatteryMonitor.cpp下面
bool BatteryMonitor::update(void) {}
太长了,就不贴了。
我们知道,电池信息节点文件是在驱动层面。kernel上报消息,用的是uevent。
static void uevent_event(uint32_t /*epevents*/) {
char msg[UEVENT_MSG_LEN+2];
char *cp;
int n;n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
if (n <= 0)
return;
if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
return;msg[n] = '\0';
msg[n+1] = '\0';
cp = msg;while (*cp) {
if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
healthd_battery_update();
break;
}/* advance to after the next \0 */
while (*cp++)
;
}
}
当系统开启时,系统会走healthd.cpp的main函数。
在这里会监听POWER_SUPPLY_SUBSYSTEM文件发生变化,会执行healthd_battery_update