As stated in the previous Android R DisplayManagerService module (1) startup, the onStart() method starts registering the default Display adapter, and this article analyzes and summarizes the process.

1. Create a screen adapter object

The onStart () method, will be in the android. The display thread that executes registerDefaultDisplayAdapters default DisplayAdapter () method to register:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

    private void registerDefaultDisplayAdapters(a) {
        // Register default display adapters.
        synchronized (mSyncRoot) {
            // main display adapter
            registerDisplayAdapterLocked(newLocalDisplayAdapter( mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); . }}Copy the code

Created here LocalDisplayAdapter object and the object as a parameter, perform registerDisplayAdapterLocked () method:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
    private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
        mDisplayAdapters.add(adapter);
        adapter.registerLocked();
    }
Copy the code

First, add the LocalDisplayAdapter object to the mDisplayAdapters. MDisplayAdapters is a list of displayAdapters used to store all displayAdapters in THE DMS. There is no extra processing in the LocalDisplayAdapter constructor. The assignment of basic attributes is in its parent DisplayAdapter class:

// frameworks/base/services/core/java/com/android/server/display/DisplayAdapter.java

public DisplayAdapter(DisplayManagerService.SyncRoot syncRoot, Context context, Handler handler, Listener listener, String name) {
    // DMS module global synchronization lock
    mSyncRoot = syncRoot;
    mContext = context;
    // Android. display Handler
    mHandler = handler;
    // Dislayapater.Listener object, used to call back DMS
    mListener = listener;
    mName = name;
}
Copy the code

2. Create physical screen objects

Create good adapter object, will perform registerLocked () method, into the DisplayAdapter, connect and physical screen, LocalDisplayAdapter. RegisterLocked () as follows:

@Override
// frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
public void registerLocked(a) {
    super.registerLocked();
    // Get the physical DisplayId from the SurfaceControl
    for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
        // Connect Physical DisplaytryConnectDisplayLocked(physicalDisplayId); }}Copy the code

TryConnectDisplayLocked () to create a physical display based on the ID and connect to the DMS:

// frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java

private void tryConnectDisplayLocked(long physicalDisplayId) {
    // Obtain the Display token based on the ID
    final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
    if(displayToken ! =null) {
        // Obtain all physical display configuration items based on the token
        SurfaceControl.PhysicalDisplayInfo[] configs =
                SurfaceControl.getDisplayConfigs(displayToken);
        // Obtain the physical display configuration item in use based on the token
        intactiveConfig = SurfaceControl.getActiveConfig(displayToken); .// Get the corresponding LocalDisplayDevice from the mDevices array based on the id
        LocalDisplayDevice device = mDevices.get(physicalDisplayId);
        if (device == null) {
            / / create LocalDisplayDevice
            final boolean isInternal = mDevices.size() == 0;
            device = new LocalDisplayDevice(displayToken, physicalDisplayId, info,
                    configs, activeConfig, configSpecs, colorModes, activeColorMode,
                    hdrCapabilities, isDefaultDisplay);
            // Add to mDevices
            mDevices.put(physicalDisplayId, device);
            // Notify DMS to add the DisplayDevice event
            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
        } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
                    allowedConfigs, colorModes, activeColorMode)) {     / / update the DisplayDevice
            // Notify DMS to update the DisplayDevice eventsendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED); }}else{}}Copy the code

Multiple physical display-related configuration properties are retrieved from the SurfaceControler. The PhysicalDisplayInfo command encapsulates all physical display attribute configurations. You can run the following command to view the configuration information:

adb shell dumpsys display | grep mDisplayInfos

Next, the obtained ID will be used to check whether the corresponding DisplayDevice object exists in the mDevices array. If not, the DisplayDevice object will be created and the DMS will be informed to create the corresponding logical screen after the creation is complete.

LocalDisplayDevice () as follows:

// frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java

        LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
                SurfaceControl.DisplayInfo info, SurfaceControl.DisplayConfig[] configs,
                int activeConfigId, SurfaceControl.DesiredDisplayConfigSpecs configSpecs,
                int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities,
                boolean isDefaultDisplay) {
            // Set the mDisplayAdapter, mDisplayToken and mUniqueId attributes
            super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
            // Physical screen ID
            mPhysicalDisplayId = physicalDisplayId;
            // Is the default screen
            mIsDefaultDisplay = isDefaultDisplay;
            mDisplayInfo = info;
            // Update the physical screen configuration
            updateDisplayProperties(configs, activeConfigId, configSpecs, colorModes,
                    activeColorMode, hdrCapabilities);
            mSidekickInternal = LocalServices.getService(SidekickInternal.class);
            // Get the LightsManager object
            if (mIsDefaultDisplay) {
                LightsManager lights = LocalServices.getService(LightsManager.class);
                mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
            } else {
                mBacklight = null; }...// Create a luminance mapping curve
            BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                    LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this));
        }
Copy the code

Here will be initialized to properties of LocalDisplayDevice, executed after updatePhysicalDisplayInfoLocked () method to update the physical screen configuration, finally get set of backlight mBacklight object, it can be seen that the native mechanism, Even though there are multiple physical screens, there is only one mBacklight.

In the updateDisplayProperties() method, the physical screen configuration, color mode, and HDR mode are updated, respectively.

Create complete LocalDisplayDevice object, after the next execution sendDisplayDeviceEventLocked () method, notice the DMS newly added DisplayDevice events.

3. Notify the DMS that the physical screen is created

The DMS is notified in the DisplayAdapter by way of a callback. The callback interface class is displayAdapter.Listener, which is implemented in the DMS and passed in as a parameter when LocalDisplayAdapter is instantiated.

Next, then see sendDisplayDeviceEventLocked () method:

// frameworks/base/services/core/java/com/android/server/display/DisplayAdapter.java

    protected final void sendDisplayDeviceEventLocked(
            final DisplayDevice device, final int event) {
        // Execute the displayAdapter.listener# onDisplayDeviceEvent() method
        mHandler.post(() -> mListener.onDisplayDeviceEvent(device, event));
    }
Copy the code

This mListener object, it is DMS DisplayAdapterListener class objects:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

private final class DisplayAdapterListener implements DisplayAdapter.Listener {
    @Override
    public void onDisplayDeviceEvent(DisplayDevice device, int event) {
        switch (event) {
            case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
                handleDisplayDeviceAdded(device);
                break;
 
            case DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED:
                handleDisplayDeviceChanged(device);
                break;
 
            case DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED:
                handleDisplayDeviceRemoved(device);
                break; }}@Override
    public void onTraversalRequested(a) {
        synchronized (mSyncRoot) {
            scheduleTraversalLocked(false); }}}Copy the code

LocalDisplayAdapter launched after the callback, therefore, to perform handleDisplayDeviceAdded () method, the direct call handleDisplayDeviceAddedLocked () method:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java

    private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
        // Get the DisplayDeviceInfo objectDisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); .// Add to the mDisplayDevices list
        mDisplayDevices.add(device);
        // Create a logical screen object
        LogicalDisplay display = addLogicalDisplayLocked(device);
        // Update the display status
        Runnable work = updateDisplayStateLocked(device);
        if(work ! =null) {
            work.run();
        }
        // Initiate window updates to WMS
        scheduleTraversalLocked(false);
    }
Copy the code

In this method, a DisplayDeviceInfo object is first created, then the corresponding logical screen object is created, and finally the status information of Display is updated and a window update request is made to WMS.

5. Create logical screen objects

In the DMS module, use addLogicalDisplayLocked() to create the corresponding logical screen object for the physical screen:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
    private LogicalDisplay addLogicalDisplayLocked(DisplayDevice device) {
        DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
        // Is the default Display
        booleanisDefault = (deviceInfo.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) ! =0; .// Assign a logical screen ID
        final int displayId = assignDisplayIdLocked(isDefault, deviceInfo.address);
        // Assign the Layer Stack ID
        final int layerStack = assignLayerStackLocked(displayId);
        // Create LogicalDisplay object
        LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
        // Update the DisplayDeviceInfo corresponding to physical Display and LogicalDisplaydisplay.updateLocked(mDisplayDevices); . configureColorModeLocked(display, device);// Add to the mLogicalDisplays list
        mLogicalDisplays.put(displayId, display);
        
        sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_ADDED);
        return display;
    }
Copy the code

In this method:

  • First, before creating a logical display object, an ID and a Layer Stack ID are assigned to the logical screen to be created.
  • Then, start creating the LogicalDisplay object;
  • Next, execute the LogicalDisplay#updateLocked() method, which updates the DisplayInfo object representing the logical screen information;
  • Finally, execute the sendDisplayEventLocked() method to notify components outside the DMS module of adding events to the logical screen.

6. Update the Display status

Back to handleDisplayDeviceAddedLocked (), LogicalDisplay related process execution created for start update DisplayDevice status:

private Runnable updateDisplayStateLocked(DisplayDevice device) {
    / / get DisplayDeviceInfo
    DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    // Without the FLAG_NEVER_BLANK flag, updates to the DisplayDevice status and brightness are requested
    if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
        return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
    }
    return null;
}
Copy the code

This method is the key method for updating Display state and brightness in DMS and will be analyzed in the next article.

The sequence diagram of the whole process is as follows: