本文是基于android11源码分析,带你一起了解android快速充电的基本流程。
Android原生在充电时下拉状态栏上会有以下之一的提示
"正在充电(还需xxx充满)"
"正在快速充电(还需xxx充满)"
"正在慢速充电(还需xxx充满)"
下面我们以快速充电作为切入点,进行分析。
这个提示是属于SystemUI的,我们直接在SystemUI下搜索"正在快速充电",发现这个字符串的ID是keyguard_indication_charging_time_fast,并且在
frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\KeyguardIndicationController.java被使用的。
KeyguardIndicationController.java
protected String computePowerIndication() {
........
if (mPowerPluggedInWired) {
switch (mChargingSpeed) {
case BatteryStatus.CHARGING_FAST:
chargingId = hasChargingTime
? R.string.keyguard_indication_charging_time_fast//正在快速充电(还需xxx充满)的字符串ID
: R.string.keyguard_plugged_in_charging_fast;
.............
}
mChargingSpeed是区分快速充电/正常充电/慢速充电,它的值是在BaseKeyguardCallback回调的传回来的
protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
public static final int HIDE_DELAY_MS = 5000;
@Override
public void onRefreshBatteryInfo(BatteryStatus status) {
...............
mChargingSpeed = status.getChargingSpeed(mContext);//配置充电速度
mBatteryLevel = status.level;
..............
}
BatteryStatus.java
public final int getChargingSpeed(Context context) {
final int slowThreshold = context.getResources().getInteger(
R.integer.config_chargingSlowlyThreshold);//慢速充电
final int fastThreshold = context.getResources().getInteger(
R.integer.config_chargingFastThreshold);//快速充电
return maxChargingWattage <= 0 ? CHARGING_UNKNOWN :
maxChargingWattage < slowThreshold ? CHARGING_SLOWLY :
maxChargingWattage > fastThreshold ? CHARGING_FAST :
CHARGING_REGULAR;
}
config_chargingFastThreshold这个值的配置是在SettingLib包下
frameworks/base/packages/SettingsLib/res/values/config.xml
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Threshold in micro watts below which a charger is rated as "slow"; 1A @ 5V -->
<integer name="config_chargingSlowlyThreshold">5000000</integer>
<!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V -->
<integer name="config_chargingFastThreshold">7500000</integer>
</resources>
到这里可以看到,显示充电快慢是可以通过config配置的,默认情况下充电功率小于5W显示慢速充电,充电瓦数大于7.5W显示快速充电,在5W和7.5W之间显示正常充电
接着看maxChargingWattage 是由BatteryStatus构造函数传入计算得到的,先看BatteryStatus的构造函数从哪里调用的。
protected KeyguardUpdateMonitorCallback getKeyguardCallback() {
if (mUpdateMonitorCallback == null) {
mUpdateMonitorCallback = new BaseKeyguardCallback();
}
return mUpdateMonitorCallback;
}
可以看到BaseKeyguardCallback是通过getKeyguardCallback()实例化的,继续查找getKeyguardCallback()是从哪里调用的
public KeyguardIndicationController(Context context,
WakeLock.Builder wakeLockBuilder,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
DockManager dockManager,
BroadcastDispatcher broadcastDispatcher,
DevicePolicyManager devicePolicyManager,
IBatteryStats iBatteryStats,
UserManager userManager) {
...........
mKeyguardUpdateMonitor.registerCallback(getKeyguardCallback());
mKeyguardUpdateMonitor.registerCallback(mTickReceiver);
mStatusBarStateController.addCallback(this);
mKeyguardStateController.addCallback(this);
}
getKeyguardCallback()是通过KeyguardUpdateMonitor注册调用的。
KeyguardUpdateMonitor.java
public void registerCallback(KeyguardUpdateMonitorCallback callback) {
............
mCallbacks.add(new WeakReference<>(callback));
removeCallback(null); // remove unused references
sendUpdates(callback);
}
registerCallback做了两个事情,一是把BaseKeyguardCallback添加到集合,二是调用sendUpdates。sendUpdates做了什么内容呢?
KeyguardUpdateMonitor.java
private void sendUpdates(KeyguardUpdateMonitorCallback callback) {
// Notify listener of the current state
callback.onRefreshBatteryInfo(mBatteryStatus);
............
}
sendUpdates回调了onRefreshBatteryInfo,并把mBatteryStatus传入,再跟mBatteryStatus是从哪里设置的
KeyguardUpdateMonitor.java
private void handleBatteryUpdate(BatteryStatus status) {
........
mBatteryStatus = status;
......
}
KeyguardUpdateMonitor.java
protected KeyguardUpdateMonitor(
Context context,
@Main Looper mainLooper,
BroadcastDispatcher broadcastDispatcher,
DumpManager dumpManager,
RingerModeTracker ringerModeTracker,
@Background Executor backgroundExecutor,
StatusBarStateController statusBarStateController,
LockPatternUtils lockPatternUtils) {
.................
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
..........
case MSG_BATTERY_UPDATE:
handleBatteryUpdate((BatteryStatus) msg.obj);
break;
................
}
KeyguardUpdateMonitor.java
protected final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
.........
} else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
final Message msg = mHandler.obtainMessage(
MSG_BATTERY_UPDATE, new BatteryStatus(intent));
mHandler.sendMessage(msg);
} else if (Intent.ACTION_SIM_STATE_CHANGED.equals(action)) {
..............
};
BatteryStatus最终是通过监听到Intent.ACTION_BATTERY_CHANGED的广播调用的。
BatteryStatus.java
public BatteryStatus(Intent batteryChangedIntent) {
status = batteryChangedIntent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN);
plugged = batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0);
level = batteryChangedIntent.getIntExtra(EXTRA_LEVEL, 0);
health = batteryChangedIntent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true);
final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT,
-1);
int maxChargingMicroVolt = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_VOLTAGE, -1);
if (maxChargingMicroVolt <= 0) {
maxChargingMicroVolt = DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT;
}
if (maxChargingMicroAmp > 0) {
// Calculating muW = muA * muV / (10^6 mu^2 / mu); splitting up the divisor
// to maintain precision equally on both factors.
maxChargingWattage = (maxChargingMicroAmp / 1000)
* (maxChargingMicroVolt / 1000);
} else {
maxChargingWattage = -1;
}
}
maxChargingWattage最大充电瓦数是通过maxChargingMicroAmp(电流)和maxChargingMicroVolt(电压)计算得出的。
至此,我们的的焦点转移到了Intent.ACTION_BATTERY_CHANGED广播的发出和广播携带的EXTRA_MAX_CHARGING_CURRENT、EXTRA_MAX_CHARGING_VOLTAGE两个参数上。
Intent.ACTION_BATTERY_CHANGED的广播是从BatteryService.java发出的。
BatteryService.java
private void sendBatteryChangedIntentLocked() {
...............
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrent);
intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mHealthInfo.maxChargingVoltage);
..........
mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL));
}
BatteryManager.EXTRA_MAX_CHARGING_CURRENT和BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE这两个值是从mHealthInfo中得到的。继续看mHealthInfo是从哪里赋值的。
BatteryService.java
private void update(android.hardware.health.V2_1.HealthInfo info) {
..............
synchronized (mLock) {
if (!mUpdatesStopped) {
mHealthInfo = info.legacy.legacy;
mHealthInfo2p1 = info;
// Process the new values.
processValuesLocked(false);
mLock.notifyAll(); // for any waiters on new info
............
}
BatteryService.java
private final class HealthHalCallback extends IHealthInfoCallback.Stub
implements HealthServiceWrapper.Callback {
@Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
...............
BatteryService.this.update(propsLatest);
}
@Override public void healthInfoChanged_2_1(android.hardware.health.V2_1.HealthInfo props) {
BatteryService.this.update(props);
}
healthInfoChanged_2_1是由Hal层的hardware\interfaces\health\utils\libhealth2impl\include\health2impl\Callback.h回调的。HAL是由不同厂商定制的,我们就不再往下跟了。
总结:充电的快慢的区分是在SettingsLib下配置的,充电的功率小于5W显示慢速充电,大于7.5W显示快速充电,在5W到7.5W之间显示正在充电,充电功率的值是进入到HAL层来获取。
本文是通过逆向思维的方法,从上往下去跟踪数据的获取/传入流程,最开始直接搜索显示的字符,快速找到调用的位置,这是在分析源码时很好的一个方法。