一、摘要
从源码看原生JobSchedulerService.setRequiresCharging 的特性,该特性竞品机器华为、Oppo也是如此。
1、应用处于前台可见,满足充电条件,立刻触发
2、应用处于后台不可见,需要设备连接USB或AC且电量大于90%,才能触发
job与充电相关的2个条件
final boolean powerConnected = mPowerTracker.isPowerConnected(); 设备连接USB或AC且Top应用且job优先级>=JobInfo.PRIORITY_DEFAULT)
final boolean stablePower = mService.isBatteryCharging() && mService.isBatteryNotLow(); 设备连接USB或AC且电量大于90%
job与电量相关的3个条件:
final boolean powerConnected = mPowerTracker.isPowerConnected();
final boolean stablePower = mService.isBatteryCharging() && mService.isBatteryNotLow(); 充电且电量大于90%
final boolean batteryNotLow = mService.isBatteryNotLow(); 电量大于15%
二、引子
视频预下载服务,需要充电电量到90%才触发,条件太苛刻,建议优化或去掉
2.1 日志分析
2.2 原始日志
行 2: 04-16 00:59:57.350 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=65, mBatteryLevel=65, isOverheat=false
行 260: 04-16 01:00:00.123 1979 7768 D JobScheduler: SCHEDULE: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 261: 04-16 01:00:00.123 1979 7768 D JobStore: Added job status to store: JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW WAIT:DEV_NOT_DOZING satisfied:0x0 unsatisfied:0x1b40000b}
行 262: 04-16 01:00:00.123 1979 7768 V JobScheduler.SC: wouldBeReadyWithConstraintLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService constraint=268435456 readyWithConstraint=false
行 264: 04-16 01:00:00.123 1979 7768 V JobScheduler.JobStatus: Constraint 268435456 is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 265: 04-16 01:00:00.124 1979 7768 I JobScheduler.Connectivity: Connectivity CHANGED for JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW WAIT:DEV_NOT_DOZING satisfied:0x10000000 unsatisfied:0xb40000b}: usable=true satisfied=true
行 266: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 2[CONSTRAINT_BATTERY_NOT_LOW] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 267: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 8[CONSTRAINT_STORAGE_NOT_LOW] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 268: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 4194304[CONSTRAINT_BACKGROUND_NOT_RESTRICTED] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 269: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 33554432[CONSTRAINT_DEVICE_NOT_DOZING] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 270: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 16777216[CONSTRAINT_WITHIN_QUOTA] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 271: 04-16 01:00:00.124 1979 7768 V JobScheduler.JobStatus: Constraint 134217728[CONSTRAINT_TARE_WEALTH] is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 272: 04-16 01:00:00.124 1979 7768 V JobScheduler.SC: wouldBeReadyWithConstraintLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService constraint=268435456 readyWithConstraint=false
行 273: 04-16 01:00:00.124 1979 7768 I JobScheduler.Connectivity: evaluateStateLocked finds job JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW satisfied:0x1b40000a unsatisfied:0x1} would not be ready.
行 274: 04-16 01:00:00.124 1979 7768 V JobScheduler: isReadyToBeExecutedLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService ready=false
行 685: 04-16 01:00:07.374 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=65, mBatteryLevel=65, isOverheat=false
行 723: 04-16 01:00:17.430 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=65, mBatteryLevel=65, isOverheat=false
行 746: 04-16 01:00:27.507 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=65, mBatteryLevel=66, isOverheat=false
行 841: 04-16 01:00:37.508 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 853: 04-16 01:00:42.275 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 898: 04-16 01:00:47.557 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 916: 04-16 01:00:57.594 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 928: 04-16 01:01:07.644 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 970: 04-16 01:01:17.644 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1039: 04-16 01:01:27.690 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1057: 04-16 01:01:37.711 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1077: 04-16 01:01:42.258 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1084: 04-16 01:01:47.757 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1134: 04-16 01:01:57.819 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1146: 04-16 01:02:07.820 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1172: 04-16 01:02:17.878 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=66, isOverheat=false
行 1183: 04-16 01:02:21.282 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=66, mBatteryLevel=80, isOverheat=false
行 1237: 04-16 01:02:29.594 1979 2056 D PowerManagerService: updateIsPoweredLocked: wasPowered=true, mIsPowered=true, oldPlugType=2, mPlugType=2, oldBatteryLevel=80, mBatteryLevel=90, isOverheat=false
行 1307: 04-16 01:02:29.617 1979 4059 V JobScheduler.JobStatus: Constraint 1 is satisfied for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1361: 04-16 01:02:29.624 1979 4059 I JobScheduler.Connectivity: Connectivity unchanged for JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY}: usable=true satisfied=true
行 1455: 04-16 01:02:29.632 1979 4059 V JobScheduler: isReadyToBeExecutedLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService ready=true
行 1456: 04-16 01:02:29.632 1979 4059 V JobScheduler: isReadyToBeExecutedLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService exists=true userStarted=true backingUp=false
行 1457: 04-16 01:02:29.632 1979 4059 V JobScheduler: isReadyToBeExecutedLocked: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService pending=false active=false
行 1458: 04-16 01:02:29.632 1979 4059 D JobScheduler: queued 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1568: 04-16 01:02:29.651 1979 4059 D JobScheduler.Concurrency: About to run job on context 24883730, job: JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY}
行 1576: 04-16 01:02:29.652 1979 4059 D JobScheduler.Battery: Prepping for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1577: 04-16 01:02:29.652 1979 4059 D JobScheduler.Quota: Prepping for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1578: 04-16 01:02:29.652 1979 4059 V JobScheduler.Quota: Starting to track 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1649: 04-16 01:02:29.664 1979 1979 D JobServiceContext: handleServiceBound for 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 1746: 04-16 01:02:29.677 1979 10282 D JobServiceContext: doCallback of : JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY} v:VERB_STARTING
行 4320: 04-16 01:04:13.310 1979 7052 D JobScheduler: CANCEL: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 4321: 04-16 01:04:13.311 1979 7052 V JobScheduler.Quota: Stopping tracking of 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
行 4364: 04-16 01:04:13.329 1979 7052 D JobServiceContext: doCallback of : JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY} v:VERB_STOPPING
行 4365: 04-16 01:04:13.329 1979 7052 D JobServiceContext: Cleaning up 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService reschedule=true reason=null
行 4384: 04-16 01:04:13.331 1979 7052 D JobScheduler: Completed JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY}, reason=0, reschedule=true
行 4385: 04-16 01:04:13.331 1979 7052 D JobStore: Couldn't remove job: didn't exist: JobStatus{7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService u=0 s=1000 NET CHARGING BATNOTLOW STORENOTLOW READY}
行 4386: 04-16 01:04:13.331 1979 7052 W JobScheduler: Job didn't exist in JobStore: 7ad35a6 #1000/20240110 com.fadi.su/com.fadi.predownload.PreDownloadJobService
三、相关源码
90%相关的逻辑,因为 JobSchedulerService 的充放电是监听 BatteryManager.ACTION_CHARGING和BatteryManager.ACTION_DISCHARGING的广播。
其中BatteryManager.ACTION_CHARGING和90%电量有关
3.1 JobSchedulerService
public class JobSchedulerService extends com.android.server.SystemService
implements StateChangedListener, JobCompletedListener {
} else if (BatteryManager.ACTION_CHARGING.equals(action)) {
if (DEBUG) {
Slog.d(TAG, "Battery charging @ " + sElapsedRealtimeClock.millis());
}
if (!mCharging) {
mCharging = true;
changed = true;
}
} else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
if (DEBUG) {
Slog.d(TAG, "Battery discharging @ " + sElapsedRealtimeClock.millis());
}
if (mCharging) {
mCharging = false;
changed = true;
}
}
3.2 BatteryController
/master_sm8650/android/qssi/frameworks/base/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
203
204 for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
205 final JobStatus ts = mTrackedTasks.valueAt(i);
206 if (ts.hasChargingConstraint()) {
207 if (hasTopExemptionLocked(ts)
208 && ts.getEffectivePriority() >= JobInfo.PRIORITY_DEFAULT) {
209 // If the job started while the app was on top or the app is currently on top,
210 // let the job run as long as there's power connected, even if the device isn't
211 // officially charging.
212 // For user requested/initiated jobs, users may be confused when the task stops
213 // running even though the device is plugged in.
214 // Low priority jobs don't need to be exempted.
215 if (ts.setChargingConstraintSatisfied(nowElapsed, powerConnected)) {// top应用满足充电条件,立刻触发
216 mChangedJobs.add(ts);
217 }
218 } else if (ts.setChargingConstraintSatisfied(nowElapsed, stablePower)) { // 后台应用设备连接USB或AC且电量大于90%
219 mChangedJobs.add(ts);
220 }
221 }
222 if (ts.hasBatteryNotLowConstraint()
223 && ts.setBatteryNotLowConstraintSatisfied(nowElapsed, batteryNotLow)) {
224 mChangedJobs.add(ts);
225 }
226 }
3.3 BatteryStatsImpl
14838 } else {
14839 if (level >= 90) {
14840 // If the battery level is at least 90%, always consider the device to be
14841 // charging even if it happens to go down a level.
14842 changed |= setChargingLocked(true);
15484
15485 boolean setChargingLocked(boolean charging) {
15486 // if the device is no longer charging, remove the callback
15487 // if the device is now charging, it means that this is either called
15488 // 1. directly when level >= 90
15489 // 2. or from within the runnable that we deferred
15490 // For 1. if we have an existing callback, remove it, since we will immediately send a
15491 // ACTION_CHARGING
15492 // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING
15493 mHandler.removeCallbacks(mDeferSetCharging);
15494 if (mCharging != charging) {
15495 mCharging = charging;
15496 if (charging) {
15497 mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
15498 } else {
15499 mHistoryCur.states2 &= ~HistoryItem.STATE2_CHARGING_FLAG;
15500 }
15501 mHandler.sendEmptyMessage(MSG_REPORT_CHARGING);
15502 return true;
15503 }
15504 return false;
15505 }
435 case MSG_REPORT_CHARGING:
436 if (cb != null) {
437 final String action;
438 synchronized (BatteryStatsImpl.this) {
439 action = mCharging ? BatteryManager.ACTION_CHARGING
440 : BatteryManager.ACTION_DISCHARGING;
441 }
442 Intent intent = new Intent(action);
443 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
444 cb.batterySendBroadcast(intent);