天天看点

Window的更新过程分析

前面的两篇文章,window的创建过程分析和window的删除过程分析分别分析了window的添加和删除过程,这篇文章

将继续分析window的更新过程。基于前面两篇文章的分析,我们知道,window的删除过程也是通过WindowManager

发起的,实际的执行是有WindowManagerImpl类的updateViewLayout方法,在通过WindowManagerGlobal的updateViewLayout方法,下面看看WindowManagerGlobal类的updateViewLayout方法的具体实现:

/frameworks/base/core/java/android/view/WindowManagerGlobal.java

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/WindowManagerGlobal.java

public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
        if (view == null) {
            throw new IllegalArgumentException("view must not be null");
        }
        if (!(params instanceof WindowManager.LayoutParams)) {
            throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
        }

        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;

        view.setLayoutParams(wparams);

        synchronized (mLock) {
            int index = findViewLocked(view, true);
            ViewRootImpl root = mRoots.get(index);
	        //移除之前的保存的wparams
            mParams.remove(index);
	        // 添加新的 wparams
            mParams.add(index, wparams);
	        // 关键代码
            root.setLayoutParams(wparams, false);
        }
}
           

可以看到这个方法内部调用了ViewRootImpl类的setLayoutParams方法,下面看看这个方法的具体实现:

/frameworks/base/core/java/android/view/ViewRootImpl.java

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/view/ViewRootImpl.java

void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
    synchronized (this) {
        // ... 省略部分代码
        scheduleTraversals();
    }
}


//  scheduleTraversals方法的具体实现
void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
	    //关键代码
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
           // ... 省略部分代码
        }
}

scheduleTraversals方法内部的Choreographer.postCallback方法,会回调到mTraversalRunnable
这个Runnable内部的run方法,我们看看

final class TraversalRunnable implements Runnable {
    @Override
    public void run() {
        doTraversal();
    }
}


// doTraversal方法的具体实现
void doTraversal() {
        if (mTraversalScheduled) {
            // ... 省略部分代码
	    // 关键代码
            performTraversals();

	    // ... 省略部分代码
        }
}


// performTraversals方法的具体实现
private void performTraversals() {
	// ... 省略部分代码

	try {
               // ... 省略部分代码
               
		// 关键点 relayoutWindow方法内部通过WindowManagerService完成Window的更新
                relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
  
            } catch (RemoteException e) {
            }

        if (mFirst || windowShouldResize || insetsChanged ||
                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
           
	        // ... 省略部分代码
           
            if (!mStopped || mReportNextDraw) {
               // ...省略部分代码
                if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth()
                        || mHeight != host.getMeasuredHeight() || contentInsetsChanged ||
                        updatedConfiguration) {
					// ...省略部分代码

                    // 关键点 
                    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

                    // ...省略部分代码

                    if (measureAgain) {
			           // 关键点 
                        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
                    }
                  // ...省略部分代码
                }
            }
        }

       // ...省略部分代码
        if (didLayout) {
	       // 关键代码
            performLayout(lp, mWidth, mHeight);
	    
	    // ... 省略部分代码
        }

       // ...省略部分代码
       
        if (!cancelDraw && !newSurface) {
           // ...省略部分代码
	    // 关键代码
            performDraw();
        }
        // ...省略部分代码
}


//从这个方法抛出的RemoteException可以猜测,这个方法内部进行了IPC通信,
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
            boolean insetsPending) throws RemoteException {

        // ... 省略部分代码
        
        int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
                (int) (mView.getMeasuredWidth() * appScale + 0.5f),
                (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
                insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
                mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingDisplayCutout,
                mPendingMergedConfiguration, mSurface);

        // ... 省略部分代码

        
        return relayoutResult;
}

           

这个方法中,mwindowSession是SystemServer进程中的Session对象在app进程的一个代理对象,通过mWindowSession

向SystemServer发起请求,会调用SystemServer进程的Session的relayout方法,下面看看Session类的relayout方法

的具体实现:

/frameworks/base/services/core/java/com/android/server/wm/Session.java

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/wm/Session.java

    @Override
    public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
            Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
            Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
            DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
            Surface outSurface) {
        // ... 省略部分代码
        int res = mService.relayoutWindow(this, window, seq, attrs,
                requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
                outStableInsets, outsets, outBackdropFrame, cutout,
                mergedConfiguration, outSurface);
	// ... 省略部分代码
        return res;
    }
           

这个方法内部,最终是调用了WindowManagerService的relayoutWindow对Window进行更新。