Android Framework-WMS-Window移除

昨天和基友装逼,结果人说你这半拉子,只写addWindow(),removeWindow() 你是一点不写啊。 抓紧补充一下。 主要我之前也没看过这部分,面试没人问啊。

大体流程

java 复制代码
ViewRootImpl.doDie(){
 dispatchDetachedFromWindow();
}

-->mWindowSession.remove(mWindow);
-->Session.remove()
-->WindowManagerService.removeWindow(this, window);
-->WindowState.removeIfPossible();

这里主要看一下WindowState.removeIfPossible()

java 复制代码
    private void removeIfPossible(boolean keepVisibleDeadWindow) {
        mWindowRemovalAllowed = true;
       

      //是启动窗口 去取消动画
        final boolean startingWindow = mAttrs.type == TYPE_APPLICATION_STARTING;
        if (startingWindow) 
            if (mActivityRecord != null) {
                mActivityRecord.forAllWindows(w -> {
                    if (w.isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) {
                        w.cancelAnimation();
                        return true;
                    }
                    return false;
                }, true);
            }
        } else if (mAttrs.type == TYPE_BASE_APPLICATION
                && isSelfAnimating(0, ANIMATION_TYPE_STARTING_REVEAL)) {
            //是应用类型 取消动画
            cancelAnimation();
        }



        final DisplayContent displayContent = getDisplayContent();
        final long origId = Binder.clearCallingIdentity();

        try {
          //取消事件
            disposeInputChannel();
            mOnBackInvokedCallbackInfo = null;

            boolean wasVisible = false;
            if (mHasSurface && mToken.okToAnimate()) {
                if (mWillReplaceWindow) {
                    mAnimatingExit = true;
                    mReplacingRemoveRequested = true;
                    return;
                }


                wasVisible = isWinVisibleLw();

              
              //标记死亡
                if (keepVisibleDeadWindow) {


                    mAppDied = true;
                    setDisplayLayoutNeeded();
                    mWmService.mWindowPlacerLocked.performSurfacePlacement();
                    openInputChannel(null);
                    displayContent.getInputMonitor().updateInputWindowsLw(true);
                    return;
                }

  
                final boolean allowExitAnimation = !displayContent.inTransition()

                        && !inRelaunchingActivity();

                if (wasVisible) {
                    final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;

                    if (allowExitAnimation && mWinAnimator.applyAnimationLocked(transit, false)) {
                       
                        mAnimatingExit = true;
                        setDisplayLayoutNeeded();
                        mWmService.requestTraversal();
                    }
                    if (mWmService.mAccessibilityController.hasCallbacks()) {
                        mWmService.mAccessibilityController.onWindowTransition(this, transit);
                    }
                }
                final boolean isAnimating = allowExitAnimation
                        && (mAnimatingExit || isExitAnimationRunningSelfOrParent());
                final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
                        && mActivityRecord.isLastWindow(this);

              //看是否有动画或者正在执行退出动画 完成后进行移除
                if (mWinAnimator.getShown() && !lastWindowIsStartingWindow && isAnimating) {

                    mAnimatingExit = true;
               
                    //
                    setupWindowForRemoveOnExit();
                    if (mActivityRecord != null) {
                        mActivityRecord.updateReportedVisibilityLocked();
                    }
                    return;
                }
            }


            final boolean windowProvidesNonDecorInsets = providesNonDecorInsets();

          //直接移除
            removeImmediately();
            boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation();
            if (windowProvidesNonDecorInsets) {
                needToSendNewConfiguration |=
                        displayContent.getDisplayPolicy().updateDecorInsetsInfo();
            }

            if (needToSendNewConfiguration) {
                displayContent.sendNewConfiguration();
            }
          //更新焦点。
            mWmService.updateFocusedWindowLocked(isFocused()
                            ? UPDATE_FOCUS_REMOVING_FOCUS
                            : UPDATE_FOCUS_NORMAL,
                    true /*updateInputWindows*/);
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

这里分2种情况,有动画的需要等待动画执行完成,没动画的直接调用了removeImmediately()

直接删除

removeImmediately()

java 复制代码
//WindowState
 void removeImmediately() {
   //销毁surface
mWinAnimator.destroySurfaceLocked(getSyncTransaction());
   //调用到父类 进入
super.removeImmediately();
   //省略..
   //断开输入
   disposeInputChannel();
   //告知Session 该窗口已经删除
    mSession.windowRemovedLocked();
   //wms进行各种清除,主要是各种缓存,简单理解观察者模式删除观察者
     mWmService.postWindowRemoveCleanupLocked(this);
 }

该方法主要是进行各种销毁,内部调用到了WindowStateAnimator.destroySurfaceLocked()super.removeImmediately() 进入了 WindowContainer.removeImmediately()

先看下 WindowStateAnimator.destroySurfaceLocked()

java 复制代码
void destroySurfaceLocked(SurfaceControl.Transaction t) {
    if (mSurfaceController == null) {
        return;
    }

    mWin.mHidden = true;

    try {
        
        destroySurface(t);
     
        mWallpaperControllerLocked.hideWallpapers(mWin);
    } catch (RuntimeException e) {
       
    }

 
    mWin.setHasSurface(false);
    if (mSurfaceController != null) {
        mSurfaceController.setShown(false);
    }
    mSurfaceController = null;
    mDrawState = NO_SURFACE;
}

WindowStateAnimator.destroySurfaceLocked() 主要是销毁 surface ,然后将状态设置到 NO_SURFACE 状态, mSurfaceController 也设置了 null , 标识当前 WindowState 不存在 surface ,有点类似Message obtain() ,把属性都清空了。

再看下WindowContainer.removeImmediately()

java 复制代码
void removeImmediately() {
    final DisplayContent dc = getDisplayContent();
    if (dc != null) {
        dc.mClosingChangingContainers.remove(this);
        mSurfaceFreezer.unfreeze(getSyncTransaction());
    }
    while (!mChildren.isEmpty()) {
        final E child = mChildren.peekLast();
        child.removeImmediately();
        if (mChildren.remove(child)) {
            onChildRemoved(child);
        }
    }

    if (mSurfaceControl != null) {
        getSyncTransaction().remove(mSurfaceControl);
        setSurfaceControl(null);
        mLastSurfacePosition.set(0, 0);
        mLastDeltaRotation = Surface.ROTATION_0;
        scheduleAnimation();
    }
    if (mOverlayHost != null) {
        mOverlayHost.release();
        mOverlayHost = null;
    }


    if (mParent != null) {
        mParent.removeChild(this);
    }
    for (int i = mListeners.size() - 1; i >= 0; --i) {
        mListeners.get(i).onRemoved();
    }
}

移除当前窗口,删除子窗口,从父亲那删除自己,清理surface ,调用mListeners 通知自己已经被移除。

有动画的时候

# Android Framework-WMS-动画-初步认识中,动画完成后会调用onAnimationFinished

java 复制代码
WindowContainer(WindowManagerService wms) {
    mWmService = wms;
    mTransitionController = mWmService.mAtmService.getTransitionController();
    mPendingTransaction = wms.mTransactionFactory.get();
    mSyncTransaction = wms.mTransactionFactory.get();
    mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
    mSurfaceFreezer = new SurfaceFreezer(this, wms);
}


   */
    protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
        doAnimationFinished(type, anim);
        mWmService.onAnimationFinished();
        mNeedsZBoost = false;
    }

这里会进入子类 WindowState

java 复制代码
@Override
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
    super.onAnimationFinished(type, anim);
    mWinAnimator.onAnimationFinished();
}

调用 WindowStateAnimator.onAnimationFinished(),继续调用到 WindowState.onExitAnimationDone()

java 复制代码
//WindowState
void onExitAnimationDone() {

   //省略///

  //注意该值设置为trye
    mDestroying = true;

    final boolean hasSurface = mWinAnimator.hasSurface();



     //hide
    mWinAnimator.hide(getPendingTransaction(), "onExitAnimationDone");

   
    if (mActivityRecord != null) {
      //如果是app 进入ActivityRecord的destroySurfaces
        if (mAttrs.type == TYPE_BASE_APPLICATION) {
            mActivityRecord.destroySurfaces();
        } else {
            destroySurface(false /* cleanupOnResume */, mActivityRecord.mAppStopped);
        }
    } else {
        if (hasSurface) {
          //
            mWmService.mDestroySurface.add(this);
        }
    }
    mAnimatingExit = false;
 
    getDisplayContent().mWallpaperController.hideWallpapers(this);
}

destroySurface() 有两个判断 分别在onExitAnimationDone()和setupWindowForRemoveOnExit()里面被设置为了true。

java 复制代码
boolean destroySurface(boolean cleanupOnResume, boolean appStopped) {
    boolean destroyedSomething = false;

  //在调用 onExitAnimationDone的时候 设置为true
    if (mDestroying) {
        //省略
      // 在 setupWindowForRemoveOnExit()里面设置为true
        if (mRemoveOnExit) {
            removeImmediately();
        }
        
        mDestroying = false;
        destroyedSomething = true;
//省略
    }

    return destroyedSomething;
}

发现进入removeImmediately()走到了无动画删除的流程。

总结一下

window的删除 从ViewRootImp通过Session,进入到WMSremoveWindow

调用removeIfPossible()

如果没有动画,则直接调用removeImmediately()。 会调用WindowStateAnimator.destroySurfaceLocked() 进行surface的清理,清理WindowState。 调用父类WindowContainer.removeImmediately() 清理surface ,从父亲删除自己,通知自己被移除。

如果有动画,会等待动画完成后,调用到 removeImmediately()。进行对应的清理和回收。

不要死记代码,主要我记不住。

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui