1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
private void processValuesLocked(boolean force) {
// 默认不记录日志
boolean logOutlier = false;
long dischargeDuration = 0;
// 当前电量值是否是危急电量
mBatteryLevelCritical =
mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mCriticalBatteryLevel;
if (mHealthInfo.chargerAcOnline) {
// AC 交流充电
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mHealthInfo.chargerUsbOnline) {
// USB 充电
mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
} else if (mHealthInfo.chargerWirelessOnline) {
// 无线充电
mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
} else {
// 未充电
mPlugType = BATTERY_PLUGGED_NONE;
}
// Let the battery stats keep track of the current level.
try {
// 将当前电池信息传给 BatteryStatsService 电量统计服务
mBatteryStats.setBatteryState(mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
mPlugType, mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
mHealthInfo.batteryVoltage, mHealthInfo.batteryChargeCounter,
mHealthInfo.batteryFullCharge);
} catch (RemoteException e) {
// Should never happen.
}
// 电池电量为零,且不处于充电状态,则弹出关机对话框
shutdownIfNoPowerLocked();
// 电池温度超过关机温度(默认:68°C),则弹出关机对话框
shutdownIfOverTempLocked();
// 电池信息发生改变或要求强制更新时
if (force || (mHealthInfo.batteryStatus != mLastBatteryStatus ||
mHealthInfo.batteryHealth != mLastBatteryHealth ||
mHealthInfo.batteryPresent != mLastBatteryPresent ||
mHealthInfo.batteryLevel != mLastBatteryLevel ||
mPlugType != mLastPlugType ||
mHealthInfo.batteryVoltage != mLastBatteryVoltage ||
mHealthInfo.batteryTemperature != mLastBatteryTemperature ||
mHealthInfo.maxChargingCurrent != mLastMaxChargingCurrent ||
mHealthInfo.maxChargingVoltage != mLastMaxChargingVoltage ||
mHealthInfo.batteryChargeCounter != mLastChargeCounter ||
mInvalidCharger != mLastInvalidCharger)) {
if (mPlugType != mLastPlugType) {
// 充电状态发生改变
if (mLastPlugType == BATTERY_PLUGGED_NONE) {
// discharging -> charging
// 未充电 -> 充电
// 充电开始的电量和时间
mChargeStartLevel = mHealthInfo.batteryLevel;
mChargeStartTime = SystemClock.elapsedRealtime();
// 记录日志
final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);
builder.setType(MetricsEvent.TYPE_ACTION);
builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mPlugType);
builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,
mHealthInfo.batteryLevel);
mMetricsLogger.write(builder);
// There's no value in this data unless we've discharged at least once and the
// battery level has changed; so don't log until it does.
// 在至少有过一次未充电状态并且电量有改变前,记录日志是无意义的,所以在此之后才开始记录日志
if (mDischargeStartTime != 0 && mDischargeStartLevel != mHealthInfo.batteryLevel) {
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
logOutlier = true;
EventLog.writeEvent(EventLogTags.BATTERY_DISCHARGE, dischargeDuration,
mDischargeStartLevel, mHealthInfo.batteryLevel);
// make sure we see a discharge event before logging again
// 再次确保在记录日志钱有过未充电状态
mDischargeStartTime = 0;
}
} else if (mPlugType == BATTERY_PLUGGED_NONE) {
// charging -> discharging or we just powered up
// 充电 -> 未充电
mDischargeStartTime = SystemClock.elapsedRealtime();
mDischargeStartLevel = mHealthInfo.batteryLevel;
long chargeDuration = SystemClock.elapsedRealtime() - mChargeStartTime;
if (mChargeStartTime != 0 && chargeDuration != 0) {
final LogMaker builder = new LogMaker(MetricsEvent.ACTION_CHARGE);
builder.setType(MetricsEvent.TYPE_DISMISS);
builder.addTaggedData(MetricsEvent.FIELD_PLUG_TYPE, mLastPlugType);
builder.addTaggedData(MetricsEvent.FIELD_CHARGING_DURATION_MILLIS,
chargeDuration);
builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_START,
mChargeStartLevel);
builder.addTaggedData(MetricsEvent.FIELD_BATTERY_LEVEL_END,
mHealthInfo.batteryLevel);
mMetricsLogger.write(builder);
}
mChargeStartTime = 0;
}
}
// 记录电池状态信息
if (mHealthInfo.batteryStatus != mLastBatteryStatus ||
mHealthInfo.batteryHealth != mLastBatteryHealth ||
mHealthInfo.batteryPresent != mLastBatteryPresent ||
mPlugType != mLastPlugType) {
EventLog.writeEvent(EventLogTags.BATTERY_STATUS,
mHealthInfo.batteryStatus, mHealthInfo.batteryHealth, mHealthInfo.batteryPresent ? 1 : 0,
mPlugType, mHealthInfo.batteryTechnology);
}
// 记录电量信息
if (mHealthInfo.batteryLevel != mLastBatteryLevel) {
// Don't do this just from voltage or temperature changes, that is
// too noisy.
EventLog.writeEvent(EventLogTags.BATTERY_LEVEL,
mHealthInfo.batteryLevel, mHealthInfo.batteryVoltage, mHealthInfo.batteryTemperature);
}
// 电量处于危急状态并且没有充电,上次状态改变后也没处于危急电量
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
mPlugType == BATTERY_PLUGGED_NONE) {
// We want to make sure we log discharge cycle outliers
// if the battery is about to die.
// 确保能记录电池即将停止工作时的日志
dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
logOutlier = true;
}
if (!mBatteryLevelLow) {
// Should we now switch in to low battery mode?
// 当前不是处于低电量状态,判断是否要置于低电量状态
if (mPlugType == BATTERY_PLUGGED_NONE
&& mHealthInfo.batteryStatus !=
BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {
// 当前处于未充电状态,电池状态已知,电量低于低电量值则标记为低电量
mBatteryLevelLow = true;
}
} else {
// Should we now switch out of low battery mode?
// 当前处于低电量状态,判断是否要退出低电量状态
if (mPlugType != BATTERY_PLUGGED_NONE) {
// 处于充电状态,退出低电量状态
mBatteryLevelLow = false;
} else if (mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
// 当前电量高于取消低电量警告值,退出低电量状态
mBatteryLevelLow = false;
} else if (force && mHealthInfo.batteryLevel >= mLowBatteryWarningLevel) {
// If being forced, the previous state doesn't matter, we will just
// absolutely check to see if we are now above the warning level.
// 如果是强制更新电池状态,则忽略之前的状态,重新检查是否高于低电量值
mBatteryLevelLow = false;
}
}
// 状态更新计数加一
mSequence++;
// Separate broadcast is sent for power connected / not connected
// since the standard intent will not wake any applications and some
// applications may want to have smart behavior based on this.
// 为 连接电源/未连接电源 单独发送广播
if (mPlugType != 0 && mLastPlugType == 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
else if (mPlugType == 0 && mLastPlugType != 0) {
final Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
// 发送低电量状态改变广播
if (shouldSendBatteryLowLocked()) {
mSentLowBatteryBroadcast = true;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
} else if (mSentLowBatteryBroadcast &&
mHealthInfo.batteryLevel >= mLowBatteryCloseWarningLevel) {
mSentLowBatteryBroadcast = false;
final Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY);
statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
statusIntent.putExtra(BatteryManager.EXTRA_SEQUENCE, mSequence);
mHandler.post(new Runnable() {
@Override
public void run() {
mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL);
}
});
}
// We are doing this after sending the above broadcasts, so anything processing
// them will get the new sequence number at that point. (See for example how testing
// of JobScheduler's BatteryController works.)
// 发送电池状态改变广播
sendBatteryChangedIntentLocked();
if (mLastBatteryLevel != mHealthInfo.batteryLevel) {
// 发送电池电量值改变广播
sendBatteryLevelChangedIntentLocked();
}
// Update the battery LED
// 更新电池通知灯状态
mLed.updateLightsLocked();
// This needs to be done after sendIntent() so that we get the lastest battery stats.
if (logOutlier && dischargeDuration != 0) {
// 记录电池耗电日志
logOutlierLocked(dischargeDuration);
}
// 更新本地变量,记录当前电池状态
mLastBatteryStatus = mHealthInfo.batteryStatus;
mLastBatteryHealth = mHealthInfo.batteryHealth;
mLastBatteryPresent = mHealthInfo.batteryPresent;
mLastBatteryLevel = mHealthInfo.batteryLevel;
mLastPlugType = mPlugType;
mLastBatteryVoltage = mHealthInfo.batteryVoltage;
mLastBatteryTemperature = mHealthInfo.batteryTemperature;
mLastMaxChargingCurrent = mHealthInfo.maxChargingCurrent;
mLastMaxChargingVoltage = mHealthInfo.maxChargingVoltage;
mLastChargeCounter = mHealthInfo.batteryChargeCounter;
mLastBatteryLevelCritical = mBatteryLevelCritical;
mLastInvalidCharger = mInvalidCharger;
}
}
|