【功耗治理】应用宝是真的猛,Doze的idle下依旧可以联网

待机联网唤醒时间点

App Processor wakeupMay 27 202515:32:27 - 15:32:27+59m23s294ms to +59m23s294ms1 occurencesApp Processor wakeup             | Number of timescom.tencent.android.qqdownloader | 1              

0

这种现象,一般查看netpolicy就可以知道原因了:​​​​​​​

2025-05-27T15:37:32:480 - Firewall rule changed: 10225-background-allow2025-05-27T15:37:32:480 - Firewall rule changed: 10225-standby-default2025-05-27T15:32:32:474 - temp-power-save whitelist for 10225 changed to: true; reason=SYNC_MANAGER <sync by top app>2025-05-27T15:32:37:677 - 10225:BTOP:LCMNFUA:290812025-05-27T15:11:19:166 - Firewall rule changed: 10225-background-allow

源码

doze模式下的联网防火墙管理​​​​​​​

NetworkPolicyManagerService:onTempPowerSaveWhitelistChange->NetworkPolicyLogger.tempPowerSaveWlChanged()NetworkPolicyLogger:tempPowerSaveWlChanged() -> NetworkPolicyLogger:getTempPowerSaveWlChangedLog()​​​​​​​
doze模式下的联网防火墙管理NetworkPolicyManagerService.java1. setDeviceIdleMode() -> handleDeviceIdleModeChangedUL(mDeviceIdleMode)2. handleDeviceIdleModeChangedUL(mDeviceIdleMode) 主要做2件事情->2.1 updateRulesForDeviceIdleUL() 重要应用的联网允许-->2.1.1 updateRulesForAllowlistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,mUidFirewallDozableRules)--->2.1.1.1 updateRulesForAllowlistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id) 临时白名单设置允许联网---->2.1.1.1.1 uidRules.put(uid, FIREWALL_RULE_ALLOW)--->2.1.1.2 updateRulesForAllowlistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id) 白名单设置允许联网---->2.1.1.2.1 uidRules.put(uid, FIREWALL_RULE_ALLOW)--->2.1.1.3 uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);  基于isProcStateAllowedWhileIdleOrPowerSaveMode进程重要度的动态白名单设置设置允许联网--->2.1.1.4 setUidFirewallRulesUL(chain, uidRules, CHAIN_TOGGLE_ENABLE);临时白名单、白名单、重要进程和省电模式白名单设置允许联网---->2.1.1.4.1 mNetworkManager.setFirewallUidRules(chain, uids, rules) 设置联网防火墙规则,设置上述名单为运行联网---->2.1.1.4.2 setUidFirewallRulesUL->NetworkPolicyLogger.firewallRulesChanged(chain, uids, rules) 打印允许联网得->2.2 updateRulesForPowerRestrictionsUL(uid):每个应用联网规则的限制与运行状态更新和通知-->2.2.1 updateRulesForPowerRestrictionsUL(uid, PROCESS_STATE_UNKNOWN)--->2.2.1.1 updateRulesForPowerRestrictionsUL(uid, isUidIdle(uid, uidProcState))----> 2.2.1.1.1 updateRulesForPowerRestrictionsULInner(uid, isUidIdle)-----> 2.2.1.1.1.1 handleBlockedReasonsChanged(uid,newEffectiveBlockedReasons,oldEffectiveBlockedReasons)------> 2.2.1.1.1.1.1 mActivityManagerInternal.onUidBlockedReasonsChanged(uid, newEffectiveBlockedReasons)------> 2.2.1.1.1.1.2 postBlockedReasonsChangedMsg(uid, newEffectiveBlockedReasons, oldEffectiveBlockedReasons)-----> 2.2.1.1.1.2 postUidRulesChangedMsg(uid, uidRules)

从源码可以得知:即使应用宝非Doze白名单,也可以通过消息通知和前台服务进程的绑定关系,将自身进程在tempwhitelist和appIdle进行动态豁免。例如下述主要是AMS的process状态进行豁免,一般只需要FOREGROUND属性即可动态豁免联网

​​​​​​​

/** @hide */public static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(        int procState, @ProcessCapability int capability) {    if (procState == PROCESS_STATE_UNKNOWN) {        return false;    }    // bv fadi add for DozePlus 20250528 start    if (NetPolicyStub.getInstance().isProcStateRestrictWhileIdleOrPowerSaveMode(uid            ,uidState.procState)) {        return false;    }    // bv fadi add for DozePlus 20250528 end    return procState <= FOREGROUND_THRESHOLD_STATE            || (capability & ActivityManager.PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;}/** @hide */public static boolean isProcStateAllowedWhileInLowPowerStandby(@Nullable UidState uidState) {    if (uidState == null) {        return false;    }    // bv fadi add for DozePlus 20250528 start    if (NetPolicyStub.getInstance().isProcStateRestrictWhileInLowPowerStandby(uid            , uidState.procState)) {        return false;    }    // bv fadi add for DozePlus 20250528 end    return uidState.procState <= TOP_THRESHOLD_STATE;}/** * This is currently only used as an implementation detail for * {@link com.android.server.net.NetworkPolicyManagerService}. * Only put here to be together with other isProcStateAllowed* methods. * * @hide */public static boolean isProcStateAllowedNetworkWhileBackground(@Nullable UidState uidState) {    if (uidState == null) {        return false;    }    // bv fadi add for DozePlus 20250528 start    if (NetPolicyStub.getInstance().isProcStateRestrictNetworkWhileBackground(uid            ,uidState.procState)) {        return false;    }    // bv fadi add for DozePlus 20250528 end    return uidState.procState < BACKGROUND_THRESHOLD_STATE            || (uidState.capability & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0;}/** @hide */public static boolean isProcStateAllowedWhileOnRestrictBackground(int procState,        @ProcessCapability int capabilities) {    if (procState == PROCESS_STATE_UNKNOWN) {        return false;    }    // bv fadi add for DozePlus 20250528 start    if (NetPolicyStub.getInstance().isProcStateRestrictWhileOnRestrictBackground(uid            ,uidState.procState)) {        return false;    }    // bv fadi add for DozePlus 20250528 end    return procState <= FOREGROUND_THRESHOLD_STATE            // This is meant to be a user-initiated job, and therefore gets similar network            // access to FGS.            || (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND                    && (capabilities                          & ActivityManager.PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0);}

对比总结

函数名称

目标场景

豁免条件

严格程度

isProcStateAllowedWhileIdleOrPowerSaveMode

省电/Doze模式

前台进程 或 有电源相关网络能力

isProcStateAllowedWhileInLowPowerStandby

低电量待机模式

仅顶级进程(如锁屏)

极高

isProcStateAllowedNetworkWhileBackground

普通后台限制

非纯后台进程 或 有网络特权

isProcStateAllowedWhileOnRestrictBackground

用户手动限制后台数据

前台进程 或 用户发起的后台任务(

经过上述优化,进程10225的应用宝进程在Doze模式下,被成功的限制网络能力了。​​​​​​​

05-29 15:20:19.009  1605  1898 D NetPolicyStubImpl: setUidFirewallRuleUL uid=10225,chain=metered_deny_admin,allow=false05-29 15:20:19.009  1605  1898 D NetPolicyStubImpl: setUidFirewallRuleUL uid=10225,chain=metered_deny_user,allow=false05-29 15:20:19.009  1605  1898 D NetPolicyStubImpl: setUidFirewallRuleUL uid=10225,chain=metered_allow,allow=false05-29 15:20:19.010  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_UidOptimizedEvent:uid=10225,uid=10225 doze 05-29 15:20:19.010  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_ProcStateRestrictWhileIdleOrPowerSaveMode:uid=10225,uid=10225 doze 05-29 15:20:19.010  1605  1898 D NetPolicyStubImpl: setUidFirewallRuleUL uid=10225,chain=standby,allow=false05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_ProcStateRestrictWhileIdleOrPowerSaveMode:uid=10225,uid=10225 doze 05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: setUidFirewallRuleUL uid=10225,chain=dozable,allow=false05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_UidOptimizedEvent:uid=10225,uid=10225 doze 05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_ProcStateRestrictWhileIdleOrPowerSaveMode:uid=10225,uid=10225 doze 05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_ProcStateRestrictWhileInLowPowerStandby:uid=10225,uid=10225 doze 05-29 15:20:19.012  1605  1898 D NetPolicyStubImpl: NetPolicyStubImpl_ProcStateWhileOnRestrictBackground:uid=10225,uid=10225 doze 05-29 15:20:19.013  1605  1898 D NetPolicyStubImpl: updateRulesForPowerRestrictionsUL(10225), isIdle: true, mRestrictPower: false, mDeviceIdleMode: true, isForeground=false, isTop=false, isWhitelisted=false, oldUidBlockedState={blocked=DOZE|APP_STANDBY|APP_BACKGROUND,allowed=NONE,effective=DOZE|APP_STANDBY|APP_BACKGROUND}, newUidBlockedState={blocked=DOZE|APP_STANDBY|APP_BACKGROUND,allowed=NONE,effective=DOZE|APP_STANDBY|APP_BACKGROUND}GetAddrInfoHandler::run: {104 262248 104 983144 10225 0}  # DNS查询请求GetAddrInfoHandler::run: network access blocked            # 防火墙规则(如 iptables)或系统策略(如 Doze 模式)已生效,但拦截发生在 DNS 查询阶段,尚未到达实际网络传输层alps/packages/modules/DnsResolver/DnsProxyListener.cppvoid DnsProxyListener::GetAddrInfoHandler::run() {    LOG(INFO) << "GetAddrInfoHandler::run: {" << mNetContext.toString() << "}";    ...    const bool isUidBlocked = isUidNetworkingBlocked(mNetContext.uid, mNetContext.dns_netid);    if (isUidBlocked) {        LOG(INFO) << "GetAddrInfoHandler::run: network access blocked";        rv = EAI_FAIL;        ...}/** * 检查指定UID的网络访问是否被阻止 * @param uid   目标用户ID(应用UID) * @param netId 网络标识符(如WiFi/移动数据等) * @return true表示网络访问被阻止,false表示允许访问 *  * 核心逻辑: * 1. 检查全局拦截功能是否启用 * 2. 排除DNS特权网络 * 3. 尊重实验性功能开关 * 4. 最终调用厂商实现判断 */bool isUidNetworkingBlocked(uid_t uid, unsigned netId) {    // 1. 检查基础拦截功能是否可用(ADnsHelper_isUidNetworkingBlocked为函数指针)    if (!ADnsHelper_isUidNetworkingBlocked) return false;    // 2. 特殊网络豁免检查(DNS特权网络)    // 当网络启用enforceDnsUid时,DNS查询使用AID_DNS(1053)而非应用UID    // 这类网络不受常规UID拦截规则限制(如企业VPN场景)    if (resolv_is_enforceDnsUid_enabled_network(netId)) return false;    // 3. 实验性功能开关检查    // 通过getFlag动态控制功能开关,默认值1表示开启(兼容性兜底)    if (!android::net::Experiments::getInstance()->getFlag(            "fail_fast_on_uid_network_blocking", 1 /* default_value */)) {        return false;    }    // 4. 调用厂商具体实现(参数说明):    // - uid: 待检查的应用UID    // - resolv_is_metered_network(netId): 判断是否为计量网络(如移动数据)    // 返回值1表示拦截,0表示放行    return (*ADnsHelper_isUngNetworkingBlocked)(uid, resolv_is_metered_network(netId)) == 1;}

从BugReport看,Doze模式下没有应用宝联网行为了。主要是常规的gms唤醒了

0

当然应用宝耗电异常不仅仅联网防火墙会管控,还有持锁、alarm、job和sync等,一般管控的方法拦截关联启动限制保活或冻结就好了(只要规避应用宝下载场景,其他的场景大胆限制就好了)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值