Android 关于设备定屏/黑屏/冻屏/ANR那些事
定屏/黑屏常见问题
我的理解是冻屏和定屏是一个意思.
冻屏:目的就是防止执行默写操作的过程出现黑屏,冻屏的过程只是不接收输入和不执行动画,并且会截取屏幕进行显示.
A:系统问题(底层/framework层)
A_1:system_server_watchdog :现象多为卡顿/黑屏
A_2:WMS(WindowManagerService)异常
A_3:surfacefling卡死,表现为定屏(冻屏)
B:app类
B_1: app ANR , 现象多为定屏/黑屏
B_2: app mainThread 阻塞, 没有触发ANR , 现象多为定屏/黑屏
C:SystemUI
C_1:systemUI ANR, 现象为定屏,按power键卡顿
[黑屏定屏那些事 - 系统机制,分析套路和实战(系统篇)](https://blog.csdn.net/feelabclihu/article/details/123911477)
//Android T
stopFreezingScreen(..)解除冻屏
startFreezingScreen(..)执行冻屏
./frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
/** Freeze the screen during a user-switch event. Called by UserController. */
//WMS暴露了一个可以通过binder调用执行的冻屏操作.
@Override
public void startFreezingScreen(int exitAnim, int enterAnim) {
if (!checkCallingPermission(android.Manifest.permission.FREEZE_SCREEN,
"startFreezingScreen()")) {
throw new SecurityException("Requires FREEZE_SCREEN permission");
}
synchronized (mGlobalLock) {
if (!mClientFreezingScreen) {
mClientFreezingScreen = true;//mClientFreezingScreen变量代表通过客户端进行冻结屏幕
final long origId = Binder.clearCallingIdentity();
try {
startFreezingDisplay(exitAnim, enterAnim);
//CLIENT_FREEZE_TIMEOUT超时的消息,用于结束冻结屏幕,因为客户端不可控,如果冻屏超时,系统会直接解除冻屏
mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT);
mH.sendEmptyMessageDelayed(H.CLIENT_FREEZE_TIMEOUT, 5000);
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
}
private void doStartFreezingDisplay(int exitAnim, int enterAnim, DisplayContent displayContent,
int overrideOriginalRotation) {
...
//获取一个WEAK LOCK防止睡眠
mScreenFrozenLock.acquire();
//应用启动电源模式以减少屏幕冻结时间
mAtmService.startLaunchPowerMode(POWER_MODE_REASON_CHANGE_DISPLAY);
...
//冻结input输入
mInputManagerCallback.freezeInputDispatchingLw();
...
}
Android R :横竖屏切换时更新方向,执行冻屏,截图显示以及计算更新基于新的方向的DisplayInfo和Configuration.
Activity::setRequestedOrientation
->ActivityTaskManagerService::setRequestedOrientation
->ActivityRecord::setRequestedOrientation
->WindowContainer::setOrientation
->WindowContainer::onDescendantOrientationChanged
->DisplayContent::onDescendantOrientationChanged
->DisplayContent::updateOrientation
->DisplayRotation::updateOrientation->DisplayRotation::updateRotationUnchecked
->DisplayRotation::prepareNormalRotationAnimation
->WindowManagerService::startFreezingDisplay
->ScreenRotationAnimation::ScreenRotationAnimation
->ScreenRotationAnimation::setRotation->RotationAnimationUtils::createRotationMatrix
->DisplayContent::updateDisplayAndOrientation
WMS->stopFreezingScreen()冻屏总结
WindowManagerService一个解决界面闪屏的例子
Android系统冻屏、黑屏问题的分析思路
黑屏定屏那些事 - 系统机制,分析套路和实战(系统篇)
定屏/应用卡死问题日志抓取
设备遇到应用卡死并且已经崩溃或者无响应弹框时,查看目录/data/anr/是否有日志生成.
如果目录下没有生成anr日志,界面假死:
adb shell
su
ps -A | grep com.android.launcher3 查看当前app进程id
debuggerd -b 进程id > /sdcard/log_anr.log 打印出包含该进程的所有线程的调用栈信息
Android 开机动画结束后,不显示FallBackHome,(冻屏)几秒后显示Launcher3
冻屏不是黑屏,屏幕看起来像是灰的.
问题:fallbackhome Activity因configChange(uiMode、density、locale变化)频繁启动导致冻屏
解决方案:在AndroidManifest.xml中为fallbackhome配置忽略这些configChanges,以避免影响生命周期
Surface(SurfaceSyncer)同步问题分析
bug:某应用打开后,在点击home键出现黑屏
现象分析:桌面的状态时黑屏的,但是SystemUI的statusBar是显示和功能都是正常的,那一般就是当前app的问题了.
抓日志分析,发现报错: E SurfaceSyncer: Failed to find sync for id=0
黑屏原因:ViewRootImpl.java和SurfaceView 通过SurfaceSyncer产生联系,实现同步更新.
假设同步出现问题,其它流程是正常提交给wms处理,那么Surface没有同步更新会导致图形无法渲染绘制出来,那就黑屏.
Surface同步机制为android13新增,代码位置./frameworks/base/core/java/android/window/SurfaceSyncer.java
,
简介:./frameworks/base/core/java/android/window/SurfaceSyncer.md
.
主要作用为提供ViewRootImpl与SurfaceView(假如窗口存在SurfaceView的情况下)同步服务,实现在主Surface与SurfaceView均完成绘制时,
再去上报至WMS进行窗口状态的切换,避免主Surface绘制完成上报至WMS后、同时SurfaceView迟迟没有绘制完成使得startingWindow过早移除从而产生黑屏的现象.
Android14上保留了Surface同步机制,但是相关代码位置发生变化,不再有SurfaceSyncer.java,
而是移动至SurfaceSyncGroup.java。相关核心方法为createSyncIfNeeded、checkIfSyncIsComplete等。
[093]SurfaceSyncer的致命缺陷
参考:探索Surface同步机制
小二哥
关于Android卡顿掉帧问题
Anroid study ANR / NE(Native exception)
step 1:get events log
adb logcat -b events > e:/log.log
I am_anr : [0,770,com.android.systemui,818462221,executing service com.android.systemui/.wallpapers.ImageWallpaper]
分析:
UserId=0,PID=770,包名=com.android.systemui,flags=...,anr原因:executing service com.android.systemui/.wallpapers.ImageWallpaper
step 2:查看trace文件
上面log打印了ANR的基本信息,具体ANR怎么生成的需要看trace文件,分析代码堆栈调用情况
//main(线程名)、prio(线程优先级,默认是5)、tid(线程唯一标识ID)、Sleeping/Runnable(线程当前状态)
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 ucsCount=0 flags=0 obj=0x722aca68 self=0xb40000764a921be0
| sysTid=943 nice=0 cgrp=default sched=0/0 handle=0x77917e74f8
| state=R schedstat=( 1265523861 1725170986 10361 ) utm=51 stm=75 core=3 HZ=100
| stack=0x7ff7673000-0x7ff7675000 stackSize=8188KB
| held mutexes= "mutator lock"(shared held)
//java 堆栈调用信息(这里可查看导致ANR的代码调用流程)(分析ANR最重要的信息)
at com.android.systemui.util.sensors.ThresholdSensorImpl_Builder_Factory.get(ThresholdSensorImpl_Builder_Factory.java:24)
at com.android.systemui.util.sensors.SensorModule_ProvidePrimaryProximitySensorFactory.get(SensorModule_ProvidePrimaryProximitySensorFactory.java:10)
at com.android.systemui.util.sensors.ProximitySensorImpl_Factory.get(ProximitySensorImpl_Factory.java:123)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0e98eb91> (a dagger.internal.DoubleCheck) // 锁住对象0x0e98eb91
at com.android.systemui.privacy.PrivacyConfig_Factory.get(PrivacyConfig_Factory.java:135)
at com.android.systemui.classifier.FalsingCollectorImpl_Factory.get(FalsingCollectorImpl_Factory.java:38)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0208aaf6> (a dagger.internal.DoubleCheck)
at com.android.systemui.keyguard.dagger.KeyguardModule_NewKeyguardViewMediatorFactory.get(KeyguardModule_NewKeyguardViewMediatorFactory.java:23)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x020beef7> (a dagger.internal.DoubleCheck)
at dagger.internal.DelegateFactory.get(DelegateFactory.java:4)
at com.android.systemui.unfold.UnfoldSharedModule_UnfoldKeyguardVisibilityProviderFactory.get(UnfoldSharedModule_UnfoldKeyguardVisibilityProviderFactory.java:49)
at com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager_Factory.get(StatusBarKeyguardViewManager_Factory.java:12)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0bee3164> (a dagger.internal.DoubleCheck)
at dagger.internal.DelegateFactory.get(DelegateFactory.java:4)
at com.android.systemui.keyguard.KeyguardUnlockAnimationController_Factory.get(KeyguardUnlockAnimationController_Factory.java:32)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0ecfafcd> (a dagger.internal.DoubleCheck)
at dagger.internal.DelegateFactory.get(DelegateFactory.java:4)
at com.android.systemui.statusbar.phone.ScrimController_Factory.get(ScrimController_Factory.java:103)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0b8c8082> (a dagger.internal.DoubleCheck)
at com.android.systemui.statusbar.phone.DozeServiceHost_Factory.get(DozeServiceHost_Factory.java:67)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x00868393> (a dagger.internal.DoubleCheck)
at com.android.systemui.keyguard.data.repository.KeyguardRepositoryImpl_Factory.get(KeyguardRepositoryImpl_Factory.java:17)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0c0effd0> (a dagger.internal.DoubleCheck)
at com.android.systemui.keyguard.domain.interactor.KeyguardInteractor_Factory.get(KeyguardInteractor_Factory.java:2)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0f347bc9> (a dagger.internal.DoubleCheck)
at com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor_Factory.get(KeyguardQuickAffordanceInteractor_Factory.java:2)
at dagger.internal.DoubleCheck.get(DoubleCheck.java:13)
- locked <0x0d8622ce> (a dagger.internal.DoubleCheck)
at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$ReferenceSysUIComponentImpl.injectCustomizationProvider(DaggerReferenceGlobalRootComponent.java:2)
at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$ReferenceSysUIComponentImpl.inject(DaggerReferenceGlobalRootComponent.java:4)
at java.lang.reflect.Method.invoke(Native method)
at com.android.systemui.SystemUIAppComponentFactoryBase$instantiateProviderCompat$1.onContextAvailable(SystemUIAppComponentFactoryBase.kt:42)
at com.android.systemui.keyguard.CustomizationProvider.attachInfo(CustomizationProvider.kt:7)
at android.app.ActivityThread.installProvider(ActivityThread.java:7514)
at android.app.ActivityThread.installContentProviders(ActivityThread.java:7025)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6796)
at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2133)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7924)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
补丁:
Traces中显示的线程状态都是C代码定义的,通过查看线程状态对应的信息分析ANR问题
TimedWaiting对应的线程状态是TIMED_WAITING;
kTimedWaiting, // TIMED_WAITING TS_WAIT in Object.wait() with a timeout 执行了无超时参数的wait函数
kSleeping, // TIMED_WAITING TS_SLEEPING in Thread.sleep() 执行了带有超时参数的sleep函数
ZOMBIE 线程死亡,终止运行
RUNNING/RUNNABLE 线程可运行或正在运行
TIMED_WAIT 执行了带有超时参数的wait、sleep或join函数
MONITOR 线程阻塞,等待获取对象锁
WAIT 执行了无超时参数的wait函数
INITIALIZING 新建,正在初始化,为其分配资源
STARTING 新建,正在启动
NATIVE 正在执行JNI本地函数
VMWAIT 正在等待VM资源
SUSPENDED 线程暂停,通常是由于GC或debug被暂停
Android中ANR的分析和解决
Android内存异常机制(用户空间)_NE
trace详解
Android ANR分析-笔记
Android ANR基本Log分析
Android ANR traces.txt文件分析
Android ANR 2
ANR 分析合集