WindowManagerService的relayoutWindow用于计算窗口的大小以及内容区域边衬大小和可见区域边衬大小,代码如下:
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
public int relayoutWindow(Session session, IWindow client, LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewVisibility, int flags, int seq,
int lastSyncSeqId, ClientWindowFrames outFrames,
MergedConfiguration outMergedConfiguration, SurfaceControl outSurfaceControl,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,
Bundle outSyncIdBundle) {
if (outActiveControls != null) {
Arrays.fill(outActiveControls, null);
}
int result = 0;
boolean configChanged = false;
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
final WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
return 0;
}
if (win.mRelayoutSeq < seq) {
win.mRelayoutSeq = seq;
} else if (win.mRelayoutSeq > seq) {
return 0;
}
if (win.cancelAndRedraw() && win.mPrepareSyncSeqId <= lastSyncSeqId) {
// The client has reported the sync draw, but we haven't finished it yet.
// Don't let the client perform a non-sync draw at this time.
result |= RELAYOUT_RES_CANCEL_AND_REDRAW;
}
final DisplayContent displayContent = win.getDisplayContent();
final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy();
WindowStateAnimator winAnimator = win.mWinAnimator;
if (viewVisibility != View.GONE) {
win.setRequestedSize(requestedWidth, requestedHeight);
}
int attrChanges = 0;
int flagChanges = 0;
int privateFlagChanges = 0;
if (attrs != null) {
displayPolicy.adjustWindowParamsLw(win, attrs);
attrs.flags = sanitizeFlagSlippery(attrs.flags, win.getName(), uid, pid);
attrs.inputFeatures = sanitizeSpyWindow(attrs.inputFeatures, win.getName(), uid,
pid);
int disableFlags =
(attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK;
if (disableFlags != 0 && !hasStatusBarPermission(pid, uid)) {
disableFlags = 0;
}
win.mDisableFlags = disableFlags;
if (win.mAttrs.type != attrs.type) {
throw new IllegalArgumentException(
"Window type can not be changed after the window is added.");
}
if (!(win.mAttrs.providedInsets == null && attrs.providedInsets == null)) {
if (win.mAttrs.providedInsets == null || attrs.providedInsets == null
|| (win.mAttrs.providedInsets.length != attrs.providedInsets.length)) {
throw new IllegalArgumentException(
"Insets types can not be changed after the window is added.");
} else {
final int insetsTypes = attrs.providedInsets.length;
for (int i = 0; i < insetsTypes; i++) {
if (win.mAttrs.providedInsets[i].type != attrs.providedInsets[i].type) {
throw new IllegalArgumentException(
"Insets types can not be changed after the window is "
+ "added.");
}
}
}
}
flagChanges = win.mAttrs.flags ^ attrs.flags;
privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
attrChanges = win.mAttrs.copyFrom(attrs);
final boolean layoutChanged =
(attrChanges & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0;
if (layoutChanged || (attrChanges
& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
win.mLayoutNeeded = true;
}
if (layoutChanged && win.providesNonDecorInsets()) {
configChanged = displayPolicy.updateDecorInsetsInfo();
}
if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
|| (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
win.mActivityRecord.checkKeyguardFlagsChanged();
}
if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
&& (mAccessibilityController.hasCallbacks())) {
// No move or resize, but the controller checks for title changes as well
mAccessibilityController.onSomeWindowResizedOrMovedWithCallingUid(
uid, win.getDisplayContent().getDisplayId());
}
if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
updateNonSystemOverlayWindowsVisibilityIfNeeded(
win, win.mWinAnimator.getShown());
}
if ((attrChanges & (WindowManager.LayoutParams.PRIVATE_FLAGS_CHANGED)) != 0) {
winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
}
if (win.mActivityRecord != null
&& !displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged(
win.mActivityRecord.info, flagChanges, privateFlagChanges)) {
mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY,
win.mActivityRecord.getTask()));
Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed,"
+ " can't remain on display " + displayContent.getDisplayId());
return 0;
}
}
if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
winAnimator.mAlpha = attrs.alpha;
}
win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
if (win.mAttrs.surfaceInsets.left != 0
|| win.mAttrs.surfaceInsets.top != 0
|| win.mAttrs.surfaceInsets.right != 0
|| win.mAttrs.surfaceInsets.bottom != 0) {
winAnimator.setOpaqueLocked(false);
}
final int oldVisibility = win.mViewVisibility;
// If the window is becoming visible, visibleOrAdding may change which may in turn
// change the IME target.
final boolean becameVisible =
(oldVisibility == View.INVISIBLE || oldVisibility == View.GONE)
&& viewVisibility == View.VISIBLE;
boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0
|| becameVisible;
boolean focusMayChange = win.mViewVisibility != viewVisibility
|| ((flagChanges & FLAG_NOT_FOCUSABLE) != 0)
|| (!win.mRelayoutCalled);
boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
&& win.hasWallpaper();
wallpaperMayMove |= (flagChanges & FLAG_SHOW_WALLPAPER) != 0;
if ((flagChanges & FLAG_SECURE) != 0 && winAnimator.mSurfaceController != null) {
winAnimator.mSurfaceController.setSecure(win.isSecureLocked());
}
win.mRelayoutCalled = true;
win.mInRelayout = true;
win.setViewVisibility(viewVisibility);
ProtoLog.i(WM_DEBUG_SCREEN_ON,
"Relayout %s: oldVis=%d newVis=%d. %s", win, oldVisibility,
viewVisibility, new RuntimeException().fillInStackTrace());
win.setDisplayLayoutNeeded();
win.mGivenInsetsPending = (flags & WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
// We should only relayout if the view is visible, it is a starting window, or the
// associated appToken is not hidden.
final boolean shouldRelayout = viewVisibility == View.VISIBLE &&
(win.mActivityRecord == null || win.mAttrs.type == TYPE_APPLICATION_STARTING
|| win.mActivityRecord.isClientVisible());
// If we are not currently running the exit animation, we need to see about starting
// one.
// We don't want to animate visibility of windows which are pending replacement.
// In the case of activity relaunch child windows could request visibility changes as
// they are detached from the main application window during the tear down process.
// If we satisfied these visibility changes though, we would cause a visual glitch
// hiding the window before it's replacement was available. So we just do nothing on
// our side.
// This must be called before the call to performSurfacePlacement.
if (!shouldRelayout && winAnimator.hasSurface() && !win.mAnimatingExit) {
if (DEBUG_VISIBILITY) {
Slog.i(TAG_WM,
"Relayout invis " + win + ": mAnimatingExit=" + win.mAnimatingExit);
}
result |= RELAYOUT_RES_SURFACE_CHANGED;
if (!win.mWillReplaceWindow) {
// When FLAG_SHOW_WALLPAPER flag is removed from a window, we usually set a flag
// in DC#pendingLayoutChanges and update the wallpaper target later.
// However it's possible that FLAG_SHOW_WALLPAPER flag is removed from a window
// when the window is about to exit, so we update the wallpaper target
// immediately here. Otherwise this window will be stuck in exiting and its
// surface remains on the screen.
// TODO(b/189856716): Allow destroying surface even if it belongs to the
// keyguard target.
if (wallpaperMayMove) {
displayContent.mWallpaperController.adjustWallpaperWindows();
}
focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
}
}
// Create surfaceControl before surface placement otherwise layout will be skipped
// (because WS.isGoneForLayout() is true when there is no surface.
if (shouldRelayout && outSurfaceControl != null) {
try {
result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
} catch (Exception e) {
displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
ProtoLog.w(WM_ERROR,
"Exception thrown when creating surface for client %s (%s). %s",
client, win.mAttrs.getTitle(), e);
Binder.restoreCallingIdentity(origId);
return 0;
}
}
// We may be deferring layout passes at the moment, but since the client is interested
// in the new out values right now we need to force a layout.
mWindowPlacerLocked.performSurfacePlacement(true /* force */);
if (shouldRelayout) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_1");
result = win.relayoutVisibleWindow(result);
if ((result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
focusMayChange = true;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD
&& displayContent.mInputMethodWindow == null) {
displayContent.setInputMethodWindowLocked(win);
imMayMove = true;
}
win.adjustStartingWindowFlags();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} else {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: viewVisibility_2");
winAnimator.mEnterAnimationPending = false;
winAnimator.mEnteringAnimation = false;
if (outSurfaceControl != null) {
if (viewVisibility == View.VISIBLE && winAnimator.hasSurface()) {
// We already told the client to go invisible, but the message may not be
// handled yet, or it might want to draw a last frame. If we already have a
// surface, let the client use that, but don't create new surface at this
// point.
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} else {
if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wmReleaseOutSurface_"
+ win.mAttrs.getTitle());
outSurfaceControl.release();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (focusMayChange) {
if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) {
imMayMove = false;
}
}
// updateFocusedWindowLocked() already assigned layers so we only need to
// reassign them at this point if the IM window state gets shuffled
boolean toBeDisplayed = (result & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0;
if (imMayMove) {
displayContent.computeImeTarget(true /* updateImeTarget */);
if (toBeDisplayed) {
// Little hack here -- we -should- be able to rely on the function to return
// true if the IME has moved and needs its layer recomputed. However, if the IME
// was hidden and isn't actually moved in the list, its layer may be out of data
// so we make sure to recompute it.
displayContent.assignWindowLayers(false /* setLayoutNeeded */);
}
}
if (wallpaperMayMove) {
displayContent.pendingLayoutChanges |=
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
if (win.mActivityRecord != null) {
displayContent.mUnknownAppVisibilityController.notifyRelayouted(win.mActivityRecord);
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: updateOrientation");
configChanged |= displayContent.updateOrientation();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (toBeDisplayed && win.mIsWallpaper) {
displayContent.mWallpaperController.updateWallpaperOffset(win, false /* sync */);
}
if (win.mActivityRecord != null) {
win.mActivityRecord.updateReportedVisibilityLocked();
}
if (displayPolicy.areSystemBarsForcedConsumedLw()) {
result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
}
if (!win.isGoneForLayout()) {
win.mResizedWhileGone = false;
}
if (outFrames != null && outMergedConfiguration != null) {
win.fillClientWindowFramesAndConfiguration(outFrames, outMergedConfiguration,
false /* useLatestConfig */, shouldRelayout);
// Set resize-handled here because the values are sent back to the client.
win.onResizeHandled();
}
if (outInsetsState != null) {
outInsetsState.set(win.getCompatInsetsState(), true /* copySources */);
}
ProtoLog.v(WM_DEBUG_FOCUS, "Relayout of %s: focusMayChange=%b",
win, focusMayChange);
if (DEBUG_LAYOUT) {
Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames);
}
win.mInRelayout = false;
if (outSyncIdBundle != null) {
final int maybeSyncSeqId;
if (USE_BLAST_SYNC && win.useBLASTSync() && viewVisibility == View.VISIBLE
&& win.mSyncSeqId > lastSyncSeqId) {
maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1;
win.markRedrawForSyncReported();
} else {
maybeSyncSeqId = -1;
}
outSyncIdBundle.putInt("seqid", maybeSyncSeqId);
}
if (configChanged) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"relayoutWindow: postNewConfigurationToHandler");
displayContent.sendNewConfiguration();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (outActiveControls != null) {
getInsetsSourceControls(win, outActiveControls);
}
}
Binder.restoreCallingIdentity(origId);
return result;
}
}
WindowManagerService createSurfaceControl
调用WindowManagerService的createSurfaceControl方法:
//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
WindowState win, WindowStateAnimator winAnimator) {
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
WindowSurfaceController surfaceController;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "createSurfaceControl");
surfaceController = winAnimator.createSurfaceLocked();
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
if (surfaceController != null) {
surfaceController.getSurfaceControl(outSurfaceControl);
ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
ProtoLog.w(WM_ERROR, "Failed to create surface control for %s", win);
outSurfaceControl.release();
}
return result;
}
}
WindowStateAnimator createSurfaceLocked
调用winAnimator(WindowStateAnimator)的createSurfaceLocked方法:
//frameworks/base/service/java/com/android/server/wm/WindowStateAnimator.java
class WindowStateAnimator {
WindowSurfaceController createSurfaceLocked() {
final WindowState w = mWin;
//一个WindowStateAnimator对象只会创建一个WindowSurfaceController
if (mSurfaceController != null) {
return mSurfaceController;
}
w.setHasSurface(false);
ProtoLog.i(WM_DEBUG_ANIM, "createSurface %s: mDrawState=DRAW_PENDING", this);
resetDrawState();
mService.makeWindowFreezingScreenIfNeededLocked(w);
int flags = SurfaceControl.HIDDEN;
final WindowManager.LayoutParams attrs = w.mAttrs;
if (w.isSecureLocked()) {
flags |= SurfaceControl.SECURE;
}
if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
flags |= SurfaceControl.SKIP_SCREENSHOT;
}
if (DEBUG_VISIBILITY) {
Slog.v(TAG, "Creating surface in session "
+ mSession.mSurfaceSession + " window " + this
+ " format=" + attrs.format + " flags=" + flags);
}
// Set up surface control with initial size.
try {
// This can be removed once we move all Buffer Layers to use BLAST.
final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
//这里直接通过new的方式创建了一个WindowSurfaceController对象
mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), format,
flags, this, attrs.type);
mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
w.setHasSurface(true);
// The surface instance is changed. Make sure the input info can be applied to the
// new surface, e.g. relaunch activity.
w.mInputWindowHandle.forceChange();
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
" CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s",
mSurfaceController, mSession.mSurfaceSession, mSession.mPid, attrs.format,
flags, this);
} catch (OutOfResourcesException e) {
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
mDrawState = NO_SURFACE;
return null;
} catch (Exception e) {
Slog.e(TAG, "Exception creating surface (parent dead?)", e);
mDrawState = NO_SURFACE;
return null;
}
if (DEBUG) {
Slog.v(TAG, "Got surface: " + mSurfaceController
+ ", set left=" + w.getFrame().left + " top=" + w.getFrame().top);
}
if (SHOW_LIGHT_TRANSACTIONS) {
Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
WindowManagerService.logSurface(w, "CREATE pos=("
+ w.getFrame().left + "," + w.getFrame().top + ") HIDE", false);
}
mLastHidden = true;
if (DEBUG) Slog.v(TAG, "Created surface " + this);
return mSurfaceController;
}
}
上面方法的主要处理如下:
1、调用WindowStateAnimator的resetDrawState方法。
2、通过new的方式创建WindowSurfaceController对象。
分析分别进行分析:
WindowStateAnimator resetDrawState
调用WindowStateAnimator的resetDrawState方法:
//frameworks/base/service/java/com/android/server/wm/WindowStateAnimator.java
class WindowStateAnimator {
void resetDrawState() {
mDrawState = DRAW_PENDING;
if (mWin.mActivityRecord == null) {
return;
}
if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
mWin.mActivityRecord.clearAllDrawn();
}
}
}
将DrawState设置为DRAW_PENDING状态,DRAW_PENDING表示窗口的绘制请求已经提交,但surface还没有真正显示。
new WindowSurfaceController
通过new的方式创建WindowSurfaceController对象,WindowSurfaceController构造方法中其实就是通过SurfaceControl的内部Builder类来创建SurfaceControl对象的,并且将SurfaceControl的Name,BufferSize,Format,Flags等等一并保存到内部Builder中,WindowSurfaceController构造方法如下:
//frameworks/base/service/java/com/android/server/wm/WindowSurfaceController.java
class WindowSurfaceController {
WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
int windowType) {
mAnimator = animator;
title = name;
mService = animator.mService;
final WindowState win = animator.mWin;
mWindowType = windowType;
mWindowSession = win.mSession;
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
final SurfaceControl.Builder b = win.makeSurface()
.setParent(win.getSurfaceControl())
.setName(name)
.setFormat(format)
.setFlags(flags)
.setMetadata(METADATA_WINDOW_TYPE, windowType)
.setMetadata(METADATA_OWNER_UID, mWindowSession.mUid)
.setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
.setCallsite("WindowSurfaceController");
final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0);
if (useBLAST) {
b.setBLASTLayer();
}
mSurfaceControl = b.build();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
上面方法主要处理如下:
1、调用WindowState的makeSurface方法获取SurfaceControl的构造器。
2、调用构造器(SurfaceControl.Builder)的build方法构造SurfaceControl对象。
下面分别进行分析:
WindowContainer makeSurface
调用win(WindowState的makeSurface方法,该方法在WindowState的父类WindowContainer中实现:
//frameworks/base/service/java/com/android/server/wm/WindowContainer.java
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
InsetsControlTarget {
SurfaceControl.Builder makeSurface() {
final WindowContainer p = getParent();
return p.makeChildSurface(this);
}
}
调用WindowContainer的makeChildSurface方法:
//frameworks/base/service/java/com/android/server/wm/WindowContainer.java
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
InsetsControlTarget {
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
final WindowContainer p = getParent();
// Give the parent a chance to set properties. In hierarchy v1 we rely
// on this to set full-screen dimensions on all our Surface-less Layers.
return p.makeChildSurface(child)
.setParent(mSurfaceControl);
}
}
返回WindowContainer对象,WindowContainer的构造方法如下:
//frameworks/base/service/java/com/android/server/wm/WindowContainer.java
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
InsetsControlTarget {
final TransitionController mTransitionController;
private final Transaction mPendingTransaction;
final SurfaceControl.Transaction mSyncTransaction;
protected final SurfaceAnimator mSurfaceAnimator;
final SurfaceFreezer mSurfaceFreezer;
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);
}
}
SurfaceControl.Builder build
调用构造器(SurfaceControl.Builder)的build方法构造SurfaceControl对象:
待更新