平台

RK3399 + Android 8.1
调试应用: com.android.documentsui

问题

  • 切换后显示异常, 如下图所示, 窗口明显被拉伸了:
  • 正确的显示效果:

调试

dumpsys window

  • 显示异常
  Window #5 Window{82f86c3 u0 com.android.documentsui/com.android.documentsui.files.FilesActivity}:    mDisplayId=0 stackId=2 mSession=Session{8e3c127 1593:u0a10012} [email protected]    mOwnerUid=10012 mShowToOwnerOnly=true package=com.android.documentsui appop=NONE    mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#10 ty=1 fl=#81810100 pfl=0x20000 fmt=-3 wanim=0x10302f6 vsysui=0x600 surfaceInsets=Rect(40, 40 - 40, 40) (manual) (!preservePreviousSurfaceInsets) needsMenuKey=2 colorMode=0}    Requested w=960 h=512 mLayoutSeq=577    mHasSurface=true mShownPosition=[484,90] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false    WindowStateAnimator{a17f258 com.android.documentsui/com.android.documentsui.files.FilesActivity}:      mAnimating=true mLocalAnimating=false mAnimationIsEntrance=false mAnimation=null mStackClip=1      XForm: has=true hasLocal=false {alpha=1.0 matrix=[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}      Surface: shown=true layer=21010 alpha=1.0 rect=(444.0,50.0) 1040.0 x 592.0 transform=(0.99166936, 0.0, 1.5310801, 0.0)      mGlobalScale=1.0 mDsDx=0.99166936 mDtDx=0.0 mDtDy=0.0 mDsDy=1.5310801    isOnScreen=true    isVisible=true
  • 正常显示
  Window #5 Window{82f86c3 u0 com.android.documentsui/com.android.documentsui.files.FilesActivity}:    mDisplayId=0 stackId=2 mSession=Session{8e3c127 1593:u0a10012} [email protected]    mOwnerUid=10012 mShowToOwnerOnly=true package=com.android.documentsui appop=NONE    mAttrs=WM.LayoutParams{(0,0)(fillxfill) sim=#10 ty=1 fl=#81810100 pfl=0x20000 fmt=-3 wanim=0x10302f6 vsysui=0x600 surfaceInsets=Rect(40, 40 - 40, 40) (manual) (!preservePreviousSurfaceInsets) needsMenuKey=2 colorMode=0}    Requested w=960 h=512 mLayoutSeq=595    mHasSurface=true mShownPosition=[480,256] isReadyForDisplay()=true hasSavedSurface()=false mWindowRemovalAllowed=false    WindowStateAnimator{a17f258 com.android.documentsui/com.android.documentsui.files.FilesActivity}:      Surface: shown=true layer=21010 alpha=1.0 rect=(440.0,216.0) 1040.0 x 592.0 transform=(1.0, 0.0, 1.0, 0.0)    isOnScreen=true    isVisible=true

从近期任务切换为FreeForm模式:

com.android.server.am.ActivityManagerService.startActivityFromRecents(ActivityManagerService.java:4935)com.android.server.am.ActivityStackSupervisor.startActivityFromRecentsInner(ActivityStackSupervisor.java:4882)com.android.server.wm.WindowManagerService.continueSurfaceLayout(WindowManagerService.java:2979)com.android.server.wm.WindowSurfacePlacer.continueLayout(WindowSurfacePlacer.java:126)com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:135)com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:145)com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:197)com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:608)com.android.server.wm.RootWindowContainer.applySurfaceChangesTransaction(RootWindowContainer.java:865)com.android.server.wm.DisplayContent.applySurfaceChangesTransaction(DisplayContent.java:2784)com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:633)com.android.server.wm.DisplayContent.forAllWindows(DisplayContent.java:1533)com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:616)com.android.server.wm.WindowContainer.forAllWindows(WindowContainer.java:616)com.android.server.wm.WindowState.forAllWindows(WindowState.java:4034)com.android.server.wm.WindowState.applyInOrderWithImeWindows(WindowState.java:4127)com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:777)com.android.server.wm.WindowContainer$ForAllWindowsConsumerWrapper.apply(WindowContainer.java:779)
  • AppWindowAnimator.java
com.android.server.wm.RootWindowContainer.performSurfacePlacement(RootWindowContainer.java:623)com.android.server.wm.WindowSurfacePlacer.handleAppTransitionReadyLocked(WindowSurfacePlacer.java:344)com.android.server.wm.WindowSurfacePlacer.handleOpeningApps(WindowSurfacePlacer.java:404)com.android.server.wm.AppWindowToken.setVisibility(AppWindowToken.java:372)com.android.server.wm.WindowManagerService.applyAnimationLocked(WindowManagerService.java:2435)com.android.server.wm.AppWindowAnimator.setAnimation(AppWindowAnimator.java:127)

在APP切换动画启动后,

DisplayContent WindowSta applySurfaceChangesTransaction computeShownFrameLocked DisplayContent WindowSta
  • WindowStateAnimator中计算并重新设置上面dump出来的相关变量: mShownPositiontransform

  • 问题的根源在于 startProlongAnimation 调用了, 但 endProlongedAnimation 却迟迟未调用, 导致动画被无限推后, mShownPosition 和 transform 也一直无变化:

  • AppWindowAnimator

    /**     * Sometimes we need to synchronize the first frame of animation with some external event, e.g.     * Recents hiding some of its content. To achieve this, we prolong the start of the animaiton     * and keep producing the first frame of the animation.     */    private long getAnimationFrameTime(Animation animation, long currentTime) {        if (mProlongAnimation == PROLONG_ANIMATION_AT_START) {            animation.setStartTime(currentTime);            return currentTime + 1;        }        return currentTime;    }    private boolean stepAnimation(long currentTime) {        if (animation == null) {            return false;        }        transformation.clear();        final long animationFrameTime = getAnimationFrameTime(animation, currentTime);...}void startProlongAnimation(int prolongType) {        if(!ffNoCaption)mProlongAnimation = prolongType;        mClearProlongedAnimation = false;    }    void endProlongedAnimation() {        mProlongAnimation = PROLONG_ANIMATION_DISABLED;    }
RecentsActivity WindowMana AppWindowAnimator endProlongedAnimations endProlongedAnimations endProlongedAnimation RecentsActivity WindowMana AppWindowAnimator
  • WindowManagerService.java
    @Override    public void endProlongedAnimations() {        synchronized (mWindowMap) {            for (final WindowState win : mWindowMap.values()) {                final AppWindowToken appToken = win.mAppToken;                if (appToken != null && appToken.mAppAnimator != null) {                    appToken.mAppAnimator.endProlongedAnimation();                }            }            mAppTransition.notifyProlongedAnimationsEnded();        }    }

加上调试LOG后输出:

//开始切换:05-30 05:13:25.287 D/AppWindowAnimator      497): startProlongAnimation 8026179405-30 05:13:25.298 D/RecentsActivity(       670): addOnPreDrawListener 205-30 05:13:25.301 D/RecentsActivity(       670): onPreDraw//从mWindowMap 中删除 com.android.documentsui05-30 05:13:25.309 D/WindowManagerService(  497): postWindowRemoveCleanupLocked remove com.android.documentsui/com.android.documentsui.files.FilesActivity05-30 05:13:25.336 D/RecentsActivity(       670): Recents.getSystemServices().endProlongedAnimations();//开始遍历并调用 AppWindowAnimator.endProlongedAnimation05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=com.android.systemui/com.android.systemui.recents.RecentsActivity05-30 05:13:25.337 D/AppWindowAnimator(     497): endProlongedAnimation 4322140005-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=NavigationBar05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=NavigationBar mAppAnimator is NULL05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=AssistPreviewPanel05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=AssistPreviewPanel mAppAnimator is NULL05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=DockedStackDivider05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=DockedStackDivider mAppAnimator is NULL05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=com.android.launcher3/com.android.launcher3.Launcher05-30 05:13:25.337 D/AppWindowAnimator(     497): endProlongedAnimation 7329598905-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=StatusBar05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=StatusBar mAppAnimator is NULL05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=com.android.systemui.ImageWallpaper05-30 05:13:25.337 D/WindowManagerService(  497): endProlongedAnimations win.mAppToken.stringName=com.android.systemui.ImageWallpaper mAppAnimator is NULL//重新将 com.android.documentsui 加入 mWindowMap 中05-30 05:13:25.404 D/WindowManagerService(  497): addWindow com.android.documentsui/com.android.documentsui.files.FilesActivity

从调试的LOG看, 对应com.android.documentsui的Window在循环调用 AppWindowAnimator.endProlongedAnimation时, 完美地错过了…

解决:

  • frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    public int addWindow(Session session, IWindow client, int seq,            WindowManager.LayoutParams attrs, int viewVisibility, int displayId,            Rect outContentInsets, Rect outStableInsets, Rect outOutsets,            InputChannel outInputChannel) {        int[] appOp = new int[1];        int res = mPolicy.checkAddPermission(attrs, appOp);//...省略代码...            } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {                atoken = token.asAppWindowToken();//增加代码if(atoken != null && atoken.mAppAnimator != null){atoken.mAppAnimator.endProlongedAnimation();}//....省略代码....

更多相关文章

  1. HTML颜色代码表
  2. android中一种欢迎界面模式
  3. 说说在 Android(安卓)中如何发送自定义广播
  4. android NoSuchMethodError getDrawable
  5. android在处理一写图片资源的时候,会进行一些类型的转换,现在有空
  6. Android(安卓)DynamicLoadApk 开源插件开发项目代码剖析
  7. Android(安卓)EditText软键盘弹出时防止布局上移和关闭软键盘
  8. Android——动态广播、静态广播
  9. 背景图片显示问题 图片显示错误 android开发

随机推荐

  1. 如何在Activity调用surfaceView实现透明
  2. Android核心模块内容概述
  3. 教你如何开关Android的APN网络
  4. Android线程之消息机制(Handler、Message
  5. 你不知道一些神奇Android(安卓)Api-比如文
  6. Android线程间通信的Message机制
  7. Unity与Android权限设置
  8. Android(安卓)服务的五大级别
  9. Android(安卓)最强RecyclerView分割线XRe
  10. Android(安卓)Recovery模式