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.
- KeyguardViewMediator is a typical application of mediator mode, which integrates all aspects of information to control the lock screen.
- 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
- It’s a singleton.
- It receives the registration callback.
- It takes advantage of KeyguardUpdateMonitor to only listen for the onTrustedChanged() callback, and calls various registered callbacks when an event occurs.
- It exposes public methods through which to set the lock screen state and then through registered callbacks.
- 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
- The security lock view is loaded into the SystemUI root view with KeyguardBouncer#needsFullScreenBouncer().
- Determine sliding lock, security lock show or hide.
- 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