As mentioned in Android R DisplayManagerService module (1) startup, every physical screen in the system corresponds to a logical screen, and DisplayInfo represents the information object encapsulated by the logical screen. It is not fixed. When the DisplayInfo object changes, The WMS module sends a notification to the DMS, telling the DMS module to do the corresponding processing. This article summarizes the DMS update process after the logical screen information changes.
The update process of Configuration parameters of logical screen and physical screen in DMS is closely related to THE WMS module, because the update of DisplayInfo takes place in WMS. When the Configuration is updated, the DisplayInfo will be updated. If any changes are found, If properties such as screen orientation, screen size, and screen density change, WMS sets a new DisplayInfo to THE DMS. At the same time, when the DMS status changes, it also sends traversal request to WMS, and sets the corresponding configuration according to the WMS window status.
1. DisplayContent# updateDisplayAndOrientation update DisplayInfo ()
After the state change in WMS, in DisplayContent# updateDisplayAndOrientation () method of updating DisplayInfo objects:
// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
private DisplayInfo updateDisplayAndOrientation(int uiMode, Configuration outConfig) {...final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
? mDisplayInfo : null; mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId, overrideDisplayInfo); .return mDisplayInfo;
}
Copy the code
The detailed process of the DisplayInfo update will be analyzed in the WMS module. Here by DMS# setDisplayInfoOverrideFromWindowManager () method, pass DisplayInfo information to DMS, according to the new update logic DisplayInfo screen information in DMS.
2. DMS# setDisplayInfoOverrideFromWindowManagerInternal update logic () screen
After entering the DMS, in setDisplayInfoOverrideFromWindowManagerInternal () method for processing:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void setDisplayInfoOverrideFromWindowManagerInternal(
int displayId, DisplayInfo info) {
synchronized (mSyncRoot) {
// Run the Display Id command to obtain the logical screen
LogicalDisplay display = mLogicalDisplays.get(displayId);
if(display ! =null) {
if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
// Update the logical screen
handleLogicalDisplayChanged(displayId, display);
// Initiate window traversal to WMS
scheduleTraversalLocked(false); }}}}Copy the code
In this method:
- First, the corresponding logical screen is obtained according to the displayId.
- And then call
LogicalDisplay#setDisplayInfoOverrideFromWindowManagerLocked()
Method to update the DisplayInfo variable in DMS; - If the logical screen information is updated, the callback is performed
onDisplayChanged()
Method and initiate window traversal to WMS;
Let’s break it down one by one.
2.1. LogicalDisplay# setDisplayInfoOverrideFromWindowManagerLocked () ` update DisplayInfo variables in DMS
// frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
if(info ! =null) {
if (mOverrideDisplayInfo == null) {
mOverrideDisplayInfo = new DisplayInfo(info);
mInfo.set(null);
return true;
MOverrideDisplayInfo is different from info
} else if(! mOverrideDisplayInfo.equals(info)) {/ / update the mOverrideDisplayInfo
mOverrideDisplayInfo.copyFrom(info);
// empty mInfo for updates
mInfo.set(null);
return true; }}else if(mOverrideDisplayInfo ! =null) {
mOverrideDisplayInfo = null;
mInfo.set(null);
return true;
}
return false;
}
Copy the code
In this method, if the mOverrideDisplayInfo is inconsistent with the INFO, it indicates that the logical screen has changed, and the info is updated to the mOverrideDisplayInfo, and mInfo is empty. At the same time, true is returned to update the logical screen.
MInfo is a DisplayInfoProxy object. It holds a DisplayInfo object, which is the global logical screen information of the current system. When mInfo is updated, it needs to be empty first.
MOverrideDisplayInfo represents the DisplayInfo object from the WMS, the actual DisplayInfo object, that will be used to update the mInfo object when it is updated.
2.2. SendDisplayEventLocked () initiated DisplayListener# onDisplayChanged () callback
If DisplayInfo changes, then execute handleLogicalDisplayChanged () method, this method is invoked in sendDisplayEventLocked () method, Finally launched DisplayManager. DisplayListener# onDisplayChanged () callback method:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void sendDisplayEventLocked(int displayId, int event) {
Message msg = mHandler.obtainMessage(MSG_DELIVER_DISPLAY_EVENT, displayId, event);
mHandler.sendMessage(msg);
}
Copy the code
2.3. ScheduleTraversalLocked () request to launch window traversal to WMS
In the method, a traversal window request is made to WMS:
private void scheduleTraversalLocked(boolean inTraversal) {
if(! mPendingTraversal && mWindowManagerInternal ! =null) {
// Initiate the tag
mPendingTraversal = true;
if(! inTraversal) { mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL); }}}Copy the code
In the Handler, direct call WMS. RequestTraversalFromDisplayManager () launched an update request, the WMS in the android. The display thread:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null.true /*async*/);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case MSG_REQUEST_TRAVERSAL:
// Initiate a traversal request to WMS
mWindowManagerInternal.requestTraversalFromDisplayManager();
break; . }}}Copy the code
2.4.dms# getDisplayInfo() completes the DisplayInfo update and returns it to the other components
When mInfo is empty, it waits to be updated again, either by the application or by system_server. DMS provides the getDisplayInfo() method, which is called by the Binder to trigger the update, for example, when the orientation is rotated, Before executing the onConfiguration() method on the Activity where the application is located, the DisplayInfo is updated:
// frameworks/base/core/java/android/app/ActivityThread.java
private void updateDisplayInfoLocked(a) { DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); . }Copy the code
DMS#getDisplayInfoLocked()
// frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
public DisplayInfo getDisplayInfoLocked(a) {
if (mInfo.get() == null) {
DisplayInfo info = new DisplayInfo();
info.copyFrom(mBaseDisplayInfo);
if(mOverrideDisplayInfo ! =null) {
info.appWidth = mOverrideDisplayInfo.appWidth;
info.appHeight = mOverrideDisplayInfo.appHeight;
info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
info.logicalWidth = mOverrideDisplayInfo.logicalWidth;
info.logicalHeight = mOverrideDisplayInfo.logicalHeight;
info.rotation = mOverrideDisplayInfo.rotation;
info.displayCutout = mOverrideDisplayInfo.displayCutout;
info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
}
mInfo.set(info);
}
return mInfo.get();
}
Copy the code
In this method, if the mInfo object is not null, it is returned directly; otherwise, the mInfo object is updated from the mOverrideDisplayInfo object to complete the update of the logical screen information.
At this point, the first phase of the DMS process is completed. In this stage, we mainly did three things:
- 1. Update mOverrideDisplayInfo and mInfo objects;
- 2. Call the DisplayListener#onDisplayChanged() method;
- 3. Initiate window traversal request to WMS for window placement;
Let’s take a look at the interaction between WMS and DMS as it traverses Windows State.
There are two interactions between WMS and DMS as it traverses the WindowState for window placement:
- First, in the traversal process, it will get the preferred parameter of the control display mode carried by the window, and set it to the DMS by the DMS#setDisplayProperties() method;
- The second is after completing the placement of all Windows Surface, through
DisplayManagerInternal#performTraversal()
Notifies the DMS that J updates the configurations related to the physical screen, such as the Layer Stack and area size displayed on the interface……
Let’s take a look at each of them.
3.DMS#setDisplayProperties() sets window preferences
The detailed process of installing Windows State in the WMS Surface is analyzed in the WMS module. Here’s a look at the process associated with this section. In the function interface object mApplySurfaceChangesTransaction DisplayContent will iterate over all the window, And will be carried in the display window mTmpApplySurfaceChangesTransactionState to maintain the preferences of the object:
// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
final booleanobscuredChanged = w.mObscured ! = mTmpApplySurfaceChangesTransactionState.obscured;final RootWindowContainer root = mWmService.mRoot;
if(! mTmpApplySurfaceChangesTransactionState.obscured) {final boolean isDisplayed = w.isDisplayedLw();
if (isDisplayed && w.isObscuringDisplay()) {
root.mObscuringWindow = w;
mTmpApplySurfaceChangesTransactionState.obscured = true;
}
// Whether there is content displayed on the logical screen to control multi-screen mirroring
final boolean displayHasContent = root.handleNotObscuredLocked(w,
mTmpApplySurfaceChangesTransactionState.obscured,
mTmpApplySurfaceChangesTransactionState.syswin);
if(! mTmpApplySurfaceChangesTransactionState.displayHasContent && ! getDisplayPolicy().isWindowExcludedFromContent(w)) { mTmpApplySurfaceChangesTransactionState.displayHasContent |= displayHasContent; }if (w.mHasSurface && isDisplayed) {
final int type = w.mAttrs.type;
// Set the preferred frame rate
if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0&& w.mAttrs.preferredRefreshRate ! =0) {
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
= w.mAttrs.preferredRefreshRate;
}
/ / set preferMinimalPostProcessing
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing
|= w.mAttrs.preferMinimalPostProcessing;
final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(w);
/ / set preferredModeId
if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0&& preferredModeId ! =0) { mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId; }}}... };Copy the code
Traverse is completed, the value stored in mTmpApplySurfaceChangesTransactionState, and in the last issue request to DMS, set the display parameters, such as high refresh rate, wide, whether the mirror…
// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
void applySurfaceChangesTransaction(a) { mTmpApplySurfaceChangesTransactionState.reset(); . mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, mLastHasContent, mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, mTmpApplySurfaceChangesTransactionState.preferredModeId, mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,true /* inTraversal, must call performTraversalInTrans... below */);
}
Copy the code
The meanings of the parameters are as follows:
- HasContent Indicates whether content is displayed on the logical screen and is used to control screen mirroring.
- PreferredRefreshRate indicates the preferredRefreshRate carried by the top-level window;
- PreferredModeId indicates the preferred mode carried by the top-level window;
- PreferMinimalPostProcessing said the smallest Post – Processing, this is a display professional term.
4.DMS#performTraversal() updates the screen configuration
When all Windows are installed, transaction commit in DMS is performed in WMS using the DMS#performTraversal() method and the mDisplayTransaction object:
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
private void applySurfaceChangesTransaction(a) {...// Iterate over each DisplayContent, placing the Surface in each Display
final int count = mChildren.size();
for (int j = 0; j < count; ++j) {
final DisplayContent dc = mChildren.get(j);
dc.applySurfaceChangesTransaction();
}
// Notify THE DMS to adjust the Display attributes
mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
// Merge mDisplayTransaction into sGlobalTransaction
SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
}
Copy the code
After entering DMS:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
void performTraversalInternal(SurfaceControl.Transaction t) {
synchronized (mSyncRoot) {
// Only mPendingTraversal can be updated
if(! mPendingTraversal) {return;
}
// Reset to false
mPendingTraversal = false;
performTraversalLocked(t);
}
for(DisplayTransactionListener listener : mDisplayTransactionListeners) { listener.onDisplayTransaction(t); }}Copy the code
As you can see, only mPendingTraversal will be updated, which happens to be true in scheduleTraversalLocked(), and performTraversalLocked(), This method completes the DMS update step by step:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void performTraversalLocked(SurfaceControl.Transaction t) {
// Clear the DisplayViewport list
clearViewportsLocked();
// Go through all physical displays
final int count = mDisplayDevices.size();
for (int i = 0; i < count; i++) {
DisplayDevice device = mDisplayDevices.get(i);
// Update the physical screen configuration
configureDisplayLocked(t, device);
device.performTraversalLocked(t);
}
// Notifies the IMS when the Viewport changes
if(mInputManagerInternal ! =null) { mHandler.sendEmptyMessage(MSG_UPDATE_VIEWPORT); }}Copy the code
In this method, the configuration of each physical display is updated. Finally, if the DisplayViewport changes, the IMS is notified.
4.1. ConfigureDisplayLocked ()
The method is as follows:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device) {
// Get the DisplayDeviceInfo object corresponding to the physical screen
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
// Whether the display can be mirrored to other displays. True indicates that the display is not allowed
final booleanownContent = (info.flags & DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY) ! =0;
// Gets the logical display object corresponding to the physical display
LogicalDisplay display = findLogicalDisplayForDeviceLocked(device);
// If the physical screen allows mirroring, determine the source of the mirroring according to display.hascontentlocked ()
if(! ownContent) {if(display ! =null && !display.hasContentLocked()) {
display = mLogicalDisplays.get(device.getDisplayIdToMirrorLocked());
}
if (display == null) { display = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); }}// Configure logical display
display.configureDisplayLocked(t, device, info.state == Display.STATE_OFF);
// Update viewPort type
final Optional<Integer> viewportType = getViewportType(info);
/ / fill the viewport
populateViewportLocked(viewportType, display.getDisplayIdLocked(), device, info.uniqueId);
}
Copy the code
This method completes the reconfiguration of the logical screen, physical screen, and ViewPort. Let’s analyze it step by step.
4.2. ConfigureDisplayLocked update physical screen configuration ()
The method is as follows:
// frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
public void configureDisplayLocked(SurfaceControl.Transaction t,
DisplayDevice device,
boolean isBlanked) {
// Set the Layer Stack ID
device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
// Set the color mode.// Get the DisplayInfo object corresponding to the logical screen
final DisplayInfo displayInfo = getDisplayInfoLocked();
// Get the DisplayDeviceInfo object corresponding to the physical screen
final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
// Set the mTempLayerStackRect area, which represents the logical screen area to display on the physical screen
mTempLayerStackRect.set(0.0, displayInfo.logicalWidth, displayInfo.logicalHeight);
// Determine the direction
int orientation = Surface.ROTATION_0;
if((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) ! =0) {
orientation = displayInfo.rotation;
}
orientation = (orientation + displayDeviceInfo.rotation) % 4;
// According to the display direction, ok
boolean rotated = (orientation == Surface.ROTATION_90
|| orientation == Surface.ROTATION_270);
// Get the physical display width
int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
// Get the hidden area
Rect maskingInsets = getMaskingInsets(displayDeviceInfo);
InsetUtils.rotateInsets(maskingInsets, orientation);
// Physical size minus the width and height of the hidden area
physWidth -= maskingInsets.left + maskingInsets.right;
physHeight -= maskingInsets.top + maskingInsets.bottom;
int displayRectWidth, displayRectHeight;
if((displayInfo.flags & Display.FLAG_SCALING_DISABLED) ! =0 || mDisplayScalingDisabled) {
displayRectWidth = displayInfo.logicalWidth;
displayRectHeight = displayInfo.logicalHeight;
} else if (physWidth * displayInfo.logicalHeight
< physHeight * displayInfo.logicalWidth) {
// Letter box
displayRectWidth = physWidth;
displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
} else {
// Pillar box. Pillar box with two black sides
displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
displayRectHeight = physHeight;
}
int displayRectTop = (physHeight - displayRectHeight) / 2;
int displayRectLeft = (physWidth - displayRectWidth) / 2;
// Set the mTempDisplayRect field
mTempDisplayRect.set(displayRectLeft, displayRectTop,
displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
// Set the offset
mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top);
// Apply offsets mDisplayOffsetX and mDisplayOffsetY
if (orientation == Surface.ROTATION_0) {
mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY);
} else if (orientation == Surface.ROTATION_90) {
mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX);
} else if (orientation == Surface.ROTATION_180) {
mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY);
} else { // Surface.ROTATION_270
mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX);
}
// Set the physical display projection
device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
}
Copy the code
In this method, the following three things are done:
- First, set the Layer Stack Id;
- Then, mTempLayerStackRect and mTempDisplayRect are determined.
- Finally, set the Display projection to the SurfaceFlinger;
4.3.DisplayDevice#setLayerStackLocked() Sets the LayerStack
Layer Stack Id Indicates the corresponding Layer Stack on each physical screen in the SurfaceFlinger. All the layers displayed on the Display are in the Layer Stack. When creating a logical screen, a Layer Stack ID is specified. When the screen is off, the Layer Stack ID is set to -1 and nothing is displayed:
// frameworks/base/services/core/java/com/android/server/display/DisplayDevice.java
public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
if(mCurrentLayerStack ! = layerStack) {// Indicates the id of the current Layer Stack
mCurrentLayerStack = layerStack;
/ / sett.setDisplayLayerStack(mDisplayToken, layerStack); }}Copy the code
4.4.DisplayDevice#setProjectionLocked() sets the projection matrix
Next, we define two objects, mTempLayerStackRect and mTempDisplayRect. MTempLayerStackRect represents the logical screen size area, mTempDisplayRect represents the physical screen display area, Through SurfaceControl. Transaction# setDisplayLayerStack () after this two area to SurfaceFlinger, calculated the final projection matrix:
//
public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation,
Rect layerStackRect, Rect displayRect) {
if(mCurrentOrientation ! = orientation || mCurrentLayerStackRect ==null| |! mCurrentLayerStackRect.equals(layerStackRect) || mCurrentDisplayRect ==null| |! mCurrentDisplayRect.equals(displayRect)) {// Current screen orientation
mCurrentOrientation = orientation;
// Update the logical display area and the corresponding physical display area. mCurrentLayerStackRect.set(layerStackRect); . mCurrentDisplayRect.set(displayRect);// Pass to the SurfaceControl to compute the projection matrixt.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect); }}Copy the code
In this method, mTempLayerStackRect and mTempDisplayRect are updated to the global variables mCurrentLayerStackRect and mCurrentDisplayRect, which will play a role in mapping the ViewPort.
At this point, the LogicalDisplay#configureDisplayLocked() method is finished, and back to DMS#configureDisplayLocked(), the viewport population will begin.
4.5 update the ViewPort
ViewPort represents the corresponding relationship between the physical screen and the logical screen. In the Input module, ViewPort is used to convert the touch event coordinates of the physical screen to the coordinates of the logical screen. Therefore, the view port is repopulated and sent to the IMS module every time the logical screen and physical screen are configured.
Each time performTraversalLocked() is performed, the current ViewPort list is first emptied:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void clearViewportsLocked(a) {
mViewports.clear();
}
Copy the code
After LogicalDisplay#configureDisplayLocked() is executed, mCurrentOrientation and mCurrentDisplayRect are updated for the physical screen, Next, DMS#getViewportType() is used to determine the new ViewPort type of the physical screen according to the physical screen properties:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private Optional<Integer> getViewportType(DisplayDeviceInfo info) {
// Built-in screen, Viewport type is VIEWPORT_INTERNAL
if((info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) ! =0) {
return Optional.of(VIEWPORT_INTERNAL);
// Set the TOUCH_EXTERNAL flag to indicate that the touch event is external and the Viewport type is VIEWPORT_INTERNAL
} else if (info.touch == DisplayDeviceInfo.TOUCH_EXTERNAL) {
return Optional.of(VIEWPORT_EXTERNAL);
} else if(info.touch == DisplayDeviceInfo.TOUCH_VIRTUAL && ! TextUtils.isEmpty(info.uniqueId)) {return Optional.of(VIEWPORT_VIRTUAL);
} else{}return Optional.empty();
}
Copy the code
4.6. PopulateViewportLocked () to fill the ViewPort
Next, fill the ViewPort with DMS#populateViewportLocked() :
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private void populateViewportLocked(int viewportType, int displayId, DisplayDevice device,
DisplayDeviceInfo info) {
final DisplayViewport viewport = getViewportLocked(viewportType, info.uniqueId);
// Go to the physical screen to fill the blanks
device.populateViewportLocked(viewport);
// Indicates valid
viewport.valid = true;
viewport.displayId = displayId;
// Use Display state to determine whether the viewPort is active
viewport.isActive = Display.isActiveState(info.state);
}
Copy the code
Enter the corresponding physical screen for filling:
// frameworks/base/services/core/java/com/android/server/display/DisplayDevice.java
public final void populateViewportLocked(DisplayViewport viewport) {
// Set the direction
viewport.orientation = mCurrentOrientation;
// Set the logical screen area
if(mCurrentLayerStackRect ! =null) {
viewport.logicalFrame.set(mCurrentLayerStackRect);
} else {
viewport.logicalFrame.setEmpty();
}
// Set the physical screen area
if(mCurrentDisplayRect ! =null) {
viewport.physicalFrame.set(mCurrentDisplayRect);
} else {
viewport.physicalFrame.setEmpty();
}
// Whether rotation occurs
boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90
|| mCurrentOrientation == Surface.ROTATION_270);
// Obtain physical screen information
DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
// Indicates the width and height of the physical screen
viewport.deviceWidth = isRotated ? info.height : info.width;
viewport.deviceHeight = isRotated ? info.width : info.height;
// Physical screen ID
viewport.uniqueId = info.uniqueId;
// Physical screen Fixed physical port
if (info.address instanceof DisplayAddress.Physical) {
viewport.physicalPort = ((DisplayAddress.Physical) info.address).getPort();
} else {
viewport.physicalPort = null; }}Copy the code
As you can see, the ViewPort is populated by passing the width and height of the display area of the logical screen, the width and height of the display area of the physical screen, and the information carried in the DisplayDeviceInfo object of the physical screen to the ViewPort object. The ViewPort.PhysicalPort object is very important, as you’ll see later there is also a static route.
4.7. Notify IMS to update ViewPort
At the end of the DMS#performTraversalLocked() method, an MSG_UPDATE_VIEWPORT is sent through the Handler, which notifies IMS of the changed viewport:
// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
private final class DisplayManagerHandler extends Handler {...@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case MSG_UPDATE_VIEWPORT: {
final boolean changed;
synchronized(mSyncRoot) { changed = ! mTempViewports.equals(mViewports);if (changed) {
mTempViewports.clear();
for(DisplayViewport d : mViewports) { mTempViewports.add(d.makeCopy()); }}}if (changed) {
mInputManagerInternal.setDisplayViewports(mTempViewports);
}
break; }... }}}Copy the code
At this point, the update in the entire DMS is complete, and finally the updated display is complete with the commit of the transaction in THE WMS.
The sequence diagram of main processes in the main process is as follows: