Android11 深休后系统定时唤醒导致网络请求服务器过载
硬件平台:QCS6125
软件平台:Android11
问题:每天的7:00和22:00 服务器会突然收到批量设备的网络请求,导致服务器过载。
通过系统的logcat日志发现了系统在休眠后,每天会有22:00、7:00的唤醒,从而导致这个时间段积累的workmanager定时任务同时批量调度,导致服务器紧张。
06-22 21:57:58.378 0 0 I : Restarting tasks ... done.
06-22 22:00:00.313 2108 2108 D Digital_clock: updateClock()!
06-22 22:00:00.314 1402 2696 I BatteryStatsService: In wakeup_callback: resumed from suspend
06-22 21:57:58.394 0 0 I : Resume caused by misconfigured IRQ 20 glink-native
06-22 22:00:00.314 0 0 I PM : PM: suspend exit 2025-06-22 14:00:00.314131022 UTC
06-22 22:00:00.314 0 0 I PM : suspend exit
06-22 22:00:00.316 1402 1402 D ConditionProviders.SCP: onReceive ScheduleConditionProvider.EVALUATE
06-22 22:00:00.317 1402 1402 D ConditionProviders.SCP: evaluateSubscriptionLocked cal=ScheduleCalendar[mDays={1, 2, 3, 4, 5, 6, 7}, mSchedule=ScheduleInfo{days=[1, 2, 3, 4, 5, 6, 7], startHour=22, startMinute=0, endHour=7, endMinute=0, exitAtAlarm=true, nextAlarm=Thu Jan 01 08:00:00 GMT+08:00 1970 (0)}], now=Sun Jun 22 22:00:00 GMT+08:00 2025 (1750600800316), nextUserAlarmTime=Thu Jan 01 08:00:00 GMT+08:00 1970 (0)
06-22 22:00:00.317 1402 1402 D ConditionProviders.SCP: notifyCondition condition://android/schedule?days=1.2.3.4.5.6.7&start=22.0&end=7.0&exitAtAlarm=true STATE_TRUE reason=meetsSchedule
06-22 22:00:00.317 1402 1402 D ConditionProviders.SCP: Scheduling evaluate for Mon Jun 23 07:00:00 GMT+08:00 2025 (1750633200000), in +8h59m59s684ms, now=Sun Jun 22 22:00:00 GMT+08:00 2025 (1750600800316)
06-22 22:00:00.326 2108 2108 D Digital_clock: updateClock()!
06-22 22:00:00.332 2108 2108 D Digital_clock: updateClock()!
06-22 22:00:00.332 839 2062 D AudioPolicyManagerCustom: setForceUse() usage 3, config 8, mPhoneState 0
06-22 22:00:00.415 0 0 I PM : PM: suspend entry 2025-06-22 14:00:00.415238470 UTC
06-22 22:00:00.415 0 0 I PM : suspend entry (deep)
06-22 22:00:00.415 0 0 I PM : Syncing filesystems ... done.
06-22 22:00:00.440 0 0 I : Freezing user space processes ...
06-22 22:00:00.450 0 0 I PM : Pending Wakeup Sources: qcom_rx_wakelock
06-22 22:00:00.450 0 0 E : Freezing of tasks aborted after 0.010 seconds
06-22 22:00:00.450 0 0 I : OOM killer enabled.
06-22 22:00:00.458 1402 2696 I BatteryStatsService: In wakeup_callback: suspend aborted
06-22 22:00:00.450 0 0 I : Restarting tasks ... done.
06-22 22:00:00.457 0 0 I : Resume caused by misconfigured IRQ 20 glink-native
06-22 22:00:00.457 0 0 I PM : PM: suspend exit 2025-06-22 14:00:00.457686751 UTC
而这个唤醒规则是按照framework层的一个勿扰模式的默认配置文件default_zen_mode_config.xml来的:
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2014, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
--><!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
<zen version="9"><allow alarms="true" media="true" system="false" calls="true" callsFrom="2" messages="false"reminders="false" events="false" repeatCallers="true" convos="false"convosFrom="3"/><automatic ruleId="EVENTS_DEFAULT_RULE" enabled="false" snoozing="false" name="Event" zen="1"component="android/com.android.server.notification.EventConditionProvider"conditionId="condition://android/event?userId=-10000&calendar=&reply=1"/><automatic ruleId="EVERY_NIGHT_DEFAULT_RULE" enabled="false" snoozing="false" name="Sleeping"zen="1" component="android/com.android.server.notification.ScheduleConditionProvider"conditionId="condition://android/schedule?days=1.2.3.4.5.6.7&start=22.0&end=7.0&exitAtAlarm=true"/><!-- all visual effects that exist as of P --><disallow visualEffects="511" /><!-- whether there are notification channels that can bypass dnd --><state areChannelsBypassingDnd="false" />
</zen>
这个规则配置的目的可能就是在相应的时间点,触发系统是否进入勿扰模式的状态评估。
针对我们这个问题,想到了大概两个方案吧,一个是直接禁用这个规则的加载;一个是把规则里边nextAlarm的时间打散,比如随机在22和7点上下浮动20min,即把唤醒的时间点从精准的7:00和22:00调整为散列在21:40~22:20以及6:40~7:20的范围。
由于不太确定规则禁用对系统的直接影响,所以采用了第二种方式。
具体改动如下:
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 35170332a07..df17b091e74 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -45,6 +45,7 @@ import java.io.PrintWriter;import java.util.ArrayList;import java.util.Calendar;import java.util.List;
+import java.util.Random;/*** Built-in zen condition provider for daily scheduled time-based conditions.
@@ -70,6 +71,7 @@ public class ScheduleConditionProvider extends SystemConditionProviderService {private AlarmManager mAlarmManager;private boolean mConnected;private boolean mRegistered;
+ private boolean mShakeValue;private long mNextAlarmTime;public ScheduleConditionProvider() {
@@ -181,6 +183,27 @@ public class ScheduleConditionProvider extends SystemConditionProviderService {updateAlarm(now, mNextAlarmTime);}+ private long getRandomTimeDelta() {
+ Random random = new Random();
+ // create a random num between 0~30
+ long randomNumber = (long) random.nextInt(21);
+
+ // set mShakeValue
+ mShakeValue = (randomNumber & 1) == 0;
+
+ if (mShakeValue)
+ return (randomNumber * 60 * 1000);
+
+ return -(randomNumber * 60 * 1000);
+ }
+
+ private boolean isNeedRandomTime(String cal) {
+ if (cal.contains("startHour=22"))
+ return true;
+
+ return false;
+ }
+@VisibleForTesting@GuardedBy("mSubscriptions")Condition evaluateSubscriptionLocked(Uri conditionId, ScheduleCalendar cal,
@@ -211,6 +234,13 @@ public class ScheduleConditionProvider extends SystemConditionProviderService {if (nextChangeTime > 0 && nextChangeTime > now) {if (mNextAlarmTime == 0 || nextChangeTime < mNextAlarmTime) {mNextAlarmTime = nextChangeTime;
+ if (DEBUG) Slog.d(TAG, String.format("mNextAlarmTime: %s",
+ ts(mNextAlarmTime)));
+ if (isNeedRandomTime(String.format("%s", cal))) {
+ mNextAlarmTime = nextChangeTime + getRandomTimeDelta();
+ if (DEBUG) Slog.d(TAG, String.format("Add random value mNextAlarmTime: %s",
+ ts(mNextAlarmTime)));
+ }}}return condition;
修改完成,编译验证日志:
06-25 16:50:39.122 1404 1404 D ConditionProviders.SCP: evaluateSubscriptionLocked cal=ScheduleCalendar[mDays={1, 2, 3, 4, 5, 6, 7}, mSchedule=ScheduleInfo{days=[1, 2, 3, 4, 5, 6, 7], startHour=22, startMinute=0, endHour=7, endMinute=0, exitAtAlarm=true, nextAlarm=Thu Jan 01 08:00:00 GMT+08:00 1970 (0)}], now=Wed Jun 25 16:50:39 GMT+08:00 2025 (1750841439104), nextUserAlarmTime=Thu Jan 01 08:00:00 GMT+08:00 1970 (0)
06-25 16:50:39.122 1404 1404 D ConditionProviders.SCP: notifyCondition condition://android/schedule?days=1.2.3.4.5.6.7&start=22.0&end=7.0&exitAtAlarm=true STATE_FALSE reason=!meetsSchedule
06-25 16:50:39.123 1404 1404 D ConditionProviders.SCP: mNextAlarmTime: Wed Jun 25 22:00:00 GMT+08:00 2025 (1750860000000)
06-25 16:50:39.124 1404 1404 D ConditionProviders.SCP: Add random value mNextAlarmTime: Wed Jun 25 22:18:00 GMT+08:00 2025 (1750861080000)
06-25 16:50:39.125 1404 1404 D ConditionProviders.SCP: Scheduling evaluate for Wed Jun 25 22:18:00 GMT+08:00 2025 (1750861080000), in +5h27m20s896ms, now=Wed Jun 25 16:50:39 GMT+08:00 2025 (1750841439104)
可以看到,默认设置的是22:00,但是通过修改的代码逻辑,下次alram的时间变成了22:18:00,即随机数生成的是18,目标达成。