We have learned how SurfaceFlinger works. With this foundation, we can analyze the UI Implementation of the Android system on the Java layer from the beginning of this article. We know that among the four components of the Android Application, only the Activity component is related to the UI, which describes the application window. Therefore, we use its UI implementation to analyze the UI Implementation of the Android system on the Java layer. This article briefly introduces the UI implementation of the Activity component and develops a learning plan.
The UI implementation of the Activity component needs to interact with the WindowManagerService and SurfaceFlinger service. From the previous analysis of the Message Processing Mechanism on the Keyboard of the Android application, we can see that after the Activity component is started, A Session-Type Binder object is used to request WindowManagerService to create a WindowState-type object for it to describe its window status. In addition, we can learn from the articles on the relationship between Android applications and SurfaceFlinger services and the learning plan, the Android Application requests the SurfaceFlinger service to create a Layer object for the Client through a Binder object of the Client type to describe its window data.
From the analysis of the process when the Android Application requests the SurfaceFlinger service to create the Surface, we can also find that after the SurfaceFlinger service creates a Layer object for the Android Application, A Binder object of SurfaceLayer type is returned to the Android Application, so that the Android Application can request the SurfaceFlinger service to allocate a graphic buffer through this Binder object.
Based on the above information, we can obtain the interaction model between the Activity component and the WindowManagerService and SurfaceFlinger service, as shown in 1:
Figure 1 Interaction Model Between Activity component and WindowManagerService and SurfaceFlinger Service
In fact, the SurfaceLayer object used to associate the Activity component and Layer object is not created by the Android application requesting the SurfaceFlinger service, but by the WindowManagerService requesting the SurfaceFlinger service. After the WindowManagerService obtains the SurfaceLayer object, it returns a proxy object to the Activity component on the Android Application side. In this way, the Activity component and WindowManagerService can use the same SurfaceLayer object to operate the Layer object on the SurfaceFlinger Service side. The Layer object is operated to modify the UI of the Activity component.
In the previous articles on the relationship between the Android Application and SurfaceFlinger service and the SurfaceFlinger service of the learning plan and the Surface mechanism of the Android system, we have analyzed the implementation of the Layer class and SurfaceLayer class on the SurfaceFlinger Service side. In this series of articles, we mainly analyze the implementation of the UI-related classes of the Activity component on the Android Application side, and the implementation of the WindowState class on the WindowManagerService side.
First, let's look at the implementation of the Activity component, as shown in 2:
Figure 2 Activity component class relationship diagram
The Activity class inherits from the ContextThemeWrapper class, while the ContextThemeWrapper class inherits from the ContextWrapper class. Finally, the ContextWrapper class inherits the Context class.
As you can see from the source code analysis in the previous Android app startup process, the system will create a ContextImpl object for the Activity component during startup to describe its running context environment. The ContextImpl object is first passed to the Acticity component by calling the attach member function of the Acitivity class, then, the member functions attachBaseContext of the parent class ContextThemeWrapper and ContextWrapper are called in sequence and saved in their member variable mBase respectively. Therefore, the member variables mBase of the ContextThemeWrapper and ContextWrapper classes actually point to a ContextImpl object.
From the source code analysis Text of the previous Android Application startup process, we can also know that after the system creates a ContextImpl object for a started Activity component, the ContextImpl object's member function setOuterContext is also called to save the started Activity component in its member variable mOuterContext. In this way, an Activity component can access a ContextImpl object used to describe its runtime context by using the member variable mBase of its parent class ContextThemeWrapper or ContextWrapper, A ContextImpl object can also access its host Activity component through its member variable mOuterContext.
The Activity class also has another member variable mWindowManager of the WindowManager type, which actually points to a LocalWindowManager object. The LocalWindowManager class is used to manage application windows. For example, it is used to maintain internal views of application windows ). The LocalWindowManager class has a member variable mWindowManager of the WindowManager type, which actually points to a WindowManagerImpl object. The system obtains a WindowManagerImpl object by calling the static member function getDefault of the WindowManagerImpl class, and then stores it in the mWindowManager member variable of the LocalWindowManager class. In this way, the LocalWindowManager class can use the WindowManagerImpl class to truly implement the function of managing the application window.
From the above analysis, we can't see how the window of an Activity component describes. To solve this problem, we continue to analyze another member variable mWindow of the Activity class, as shown in 3:
Figure 3 Implementation of the Window class
The mWindow type of the Activity class member variable is Window, which is used to describe an application Window. In this way, with this member variable, each Activity component will have a corresponding Window object, that is, a corresponding application Window.
The Window class has a member variable mContext of the Context type. This member variable points to a ContextImpl object. When the system creates a corresponding Window object for an Activity component, A ContextImpl object used to describe the running Context Environment of the Activity component will be saved in the mContext member variable of the corresponding Window object. In this way, a Window object can access the runtime Context Environment of the Activity component described by it through its member variable mContext.
The Window class also has a member variable mCallback of the type Window. Callback. This member variable points to an Activity object, because the Activity class implements the Window. Callback interface. When the system creates a corresponding Window object for an Activity component, the Window implemented by the Activity component will be used. the Callback interface uses the Window class member function setCallback to save the member variable mCallback in the corresponding Window object. In this way, a Window object can pass some events to the Activity component corresponding to it through its member variable mCallback. For example, send the received Keyboard Events to the corresponding Activity component for processing.
Finally, the Window class also has a member variable mWindowManager of the WindowManager type. This member variable points to a LocalWindowManager object. As mentioned above, the Activity component's member variable mWindowManager points to a LocalWindowManager object. When the system starts an Activity component, the setWindowManager function of the Window class is used to save a LocalWindowManager object stored in its member variable mWindowManager to the member variable mWindowManager of the corresponding Window object. In this way, an Activity component and its corresponding Window object can use the same LocalWindowManager object to manage the UI they describe.
In fact, mWindow, a member variable of the Activity class, points to a PhoneWindow object instead of a Window object. That is to say, the UI of an Activity component is described using a PhoneWindow object.
A PhoneWindow object pointed to by the mWindow member variable of the Activity class is created by calling the static member function makeNewWindow of the PolicyManager class. Implementation 4 of the PolicyManager class is shown below:
Figure 4 Implementation of the PolicyManager class
The PolicyManager class has a static member variable sPolicy of the IPolicy type, which actually points to a Policy object. The Policy class implements the member function makeNewWindow of the IPolicy interface, and the PolicyManager class creates a PhoneWindow object for an Activity component through this member function.
The PhoneWindow class inherits the Window class. Therefore, its object can save the mWindow member variable of the Activity class. Implementation 5 of the PhoneWindow class is shown below:
Figure 5 Implementation of the PhoneWindow class
The PhoneWindow class has two important member variables: mDecor and mContentParent. Their types are DecorView and ViewGroup. The member variable mDecor is used to describe its own window view, while the member variable mContentParent is used to describe the parent window view.
The DecorView class inherits the FrameLayout class, the FrameLayout class inherits the ViewGroup class, And the ViewGroup class inherits the View class. The View class has a member function draw, which is used to draw the UI of the application window. The DecorView class, FrameLayout class, And ViewGroup class override the member function draw of the parent class, so that they can all customize their own UI.
Whether the application window view described by the DecorView class needs to be re-drawn is controlled by another class ViewRoot. When the system starts an Activity component, it creates a ViewRoot object for the Activity component, at the same time, a view (DecorView) described by mDecor, a member variable of a PhoneWindow object created for this Activity component, will be saved in the mView member variable of this ViewRoot object. In this way, the ViewRoot object can draw the UI of an Acitivity component by calling the DecorView member function draw described by its member variable mView. The ViewRoot class is very powerful. In addition to controlling the UI rendering of an acitiworkflow component, it is also responsible for receiving IO input events of the acitiworkflow component, such as Keyboard Events, for more information about this, see the previous analysis of the Message Processing Mechanism on the Keyboard of the Android application.
Implementation 6 of the ViewRoot class is shown below:
Figure 6 Implementation of the ViewRoot class
The ViewRoot class is inherited from the Handler class. From the previous analysis of the Message Processing Mechanism (loaning and Handler) of Android applications, the subclass inherited from the Handler class can call the member function sendMessage of the parent class to send messages to the Message Queue of the specified thread, and process the message in the handleMessage function that you override. ViewRoot needs to send messages to the Message Queue of the main thread of the application process in two cases.
The first case is that when the ViewRoot class receives input events such as the keyboard and touch screen from the system input manager InputManager, it encapsulates these input events into a message, the message queue sent to the main thread of the application process for further processing. This ensures that input events such as the keyboard and touch screen can be processed in the main thread of the application process. For more information about this, see the previous analysis of the Message Processing Mechanism on the Keyboard of the Android application.
The second case is that when the ViewRoot class needs to re-draw the UI of an Activity component associated with it, it will encapsulate the UI painting operation into a message, in addition, the Message Queue sent to the main thread of the application process for further processing. This ensures that the operations to draw the UI can be executed in the main thread of the application process.
Each ViewRoot object has a View member variable mView, which points to a DecorView object. Where does this DecorView object come from? As mentioned above, each Activity component has a corresponding ViewRoot object and a corresponding PhoneWindow object. This DecorView object is the member variable mDecor from the corresponding PhoneWindow object. That is to say, the ViewRoot object and the PhoneWindow object corresponding to the same Activity component reference A DecorView object through their respective member variables mView and mDecor.
Each ViewRoot object has a type of WindowManager. the member variable m1_wattributes of LayoutParams points to a ViewGroup. layoutParams object, used to describe the UI layout information of an Activity component corresponding to the ViewRoot object.
As described above, each Activity component has a corresponding ViewRoot object, View object, and WindowManager. LayoutParams object. The ing between the three objects is maintained by the WindowManagerImpl class. Specifically, it is maintained by the three arrays described by the member variables mRoots, mViews, and mParams of the WindowManagerImpl class. For example, if an application process runs with two Activity components, the size of the three arrays described by the WindowManagerImpl member variables mRoots, mViews, and mParams is equal to 2, mRoots [0], mViews [0], and mParams [0] correspond to the first started Activity component, mRoots [1], mViews [1], and mParams [1] correspond to the second started Activity component.
Each ViewRoot object has a member variable mSurface of the Surface type, which points to a Surface object at the Java layer. The Surface object of this Java layer uses its member variable mNativeSurface to correspond to a Surface object of the C ++ layer. The Surface object on the C ++ layer is an example of the Surface class analyzed in the series of articles on the relationship between the Android Application and SurfaceFlinger service and the learning plan. This Surface class is used to describe the application window on the Android Application Process side. You can see from the analysis article on the process when the Android Application requested the SurfaceFlinger service to create the Surface. On the C ++ layer, each Surface object has a corresponding SurfaceControl object. This SurfaceControl object is used to set properties of the application window, such as setting properties such as size and position.
However, the Surface object in the C ++ layer corresponding to the ViewRoot member variable mSurface does not have a corresponding SurfaceControl object, this is because the ViewRoot class does not need to set the properties of the application window. All it needs to do is to fill the UI data in the graphic buffer of the application window, that is, it only needs to set the texture of the application window. The texture of the application window is stored in a Canvas described by mCanvas, a member variable of the Surface class on the Java layer. This Canvas allows you to access the graphic buffer zone of the application window. When the ViewRoot class needs to re-draw the UI of its corresponding Activity component, it will call its member function draw to execute this painting operation. The member function draw of the ViewRoot class first obtains a canvas inside the mSurface member variable to save it, then pass the canvas to the member function draw of a View object described by its member variable mView. After obtaining the canvas, the View class member function draw can draw the texture of the application window as needed. These textures are drawn through the Skia graphics library API.
Who manages the properties of the application window? This is managed by the WindowManagerService. As mentioned above, the Activity component on the Android Application side is created by the WindowManagerService to request SurfaceFlinger service to create a Layer object and a SurfaceLayer object. After this SurfaceLayer object is created, the WindowManagerService encapsulates it in a Surface object on the Java layer, in the future, you can request the SurfaceFlinger service to set the properties of a corresponding application window through the Surface object of the Java layer.
Because the Surface object of the Java Layer implements the Parcelable interface, WindowManagerService creates a Layer object and a SurfaceLayer object after requesting SurfaceFlinger service for an Activity component, you can return the Surface object of the Java layer to the Activity component across processes. After the Activity component obtains the Surface object, it uses the SurfaceLayer object stored in it to initialize a Java Layer Surface object described by mSurface, the member variable of a ViewRoot object corresponding to it.
When will the WindowManagerService request SurfaceFlinger service to create a Layer object and a SurfaceLayer object for an Activity component? The ViewRoot class has a static member variable sWindowSession of the IWindowSession type, which is actually a Binder object that implements the IWindowSession interface. The Binder object is of the Session type and runs on the WindowManagerService side. Before the UI of an Activity component is drawn for the first time, the application process in which it runs sends a request to the WindowManagerService through the static member variable sWindowSession of the ViewRoot class. After receiving the request, the WindowManagerService requests the SurfaceFlinger service to create a Layer object and a SurfaceLayer object for the Activity component. In this way, the UI of this Activity component can be truly drawn on the screen.
Now, we have briefly analyzed the implementation of the Activity component and UI-related classes on the Android Application side. Next we will continue to analyze the implementation of the WindowState class on the WindowManagerService side.
WindowState class implementation 7 is shown in:
Figure 7 implementation of the WindowState class
On the Android Application side, each Activity component has a corresponding WindowState object on the WindowManagerService side to describe the window status of the Activity component. The WindowState class has two important member variables: mSession and mSurface. Their types are SurfaceSession and Surface. Next, we will describe the functions of these two member variables.
As mentioned above, the Activity component requests the WindowManagerService service to create a WindowState object for it after it is started. After the WindowState object is created, the WindowManagerService calls its member function attach to attach a SurfaceSession object to it. The attach function of the WindowState class attaches a SurfaceSession object by calling the member function windowAddedLocked of a Session object described by its member variable mSession.
The Session class has a member variable mSurfaceSession of the SurfaceSession type. When the attach function of the WindowState class calls the windowAddedLocked function of the Session class to append a SurfaceSession object to a WindowState object, the latter first checks whether its member variable mSurfaceSession has pointed to a SurfaceSession object. If it is pointed to, the Session class member function windowAddedLocked does not need to do anything. Otherwise, the ession class member function windowAddedLocked creates a SurfaceSession object, and stored in its member variable mSurfaceSession.
The SurfaceSession class has a member variable mClient of the int type, which stores the address of a SurfaceComposerClient object on the C ++ layer, that is, the SurfaceSession object of each Java layer has a corresponding SurfaceComposerClient object in the C ++ layer. When a SurfaceSession object is created, the SurfaceComposerClient object associated with it is also created. The SurfaceComposerClient class describes a connection between an Android application process and a SurfaceFlinger service, that is, each Android application process related to the UI has a SurfaceComposerClient object.
Readers may wonder why the WindowManagerService creates a SurfaceComposerClient object internally, since SurfaceComposerClient is used to describe the connection between the Android Application Process and SurfaceFlinger service? Because WindowManagerService needs to request the SurfaceFlinger service to set the properties of the Android application window, such as setting the location and size of the application window, it creates a SurfaceComposerClient object for each Android application process to connect to the SurfaceFlinger service so that it can communicate with the SurfaceFlinger service.
From the above description, we can know that in the WindowManagerService, each Android application process corresponds to a SurfaceComposerClient object. Because each SurfaceComposerClient object is associated with a SurfaceSession object, we can infer that each Android application process corresponds to a SurfaceSession object in the WindowManagerService. Because the Session object of each SurfaceSession object is a local Binder object, and its Binder proxy object is saved in the sWindowSession static member variable of the ViewRoot class on the side of the Android application process, therefore, we can infer that every Android application process has a corresponding Session object in the WindowManagerService. In summary, each Android application process corresponds to a Session object, a SurfaceSession object, and a SurfaceComposerClient object on the WindowManagerService side. Since each Android application process can run several Activity components, we can say that, the relationship between the Activity component and the Session object, SurfaceSession object, and SurfaceComposerClient object of the WindowServiceManager service is one-to-one.
After introducing the member variable mSession of the WindowState class, we will introduce another member variable mSurface, whose type is Surface, we have already introduced the role of the Surface class on the Android Application Process side. Next we will introduce its role on the WindowManagerService side.
As mentioned above, the WindowManagerService creates a SurfaceLayer object for each application window, namely, each Activity component, and encapsulates the SurfaceLayer object into a Surface object on the Java layer. In the Surface class of the Java layer, mSurfaceControl, a member variable of the int type, stores the address value of a SurfaceControl object on the C ++ layer, that is, on the WindowManagerService side, each Java Layer Surface object has a corresponding SurfaceControl object on the C ++ layer. Here we emphasize that it is on the WindowManagerService side because, as mentioned above, on the Android Application side, the Surface object of the Java layer corresponding to each Activity component does not have a corresponding SurfaceControl object on the C ++ layer, but only corresponds to a Surface object on the C ++ layer. The SurfaceControl object of the C ++ layer can be used to set the properties of the application window, while the graphic buffer of the application window can be set through the Surface object of the C ++ layer, that is, to set the texture of the application window, we can know that the properties of the application window are set by the WindowManagerService, the texture of the application window is set by the process in which it is located.
So far, we have briefly introduced the implementation framework of the Android application window. The classes and their interactions described above may be vague and difficult to understand. It doesn't matter. Next we will use a series of articles to figure out their ins and outs:
1. the creation process of the running context in the Android application window, that is, the creation process of ContextImpl;
2. the creation process of the Android application window, that is, the PhoneWindow creation process;
3. the creation process of the view in the Android application window, that is, the creation process of the DecorView;
4. connection process between the Android application window and the WindowManagerService service, that is, the WindowState creation process;
5. connection process between the Android Application Window and SurfaceFlinger service, that is, the Surface creation process;
6. The rendering process of the Android application window, that is, the rendering process of the Surface; www.2cto.com
After learning these articles, we can understand the implementation framework of the Android application window. After mastering the implementation framework of the Android application window, we can further learn the rendering process of the Android application window. Stay tuned!