Android15 AndroidV冻结和解冻的场景

摘要

cgroup 最初由 Google 工程师 Paul Menage 和 Rohit Seth 在 2006 年提出,是一种细粒度资源控制的Linux内核机制。于 2007 年合并到 Linux 内核主线中。然而 Google 原生系统直到 Android 11 或更高版本上才支持 CACHE 应用的 CPU 冻结功能。当应用切换到后台并且没有其他活动时,系统会在一定时间内通过状态判断,将进程 ID 迁移到冻结的 cgroup 节点上,实现冻结 CACHE 应用。这项功能可以减少活跃缓存应用在后台存在时所消耗的 CPU 资源,从而达到节电的目的。当应用再次切换到前台时,系统会将该应用的进程解冻,以实现快速启动。

0

0

一、冻结场景

主要看哪些场景调用到 freezeAppAsyncInternalLSP 函数

冻结场景

触发条件

执行逻辑

操作示例/命令

Adj更新触发冻结

进程的OOM_ADJ值≥CACHED_APP_MIN_ADJ(900)且持续10秒无交互

系统通过CachedAppOptimizer.freezeAppAsyncLSP延迟10秒执行冻结

自动触发,无需手动操作

广播发送方冻结

发送方进程(callerApp)满足isProcessFreezable条件(adj≥900且非豁免)

1. 检查广播发送数量阈值

2. 调用forceFreezeAppAsyncLSP立即冻结

代码逻辑:BroadcastQueueModernImpl.enqueueBroadcastLocked()

ADB命令手动冻结

通过am freeze命令指定目标进程

1. 解析包名/PID

2. 调用runFreeze(pw, true)写入cgroup.freeze=1

adb shell am freeze com.tencent.mp

adb shell am freeze --pid 9432

1.1 Adj 更新触发大于900判断,10秒后执行冻结

冻结流程:前台进程 --> 可感知进程--> 服务进程 --> Cached进程->10秒后->cgroup freeze子系统冻结

CachedAppOptimizer.freezeAppAsyncLSP(ProcessRecord app, @UptimeMillisLong long delayMillis) // 10 秒后冻结->CachedAppOptimizer.freezeAppAsyncInternalLSP(ProcessRecord app, @UptimeMillisLong long delayMillis, boolean force)ActivityManagerService.updateOomAdjLocked→OomAdjuster.updateOomAdjLocked→→OomAdjuster.updateOomAdjLSP→→→OomAdjusterModernImpl.performUpdateOomAdjLSP→→→→OomAdjusterModernImpl.performUpdateOomAdjPendingTargetsLocked→→→→→OomAdjusterModernImpl.partialUpdateLSP→→→→→→OomAdjuster.postUpdateOomAdjInnerLSP→→→→→→→OomAdjuster.updateAndTrimProcessLSP→→→→→→→→OomAdjuster.applyOomAdjLSP→→→→→→→→→OomAdjuster.updateAppFreezeStateLSP adj大于900进程(FREEZER_CUTOFF_ADJ)→→→→→→→→→→CachedAppOptimizer.freezeAppAsyncLSP→→→→→→→→→→→CachedAppOptimizer.freezeAppAsyncInternalLSP 防抖超时阈值(默认10秒)→→→→→→→→→→→→SET_FROZEN_PROCESS_MSG 等10秒(默认10秒防抖)→→→→→→→→→→→→→CachedAppOptimizer.freezeBinder 先冻结Binder再冻结进程的原则→→→→→→→→→→→→→CachedAppOptimizer.freezeProcess 通过cgroup v2 freezer子系统实现→→→→→→→→→→→→→→Process.setProcessFrozen(pid, proc.uid, true) 内核级冻结→→→→→→→→→→→→→→→android_os_Process.android_os_Process_setProcessFrozen(jint pid, jint uid, jboolean freeze)→→→→→→→→→→→→→→→→processgroup.SetProcessProfiles→→→→→→→→→→→→→→→→→TaskProfiles.SetProcessProfiles()→→→→→→→→→→→→→→→→→→TaskProfiles.ExecuteForProcess()→→→→→→→→→→→→→→→→→→→TaskProfiles.ExecuteForProcess()写冻结的文件节点:/sys/fs/cgroup/uid_1000/pid_1234/cgroup.freeze,例如1

1.2 广播发送方若可被冻结,则立刻冻结

防止广播发送方滥用后台资源

当广播发送方进程(callerApp)处于缓存状态(adj≥900)时,若其频繁发送广播,可能通过跨进程通信(Binder)持续占用CPU资源。冻结发送方进程可强制中断其广播发送能力,避免后台进程通过广播保活或消耗系统资源

​​​​​​​

BroadcastQueueModernImpl.enqueueBroadcastLocked->->CachedAppOptimizer.freezeAppAsyncImmediateLSP(ProcessRecord app) // 立即冻结->->->CachedAppOptimizer.freezeAppAsyncInternalLSP(ProcessRecord app, @UptimeMillisLong long delayMillis, boolean force)/** * 处理广播入队逻辑,并对后台进程的广播发送行为进行限制 *  * 核心设计原则: * 1. 选择性冻结广播发送方(callerApp)而非接收方,原因: *    - 发送方通常是后台进程(adj≥900),冻结可防止其滥用广播保活 *    - 接收方多为用户交互进程(adj≤700),冻结会导致功能中断 *    - 符合Android非对称优先级策略:牺牲后台进程保前台体验 *  * 2. 异步冻结机制确保系统稳定性: *    - freezeAppAsyncImmediateLSP的延迟执行(默认0秒)避免误杀临时性广播 *    - 超过MAX_FROZEN_OUTGOING_BROADCASTS阈值时立即终止进程 */@Overridepublic void enqueueBroadcastLocked(@NonNull BroadcastRecord r) {
  
      // TODO: Apply delivery group policies and FLAG_REPLACE_PENDING to collapse the    // outgoing broadcasts.    // TODO: Add traces/logs for the enqueueing outgoing broadcasts logic.    /* 后台进程广播限制逻辑     * 触发条件:     * 1. 系统启用广播延迟策略(Flags.deferOutgoingBroadcasts)     * 2. 发送方为可冻结进程(adj≥900且非豁免状态)     */    if (Flags.deferOutgoingBroadcasts() && isProcessFreezable(r.callerApp)) {
  
          // 获取或创建进程专属的广播队列        final BroadcastProcessQueue queue = getOrCreateProcessQueue(                r.callerApp.processName, r.callerApp.uid);        /* 广播流量控制         * 当单个后台进程发送广播超过阈值时(防DoS攻击):         * 1. 记录异常日志(noisy=true触发Log.wtf)         * 2. 立即终止进程而非冻结,避免资源持续泄漏         *          * 典型阈值:MAX_FROZEN_OUTGOING_BROADCASTS=5(机型可配置)         */        if (queue.getOutgoingBroadcastCount() >= mConstants.MAX_FROZEN_OUTGOING_BROADCASTS) {
  
              r.callerApp.killLocked("Too many outgoing broadcasts in cached state",                    ApplicationExitInfo.REASON_OTHER,                    ApplicationExitInfo.SUBREASON_EXCESSIVE_OUTGOING_BROADCASTS_WHILE_CACHED,                    true /* noisy */);            return;        }        // 记录广播到进程历史(用于ANR分析和状态恢复)        queue.enqueueOutgoingBroadcast(r);        mHistory.onBroadcastFrozenLocked(r);        /* 执行异步冻结         * 关键特性:         * 1. 延迟10秒执行,允许短时突发广播         * 2. 通过Binder冻结+内存压缩双重优化         * 3. 与OomAdjuster协同更新adj值         */        mService.mOomAdjuster.mCachedAppOptimizer.freezeAppAsyncImmediateLSP(r.callerApp);        return;    }}

1.3 adb shell 命令冻结

冻结命令

基础命令格式:adb shell am freeze[options]

:目标应用的包名(如 com.example.app)或进程ID(如 1234)

options]:可选参数(如 --user 0指定用户)

例如

adb shell am freeze com.tencent.mp

adb shell am freeze --pid 9432

0

ActivityManagerShellCommand.runFreeze->CachedAppOptimizer.forceFreezeAppAsyncLSP(ProcessRecord app)/** * 执行进程冻结/解冻操作的命令行接口实现 *  * @param pw 输出流,用于打印操作结果 * @param freeze 操作类型:true=冻结,false=解冻 * @return 执行状态:0=成功,-1=失败 * @throws RemoteException 远程调用异常 *  * 关键流程说明: * 1. 解析命令行参数(如--sticky标记) * 2. 获取目标进程记录(ProcessRecord) * 3. 执行冻结/解冻操作并输出结果 */@NeverCompile  // 标记该方法不参与编译时优化int runFreeze(PrintWriter pw, boolean freeze) throws RemoteException {
  
      // 解析命令行附加参数(如--sticky持久化标记)    String freezerOpt = getNextOption();    boolean isSticky = false;    if (freezerOpt != null) {
  
          isSticky = freezerOpt.equals("--sticky");    }    // 通过shell命令获取目标进程信息    ProcessRecord proc = getProcessFromShell();    if (proc == null) {
  
          return -1;  // 进程不存在或权限不足    }    // 打印操作日志(包含进程名、PID和sticky状态)    pw.print(freeze ? "Freezing" : "Unfreezing");    pw.print(" process " + proc.processName);    pw.println(" (" + proc.mPid + ") sticky=" + isSticky);    /* 核心冻结/解冻逻辑(需双重锁保护)     * 同步块说明:     * 1. mInternal锁:保证AMS服务状态一致性     * 2. mProcLock锁:防止进程状态并发修改     */    synchronized (mInternal) {
  
          synchronized (mInternal.mProcLock) {
  
              // 设置持久化标记(控制解冻后是否保持低优先级)            proc.mOptRecord.setFreezeSticky(isSticky);            if (freeze) {
  
                  /* 强制异步冻结                 * 内部流程:                 * 1. 延迟10ms执行(避免锁竞争)                 * 2. 调用Binder驱动冻结IPC通信                 * 3. 写入cgroup.freeze=1触发内核冻结                 */                mInternal.mOomAdjuster.mCachedAppOptimizer.forceFreezeAppAsyncLSP(proc);            } else {
  
                  /* 内部解冻                 * 参数说明:                 * @param proc 目标进程                 * @param reason 解冻原因(0=手动触发)                 * @param immediate 是否跳过延迟立即执行                 */                mInternal.mOomAdjuster.mCachedAppOptimizer.unfreezeAppInternalLSP(proc, 0, true);           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

法迪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值