WindowManager的updateViewLayout用于更新View的布局,updateViewLayout方法定义在WindowManager的父类接口ViewManager中,而实现addView方法的则是WindowManagerImpl中,如下所示:
//frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyTokens(params);
mGlobal.updateViewLayout(view, params);
}
}
WindowManagerGlobal updateViewLayout
调用WindowManagerGlobal的updateViewLayout方法:
//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public final class WindowManagerGlobal {
public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
// 校验 LayoutParams 类型
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
// 将 LayoutParams 添加到根 View 中
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params;
view.setLayoutParams(wparams);
synchronized (mLock) {
// 替换 View 相关的参数(添加 View 时将 View,ViewRootImpl,LayoutParams 添加到三个集合中)
int index = findViewLocked(view, true); // 查询指定 View 在 mViews 集合中的位置。
ViewRootImpl root = mRoots.get(index);
mParams.remove(index);
mParams.add(index, wparams);
// 这里调用 ViewRootImpl.setLayoutParams 进行更新
root.setLayoutParams(wparams, false);
}
}
}
上面方法主要处理如下:
1、调用WindowManagerGlobal的findViewLocked方法,查询指定 View 在 mViews 集合中的位置。
2、调用ViewRootImpl的setLayoutParams方法,设置视图的布局参数。
下面分别进行分析:
WindowManagerGlobal findViewLocked
调用WindowManagerGlobal的findViewLocked方法,查询指定 View 在 mViews 集合中的位置。
//frameworks/base/core/java/android/view/WindowManagerGlobal.java
public final class WindowManagerGlobal {
private int findViewLocked(View view, boolean required) {
final int index = mViews.indexOf(view);
if (required && index < 0) {
throw new IllegalArgumentException("View=" + view + " not attached to window manager");
}
return index;
}
}
ViewRootImpl setLayoutParams
调用ViewRootImpl的setLayoutParams方法,设置视图的布局参数:
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
public final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
public void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
synchronized (this) {
final int oldInsetLeft = mWindowAttributes.surfaceInsets.left;
final int oldInsetTop = mWindowAttributes.surfaceInsets.top;
final int oldInsetRight = mWindowAttributes.surfaceInsets.right;
final int oldInsetBottom = mWindowAttributes.surfaceInsets.bottom;
final int oldSoftInputMode = mWindowAttributes.softInputMode;
final boolean oldHasManualSurfaceInsets = mWindowAttributes.hasManualSurfaceInsets;
if (DEBUG_KEEP_SCREEN_ON && (mClientWindowLayoutFlags
& WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) != 0
&& (attrs.flags&WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) == 0) {
Slog.d(mTag, "setLayoutParams: FLAG_KEEP_SCREEN_ON from true to false!");
}
// Keep track of the actual window flags supplied by the client.
mClientWindowLayoutFlags = attrs.flags;
// Preserve compatible window flag if exists.
final int compatibleWindowFlag = mWindowAttributes.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
// Preserve system UI visibility.
final int systemUiVisibility = mWindowAttributes.systemUiVisibility;
final int subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
// Preserve appearance and behavior.
final int appearance = mWindowAttributes.insetsFlags.appearance;
final int behavior = mWindowAttributes.insetsFlags.behavior;
final int appearanceAndBehaviorPrivateFlags = mWindowAttributes.privateFlags
& (PRIVATE_FLAG_APPEARANCE_CONTROLLED | PRIVATE_FLAG_BEHAVIOR_CONTROLLED);
final int changes = mWindowAttributes.copyFrom(attrs);
if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) {
// Recompute system ui visibility.
mAttachInfo.mRecomputeGlobalAttributes = true;
}
if ((changes & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) {
// Request to update light center.
mAttachInfo.mNeedsUpdateLightCenter = true;
}
if (mWindowAttributes.packageName == null) {
mWindowAttributes.packageName = mBasePackageName;
}
// Restore preserved flags.
mWindowAttributes.systemUiVisibility = systemUiVisibility;
mWindowAttributes.subtreeSystemUiVisibility = subtreeSystemUiVisibility;
mWindowAttributes.insetsFlags.appearance = appearance;
mWindowAttributes.insetsFlags.behavior = behavior;
mWindowAttributes.privateFlags |= compatibleWindowFlag
| appearanceAndBehaviorPrivateFlags
| WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST;
if (mWindowAttributes.preservePreviousSurfaceInsets) {
// Restore old surface insets.
mWindowAttributes.surfaceInsets.set(
oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
} else if (mWindowAttributes.surfaceInsets.left != oldInsetLeft
|| mWindowAttributes.surfaceInsets.top != oldInsetTop
|| mWindowAttributes.surfaceInsets.right != oldInsetRight
|| mWindowAttributes.surfaceInsets.bottom != oldInsetBottom) {
mNeedsRendererSetup = true;
}
applyKeepScreenOnFlag(mWindowAttributes);
if (newView) {
mSoftInputMode = attrs.softInputMode;
requestLayout(); //请求重新布局视图树
}
// Don't lose the mode we last auto-computed.
if ((attrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
& ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST);
}
if (mWindowAttributes.softInputMode != oldSoftInputMode) {
requestFitSystemWindows();
}
mWindowAttributesChanged = true;
scheduleTraversals(); //调度视图的遍历和绘制过程
}
}
}
上面方法主要处理如下:
1、调用ViewRootImpl的requestLayout方法,请求重新布局视图树。
2、调用ViewRootImpl的scheduleTraversals方法,调度视图的遍历和绘制过程。
下面分别进行分析:
ViewRootImpl requestLayout
调用ViewRootImpl的requestLayout方法,请求重新布局:
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread(); //校验所在线程
mLayoutRequested = true;
scheduleTraversals(); //调度视图的遍历和绘制过程
}
}
}
调用ViewRootImpl的scheduleTraversals方法,调度视图的遍历和绘制过程:
/frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
public boolean mTraversalScheduled;
final Choreographer mChoreographer;
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier(); //发送一个同步屏障,以确保后续的同步消息在视图绘制完成之前不会执行
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); //下一帧绘制之前执行mTraversalRunnable
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
}
上面方法主要处理如下:
1、调用Choreographer的postCallback方法,在下一帧绘制之前执行mTraversalRunnable。
2、调用ViewRootImpl的pokeDrawLockIfNeeded方法,请求绘制锁定。
下面分别进行分析:
Choreographer postCallback
调用Choreographer的postCallback方法,用于将一个任务添加到Choreographer的任务队列中,以便在下一帧绘制之前执行。
传入的mTraversalRunnable为TraversalRunnable类,在下一帧绘制前调用TraversalRunnable的run方法,在run方法中调用doTraversal方法:
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
private boolean mProfile = false;
final ViewRootHandler mHandler = new ViewRootHandler();
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
}
ViewRootImpl performTraversals
调用ViewRootImpl的performTraversals方法,执行View的三大流程(measure、layout、draw):
Android13 ViewRootImpl performTraversals流程分析-CSDN博客
ViewRootImpl pokeDrawLockIfNeeded
调用ViewRootImpl的pokeDrawLockIfNeeded方法:
//frameworks/base/core/java/android/view/ViewRootImpl.java
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
final IWindowSession mWindowSession;
void pokeDrawLockIfNeeded() {
if (!Display.isDozeState(mAttachInfo.mDisplayState)) {
// Only need to acquire wake lock for DOZE state.
return;
}
if (mWindowAttributes.type != WindowManager.LayoutParams.TYPE_BASE_APPLICATION) {
// Non-activity windows should be responsible to hold wake lock by themself, because
// usually they are system windows.
return;
}
if (mAdded && mTraversalScheduled && mAttachInfo.mHasWindowFocus) {
try {
mWindowSession.pokeDrawLock(mWindow);
} catch (RemoteException ex) {
// System server died, oh well.
}
}
}
}
调用mWindowSession(IWindowSession)的pokeDrawLock方法,IWindowSession是一个接口,由Session实现:
//frameworks/base/services/core/java/com/android/server/wm/Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
final WindowManagerService mService;
public void pokeDrawLock(IBinder window) {
final long identity = Binder.clearCallingIdentity();
try {
mService.pokeDrawLock(this, window);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
调用WindowManagerService的pokeDrawLock方法,请求绘制锁定:
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
public void pokeDrawLock(Session session, IBinder token) {
synchronized (mGlobalLock) {
WindowState window = windowForClientLocked(session, token, false);
if (window != null) {
window.pokeDrawLockLw(mDrawLockTimeoutMillis);
}
}
}
}
ViewRootImpl scheduleTraversals
调用ViewRootImpl的scheduleTraversals方法,调度视图的遍历和绘制过程,与上面流程一致。