Long monitor contention with owner

当应用出现'Lost 30 frames!'警告时,可能表明主线程工作量过大。通过分析日志和滑动滚轮查看CPU占用高的函数,重点关注Cpu Time、Real Time及调用次数。例如,startService的Real Time显著高于Cpu Time,揭示了同步机制导致的阻塞。通过搜索'too much'关键字进一步定位问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

安卓Activity在finish后出现黑屏, 大概率是因为主线程卡死。 抓trace和logcat。
04-16 16:18:17.359 W/m.lianjia.beik(30714): Long monitor contention with owner Binder:30714_6 (32307) at void java.lang.Object.wait(long, int)(Object.java:-2) waiters=0 in android.content.ComponentName com.ke.ljplugin.component.service.server.PluginServiceServer$Stub.startService(android.content.Intent, android.os.Messenger) for 5.996s
04-16 16:18:17.360 W/m.lianjia.beik(30714): Current owner stack:
04-16 16:18:17.360 W/m.lianjia.beik(30714):   (no managed stack frames)
04-16 16:18:17.360 W/m.lianjia.beik(30714): Contender stack:
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.ke.ljplugin.component.service.server.PluginServiceServer$Stub.startService(PluginServiceServer.java:554)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.ke.ljplugin.component.service.PluginServiceClient.startService(PluginServiceClient.java:106)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.ke.loader2.PluginContext.startService(PluginContext.java:516)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.service.IMService.startIMService(link:100)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.IMManager.initIMService(link:316)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.IMManager.syncData(link:263)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.IMManager.access$200(link:51)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.IMManager$2.call(link:250)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.lianjia.sdk.im.IMManager$2.call(link:240)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at rx.internal.util.ActionSubscriber.onNext(ActionSubscriber.java:39)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:134)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:224)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at rx.android.schedulers.LooperScheduler$ScheduledAction.run(LooperScheduler.java:107)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at android.os.Handler.handleCallback(Handler.java:873)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at android.os.Looper.loop(Looper.java:201)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at android.app.ActivityThread.main(ActivityThread.java:6806)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at java.lang.reflect.Method.invoke(Native method)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
04-16 16:18:17.360 W/m.lianjia.beik(30714):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:873)
04-16 16:18:17.360 W/m.lianjia.beik(30714): 
04-16 16:18:17.388 I/Choreographer(30714): Skipped 361 frames!  The application may be doing too much work on its main thread.

二、原因分析

日志示例:“
04-15 14:11:33.634 I/Choreographer(23776): Skipped 365 frames! The application may be doing too much work on its main thread.

触发条件: SKIPPED_FRAME_WARNING_LIMIT值为30, 即丢了30帧时打印这行日志, 对应0.5秒。

void doFrame(long frameTimeNanos, int frame) {
     。。。
            if (skippedFrames >= SKIPPED_FRAME_WARNING_LIMIT) {
                Log.i(TAG, "Skipped " + skippedFrames + " frames!  "
                        + "The application may be doing too much work on its main thread.");
            }

滑动滚轮在main里找宽度大的条目(每种颜色代码一个函数), 宽度越大说明占用CPU越长。 点击图像里的条目可以索引到下面的函数。
PS:滑动鼠标中间的滚轮可以放大或缩小柱状图。
关注核心指标:
Cpu Time/Call, 函数执行时长
Real Time/Call, 占用CPU时间,包括切换、阻塞时间。 Calls+Recur/Call, 调用次数(含递归)总次数

例如图片里startService的Cpu Time等于12.964ms, 但Real Time等于6013.609ms, 差距非常大。 原因在于startService使用了同步机制,即阻塞等待。 Logcat的第一句java.lang.Object.wait…, 当主线程卡死但没到ANR程度时, logcat里提示丢帧“too much work on its main thread"。

打印日志后可以搜索“too much”关键字。

解释下 03-28 16:47:43.023318 1873 3385 I AS.AudioService: getMode, get current owner's mode 03-28 16:47:43.023541 1873 3318 W system_server: Long monitor contention with owner AudioService (3321) at void com.android.server.audio.AudioService$AudioHandler.handleMessage(android.os.Message)(AudioService.java:11440) waiters=2 in void com.android.server.audio.AudioDeviceBroker$BrokerHandler.handleMessage(android.os.Message) for 258ms 03-28 16:47:43.023822 1873 3318 V AS.AudioDeviceBroker: onSetCommunicationDeviceForClient: CommunicationDeviceInfo mCb=android.os.BinderProxy@8ad4d2f mUid=10309 mDevice=[null] mOn=false mScoAudioMode=-1 mIsPrivileged=false mEventSource=clearCommunicationDevice() from u/pid:10309/20020 03-28 16:47:43.023863 1873 3318 V AS.AudioDeviceBroker: setCommunicationRouteForClient: device: null, eventSource: clearCommunicationDevice() from u/pid:10309/20020 03-28 16:47:43.023893 1873 3318 I AS.AudioDeviceBroker: setCommunicationRouteForClient for uid: 10309 device: null isPrivileged: false from API: clearCommunicationDevice() from u/pid:10309/20020 03-28 16:47:43.024084 1873 3318 V AS.AudioDeviceBroker: requestedCommunicationDevice: AudioDeviceAttributes: role:output type:bt_sco_hs addr:XX:XX:XX:XX:33:AD name:Redmi Buds 5 Pro profiles:[{ENCODING_PCM_16BIT, sampling rates=[8000, 16000], channel masks=0x04, encapsulation type=0}, {ENCODING_PCM_16BIT, sampling rates=[8000, 16000], channel masks=0x04, encapsulation type=0}] descriptors:[] mAudioModeOwner: AudioModeInfo: mMode=MODE_NORMAL, mPid=0, mUid=0 03-28 16:47:43.024202 1873 3318 V AS.AudioDeviceBroker: requestedCommunicationDevice: AudioDeviceAttributes: role:output type:bt_sco_hs addr:XX:XX:XX:XX:33:AD name:Redmi Buds 5 Pro profiles:[{ENCODING_PCM_16BIT, sampling rates=[8000, 16000], channel masks=0x04, encapsulation type=0}, {ENCODING_PCM_16BIT, sampling rates=[8000, 16000], channel masks=0x04, encapsulation type=0}] descriptors:[] mAudioModeOwner: AudioModeInfo: mMode=MODE_NORMAL, mPid=0, mUid=0 03-28 16:47:43.024277 1873 3318 V AS.AudioDeviceBroker: requestedCommunicationDevice: null mAudioModeOwner: AudioModeInfo: mMode=MODE_NORMAL, mPid=0, mUid=0 03-28 16:47:43.024314 1873 3318 D AudioServiceStubImpl: modeOwnerPidFromAudioService:20020, mModeOwnerPid: 0
最新发布
04-03
<think>好的,我现在需要帮助用户分析他们提供的Android系统日志。用户之前询问过蓝牙HFP中的CIEV指令,现在他们给出了一组系统日志,并希望得到解释。首先,我需要仔细阅读这些日志,理解每一行的含义,然后将其整合成一个结构清晰的回答。 首先,日志中的时间戳是03-28 16:47:43.023318到后面的几行,涉及进程1873和3385、3318等。用户可能是在调试蓝牙音频设备时遇到问题,比如连接或通信问题。用户可能想知道这些日志的含义,特别是与音频服务、设备通信相关的部分。 接下来,我需要逐条分析日志: 1. **AS.AudioService: getMode, get current owner's mode** 这表明音频服务正在获取当前的音频模式所有者,可能是检查哪个应用或服务当前控制音频模式,比如通话模式或媒体模式。 2. **system_server警告:Long monitor contention...** 这里提到与AudioService的监视器竞争,导致等待了258ms。这可能意味着系统服务在处理音频设备时遇到了延迟,可能是由于资源争用或代码中的锁问题。 3. **AS.AudioDeviceBroker相关日志** 这几条日志涉及设置通信设备,特别是蓝牙SCO设备(如Redmi Buds 5 Pro)。其中,设备被设置为null,可能是因为正在清除之前的通信设备,或者切换设备时出现问题。提到了uid=10309,pid=20020,这可能是一个应用或服务尝试修改通信设备。 4. **requestedCommunicationDevice显示设备信息** 这里详细描述了请求的蓝牙设备信息,包括编码格式、采样率等。但后续的日志显示请求的设备变为null,可能表示设备被断开或切换失败。 5. **AudioServiceStubImpl: modeOwnerPidFromAudioService:20020, mModeOwnerPid:0** 这里显示模式所有者的PID从20020变为0,可能表示该进程释放了音频模式的控制权,或者发生了异常。 用户可能的疑问是这些日志是否正常,或者是否反映了他们遇到的问题,比如蓝牙耳机连接问题,音频切换失败,或者系统延迟。需要解释这些日志中的关键点,指出可能的竞争状况、设备切换过程以及权限问题。同时,用户可能需要知道这些日志背后的系统行为,以及如何进一步调试或解决问题。 我需要将这些分析组织成清晰的步骤,解释每条日志的含义,并综合起来说明整体情况。此外,用户可能希望了解这些日志是否指示了错误,比如监视器竞争是否严重,设备设置为null是否正常,或者权限问题(mIsPrivileged=false)可能的影响。 最后,根据分析,可能需要建议用户检查应用权限,确认蓝牙设备连接状态,或者查看是否有异常进程占用音频资源。同时,如果存在性能问题,可能需要优化代码以避免长时间锁竞争。</think>以下是对日志的逐条解析及整体分析: --- ### **1. 日志概览** 日志来自Android系统服务(`system_server`进程),涉及音频服务(`AudioService`和`AudioDeviceBroker`),主要记录了**音频设备切换**和**资源竞争**事件,可能与蓝牙耳机(Redmi Buds 5 Pro)的通信状态变更相关。 --- ### **2. 关键日志解析** #### **(1) 音频模式查询** ```log 03-28 16:47:43.023318 1873 3385 I AS.AudioService: getMode, get current owner's mode ``` - **含义**:系统正在查询当前音频模式的所有者(例如通话模式、音乐模式)。 - **背景**:当应用(如电话、音乐播放器)请求音频焦点时,需确定当前哪个应用占用音频模式。 --- #### **(2) 系统资源竞争警告** ```log 03-28 16:47:43.023541 1873 3318 W system_server: Long monitor contention with owner AudioService (3321)... waiters=2 for 258ms ``` - **含义**:`AudioDeviceBroker`线程(3318)与`AudioService`线程(3321)发生**锁竞争**,导致`system_server`线程阻塞258ms。 - **原因**:多线程同时访问音频设备资源(如蓝牙设备状态变更),引发同步问题。 - **风险**:长时间阻塞可能影响音频响应速度或导致ANR(应用无响应)。 --- #### **(3) 蓝牙通信设备状态变更** ```log 03-28 16:47:43.023822 ... V AS.AudioDeviceBroker: onSetCommunicationDeviceForClient: ... mDevice=[null] mOn=false ... mEventSource=clearCommunicationDevice() ``` - **关键字段**: - `mDevice=[null]`:当前通信设备被清除(蓝牙耳机断开或切换)。 - `mUid=10309`:发起操作的应用程序用户ID。 - `mIsPrivileged=false`:应用未获得特权权限(可能无权直接操作音频设备)。 --- #### **(4) 蓝牙设备详细信息** ```log 03-28 16:47:43.024084 ... V AS.AudioDeviceBroker: requestedCommunicationDevice: AudioDeviceAttributes: type:bt_sco_hs ... Redmi Buds 5 Pro ``` - **设备类型**:`bt_sco_hs`表示蓝牙SCO(Synchronous Connection-Oriented)耳机,用于通话音频。 - **编码参数**:支持16位PCM编码、8kHz/16kHz采样率(典型通话质量)。 --- #### **(5) 通信设备切换结果** ```log 03-28 16:47:43.024277 ... V AS.AudioDeviceBroker: requestedCommunicationDevice: null ... 03-28 16:47:43.024314 ... D AudioServiceStubImpl: modeOwnerPidFromAudioService:20020, mModeOwnerPid:0 ``` - **最终状态**:请求的通信设备被设为`null`(未成功绑定),且音频模式所有者PID从`20020`变为`0`(释放控制权)。 --- ### **3. 综合事件还原** 1. **触发操作**:UID为10309的应用(PID=20020)尝试**清除当前通信设备**(可能是断开蓝牙耳机)。 2. **权限问题**:因`mIsPrivileged=false`,该应用可能无权限直接操作设备,导致操作失败。 3. **资源竞争**:在设备切换过程中,`AudioService`与`AudioDeviceBroker`发生锁竞争,引发系统警告。 4. **结果**:蓝牙耳机(Redmi Buds 5 Pro)未被正确绑定,音频模式控制权被释放。 --- ### **4. 潜在问题与建议** #### **问题诊断** - **权限不足**:应用需声明`MODIFY_AUDIO_SETTINGS`权限或系统签名才能操作通信设备。 - **性能瓶颈**:锁竞争导致阻塞258ms,需优化音频服务线程同步逻辑。 - **设备切换异常**:蓝牙SCO连接可能被意外中断,需检查耳机状态或HFP协议兼容性。 #### **调试建议** 1. 检查应用权限,确认是否声明了`android.permission.MODIFY_AUDIO_SETTINGS`。 2. 捕获蓝牙HFP协议日志,分析耳机连接/断开的详细流程。 3. 监控`AudioService`锁竞争频率,优化高频调用场景。 如需进一步分析,可提供完整日志或具体问题现象。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值