DisplayManagerService(DMS for short) is a module in the Android Framework that manages the connection and configuration of displays.

In THE DMS module, the description of the display screen is divided into physical display and logical display. The physical screen is mainly created by reading parameters from SurfaceFlinger, representing the real physical screen and describing its physical characteristics. Different physical screens have different properties. The logical screen focuses on different logical Settings on the same physical screen, such as display area, display position coordinates, and display direction, depending on the application and WMS module. Each physical screen corresponds to a logical screen. You can modify the logical screen parameters to display the same physical screen in different modes.

Because different physical displays have different properties and processing modes, DMS is connected with different physical displays through a series of display Adapters.

1. Class structure

The relationship of main classes in DMS module is as follows:

Global management class:

  1. IDisplayManager: IBinder interface, responsible for DMS and other IPC work;
  2. DisplayManagerService: SystemService inherited from SystemService, responsible for display control and management of the entire system.
  3. DisplayManagerService. LocalService: inheritance in DisplayManagerInternal, responsible for other modules within the system_server and DMS interaction;
  4. DisplayManagerService. BindService: inheritance in IDisplayManager, is IDisplayManager concrete implementation class;
  5. DisplayManagerService. CallbackRecord: DMS inner classes, internal hold IDisplayManagerCallback object, is responsible for executing IDisplayManagerCallback callback;
  6. DisplayManager: an interface exposed to the App layer that holds a reference to the DisplayManagerGlobal object and interacts with the DMS using DisplayManagerGlobal;
  7. IDisplayManagerCallback: an IBinder interface that notifies DisplayManagerGlobal when a display action occurs in the DMS.
  8. DisplayManagerGlobal: Internally holds a reference to the IDisplayManager object through which the App layer interacts with the DMS across IPC;
  9. DisplayManagerGlobal. DisplayManagerCallback: inheritance in IDisplayManagerCallback interface, is responsible for receiving from DMS display event callback;

Data encapsulation classes:

  1. DisplayDevice: physical display;
  2. LocalDisplayDevice: a subclass of DisplayDevice that represents the built-in physical screen. SurfaceControl reads the built-in screen data after DMS starts and creates the object.
  3. WifiDisplayDevice: a subclass of DisplayDevice, which represents a physical screen displayed over a Wifi connection;
  4. OverlayDisplayDevice: subclass of DisplayDevice, developer option -> Analog Assisted display, which is created when enabled;
  5. VirtualDisplayDevice: a subclass of DisplayDevice, representing the virtual display screen, used for screen recording, etc.
  6. LogicalDisplay: indicates the logical display. Each physical display corresponds to a logical display.
  7. DisplayDeviceInfo: The DisplayDevice message encapsulation class, which is created when the DisplayDevice is created, corresponds to the DisplayInfo of Logical Display;
  8. DisplayInfo: Encapsulation class of LogicalDisplay information. The basic data is obtained from DisplayDeviceInfo. The APP can modify its parameters through WMS.
  9. DisplayAdapter: the adapter that connects the physical screen to the DMS.
  10. LocalDisplayAdapter: Inherits from DisplayAdapter and is used to connect LocalDisplayDevice to DMS.
  11. WifiDisplayAdapter: Inherits from DisplayAdapter for the connection between WifiDisplayDevice and DMS;
  12. OverlayDisplayAdapter: Inherits from DisplayAdapter and is used to connect OverlayDisplayDevice and DMS;
  13. VirtualDisplayAdapter: Inherits from DisplayAdapter and is used to connect VirtualDisplayDevice to DMS.
  14. Displayadapter. Listener: Interface used to notify DisplayDevice of changes, implemented in DMS, receives the following three events and makes global responses based on the events:
    • A. Add a new DisplayDevice;
    • B. DisplayDevice status changes;
    • C. Remove the DisplayDevice.
  1. DisplayViewport: carries the physical display parameter and notifies the IMS of the display information.

Not all of the above classes are in the same package, but have the following locations:

Package Name Directory Description Example
android.hardware.display frameworks/base/core/java/android/hardware/display An external module can access a class without an @hide annotation DisplayManager, DisplayMangaerGlobal, …
android.view frameworks/base/core/java/android/view The logical screen configuration is related DisplayInfo, DisplayViewport, …
com.android.server.display frameworks/base/services/core/java/com/android/server/display DMS core, external modules have no permission to access directly DMS,DisplayDevice, …

The following diagram lists the Physical and Logical Display mappings in the DMS module:

2.DMS startup process

DisplayManagerService inherits from SystemService, so its startup process is started by SystemServer, just like any other SystemService. In SytemServer:

// frameworks/base/services/java/com/android/server/SystemServer.java

    private void startBootstrapServices(a) {... mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); }Copy the code

When DMS is started in SystemServer, DMS object references are kept, so in addition to the normal startup method, the following operations are performed:

// frameworks/base/services/java/com/android/server/SystemServer.java

    private void startBootstrapServices(a) {... mDisplayManagerService.setupSchedulerPolicies(); }private void startOtherServices(a) {... mDisplayManagerService.windowManagerAndInputReady(); mDisplayManagerService.systemReady(safeMode, mOnlyCore); }Copy the code

Let’s look at each of these in turn.

2.1 perform DisplayManagerService ()

During startup, its constructor is first executed:

@VisibleForTesting
    DisplayManagerService(Context context, Injector injector) {
        super(context);
        mInjector = injector;
        mContext = context;
        // android.display thread handler
        mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
        // Android. UI thread Handler
        mUiHandler = UiThread.getHandler();
        // Create the displayAdapter.listener object
        mDisplayAdapterListener = new DisplayAdapterListener();
        // Create the DisplayModeDirector object
        mDisplayModeDirector = newDisplayModeDirector(context, mHandler); . mSystemReady =false;
    }
Copy the code

DisplayAdapterListener inherits from DisplayAdapter.Listener and is responsible for passing events emitted from each DisplayAdapter to the DMS. DisplayModeDirector is responsible for listening and selecting various Display configuration combinations in the system.

2.2. To perform the onStart ()

Next, execute the onStart() method:

// frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
    public void onStart(a) {
        // Load data
        synchronized (mSyncRoot) {
            mPersistentDataStore.loadIfNeeded();
            loadStableDisplayValuesLocked();
        }
        // create a default DisplayAdapter in the android.display thread
        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
 
        // Register Binder Services with ServiceManager
        publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                true /*allowIsolated*/);
        // Register Local Service
        publishLocalService(DisplayManagerInternal.class, new LocalService());
    }
Copy the code

First, the PersistentDataStore is used to load the fixed data in display in the form of XML files stored in /data/system/display-manager-state.xml. Then, start registering the default DisplayAdapter in the Android. display thread; Finally, the internal BinderService object is registered with the ServiceManager, the LocalService is published to the LocalServices, and the internal and external interactions of system_server are performed.

Register the default DisplayAdapter through registerDefaultDisplayAdapters () method:

private void registerDefaultDisplayAdapters(a) {
    synchronized (mSyncRoot) {
        registerDisplayAdapterLocked(newLocalDisplayAdapter( mSyncRoot, mContext, mHandler, mDisplayAdapterListener)); . }}Copy the code

Here we create the LocalDisplayAdapter object and add it to the DisplayAdapter list:

private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
    mDisplayAdapters.add(adapter);  // Add to the DisplayAdapter list
    adapter.registerLocked();       // Register in DisplayAdapter
}
Copy the code

Here will perform various DisplayAdapter. RegisterLocked () method is a different adapter registration work. In the LocalDisplayAdapter, a logical screen is created based on the physical screen. See Android R DisplayManagerService module (2) for a detailed analysis of this part of the DisplayAdapter and DisplayDevice creation.

2.3 perform onBootPhase ()

After onStart() completes, the onBootPhase() method is executed:

@Override
public void onBootPhase(int phase) {
    if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
        synchronized (mSyncRoot) {
            long timeout = SystemClock.uptimeMillis()
                    + mInjector.getDefaultDisplayDelayTimeout();
            If no logical display has been added to the mLogicalDisplays list after timeout, an exception is thrown
            while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
                    mVirtualDisplayAdapter == null) {
                long delay = timeout - SystemClock.uptimeMillis();
                if (delay <= 0) {
                    throw new RuntimeException("Timeout waiting ....");
                }
                try {
                    mSyncRoot.wait(delay);
                } catch (InterruptedException ex) {
                }
            }
        }
    }
}
Copy the code

The PHASE_WAIT_FOR_DEFAULT_DISPLAY phase is the earliest startup phase. After some boot services have been started, the DMS checks whether the default logical screen has been created when starting subsequent services. If the default LogicalDisplay has not been created within 10 seconds, an exception is thrown.

Now that the SystemService lifecycle methods are complete, continue to look at other methods that SytemServer executes during startup.

2.4. SetupSchedulerPolicies ()

public void setupSchedulerPolicies(a) {
    Android. display, android.anim, android.anim.lf thread group and CPU set
    Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
            Process.THREAD_GROUP_TOP_APP);
    Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
            Process.THREAD_GROUP_TOP_APP);
    Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
            Process.THREAD_GROUP_TOP_APP);
}
Copy the code

In this method, set the thread group and schedule set for the above three threads, with the thread group set to process.thread_group_top_app to ensure more efficient execution.

2.5. WindowManagerAndInputReady ()

When WindowManagerService and InputManagerService are started in SystemServer, this method is called to inform DMS:

// TODO: Use dependencies or a boot phase
public void windowManagerAndInputReady(a) {
    synchronized (mSyncRoot) {
        // Get the LocalService object interacting within each module process
        mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
        // Request WMS to perform window update process
        scheduleTraversalLocked(false); }}Copy the code

In this method, the respective LocalService objects of WMS and IMS are obtained, and then the display content update process is initiated, requesting the WMS module to update the window. DMS and WMS are closely related. Usually, when the related attributes in DMS change, WMS will notify WMS to update the window, and WMS will also notify DMS during the update process and apply the Display related attributes from the window.

2.6. SystemReady ()

This method is the last call made in SystemServer to inform DMS that startup is complete:

public void systemReady(boolean safeMode, boolean onlyCore) {
    synchronized (mSyncRoot) {
        ......
        mSystemReady = true; // The startup is complete
        / / the default Display the top of an inset store to persist. The sys. Displayinset. Top
        recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));
    }
    // Set the listener
    mDisplayModeDirector.setListener(new AllowedDisplayModeObserver());
    / / start
    mDisplayModeDirector.start();
    // Register other displayAdapters
    mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
}
Copy the code

In this method, operations to register other DeviceAdapters are initiated via mHandler. Finally, the four displayAdapters are registered.

The DMS startup process is complete. On the whole, there is no complicated process involved in the startup process, and its sequence diagram is as follows: