前言
DisplayContent 用于管理屏幕,一塊DisplayContent 對象實例代表一個屏幕設(shè)備,這樣有多個屏幕的設(shè)備就可以創(chuàng)建多個DisplayContent 對象,雖然多數(shù)設(shè)備只有一個顯示屏,但它們同樣可以創(chuàng)建多個 DisplayContent 對象,如投屏的時候,可以創(chuàng)建一個虛擬的DisplayContent。
一、DisplayContent 的創(chuàng)建
1、DisplayContent對象實例的創(chuàng)建最早是在SystemServer中被觸發(fā)的。
frameworks/base/services/java/com/android/server/SystemServer.java
public final class SystemServer implements Dumpable {
private ActivityManagerService mActivityManagerService;
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...代碼省略...
t.traceBegin("SetWindowManagerService");
mActivityManagerService.setWindowManager(wm);//創(chuàng)建屏幕設(shè)備對象
t.traceEnd();
...代碼省略...
}
}
該方法會調(diào)用ActivityManagerService的setWindowManager方法。
2、ActivityManagerService的setWindowManager方法如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock {
public WindowManagerService mWindowManager;
public ActivityTaskManagerService mActivityTaskManager;
public void setWindowManager(WindowManagerService wm) {
synchronized (this) {
mWindowManager = wm;
mWmInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityTaskManager.setWindowManager(wm);//創(chuàng)建屏幕設(shè)備對象
}
}
}
該方法會調(diào)用ActivityTaskManagerService的setWindowManager方法。
3、ActivityTaskManagerService的setWindowManager方法如下所示。
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
RootWindowContainer mRootWindowContainer;
public void setWindowManager(WindowManagerService wm) {
synchronized (mGlobalLock) {
mWindowManager = wm;
mRootWindowContainer = wm.mRoot;//獲取WindowManagerService的RootWindowContainer對象
mWindowOrganizerController.setWindowManager(wm);
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
mConfigurationSeq = mTempConfig.seq = 1;
mRootWindowContainer.onConfigurationChanged(mTempConfig);
mLockTaskController.setWindowManager(wm);
mTaskSupervisor.setWindowManager(wm);
mRootWindowContainer.setWindowManager(wm);//創(chuàng)建屏幕設(shè)備對象
}
}
}
該方法會繼續(xù)調(diào)用RootWindowContainer的setWindowManager方法。
4、DisplayContent對象實例就是在RootWindowContainer的setWindowManager方法中創(chuàng)建的。
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
class RootWindowContainer extends WindowContainer<DisplayContent>
implements DisplayManager.DisplayListener {
DisplayManager mDisplayManager;
/** Reference to default display so we can quickly look it up. */
private DisplayContent mDefaultDisplay;
void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
mDisplayManager.registerDisplayListener(this, mService.mUiHandler);
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
final Display[] displays = mDisplayManager.getDisplays();//通過DisplayManager獲取屏幕設(shè)備信息
for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) {//遍歷屏幕設(shè)備,為每個設(shè)備創(chuàng)建DisplayContent對象
final Display display = displays[displayNdx];
final DisplayContent displayContent = new DisplayContent(display, this);//創(chuàng)建屏幕對象DisplayContent實例
addChild(displayContent, POSITION_BOTTOM);
if (displayContent.mDisplayId == DEFAULT_DISPLAY) {
mDefaultDisplay = displayContent;
}
}
calculateDefaultMinimalSizeOfResizeableTasks();
final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea();
defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP);
positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent,
false /* includingParents */);
}
//添加新創(chuàng)建的DisplayContent屏幕設(shè)備對象,將其存儲到父類屬性mChildren集合中
void addChild(E child, int index) {
if (!child.mReparenting && child.getParent() != null) {
throw new IllegalArgumentException("addChild: container=" + child.getName()
+ " is already a child of container=" + child.getParent().getName()
+ " can't add to container=" + getName()
+ "\n callers=" + Debug.getCallers(15, "\n"));
}
if ((index < 0 && index != POSITION_BOTTOM)
|| (index > mChildren.size() && index != POSITION_TOP)) {
throw new IllegalArgumentException("addChild: invalid position=" + index
+ ", children number=" + mChildren.size());
}
if (index == POSITION_TOP) {
index = mChildren.size();
} else if (index == POSITION_BOTTOM) {
index = 0;
}
//將DisplayContent屏幕設(shè)備對象存儲到父類屬性mChildren集合中
mChildren.add(index, child);
// Set the parent after we've actually added a child in case a subclass depends on this.
child.setParent(this);
}
}
frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {
protected final WindowList<E> mChildren = new WindowList<E>();
}
1)首先通過DisplayManager獲取當前存在的屏幕設(shè)備信息數(shù)組,然后遍歷該數(shù)組為每個屏幕設(shè)備創(chuàng)建對應(yīng)的DisplayContent對象實例。
2)調(diào)用addChild方法依次將創(chuàng)建的DisplayContent對象實例存儲到父類的mChildren集合中。文章來源:http://www.zghlxwxcb.cn/news/detail-467817.html
二、DisplayContent類定義
frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java文章來源地址http://www.zghlxwxcb.cn/news/detail-467817.html
class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.DisplayContentInfo {
/**
* Create new {@link DisplayContent} instance, add itself to the root window container and
* initialize direct children.
* @param display May not be null.
* @param root {@link RootWindowContainer}
*/
DisplayContent(Display display, RootWindowContainer root) {
super(root.mWindowManager, "DisplayContent", FEATURE_ROOT);
if (mWmService.mRoot.getDisplayContent(display.getDisplayId()) != null) {
throw new IllegalArgumentException("Display with ID=" + display.getDisplayId()
+ " already exists="
+ mWmService.mRoot.getDisplayContent(display.getDisplayId())
+ " new=" + display);
}
mRootWindowContainer = root;
mAtmService = mWmService.mAtmService;
mDisplay = display;
mDisplayId = display.getDisplayId();
mCurrentUniqueDisplayId = display.getUniqueId();
mOffTokenAcquirer = mRootWindowContainer.mDisplayOffTokenAcquirer;
mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
mSystemGestureExclusionLimit = mWmService.mConstants.mSystemGestureExclusionLimitDp
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
mInsetsStateController = new InsetsStateController(this);
mDisplayFrames = new DisplayFrames(mDisplayId, mInsetsStateController.getRawInsetsState(),
mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation),
calculateRoundedCornersForRotation(mDisplayInfo.rotation),
calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation));
initializeDisplayBaseInfo();
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
mAppTransitionController = new AppTransitionController(mWmService, this);
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
final InputChannel inputChannel = mWmService.mInputManager.monitorInput(
"PointerEventDispatcher" + mDisplayId, mDisplayId);
mPointerEventDispatcher = new PointerEventDispatcher(inputChannel, this);
// Tap Listeners are supported for:
// 1. All physical displays (multi-display).
// 2. VirtualDisplays on VR, AA (and everything else).
mTapDetector = new TaskTapPointerEventListener(mWmService, this);
registerPointerEventListener(mTapDetector);
registerPointerEventListener(mWmService.mMousePositionTracker);
if (mWmService.mAtmService.getRecentTasks() != null) {
registerPointerEventListener(
mWmService.mAtmService.getRecentTasks().getInputListener());
}
mDisplayPolicy = new DisplayPolicy(mWmService, this);
mDisplayRotation = new DisplayRotation(mWmService, this);
mCloseToSquareMaxAspectRatio = mWmService.mContext.getResources().getFloat(
com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio);
if (isDefaultDisplay) {
// The policy may be invoked right after here, so it requires the necessary default
// fields of this display content.
mWmService.mPolicy.setDefaultDisplay(this);
}
if (mWmService.mDisplayReady) {
mDisplayPolicy.onConfigurationChanged();
}
if (mWmService.mSystemReady) {
mDisplayPolicy.systemReady();
}
mWindowCornerRadius = mDisplayPolicy.getWindowCornerRadius();
mDividerControllerLocked = new DockedTaskDividerController(this);
mPinnedTaskController = new PinnedTaskController(mWmService, this);
final Transaction pendingTransaction = getPendingTransaction();
configureSurfaces(pendingTransaction);
pendingTransaction.apply();
// Sets the display content for the children.
onDisplayChanged(this);
updateDisplayAreaOrganizers();
mInputMonitor = new InputMonitor(mWmService, this);
mInsetsPolicy = new InsetsPolicy(mInsetsStateController, this);
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display);
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
}
}
到了這里,關(guān)于Android 12系統(tǒng)源碼_窗口管理(五)DisplayContent簡介的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!