MTK Android DuraSpeed优化机制导致app应用收不到广播分析解决

文章目录

简介

芯片:MTK

版本:android8

app名称:test

app包名:com.test

广播注册方法:动态注册

复现方法:

  1. app test内置到系统中并烧录到设备中,正常接收adb发送的广播;
  2. android studio run app test到设备,无法接收广播;
  3. 恢复出厂,或者卸载app test再重启后,正常接收广播。
  4. adb发送广播指令adb shell am broadcast -n com.test/.Receiver -a com.test --es cmd play

简单总结:一个运行中app,使用动态注册广播接收器,接收不到别人发的广播。

广播Receiver伪代码

动态注册广播接收器

java 复制代码
//广播接受类:
public class Receiver extends BroadcastReceiver {
}

// 在app启动MainActivity时,会调用
myReceiver = new Receiver();
registerReceiver(myReceiver, new IntentFilter("com.test"));

AndroidManifest.xml中设置exported属性为true

xml 复制代码
        <receiver android:name=".Receiver"
            android:exported="true">
        </receiver>

分析过程

查看logcat

当收不到广播时,会有如下打印,大致原因是被拦截了,没有正常分发给应用:

text 复制代码
BroadcastQueue   system_process   D  processNextBroadcastLocked, suppress to start process of staticReceiver for package:com.test

就一行打印,太少了,到sdk中定位BroadcastQueue.java这个类,

找到位置:

复制代码
frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

其打印是由DEBUG_BROADCAST控制的:

在BroadcastQueue.java文件夹下搜索所有.java的文件,查看哪个文件有DEBUG_BROADCAST,定位到文件

复制代码
frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java

把上图中的DEBUG_BROADCAST改成true,就可以打开:

java 复制代码
diff --git a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 858e50b175..5bac0fefaf 100755
--- a/frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -46,7 +46,7 @@ public class ActivityManagerDebugConfig {
     public static boolean DEBUG_ANR = false;
     public static boolean DEBUG_BACKGROUND_CHECK = DEBUG_ALL || false;
     public static boolean DEBUG_BACKUP = DEBUG_ALL || false;
-    public static boolean DEBUG_BROADCAST = DEBUG_ALL || false;
+    public static boolean DEBUG_BROADCAST = true;//DEBUG_ALL || false;
     public static boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false;
     public static boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
     public static boolean DEBUG_BROADCAST_DEFERRAL = DEBUG_BROADCAST || false;

这样重新编译后,就可以查看到更多的logcat打印。

text 复制代码
2026-01-05 15:36:20.915   999-4284  ActivityManager         system_process     V  Broadcast: Intent { act=com.test flg=0x400010 cmp=com.test/.Receiver (has extras) } ordered=true userid=-2
2026-01-05 15:36:20.915   999-4284  ActivityManager         system_process     V  Enqueueing broadcast: com.test replacePending=false
2026-01-05 15:36:20.916   999-4284  ActivityManager         system_process     I  Broadcast intent Intent { act=com.test flg=0x400010 cmp=com.test/.Receiver (has extras) } on background queue
2026-01-05 15:36:20.916   999-4284  ActivityManager         system_process     V  Enqueueing ordered broadcast BroadcastRecord{82678d3 u0 com.test}
2026-01-05 15:36:20.916   999-4284  BroadcastQueue          system_process     V  Schedule broadcasts [background]: current=false
2026-01-05 15:36:20.916   999-1052  BroadcastQueue          system_process     V  Received BROADCAST_INTENT_MSG [background]
2026-01-05 15:36:20.916   999-1052  BroadcastQueue          system_process     V  processNextBroadcast [background]: 0 parallel broadcasts; 1 ordered
2026-01-05 15:36:20.916   999-1052  BroadcastDispatcher     system_process     I  Next broadcast from main queue: BroadcastRecord{82678d3 u0 com.test}
2026-01-05 15:36:20.916   999-1052  BroadcastQueue          system_process     V  Processing ordered broadcast [background] BroadcastRecord{82678d3 u0 com.test}
2026-01-05 15:36:20.916   999-1052  BroadcastQueue          system_process     V  Submitting BROADCAST_TIMEOUT_MSG [background] for BroadcastRecord{82678d3 u0 com.test} at 410497
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     D  processNextBroadcastLocked, suppress to start process of staticReceiver for package:com.test
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     V  Skipping delivery of ordered [background] BroadcastRecord{82678d3 u0 com.test} for reason described above
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     V  Schedule broadcasts [background]: current=false
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     V  Received BROADCAST_INTENT_MSG [background]
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     V  processNextBroadcast [background]: 0 parallel broadcasts; 1 in flight, 0 ordered
2026-01-05 15:36:20.917   999-1052  BroadcastQueue          system_process     I  Finishing broadcast [background] com.test app=null
2026-01-05 15:36:20.918   999-1052  BroadcastQueue          system_process     V  Cancelling BROADCAST_TIMEOUT_MSG
2026-01-05 15:36:20.918   999-1052  BroadcastQueue          system_process     V  Finished with ordered broadcast BroadcastRecord{82678d3 u0 com.test}

日志时间线分析:

text 复制代码
15:36:20.915 - 广播入队(后台队列)
15:36:20.916 - 开始处理有序广播
15:36:20.917 - 抑制启动接收器进程
15:36:20.917 - 广播被跳过并完成

原因排查

疑问:内置app到系统中,烧录后,再run相同的app到设备中,为什么就会导致app在运行广播也收不到。

从app的状态排查

可能原因:

  1. 签名不一致
    基本排除,因为是同一个包名,如果签名不一样,是run不进去的。
  2. 应用处于"stopped state"
    基本排除,因为app是运行的,有MainActivity在前台。
  3. 组件被 disable

排查指令:

bash 复制代码
adb shell dumpsys package com.test | grep -E "enabled|stopped|versionCode|signatures"

重点关注:

  1. enabled=true?(组件是否启用)
  2. stopped=true?(是否被停止)
  3. signatures 是否和系统一致?
    是否有 Error: ... signature mismatch?

输入如下:

text 复制代码
versionCode=1 minSdk=26 targetSdk=32
signatures=PackageSignatures{6091f09 version:2, signatures:[b4addb29], past signatures:[]}
User 0: ceDataInode=2682 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false
versionCode=1 minSdk=26 targetSdk=32
signatures=PackageSignatures{6091f09 version:2, signatures:[b4addb29], past signatures:[]}
User 0: ceDataInode=2682 installed=true hidden=false suspended=false distractionFlags=0 stopped=false notLaunched=false enabled=0 instant=false virtual=false

注意到里面的enabled=0,怀疑是这个状态导致的:

在 Android 系统中,enabled=0 表示该应用的 所有组件(Activity、Service、BroadcastReceiver 等)都被禁用了,即使代码逻辑正确、注册无误,系统也不会启动它或分发广播给它。

enabled=0的原因:

系统策略限制(如 priv-app 权限丢失)

如果原 APK 在 /system/priv-app,拥有 signature|privileged 权限。

调试版安装到 /data/app,失去特权,某些系统服务可能主动 disable 它(较少见,但可能)。

临时启用(用于快速验证是否是 enabled 问题)
bash

adb shell pm enable com.test

复制代码
执行后再次检查:
```bash
adb shell dumpsys package com.test | grep enabled

如果变成 enabled=1,再发送广播测试是否能收到。

测试结果是收不到,所以不是这个导致的。说明问题不在"组件被禁用",而是更深层的原因。

其它方面排查

接收不到的可能原因:

  1. 只用了 动态注册 → 应用没启动就没人监听。
  2. 如果发送的是 隐式广播(没指定包名),Android 8.0+ 会直接丢弃,不唤醒应用。
  3. 即使是静态注册,若未设置 android:exported="true",外部也无法发送广播给它。

第1,与3都排除,因为代码中使用的是动态册且app已经运行起来了,而且也设置了exported。

测试过程中发现:

使用这条显式指定完整 ComponentName指令发广播,收不到:

bash 复制代码
adb shell am broadcast -n com.test/.Receiver -a com.test --es cmd play

使用这条指定包名的方式能收到:

bash 复制代码
adb shell am broadcast -p com.test -a com.test --es cmd play

真相是MTK的快霸(DuraSpeed)搞的鬼

后面在MTK中设置中发现了快霸(DuraSpeed)这个东西,

这个功能是联发科(MTK)为旗下搭载Android系统的设备开发的一套后台进程管理机制,其主要目的是通过限制非关键后台应用的活跃度,来确保前台应用能获得更多系统资源,从而提升手机长期使用后的流畅度。

把这个功能关掉,就正常了。

Android Framework专栏链接
Android专栏

作者:帅得不敢出门

相关推荐
阿巴斯甜7 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker8 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95279 小时前
Andorid Google 登录接入文档
android
黄林晴10 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android