MTK Android 14 锁屏通知栏与相机预览界面重叠

这篇具有很好参考价值的文章主要介绍了MTK Android 14 锁屏通知栏与相机预览界面重叠。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Bug触发前提和操作:

  • 设置为滑动解锁

  • 支持双击power按键跳转相机功能

  • 反复亮灭屏,并通过双击power按键唤醒相机就有几率触发此问题

Bug具体表现如下图:

keyguard壁纸图层消失,显示出了底下的camera预览界面,且当前keyguard时序错乱,解锁流程异常

ransit_to_back,数码相机,android

分析流程:

因为是静态壁纸,所以最早的考虑可能和Systemui的LockscreenWallpaper.java 和NotificationMediaManager.java这两部分壁纸处理部可能有些问题,但通过调试验证后发现LockscreenWallpaper 默认的情况使用的是系统wallpaper图层,具体看下面loadBitmap方法注释;根据上述分析,尝试锁屏壁纸为null直接去取launcher的壁纸后测试,这个时候可以发现壁纸确实不会异常消失了,但是问题依然存在,解锁流程异常,上划解锁的时候会卡顿,有时候还要解锁两遍才行,所以这个问题并没有解决,还要继续分析,

//system/vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
  
public LoaderResult loadBitmap(int currentUserId, UserHandle selectedUser) {

        final int lockWallpaperUserId =
                selectedUser != null ? selectedUser.getIdentifier() : currentUserId;
        ParcelFileDescriptor fd = mWallpaperManager.getWallpaperFile(
                WallpaperManager.FLAG_LOCK, lockWallpaperUserId);

        //未单独设置锁屏壁纸时,锁屏壁纸为null,这里默认取的是桌面壁纸,这样NotificationMediaManager那边一直可以通过getBitmap正常取到壁纸
        if(fd == null){
            fd = mWallpaperManager.getWallpaperFile(WallpaperManager.FLAG_SYSTEM,lockWallpaperUserId);
        }

        if (fd != null) {
 
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.HARDWARE;
                return LoaderResult.success(BitmapFactory.decodeFileDescriptor(
                        fd.getFileDescriptor(), null, options));

        } else {
            if (selectedUser != null) {
                // Show the selected user's static wallpaper.
                return LoaderResult.success(mWallpaperManager.getBitmapAsUser(
                        selectedUser.getIdentifier(), true /* hardware */));

            } else {
                //默认会走到这里,使用系统默认wallpaper图层,此时getBitmap一直为null
                // When there is no selected user, show the system wallpaper
                return LoaderResult.success(null);
            }
        }
    }

初步来看不是systemui 壁纸部分的逻辑问题,可以看看是否为壁纸图层问题,重新复现此问题后通过dump SurfaceFlinger读取图层,对比正常逻辑来看,异常的时候壁纸图层消失了,然后从抓取的log分析,systemui时序也有些问题,对比正常和异常的时序log如下,keyguardGoingAway 之后没有正常去执行handleStartKeyguardExitAnimation的退出动画流程,目前来看就是没有正常退出keyguard动画导致后续时序错乱,

正常流程: 

  36636: 01-14 17:57:04.877845  1450  1450 D KeyguardViewMediator: handleKeyguardDone
  36637: 01-14 17:57:04.877935  1450  1450 D KeyguardViewMediator: handleHide
  36638: 01-14 17:57:04.877965  1450  1450 D KeyguardViewMediator: keyguardGoingAway
  37048: 01-14 17:57:04.998568  1450  1450 D KeyguardViewMediator: handleStartKeyguardExitAnimation, the startTime=0 fadeoutDuration=0
  37053: 01-14 17:57:04.999293  1450  1450 D KeyguardViewMediator: set mKeyguardDoneOnGoing = false
  39240: 01-14 17:57:05.306755  1450  1450 D KeyguardViewMediator: onKeyguardExitRemoteAnimationFinished
  39398: 01-14 17:57:05.315843  1450  1450 D KeyguardViewMediator: onKeyguardExitFinished()
  39405: 01-14 17:57:05.316766  1450  1450 D KeyguardViewMediator: adjustStatusBarLocked: mShowing=false mOccluded=false isSecure=false force=false mPowerGestureIntercepted=false --> flags=0x0
  39407: 01-14 17:57:05.317367  1450  1450 D KeyguardViewMediator: onKeyguardExitRemoteAnimationFinished#hideKeyguardViewAfterRemoteAnimation
  39523: 01-14 17:57:05.348362  1450  1450 D KeyguardViewMediator: keyguardGone
  40071: 01-14 17:57:05.393523  1450  1804 D KeyguardViewMediator: updateActivityLockScreenState(false, false)
  42114: 01-14 17:57:05.705789  1450  7484 D KeyguardViewMediator: setOccluded(false)
  42115: 01-14 17:57:05.705812  1450  7484 D KeyguardViewMediator: setOccluded false

异常流程:

  49189: 01-14 17:57:07.474846  1450  1450 D KeyguardViewMediator: handleKeyguardDone
  49190: 01-14 17:57:07.474904  1450  1450 D KeyguardViewMediator: handleHide
  49191: 01-14 17:57:07.474943  1450  1450 D KeyguardViewMediator: keyguardGoingAway
  53185: 01-14 17:57:08.217943  1450  6811 D KeyguardViewMediator: setOccluded(false)
  53186: 01-14 17:57:08.217971  1450  6811 D KeyguardViewMediator: setOccluded false
  53187: 01-14 17:57:08.218512  1450  1450 D KeyguardViewMediator: handleSetOccluded(false)
  53188: 01-14 17:57:08.218645  1450  1450 D KeyguardViewMediator: isOccluded=false,mPowerGestureIntercepted=false
  57112: 01-14 17:57:09.654649  1450  1450 D KeyguardViewMediator: received DELAYED_KEYGUARD_ACTION with seq = 14, mDelayedShowingSequence = 16

继续加了一些log调试,通过对比正常和异常时候日志,可以发现正常过渡动画的流程,最终是会执行TRANSIT_TO_BACK的过渡动画的,异常的时候这个操作被丢失掉了,会卡在 TRANSIT_WAKE的动画,一直到TRANSIT_WAKE被abort;而TRANSIT_TO_BACK这个过渡动画就是KeyguardController的requestTransitionIfNeeded调用产生的,并且会让壁纸可见(和异常时候表现一致,大致确定是这个动画没有正常执行的问题了)

// system/frameworks/base/services/core/java/com/android/server/wm/KeyguardController.java
void keyguardGoingAway(int displayId, int flags) {
        ...
        final int transitFlags = convertTransitFlags(flags);
        final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
        dc.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, transitFlags);
        // We are deprecating TRANSIT_KEYGUARD_GOING_AWAY for Shell transition and use
        // TRANSIT_FLAG_KEYGUARD_GOING_AWAY to indicate that it should animate keyguard going
        // away.
        dc.mAtmService.getTransitionController().requestTransitionIfNeeded(
                TRANSIT_TO_BACK, transitFlags, null /* trigger */, dc);
        updateKeyguardSleepToken();
        // Make the home wallpaper visible
        dc.mWallpaperController.showWallpaperInTransition(true /* showHome */);
        // Some stack visibility might change (e.g. docked stack)
        mRootWindowContainer.resumeFocusedTasksTopActivities();
        mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
        mRootWindowContainer.addStartingWindowsForVisibleActivities();
        mWindowManager.executeAppTransition();
    } finally {
        mService.continueWindowLayout();
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
}

继续调试,可以知道是isCollecting为true导致无法被正常创建导致;最开始尝试过滤TRANSIT_TO_BACK来调试,但后续的createTransition的有做mTransitionPlayer和mCollectingTransition 的是否为null做判断,修改对逻辑影响太大,遂放弃;继续看Transition的操作逻辑和调试的log, mCollectingTransition的collectting有超时机制,而Transition最终会去执行TransitionController.onAbort中断当前的Transition,

// system/frameworks/base/services/core/java/com/android/server/wm/TransitionController.java
Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
      ... ) {
    if (mTransitionPlayer == null) {
        return null;
    }
    Transition newTransition = null;
    if (isCollecting()) {
        ...
    } else {
        newTransition = requestStartTransition(createTransition(type, flags),
                trigger != null ? trigger.asTask() : null, remoteTransition, displayChange);
        if (newTransition != null && displayChange != null && trigger != null
                && trigger.asDisplayContent() != null) {
            setDisplaySyncMethod(displayChange, newTransition, trigger.asDisplayContent());
        }
    }
    ...
    return newTransition;
}


/**
* @return {@code true} if transition is actively collecting changes. This is {@code false}
* once a transition is playing
*/
boolean isCollecting() {
    return mCollectingTransition != null;
}

/** Called when a transition is aborted. This should only be called by {@link Transition} */
void onAbort(Transition transition) {
    if (transition != mCollectingTransition) {
        int waitingIdx = mWaitingTransitions.indexOf(transition);
        if (waitingIdx < 0) {
            throw new IllegalStateException("Too late for abort.");
        }
        mWaitingTransitions.remove(waitingIdx);
    } else {
        mCollectingTransition = null;
        if (!mWaitingTransitions.isEmpty()) {
            mCollectingTransition = mWaitingTransitions.remove(0);
        }
        if (mCollectingTransition == null) {
            // nothing collecting anymore, so clear order records.
            mLatestOnTopTasksReported.clear();
        }
    }
    // This is called during Transition.abort whose codepath will eventually check the queue
    // via sync-engine idle.
}

有了上述两点分析,而且TRANSIT_TO_BACK 是正常解锁后最终Transition动画,所以可以尝试针对TRANSIT_TO_BACK创建失败时候做保存操作,在上个Transition被Abort了之后重新去走TRANSIT_TO_BACK的创建流程,具体修改如下代码,然后再次测试验证ok,算是暂时修复了此问题

// system/frameworks/base/services/core/java/com/android/server/wm/TransitionController.java   
+  private int waitType;
+  private int waitFlag;
+  private WindowContainer waitTrigger;
+  private WindowContainer waitReadyGroupRef

    @Nullable
    Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
            @WindowManager.TransitionFlags int flags, @Nullable WindowContainer trigger,
            @NonNull WindowContainer readyGroupRef) {
-        return requestTransitionIfNeeded(type, flags, trigger, readyGroupRef,
+        // BEGIN <When the TRANSIT_TO_BACK animation fails to be added, it will be re-executed after the collection is completed.>
+        Transition  mTransition = requestTransitionIfNeeded(type, flags, trigger, readyGroupRef,
                null /* remoteTransition */, null /* displayChange */);
+        if (mTransition == null && type == TRANSIT_TO_BACK) {
+            waitType = type;
+            waitFlag = flags;
+            waitTrigger = trigger;
+            waitReadyGroupRef = readyGroupRef;
+            Log.e(TAG,"Add TRANSIT_TO_BACK transition until collecting finish");
+        }
+        return mTransition;
+        // END <When the TRANSIT_TO_BACK animation fails to be added, it will be re-executed after the collection is completed.> 
    }
                                          
    /** Called when a transition is aborted. This should only be called by {@link Transition} */
    void onAbort(Transition transition) {
        if (transition != mCollectingTransition) {
            int waitingIdx = mWaitingTransitions.indexOf(transition);
            if (waitingIdx < 0) {
                throw new IllegalStateException("Too late for abort.");
            }
            mWaitingTransitions.remove(waitingIdx);
        } else {
            mCollectingTransition = null;
            if (!mWaitingTransitions.isEmpty()) {
                mCollectingTransition = mWaitingTransitions.remove(0);
            }
            if (mCollectingTransition == null) {
                // nothing collecting anymore, so clear order records.
                mLatestOnTopTasksReported.clear();
            }
+            // BEGIN <When the TRANSIT_TO_BACK animation fails to be added, it will be re-executed after the collection is completed.> 
+            if (waitType == TRANSIT_TO_BACK && mCollectingTransition == null) {
+                Log.e(TAG,"come to here continue play animation");
+                waitType = -1;
+                requestTransitionIfNeeded(waitType,waitFlag,waitTrigger,waitReadyGroupRef);
+            }
+            // END <When the TRANSIT_TO_BACK animation fails to be added, it will be re-executed after the collection is completed.> 
        }
        // This is called during Transition.abort whose codepath will eventually check the queue
        // via sync-engine idle.
    }

总结:

最后总结一下,这个Keyguard壁纸图层消失的问题,主要还是亮灭屏太快,framework的动画流程出现问题,前面一个Transition还没有collecting执行完毕,就执行到了TRANSIT_TO_BACK的过渡,导致过渡动画被废弃无法正常执行,目前的方案是把前面废弃的动画TRANSIT_TO_BACK重新执行,暂时解决了这个问题,另外附上调试捋出来的keyguard退出动画完整的创建过渡动画和调用的流程

ransit_to_back,数码相机,android

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
ransit_to_back,数码相机,android
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)
ransit_to_back,数码相机,android

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题
ransit_to_back,数码相机,android文章来源地址https://www.toymoban.com/news/detail-836572.html

到了这里,关于MTK Android 14 锁屏通知栏与相机预览界面重叠的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 12.0下拉状态栏通知栏的通知设置默认展开

    在12.0的产品定制化中,对于SystemUI的定制也是常用的功能,而在下拉状态栏中的通知栏部分也是极其重要的部分,每条通知实时更新在通知栏部分,由于通知栏高度的限制,每条通知是默认收缩的,功能开发需要要求通知默认展开,所以就要从通知的加载流程分析 如图:    

    2024年02月07日
    浏览(71)
  • Android——8种通知栏-超简单自定义

    GT库在很早的版本里就有出 通知栏封装方法,但使用起来非常有局限性,接下来咋们来看看新版GT库里的 8种通知栏 ,是如何实现的。 通知栏效果图:(博主真机 一加10T pro  Android版本12)         目录 通知栏效果图:(博主真机 一加10T pro  Adnroid版本12) 使用GT库里的,当然需

    2024年02月14日
    浏览(41)
  • Android——8种通知栏-适配 Adnroid12

    GT库在很早的版本里就有出 通知栏封装方法,但使用起来非常有局限性,接下来咋们来看看新版GT库里的 8种通知栏 ,是如何实现的。 通知栏效果图:(博主真机 一加10T pro  Android版本12)         目录 通知栏效果图:(博主真机 一加10T pro  Adnroid版本12) 使用GT库里的,当然需

    2023年04月08日
    浏览(44)
  • Android 10.0 系统systemui下拉通知栏的通知布局相关源码分析

     在android10.0的系统rom开发中,在进行systemui中的下拉通知栏的布局自定义的时候,对于原生systemui的 系统的下拉通知栏的通知布局的了解也是非常重要的,接下来就来分析下相关的下拉通知栏的通知布局的相关 源码流程,了解这些才方便对通知栏的布局做修改   在10.0的系统

    2023年04月21日
    浏览(48)
  • Android 10.0 原生SystemUI下拉通知栏每条通知默认展开

    在10.0的系统rom原生开发中,在在对SystemUI下拉通知栏做定制的时候,在下拉状态栏的时候,通知栏中最后一条通知默认是收缩的 点击按钮 就会展开 原生系统systemui就是如此,为了更美观 所以要求最后一条通知也默认展开,显得更美观 最终效果图:   在systemui中,关于下拉通

    2023年04月08日
    浏览(48)
  • Android 12.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(一)

     在12.0的系统rom定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的背景是白色四角的背景,由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景,然后通过systemui的通知流程,设置默认下拉状态栏UI中的通知

    2024年02月05日
    浏览(67)
  • Android 9.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(一)

     在9.0的系统rom产品定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的通知背景默认是白色四角的背景, 由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景, 然后通知显示流程,设置默认下拉状态栏UI中

    2024年02月01日
    浏览(47)
  • Android 9.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(二)

     在9.0的系统rom定制化开发中,在原生系统SystemUI下拉状态栏的通知栏的背景是默认白色四角的背景,由于在产品设计中,需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景,然后通过熟悉systemui的通知栏流程,设置默认下拉状态栏

    2024年02月05日
    浏览(51)
  • Android 12.0 原生SystemUI下拉通知栏UI背景设置为圆角背景的定制(二)

     在12.0的系统rom定制化开发中,在原生系统SystemUI下拉状态栏的下拉通知栏的背景默认是白色四角的背景, 由于在产品设计中,在对下拉通知栏通知的背景需要把四角背景默认改成圆角背景,所以就需要分析系统原生下拉通知栏的每条通知的默认背景, 然后通过systemui的通知

    2024年02月08日
    浏览(50)
  • Android 12.0 系统systemui状态栏下拉左滑显示通知栏右滑显示控制中心模块的流程分析

      在android12.0的系统rom定制化开发中,在系统原生systemui进行自定义下拉状态栏布局的定制的时候,需要在systemui下拉状态栏下滑的时候,根据下滑坐标来 判断当前是滑出通知栏还是滑出控制中心模块,所以就需要根据屏幕宽度,来区分x坐标值为多少是左滑出通知栏或者右滑

    2024年02月09日
    浏览(94)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包