Android 12 source code analysis - application layer four (basic layout design and basic concepts of SystemUI)

Android 12 source code analysis - application layer four (basic layout design and basic concepts of SystemUI)

In the last two articles, we introduced the startup process of SystemUI and the basic component dependencies. Readers must master the basic dependencies, because in the following articles, the use of these dependencies will often appear, and they will be briefly mentioned without explaining their implementation details and principles in detail.

Next, we will introduce how each UI part in SystemUI is added to the screen, and see the implementation of each icon in the drop-down state.

But before entering the real topic, we also need to understand the basic layout and names of each UI in SystemUI. Only by understanding these basic layouts and names can we distinguish the specific object among many similar names.

Next, we will introduce the basic layout design of SystemUI to see what content the entire SystemUI layout is roughly divided into, and what businesses these contents correspond to.

SystemUI window division

In the article "Android 12 Source Code Analysis - Application Layer 2 (General Organization and Startup Process of SystemUI) http://t.csdn.cn/chk6Y ", we mentioned that SystemUI can display its own UI through WindowManager.

In fact, SystemUI adds its main UI view through WindowManager. In SystemUI, place the following parts in different Windows, and then add them to the screen through WindowManager.

  1. StatusBar——Status bar
  2. NotificationShade——notification shutter (the drop-down status bar we often say)
  3. NavigationBar——Navigation bar

Note: In addition to the three common windows above, there are other windows, such as GlobalActionDialog (responsible for displaying the pop-up box of shutdown and restart) and VolumeDialog (displaying volume adjustment). These windows will be introduced in each sub-topic. time, appear one after another

Some readers may be wondering: What about the lock screen? Not under a separate window? In fact, the lock screen is not in a separate window, it is NotificationShade itself (notification roller shutter, that is, pull down the status bar). In other words, the content of the lock screen and the content of the pull-down status bar are in the same window.

One thing that must be noted here is: the corresponding Chinese naming method, from now on, will use parentheses to mark the Chinese name after the corresponding class. The reason for such marking is because the English names have many similarities, maybe It is not conducive to memory. For example: Although StatusBar is called the status bar, there are different StatusBars (status bars) in different Windows. For example, there is KeyguardViewStatusBar (lock screen status bar) in the lock screen state; similarly, in the NotificationShade (notification The place in the rolling shutter (that is, the drop-down status bar) where the StatusBar (status bar) should be displayed is not called the StatusBar. To make it easier to remember, put its Chinese name in parentheses.

For ease of understanding, window is now marked as follows:
Insert image description here

Insert image description here

Insert image description here
Insert image description here

With the above intuitive feeling, we will combine the layout file of SystemUI to generally introduce its UI layout and related concepts. With these concepts, we can find the corresponding implementation entities in the complicated source code.

SystemUI naming rules and design patterns

The topic of this article is an introduction to the layout of SystemUI, but there may still be questions: When are these layouts loaded? What is their loading process like?

In subsequent articles, we will introduce the loading of these layouts and how to handle various events, but before that, we need to understand the design patterns and naming rules between them.

Each small module of SystemUI adopts design patterns such as MVC and MVP, so in their naming system, they are often represented by xxxView, xxxController, and xxxPresenter. For example, StatusBarWindowView (status bar window view) and StatusBarWindowController (status bar window controller) represent StatusBar (status bar), and the model related to StatusBarWindow is StatusBar (status bar)

Of course, SystemUI has a long editing history with several major modifications. Not all classes follow these rules, but readers can think along these lines when reading the source code.

This article focuses on introducing the SystemUI layout and does not care about the loading time and process of these layouts. However, we will use a small tip to briefly summarize the loading process of these layouts. When reading these brief loading processes, many similar names will appear, so you can correspond to the corresponding entities according to the above naming rules.

Readers can ignore these loading processes, because in subsequent articles, the loading processes and user operations of these UIs will be introduced in detail.

Let’s start with the most complicated NotificationShade (notification roller shutter, drop-down status bar).

Detailed layout of SystemUI's NotificationShade (notification roller shutter, that is, drop-down status bar) window

NotificationShade (notification roller shutter, pull-down status bar) window loading process

According to the above description, we will first briefly introduce the loading process of this layout, as follows:

  1. After SytemUIService is started, call SystemUIApplication's startServicesIfNeeded() to start the corresponding service ("Android 12 source code analysis - Application layer two (SystemUI general organization and startup process) http://t.csdn.cn/chk6Y " )
  2. Among the started services, there is one called StatusBar, which will be called the start() method in the first step
  3. In the start() method, the createAndAddWindows() method is called
  4. The createAndAddWindows() method calls the makeStatusBarView() method
  5. The makeStatusBarView() method calls the inflateStatusBarWindow() method
  6. The inflateStatusBarWindow() method will call the getNotificationShadeWindowView() method of SuperStatusBarViewFactory
  7. The getNotificationShadeWindowView() method will load and parse R.layout.super_notification_shade, which is super_notification_shade.xml
  8. After step 7 is completed, you will return to step 4 and call the attach() method of NotificationShadeWindowController to add the corresponding UI to the screen.

Note: Readers don’t need to worry about the above calling process at all, because the following articles will introduce it in detail.

Next, analyze, super_notification_shade.xml

NotificationShade (notification shutter, that is, the pull-down status bar) window's top-level view

The source file of super_notification_shade.xml is as follows:

Note: In order to reduce reading difficulties, I will omit some very common code, such as the definition and assignment of some properties, and some very simple layout views.

<com.android.systemui.statusbar.phone.NotificationShadeWindowView>

    <com.android.systemui.statusbar.BackDropView>
        
    </com.android.systemui.statusbar.BackDropView>

    <com.android.systemui.scrim.ScrimView
        android:id="@+id/scrim_behind" />

    <com.android.systemui.scrim.ScrimView
        android:id="@+id/scrim_notifications"/>

    <com.android.systemui.statusbar.LightRevealScrim
            android:id="@+id/light_reveal_scrim" />

    <include layout="@layout/status_bar_expanded"/>

    <include layout="@layout/brightness_mirror_container" />

    <com.android.systemui.scrim.ScrimView
        android:id="@+id/scrim_in_front" />

    <!-- Keyguard messages -->
    <FrameLayout>
        <com.android.keyguard.KeyguardMessageArea
            android:id="@+id/keyguard_message_area"/>
    </FrameLayout>

    <com.android.systemui.biometrics.AuthRippleView/>
</com.android.systemui.statusbar.phone.NotificationShadeWindowView>

From the above code structure, it is very simple, we will introduce it as follows:

  1. NotificationShadeWindowView: notification shutter window, which is the topmost view of the pull-down status bar window

  2. BackDropView: Curtain view, it will display some backgrounds at the bottom, such as when playing music, display the album picture of the music

  3. ScrimView: There are three in total. They are mainly responsible for masking. For example, in the lock screen state, the entire lock screen interface becomes slightly darker, which is achieved by setting the transparency of the mask.

  4. LightRevealScrim: It is also a mask-related view. It is responsible for processing some gradient animations. For example, if you turn on the screen display in the settings, then when you click the power button, the corresponding animation will be displayed, as shown below. Insert picture description
    here

  5. status_bar_expanded.xml: That is, the layout in the expanded state, which lists in detail what content should be displayed after the status bar is pulled down

  6. brightness_mirror_container.xml: This is the mirror view corresponding to the brightness adjustment bar, because there is also a brightness adjustment bar in status_bar_expanded. The reason for this is to hide the content in status_bar_expanded when adjusting the brightness.

  7. KeyguardMessageArea: Lock screen information display area, if the input pin is wrong, the wrong pin will be displayed here

Except for the seventh point, which can directly give reference pictures, the others cannot give particularly good reference pictures, so you can use the layout viewing tool recommended at the end of the article to view it.

There are two include xml files in the above. If each file is introduced, it will consume a lot of space, and at the same time, some details are not appropriate. Therefore, some simple layout files will be briefly mentioned, such as the above brightness_mirror_container.xml file. These skipped files will be introduced in detail under certain sub-topics. For example, the brightness_mirror_container.xml above will be introduced in detail in the article about adjusting the volume.

So the status_bar_expanded.xml file will be introduced next

status_bar_expanded.xml file analysis

The original text of the status_bar_expanded.xml file is as follows:

Note: Some attribute definitions and assignments will still be omitted here.

<com.android.systemui.statusbar.phone.NotificationPanelView
    android:id="@+id/notification_panel">
    <FrameLayout
        android:id="@+id/big_clock_container" />

    <ViewStub
        android:id="@+id/keyguard_qs_user_switch_stub"/>

    <include
        layout="@layout/keyguard_bottom_area"
        android:visibility="gone" />

    <ViewStub
        android:id="@+id/keyguard_user_switcher_stub" />

    <include layout="@layout/status_bar_expanded_plugin_frame"/>

    <include layout="@layout/dock_info_bottom_area_overlay" />

    <com.android.keyguard.LockIconView
        android:id="@+id/lock_icon_view">
    </com.android.keyguard.LockIconView>

    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
        android:id="@+id/notification_container_parent">

        <include layout="@layout/keyguard_status_view"/>

        <include layout="@layout/dock_info_overlay" />

        <FrameLayout android:id="@+id/qs_frame"/>

        <androidx.constraintlayout.widget.Guideline 
            android:id="@+id/qs_edge_guideline"/>

        <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
            android:id="@+id/notification_stack_scroller"/>

        <include layout="@layout/ambient_indication"
            android:id="@+id/ambient_indication_container" />

        <include layout="@layout/photo_preview_overlay" />

        <include
            layout="@layout/keyguard_status_bar"
            android:visibility="invisible" />

        <Button
            android:id="@+id/report_rejected_touch"/>
        <com.android.systemui.statusbar.phone.TapAgainView
            android:id="@+id/shade_falsing_tap_again"/>
    </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>

    <FrameLayout
        android:id="@+id/preview_container">
    </FrameLayout>
</com.android.systemui.statusbar.phone.NotificationPanelView>

An introduction to the above files is as follows:

  1. NotificationPanelView: Top-level directory of the entire notification bar and quick settings icons
  2. FrameLayout with id big_clock_container: displays a larger clock view
  3. Two ViewStubs: This is related to the switching view of multiple users. When multiple users are clicked, the switched view will be displayed in one of the two ViewStubs.
  4. keyguard_bottom_area.xml: Display the bottom area of ​​the lock screen, such as charging...
  5. status_bar_expanded_plugin_frame.xml: It is related to the SystemUI plug-in. Readers can ignore it now. The details will be introduced in detail later.
  6. dock_info_bottom_area_overlay.xml:Empty
  7. LockIconView: The lock icon under the lock screen interface
  8. NotificationsQuickSettingsContainer: Container for notifications and quick settings, where notifications and quick settings are displayed
  • keyguard_status_view.xml: Display status views related to the lock screen, such as displaying the date
  • dock_info_overlay.xml: empty
  • FrameLayout with id qs_frame: parent container for quick settings
  • Guideline: View used to adjust layout
  • NotificationStackScrollLayout: the parent container used to display notifications
  • ambient_indication.xml: empty
  • photo_preview_overlay.xml: empty
  • keyguard_status_bar.xml: status bar in lock screen state
  • Button: Use for debugging, don’t worry about it
  • TapAgainView: Displays the view of pressing again. It is no longer used.
  1. FrameLayout with id preview_container: preview image display view, such as sliding a camera image, a camera image will be displayed first

Note: The description of some of the above xml files is: empty. On the one hand, some of the content is no longer used. On the other hand, some of the content will appear in subsequent articles.

In the above xml file, careful readers may have noticed that the lock screen is also in the NotificationShade window. In order to be able to observe the above content intuitively, we use pictures to illustrate, as shown in the following figure:
Insert image description here

In the above source code, there is

  1. keyguard_bottom_area.xml
  2. status_bar_expanded_plugin_frame.xml
  3. dock_info_bottom_area_overlay.xml
  4. keyguard_status_view.xml
  5. dock_info_overlay.xml
  6. ambient_indication.xml
  7. photo_preview_overlay.xml
  8. keyguard_status_bar.xml
    is in the above file. Some of status_bar_expanded_plugin_frame.xml, dock_info_bottom_area_overlay.xml, dock_info_overlay.xml, ambient_indication.xml, and photo_preview_overlay.xml are not used. Some of them will be introduced in subsequent subtopics. Skipping them now does not affect reading. and understand

The remaining three files keyguard_bottom_area.xml, keyguard_status_view.xml and keyguard_status_bar.xml are simple and clear, and can easily correspond to the UI, so they are not introduced here. This does not affect the reading and understanding of this article. But don’t worry, in subsequent articles, we will also introduce these three files to see their interaction and initialization process. For the sake of compactness, we will omit them here.

Although we have been able to establish a connection between the UI and code related to the lock screen, we cannot yet establish a connection between the UI and code in the drop-down settings. Next, we deal with this part.

Layout analysis of QuickSettings

In the above code, it has been introduced that the FrameLayout with the id of qs_frame will be used to display the quick settings. Next, let’s take a look at how they are laid out.

Note: The layout details of NotificationStackScrollLayout will be explained in detail later.

QuickSettings loading process

As we know above, FrameLayout with id qs_frame does not use include to load a layout, because we need to briefly explain its loading process first, and then look at its layout structure

  1. After SytemUIService is started, call SystemUIApplication's startServicesIfNeeded() to start the corresponding service ("Android 12 source code analysis - Application layer two (SystemUI general organization and startup process) http://t.csdn.cn/chk6Y " )
  2. Among the started services, there is one called StatusBar, which will be called the start() method in the first step
  3. In the start() method, the createAndAddWindows() method is called
  4. The createAndAddWindows() method calls the makeStatusBarView() method
  5. The makeStatusBarView() method will find the FrameLayout with the id qs_frame and add a QSFragment to it
  6. QSFragment will load the qs_panel.xml file, and this file is our quick setup layout file.

qs_panel.xml file analysis

The original text of qs_panel.xml is as follows:

<com.android.systemui.qs.QSContainerImpl
    android:id="@+id/quick_settings_container" >

    <com.android.systemui.qs.NonInterceptingScrollView
        android:id="@+id/expanded_qs_scroll_view">
        <com.android.systemui.qs.QSPanel
            android:id="@+id/quick_settings_panel">
            <include layout="@layout/qs_footer_impl" />
        </com.android.systemui.qs.QSPanel>
    </com.android.systemui.qs.NonInterceptingScrollView>

    <include layout="@layout/quick_status_bar_expanded_header" />

    <include android:id="@+id/qs_detail" layout="@layout/qs_detail" />

    <include android:id="@+id/qs_customize" layout="@layout/qs_customize_panel"
        android:visibility="gone" />

</com.android.systemui.qs.QSContainerImpl>
  1. QSContainerImpl: parent container for quick settings
  2. NonInterceptingScrollView: ScrollView of each icon in quick settings
  • QSPanel: QSPanel displays the specific details inside
  • qs_footer_impl.xml: Quickly set the display view at the bottom, such as editing the quick settings icon, see the corresponding relationship in the following pictures
  1. quick_status_bar_expanded_header.xml: The header area in the quick settings, see the image settings below
  2. qs_detail.xml: Quick setup details
  3. qs_customize.xml: Edit quick settings interface

In order to facilitate the correspondence, see the picture below

Insert image description here

Insert image description here
Insert image description here

In the picture above, we can see that inside QSPanel, there will be a variety of small icons for quick settings, and these icons are called QSTile.

We will explain their loading process in detail in the source code analysis of QSPanel. This article aims to introduce the layout design of SystemUI, rather than the specific details of a certain UI.

After introducing the layout of qs_frame, we also need to check the last layout under the window, NotificationStackScrollLayout.

NotificationStackScrollLayout layout analysis

NotificationStackScrollLayout is a class that does not use include to reference other layout files, but internally adds layout in other ways.

The process of loading notification layout by NotificationStackScrollLayout

  1. When a notification arrives from the system, call the onNotificationPosted() method of NotificationListener
  2. In the onNotificationPosted method, the onNotificationPosted() method of mNotifiListener of NotificationEntryManager will be notified
  3. In this method, the addNotification() method is called, and then the addNotificationInternal() method is called in addNotification()
  4. In the addNotificationInternal() method, the inflateViews() method of NotificationRowBinderImpl will be called
  5. In this method, the inflate() method of RowInFlaterTask will be called.
  6. In the inflate() method, the status_bar_notification_row.xml file will be loaded.

Next, let's look at the content of this file

status_bar_notification_row.xml file analysis

The original text of the status_bar_notification_row.xml file is as follows:

<com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
    android:id="@+id/expandableNotificationRow">
 <!--只有一个ExpandableNotificationRow-->
</com.android.systemui.statusbar.notification.row.ExpandableNotificationRow>

There is only one piece of content. Of course, we don’t need to relate to its internal content now. ExpandableNotificationRow is the smallest layout we observe, because it already involves how to display specific content. Now we only need to understand the general layout and understand the relevant the concept of

  1. ExpandableNotificationRow: an expandable notification

Insert image description here

Note: We will introduce the sorting, priority, etc. of notifications one by one in subsequent articles. Here you only need to understand the overall layout and basic concepts.

At this point, the introduction to the layout of the NotificationShade window has basically been completed. Here we are familiar with the entities of each UI. Of course, some UI entities have been omitted. The omitted
parts will be introduced in detail in the sub-topics of the following articles.

Next, we continue to look at the remaining two windows-StatusBar and NavigationBar

Detailed layout of StatusBar Window

Loading process of StatusBar window

First, let’s briefly introduce its loading process.

  1. After SytemUIService is started, call SystemUIApplication's startServicesIfNeeded() to start the corresponding service ("Android 12 source code analysis - Application layer two (SystemUI general organization and startup process) http://t.csdn.cn/chk6Y " )
  2. Among the started services, there is one called StatusBar, which will be called the start() method in the first step
  3. In the start() method, the createAndAddWindows() method is called
  4. The createAndAddWindows() method calls the makeStatusBarView() method
  5. In the makeStatusBarView() method, the inflateStatusBarWindow() method will be called
  6. In the inflateStatusBarWindow() method, StatusBarWindowController will be obtained through the getStatusBarWindowController() method of StatusBarComponent.
  7. In the constructor of StatusBarWindowController, the getStatusBarWindow() method of SuperStatusBarViewFactory will be called.
  8. The getStatusBarWindow() method of SuperStatusBarViewFactory will load the super_status_bar.xml file
  9. In the createAndAddWindows() method in step 4, the attach() method of StatusBarWindowController will be called to add it to the screen.

Next, take a look at the layout file of StatusBar (status bar)

StatusBar (status bar) top view of Window

The source file of super_status_bar.xml is as follows:

<com.android.systemui.statusbar.phone.StatusBarWindowView>
    <FrameLayout
        android:id="@+id/status_bar_launch_animation_container"/>
    <FrameLayout
        android:id="@+id/status_bar_container" />
</com.android.systemui.statusbar.phone.StatusBarWindowView>

Very, very refreshing! !

  1. StatusBarWindow: Represents the topmost view of the status bar
  2. FrameLayout with id status_bar_launch_animation_container: Display animation in it, for example: animation display area when starting an Activity from StatusBar (status bar)
  3. FrameLayout with id status_bar_contianer: This is the main area of ​​the actual status bar content

Next we look at the details

Layout analysis of StatusBar (status bar)

The above id is status_bar_contianer is a FrameLayout, let's see how it loads the layout. First, let’s briefly introduce its layout loading process.

StatusBar (status bar) layout loading process

  1. After SytemUIService is started, call SystemUIApplication's startServicesIfNeeded() to start the corresponding service ("Android 12 source code analysis - Application layer two (SystemUI general organization and startup process) http://t.csdn.cn/chk6Y " )
  2. Among the started services, there is one called StatusBar, which will be called the start() method in the first step
  3. In the start() method, the createAndAddWindows() method is called
  4. The createAndAddWindows() method calls the makeStatusBarView() method
  5. The makeStatusBarView() method will put the CollapsedStatusBarFragment into the FrameLayout with the ID status_bar_container
  6. The CollapsedStatusBarFragment will load and initialize the status_bar.xml file during its onCreateView.

status_bar.xml file analysis

The original text of the status_bar.xml file is as follows:

<com.android.systemui.statusbar.phone.PhoneStatusBarView
    android:id="@+id/status_bar">

    <ImageView
        android:id="@+id/notification_lights_out"/>

    <LinearLayout android:id="@+id/status_bar_contents">
        <FrameLayout>
            <include layout="@layout/heads_up_status_bar_layout" />

            <LinearLayout
                android:id="@+id/status_bar_left_side">
                <ViewStub
                    android:id="@+id/operator_name"/>

                <com.android.systemui.statusbar.policy.Clock
                    android:id="@+id/clock"/>

                <include layout="@layout/ongoing_call_chip" />

                <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
                    android:id="@+id/notification_icon_area"/>

            </LinearLayout>
        </FrameLayout>

        <!-- Space should cover the notch (if it exists) and let other views lay out around it -->
        <android.widget.Space
            android:id="@+id/cutout_space_view" />

        <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
            android:id="@+id/centered_icon_area"/>

        <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area">

            <include layout="@layout/system_icons" />
        </com.android.keyguard.AlphaOptimizedLinearLayout>
    </LinearLayout>

    <ViewStub
        android:id="@+id/emergency_cryptkeeper_text"/>

</com.android.systemui.statusbar.phone.PhoneStatusBarView>
  1. PhoneStatusBarView: parent container of status bar content
  2. This view is responsible for displaying a small dot when the status bar is requested to be displayed in SYSTEM_UI_FLAG_LOW_PROFILE mode
  3. LinearLayout with id status_bar_content: displays status bar content
  • heads_up_status_bar_layout.xml: Part of the prompt information in StatusBar
  • LinearLayout with id status_bar_left_side: the display area on the left side of the status bar
  • Space: fill the empty space in the middle
  • AlphaOptimizedFrameLayout: Center icon display area
  • AlphaOptimizedLinearLayout: System icon display area, such as battery percentage
  1. ViewStub with id emergency_cryptkeeper_text: Displays that only emergency calls can be made

As you can see from the layout file above, the StatusBar (status bar) is roughly divided into three areas, left, middle, and right. Now you only need to understand the general layout, that is, you can know the View in the source code when reading the source code. It doesn’t matter which part of the area you are referring to. In later articles, we will detail the content and implementation details of these layouts.

So far, we understand the layout of the two most important Window in SystemUI. The last Window left is NavigationBar. Because of its simple layout, we will introduce it when analyzing Android navigation gestures.

In this article, you only need to master the following concepts, because they will be mentioned repeatedly in the following series of articles:

  1. Division of SystemUI Window
  2. The names of each UI of SystemUI are such as NotificationShadeView, QS, etc.
  3. Know the name of the corresponding View's Controller, and what it will probably look like. For example, the Controller of NotificationShadeWindowView should be called NotificationShadeWindowViewController, and vice versa.

Because I have been in poor health recently, and school has started, my studies are heavy, and my writing is in a hurry. It is inevitable that there will be some mistakes. Readers who have forgotten to see them will remind me. Thank you in advance.

Supplement: Layout viewing tool

Readers can use the following tools to view the corresponding layout.

  1. Old version of DDMS, hierarchy view
  2. YALI for Android Studio (installed through the plugin market)
  3. Legacy Layout Inspector for Android Studio (installed through the plugin market)

As for the Layout Inspector that comes with Android Studio, it is not recommended to use it.

Guess you like

Origin blog.csdn.net/xiaowanbiao123/article/details/132654468