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专栏

作者:帅得不敢出门

相关推荐
2501_915106322 小时前
HBuilderX 项目上架 iOS app上架 App Store 的关键流程
android·ios·小程序·https·uni-app·iphone·webview
2501_915106322 小时前
iOS 文件管理,在不越狱的前提下管理 iPhone / iPad 文件
android·ios·小程序·uni-app·iphone·webview·ipad
编程之路从0到12 小时前
React Native 之Android端Bolts库
android·react native
超级任性2 小时前
Android Studio 各种版本及官方下载地址
android·ide·android studio·android-studio
trojan__2 小时前
Android studio报错:Unsupported Gradle JVM
android·ide·android studio
wuzesong2 小时前
Android的apk在加固后如何在MacOS系统下重新签名
android·安卓
cd ~/Homestead2 小时前
PHP 变量、类型、运算符
android·开发语言·php
weixin_462446232 小时前
Open-AutoGLM项目实战:在Android设备上实现自动操作与ADB键盘控制
android·adb·计算机外设