In Android system, WindowManager(hereinafter referred to as WMS) is responsible for the management of all Windows. Windows can be understood as various display areas on the screen, such as status bar, Activity, lock screen…… For WMS, is a concrete window instance. Starting with this article, you’ll summarize the Windows Manager module.
1. The WMS architecture
In WindowManager, Windows are managed in the form of a container + tree structure. The top container is ConfigurationContainer, which is the parent of all containers. The inheritance relationship of each container is as follows:
The figure above contains all containers in the WMS. The meanings of each sub-container are as follows:
- ConfigurationContainer: A top-level container that defines multiple Configuration objects and provides common logic for organizing each container level.
- WindowProcessController: used to communicate with ProcessRecord in AMS. When ProcessRecord adjusts the application process, it communicates with WM through WindowProcessController.
- WindowContainer: As the parent of the save window class, it defines all the public methods used to manipulate the window.
- RootWindowContainer: The root node of the window container in the tree.
- DisplayContent: As a child of RootWindowContainer, used to manage Windows on the same logical screen;
- DisplayChildWindowContainer: DisplayContent all child nodes of the parent class;
- NonAppWindowContainers: inheritance in DisplayChildWindowContainer, the main save not WindowToken from application;
- WindowContainers: contains only one child node — displayArea.root, in which large sections of Windows are stored;
- DisplayArea: used for group management of nodes in DisplayContent, mainly divided into three categories;
- Root: subclass of DisplayArea. The container is the top-level DisplayArea of DisplayContent to hold Tokens, TaskDisplayArea, and ImeContainer containers.
- TaskDisplayArea: a subclass of DisplayArea used to manage tasks;
- Tokens: A subclass of DisplayArea that holds WindowTokens for normal Windows;
- ImeContainer: a subclass of Tokens. This container holds windowTokens for IME Windows.
- Task: Used to save ActivityRecord, which is often called “Task”;
- ActivityStack: subclass of Task, used to manage activities in the same stack, special stack can hold tasks;
- WindowToken: Used to manage Windows, multiple Windows can be managed by a WindowToken;
- ActivityRecord: Inherits from Windows Token and represents an Activity instance in ActivityStack;
- WallpaperWindowToken: Inherits from WindowToken. The wallpaper window is special, so it is managed by WallpaperWindowToken.
- WindowState: window object instance;
DisplayArea is a new container added to Android R to simplify and decouple complex window hierarchies.
In the tree structure, each container structure is as follows:
As you can see, in the tree structure, the root node is RootWindowContainer and the leaf node is WindowState. It is through this structure that WMS manages all window displays in the system in order, and sends all Windows to SurfacaFlinger in the form of Surface for synthesis and display.
2.WMS startup process
Let’s take a look at the WMS startup process. WindowManagerService does not inherit from SystemService, but directly inherits the iWindowManager. Stub interface. Therefore, the startup process is different from that of SytemService. In system_server, WMS is started by doing the following:
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
/ / create the WMSwm = WindowManagerService.main(context, inputManager, ! mFirstBoot, mOnlyCore,new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// Initialize
wm.onInitReady();
// Set the InputCallback interface
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
// Update the Display configuration
wm.displayReady();
// The system is started
wm.systemReady();
/ / calculate the Configuration
final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
DisplayMetrics metrics = new DisplayMetrics();
context.getDisplay().getMetrics(metrics);
context.getResources().updateConfiguration(config, metrics);
}
Copy the code
The above operations are analyzed respectively below.
1.1.wms #main() creates a WMS object
After executing the main() method, an instance of WMS is eventually created on the Android.display thread:
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {.../ / Tranaction object
mTransaction = mTransactionFactory.get();
// Create WindowAnimator objects
mAnimator = new WindowAnimator(this);
// Create RootWindowContainer object
mRoot = new RootWindowContainer(this);
Create a WindowSurfacePlacer object
mWindowPlacerLocked = new WindowSurfacePlacer(this);
// Create a TaskSnapshotController object
mTaskSnapshotController = new TaskSnapshotController(this);
/ / create DisplayWindowListenerController object
mDisplayNotificationController = new DisplayWindowListenerController(this); .// Create the SurfaceAnimationRunner object
mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
mPowerManagerInternal);
/ / create TaskPositioningController
mTaskPositioningController = new TaskPositioningController(
this, mInputManager, mActivityTaskManager, mH.getLooper());
// Create the DragDropController object
mDragDropController = new DragDropController(this, mH.getLooper());
/ / create EmbeddedWindowController
mEmbeddedWindowController = new EmbeddedWindowController(mAtmService);
/ / create DisplayAreaPolicy. The Provider objectmDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources( mContext.getResources()); . }Copy the code
In the constructor, you create multiple objects used by WMS.
2.2.WMS#onInitReady() initializes the Policy
The onInitReady() method is then used to initialize, in which the WindowManagerPolicy#init() method is called in the android.ui thread:
// frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
public void init(Context context, IWindowManager windowManager, WindowManagerFuncs windowManagerFuncs) { mContext = context; mWindowManager = windowManager; mWindowManagerFuncs = windowManagerFuncs; . }Copy the code
A lot of initialization is done in this method. Inheriting from WindowManagerPolicy, PhoneWindowManager is a policy class in the process of managing Windows in WMS. The display of Windows and the distribution of events are affected by the policies in PhoneWindowManager. MWindowManager and mWindowManagerFuncs are WMS objects themselves.
2.3. IMS# setWindowManagerCallbacks () sets the InputCallback callback
This method is used to set the InputManagerCallback callback to the IMS:
// frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
mWindowManagerCallbacks = callbacks;
}
Copy the code
The InputManagerCallback object is created when THE WMS is loaded:
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
// Create InputManagerCallback
final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
public InputManagerCallback getInputManagerCallback(a) {
return mInputManagerCallback;
}
Copy the code
The InputManagerCallback interface is used to receive IMS callbacks, such as ANR during input event distribution, and transmit them to WMS through this interface.
2.4.WMS#displayReady() updates the DisplayContent configuration
This method is used to perform the first update of the Display configuration:
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public void displayReady(a) {
synchronized (mGlobalLock) {
......
// Tell WindowAnimator that initialization is complete
mAnimator.ready();
// Indicates that Display is ready to complete
mDisplayReady = true;
/ / update the Configuration
mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked);
}
try {
/ / update the Configuration
mActivityTaskManager.updateConfiguration(null);
} catch (RemoteException e) {
}
}
Copy the code
Here we update the DisplayContent configuration with DisplayContent#reconfigureDisplayLocked().
2.5. WMS# systemReady () method
WMS will execute the systemReady() method of other components separately:
// frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
public void systemReady(a) {
/ / system
mSystemReady = true;
// PhoneWindowManager
mPolicy.systemReady();
/ / execution DisplayPolicy# systemReadymRoot.forAllDisplayPolicies(DisplayPolicy::systemReady); mTaskSnapshotController.systemReady(); mHasWideColorGamutSupport = queryWideColorGamutSupport(); mHasHdrSupport = queryHdrSupport(); UiThread.getHandler().post(mSettingsObserver::loadSettings); . }Copy the code
2.6. WMS# computeNewConfiguration ()
This method is the last method executed during startup to update the global configuration status:
// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private Configuration computeNewConfigurationLocked(int displayId) {
if(! mDisplayReady) {return null;
}
final Configuration config = new Configuration();
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
displayContent.computeScreenConfiguration(config);
return config;
}
Copy the code
In this method, it obtains the corresponding DisplayContent object based on the logical screen ID to update the configuration. After the update, it sets the configuration to the Resource object of the corresponding Context. The update configuration update process in DisplayContent will be explained in detail in future articles in combination with specific scenarios.
After the above steps, the WMS startup is complete.