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  打印出包含该进程的所有线程的调用栈信息

定屏死机问题抓取 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卡顿掉帧问题

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值