While the previous articles gave an overview of SystemUI’s two modules, StatusBar and QuickSetting, this article begins by examining the Keyguard module.

For lock screen, need to have a basic understanding, it is divided into two categories, one is sliding lock screen, one is security lock screen. Sliding lock screen refers to a lock screen that can be unlocked by sliding your finger. Security lock screen refers to a combination lock, pattern lock, PIN code lock, etc. The two lock screens were created in different places and cannot be generalized, but this article will only analyze the sliding lock screen.

Slide lock screen view

The entire SystemUI view is created by super_status_bar.xml

<! -- Root FrameLayout-->
<com.android.systemui.statusbar.phone.StatusBarWindowView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:sysui="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <com.android.systemui.statusbar.BackDropView
            android:id="@+id/backdrop">
        <ImageView android:id="@+id/backdrop_back" />
        <ImageView android:id="@+id/backdrop_front"/>
    </com.android.systemui.statusbar.BackDropView>

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

    <! -- Status bar container -->
    <FrameLayout
        android:id="@+id/status_bar_container" />

    <! -- The entire drop-down notification screen, including the sliding lock screen -->
    <include layout="@layout/status_bar_expanded" />

    <! -- Here brightness adjustment bar-->
    <include layout="@layout/brightness_mirror" />

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

    <! -- In the lock screen, display under the status bar, display above the time -->
    <LinearLayout
        android:id="@+id/lock_icon_container">
        <com.android.systemui.statusbar.phone.LockIcon
            android:id="@+id/lock_icon" />
        <com.android.keyguard.KeyguardMessageArea
            android:id="@+id/keyguard_message_area" />
    </LinearLayout>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
Copy the code

In this layout, the lock_icon_container layout displays the lock icon and some information on the lock screen. This layout includes a status_bar_expanded. XML layout. This is the entire drop-down notification surface, including various controls for sliding the lock screen

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

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

    <! Sliding lock screen status view: Time, date -->
    <include
        layout="@layout/keyguard_status_view"
        android:visibility="gone" />

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

        <include layout="@layout/dock_info_overlay" />
        
        <! - QS interface - >
        <FrameLayout
            android:id="@+id/qs_frame"
            android:layout="@layout/qs_panel" />
            
        <! -- Container to display notifications -->
        <com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
            android:id="@+id/notification_stack_scroller"/>

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

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

        <! -- Slide lock screen status bar -->
        <include
            layout="@layout/keyguard_status_bar"
            android:visibility="invisible" />

        <Button
            android:id="@+id/report_rejected_touch" />

    </com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer>

    <! Lock the bottom of the screen icon, fill the entire parent layout, such as the icon in the bottom left corner, the icon in the bottom right corner Camera-->
    <include
        layout="@layout/keyguard_bottom_area"
        android:visibility="gone" />

    <com.android.systemui.statusbar.AlphaOptimizedView
        android:id="@+id/qs_navbar_scrim"/>

</com.android.systemui.statusbar.phone.NotificationPanelView>
Copy the code

As you can see, the parts of the sliding lock screen are scattered and not created centrally in the same container.

Slide lock screen display

Generally, we lock the screen through the switch of the power button. This article analyzes the process from the boot to the sliding lock screen display.

During startup, after ActivityManagerService is started, SystemUI is created

    // frameworks/base/services/java/com/android/server/SystemServer.java
    
    private static void startSystemUi(Context context, WindowManagerService windowManager) {
        Intent intent = new Intent();
        // 1. Start SystemUIService
        intent.setComponent(new ComponentName("com.android.systemui"."com.android.systemui.SystemUIService"));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        
        // 2. Notify WMS that SystemUI has started
        windowManager.onSystemUiStarted();
    }
Copy the code

Previous articles have examined SystemUI startup, which creates a view of the entire SystemUI, including a view of the sliding lock screen. Now what does Windows ManagerService do after SystemUI starts

    // frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
    
    public void onSystemUiStarted(a) {
        mPolicy.onSystemUiStarted();
    }
Copy the code

The WindowManager notifies the PhoneWindowManager that SystemUI has started

    // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    
    public void onSystemUiStarted(a) {
    	/ / bind KeyguardService
        bindKeyguard();
    }
    
    private void bindKeyguard(a) {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
		// Binding KeyguardService is handed over to the agent class KeyguardServiceDelegate
        mKeyguardDelegate.bindService(mContext);
    }    
Copy the code

The policy class PhoneWindowManager binds KeyguardService through a proxy class KeyguardServiceDelegate.

KeyguardService is a standard Service that returns an IBinder object, or server interface, when bound to it. We will refer to KeyguardService as the lock screen server.

    // frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
    
    public void bindService(Context context) {
        Intent intent = new Intent();
        final Resources resources = context.getApplicationContext().getResources();
        // KeyguardService
        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                resources.getString(com.android.internal.R.string.config_keyguardComponent));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);
   
        if(! context.bindServiceAsUser(intent, mKeyguardConnection, Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {// ...}}Copy the code

This is a standard binding Service flow, and the mKeyguardConnection parameter passed during the binding can be used to see what happens after the successful binding

    // frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
    
    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {

            mKeyguardService = new KeyguardServiceWrapper(mContext,
                    IKeyguardService.Stub.asInterface(service), mCallback);

            if (mKeyguardState.systemIsReady) {
            
                mKeyguardService.onSystemReady();
                
                if(mKeyguardState.currentUser ! = UserHandle.USER_NULL) { mKeyguardService.setCurrentUser(mKeyguardState.currentUser); }if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
                        || mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
                    mKeyguardService.onStartedWakingUp();
                }
                
                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
                    mKeyguardService.onFinishedWakingUp();
                }
                
                if (mKeyguardState.screenState == SCREEN_STATE_ON
                        || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
                    mKeyguardService.onScreenTurningOn(
                            new KeyguardShowDelegate(mDrawnListenerWhenConnect));
                }
                
                if (mKeyguardState.screenState == SCREEN_STATE_ON) {
                    mKeyguardService.onScreenTurnedOn();
                }
                
                mDrawnListenerWhenConnect = null;
            }

            if (mKeyguardState.bootCompleted) {
                mKeyguardService.onBootCompleted();
            }
            
            if (mKeyguardState.occluded) {
                mKeyguardService.setOccluded(mKeyguardState.occluded, false /* animate */);
            }

            if(! mKeyguardState.enabled) { mKeyguardService.setKeyguardEnabled(mKeyguardState.enabled); }}}Copy the code

Query various states and then send commands to the screen lock server in sequence. I’ll just look at the onSystemReady() implementation on the server side

The agent KeyguardServiceDelegate controls the behavior of KeyguardService by storing the screen-lock status through the KeyguardState object.

    // frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
    
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
        public void onSystemReady(a) {
            / / the SYSTEM user or with android. The Manifest. Permission. CONTROL_KEYGUARD permissionscheckPermission(); mKeyguardViewMediator.onSystemReady(); }}Copy the code

The KeyguardViewMediator sends a SYSTEM_READY event to the Handler, which eventually calls handleSystemReady.

  1. KeyguardViewMediator is a typical application of mediator mode, which integrates all aspects of information to control the lock screen.
  2. KeyguardViewMediator has a Handler associated with the main Looper process, through which events and processes are handled, thus ensuring that events are handled in an orderly manner without causing interface refresh chaos.
    // frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
    
    private void handleSystemReady(a) {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            
            // Enable screen lock. The parameter is null
            doKeyguardLocked(null);

            // KeyguardUpdateMonitor gets screen-lockrelated updates by listening to database URIs, registering broadcast receivers, and registering listeners with various services
            // KeyguardViewMediator is concerned with the following callback
            // 1. onClockVisibilityChanged
            // 2. onDeviceProvisioned
            // 3. onSimStateChanged
            // 4. onBiometricAuthFailed, onBiometricAuthenticated
            // 5. onHasLockscreenWallpaperChanged
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
Copy the code

Dokeyguardmediator initiates the lock screen through doKeyguardLocked(), which is also handled by the main thread Handler, and finally calls handleShow().

    // frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
    
    private void handleShow(Bundle options) {

        // ...

        synchronized (KeyguardViewMediator.this) {
            if(! mSystemReady) {return;
            }
            // Notify listeners that the lock screen status has changed
            setShowingLocked(true, mAodShowing);
            // The lock screen is displayed
            mStatusBarKeyguardViewManager.show(options);
            mHiding = false;
            mWakeAndUnlocking = false;
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            // Adjust the status bar via StatusBarManager
            adjustStatusBarLocked();
            userActivity();
            // KeyguardUpdateMonitor saves the screen-lock status
            mUpdateMonitor.setKeyguardGoingAway(false /* away */);
            mShowKeyguardWakeLock.release();
        }
        // What does the update show
        mKeyguardDisplayManager.show();
    }
Copy the code

The lock screen broker KeyguardViewMediator finally locked display screen to StatusBarKeyguardViewManager this task.

Lock screen StatusBarKeyguardViewManager management to create, display, hide, reset.

    // frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
    
    public void show(Bundle options) {
        mShowing = true;
        // Update the screen lock status
        mStatusBarWindowController.setKeyguardShowing(true);

        // Notify various components concerned about the screen lock status that the screen lock status has changed
        mKeyguardMonitor.notifyKeyguardState(
                mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());

        // Reset the lock screen. If the parameter is true, the security lock interface is hidden when the sliding lock screen is displayed
        reset(true /* hideBouncerWhenShowing */);
    }

Copy the code

KeyguardMonitorImpl introduction

  1. It’s a singleton.
  2. It receives the registration callback.
  3. It takes advantage of KeyguardUpdateMonitor to only listen for the onTrustedChanged() callback, and calls various registered callbacks when an event occurs.
  4. It exposes public methods through which to set the lock screen state and then through registered callbacks.
  5. It allows other SystemUI components to get the latest screen-lock status.

Lock screen managers StatusBarKeyguardViewManager first notify outfits, lock screen state has changed, and then reset the lock screen interface

    // frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
    
    public void reset(boolean hideBouncerWhenShowing) {
        if (mShowing) {
            if(mOccluded && ! mDozing) {// ...
            } else {
                // If the parameter is true, the security lock interface is hidden and the sliding lock interface is displayed
                showBouncerOrKeyguard(hideBouncerWhenShowing);
            }
            / / call KeyguardUpdateMonitor# handleKeyguardReset ()
            // Update the fingerprint unlock and face unlock statusKeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); updateStates(); }}protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
        /** * Note: needsFullscreenBouncer() will load the security lock view and add it to the root view of SystemUI * but this method will only return true if the SIM PIN/PUK lock is displayed, indicating that full screen display is required */
        if(mBouncer.needsFullscreenBouncer() && ! mDozing) {// ...
        } else {
            // Displays a sliding lock screen
            mStatusBar.showKeyguard();
            // Hide the security lock
            if (hideBouncerWhenShowing) {
                hideBouncer(shouldDestroyViewOnReset() /* destroyView */); mBouncer.prepare(); }}// Update the status of all parties
        updateStates();
    }    
Copy the code

The reset() method is not an intuitive name. It does a number of things

  1. The security lock view is loaded into the SystemUI root view with KeyguardBouncer#needsFullScreenBouncer().
  2. Determine sliding lock, security lock show or hide.
  3. Notify parties that the lock screen status has changed.

The process of loading the security lock view is not analyzed. It is simple to load the layout and add it to the SystemUI root view.

Should be only concerned with sliding lock, from the code you can see, the lock screen managers StatusBarKeyguardViewManager shows that the task of sliding lock to the StatusBar.

StatusBar creates and manages the entire SystemUI view, so it makes sense that it will eventually display sliding locks.

StatusBar#showKeyguard() has a long call chain, so I won’t show the code here.

showKeyguard() -> updateIsKeyguard() -> showKeyguardImpl() -> updatePanelExpansionForKeyguard() -> instantExpandNotificationsPanel()

    // frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
    
    public void showKeyguard(a) {
        // Save the state
        mStatusBarStateController.setKeyguardRequested(true);
        mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
        mPendingRemoteInputView = null;
        
        / / update the slide lock screen, and ultimately calls the instantExpandNotificationsPanel ()
        updateIsKeyguard();
        
        mAssistManager.onLockscreenShown();
    }
    
    
    @Override
    public void instantExpandNotificationsPanel(a) {
        // Make our window larger and the panel expanded.
        // Make the notification panel visible
        makeExpandedVisible(true);
        // expand with false to indicate that no animation is required  
        mNotificationPanel.expand(false /* animate */);
        mCommandQueue.recomputeDisableFlags(mDisplayId, false /* animate */);
    }    
Copy the code

The mNotificationPanel is the parent container of the dropdown notification panel. At the beginning of this article, looking at the layout, you can see that most of the controls on the sliding lock screen are in the dropdown notification panel, so it is not surprising to see the action here.

    // frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
    
    @Override
    public void expand(boolean animate) {
        // The parent PanelView implements the expansion and eventually calls requestLayout() to rearrange the layout
        super.expand(animate);
        // Let various controls listen for things it is interested in, such as KeyguardStatusBarView listening for battery events
        setListening(true);
    }
Copy the code

This is all part of the Android control’s various operations, which won’t be expanded here, and eventually it will call requestLayout() to rearrange, so it will call onLayout() to update the layout

    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        
        // ...
        
        // Display Clock and Notification
        positionClockAndNotifications();

        // ...
        
        // There is an update to the lock screen with a large clock, as well as the icon area at the bottom
        updateExpandedHeight(getExpandedHeight());

        // Display time, date status view
        updateHeader();

        // ...
    }
Copy the code

You can see the various lock screen controls displayed.

The end of the

From the system start to display sliding lock screen, this process is not complicated, with this basis, you can analyze the display process of the security lock interface.

In addition, we should be interested in the power button to control the display and hide of the lock screen. In fact, this paper also gives the implementation, such as the process of lighting up the screen to display the lock screen

DisplayManagerService -> DisplayPowerController -> PhoneWindowManager#screenTurnedOff() -> KeyguardServiceDelegate# onScreenTurnedOff () – > KeyguardService# onScreenTurnedOff ().

VolumeUI, SystemUI, VolumeUI, VolumeUI, VolumeUI, VolumeUI, VolumeUI, VolumeUI