天天看點

AndroidQ SystemUI之鎖屏加載(上)滑動鎖屏

本篇來分析下Android鎖屏的加載流程,鎖屏加載比較複雜,涉及framework和SystemUI,這篇主要分析SystemUI部分,鎖屏有兩種,一種滑動鎖屏,另一種密碼鎖屏,也叫Bouncer。

前面AndroidQ SystemUI之啟動 中分析了SystemUI啟動過程中會加載一個config數組,裡面定義了SystemUI的重要的類,之後周遊此數組,以此調用其Start方法,我們就從StatusBar.start方法開始分析鎖屏相關的流程

StatusBar.start

public void start() {

createAndAddWindows(result);

}

public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {

makeStatusBarView(result);

mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);

mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());

}

1

2

3

4

5

6

7

8

9

10

makeStatusBarView方法裡面會初始化很多SystemUI的View

makeStatusBarView

protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {

...
    inflateStatusBarWindow(context);
    ...
           

}

1

2

3

4

5

6

inflateStatusBarWindow

protected void inflateStatusBarWindow(Context context) {

mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(

LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);

}

1

2

3

4

這個方法,加載了整個StatusBar的頂層自定義布局,類型為StatusBarWindowView,繼承FrameLayout,布局檔案是super_status_bar.xml,

<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:background="#698541"

android:fitsSystemWindows=“true”>

<com.android.systemui.statusbar.BackDropView
        android:id="@+id/backdrop"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        sysui:ignoreRightInset="true"
        >
    <ImageView android:id="@+id/backdrop_back"
               android:layout_width="match_parent"
               android:scaleType="centerCrop"
               android:layout_height="match_parent" />
    <ImageView android:id="@+id/backdrop_front"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:scaleType="centerCrop"
               android:visibility="invisible" />
</com.android.systemui.statusbar.BackDropView>

<com.android.systemui.statusbar.ScrimView
    android:id="@+id/scrim_behind"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:importantForAccessibility="no"
    sysui:ignoreRightInset="true"
    />

<FrameLayout
    android:id="@+id/status_bar_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<include layout="@layout/status_bar_expanded"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="invisible" />

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

<com.android.systemui.statusbar.ScrimView
    android:id="@+id/scrim_in_front"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:importantForAccessibility="no"
    sysui:ignoreRightInset="true"
/>

<LinearLayout
    android:id="@+id/lock_icon_container"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/status_bar_height"
    android:layout_gravity="top|center_horizontal">
    <com.android.systemui.statusbar.phone.LockIcon
        android:id="@+id/lock_icon"
        android:layout_width="@dimen/keyguard_lock_width"
        android:layout_height="@dimen/keyguard_lock_height"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="@dimen/keyguard_lock_padding"
        android:contentDescription="@string/accessibility_unlock_button"
        android:src="@*android:drawable/ic_lock"
        android:scaleType="center" />
    <com.android.keyguard.KeyguardMessageArea
        android:id="@+id/keyguard_message_area"
        style="@style/Keyguard.TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/keyguard_lock_padding"
        android:gravity="center"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:focusable="true" />
</LinearLayout>
           

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

接着我們看下StatusBarWindowView的onFinishInflate方法

onFinishInflate

@Override

protected void onFinishInflate() {

super.onFinishInflate();

mStackScrollLayout = findViewById(R.id.notification_stack_scroller);

mNotificationPanel = findViewById(R.id.notification_panel);

mBrightnessMirror = findViewById(R.id.brightness_mirror);

mLockIcon = findViewById(R.id.lock_icon);

}

1

2

3

4

5

6

7

8

這裡分别加載了id為notification_stack_scroller,notification_panel,brightness_mirror,lock_icon的View,

notification_stack_scroller是鎖屏上承載notification的View

notification_panel是滑動鎖屏

brightness_mirror是調節亮度條的View

lock_icon是鎖屏上的那個鎖一樣的View

再回到makeStatusBarView方法

protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {

...
	//此方法已經完成StatusBar頂層View,已經滑動鎖屏相關View的加載
    inflateStatusBarWindow(context);
    //擷取滑動鎖屏的View
    mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
    //擷取鎖屏上承載通知的View
    mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
    
    ...
           

}

1

2

3

4

5

6

7

8

9

10

11

12

makeStatusBarView方法中擷取到了滑動鎖屏的View,再回到createAndAddWindows

public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {

makeStatusBarView(result);

mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);

mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());

}

1

2

3

4

5

mStatusBarWindowController.add

下面代碼很明顯了,通過mWindowManager添加了一個視窗,這樣SystemUI的頂層自定義ViewGroup就被添加到了WMS,自然,滑動鎖屏作為mStatusBarWindow的子View也就被添加了

public void add(ViewGroup statusBarView, int barHeight) {

//建立LayoutParams,定義了一些視窗屬性
    mLp = new WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            barHeight,
            WindowManager.LayoutParams.TYPE_STATUS_BAR,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                    | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
            PixelFormat.TRANSLUCENT);
            //建立Token
    mLp.token = new Binder();
    //位置在最頂部
    mLp.gravity = Gravity.TOP;
    mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
    mLp.setTitle("StatusBar");
    mLp.packageName = mContext.getPackageName();
    mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
    mStatusBarView = statusBarView;
    mBarHeight = barHeight;
    //添加到WMS
    mWindowManager.addView(mStatusBarView, mLp);
    mLpChanged.copyFrom(mLp);
    onThemeChanged();
}
           

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

我們會發現密碼鎖屏并不是直接寫死在xml檔案中的,密碼鎖屏是通過動态加載的,我們接下來分析密碼鎖屏是如何建立以及添加到Keyguard布局中的

回到最開始的StatusBar的start方法中,在調用createAndAddWindows加載完SyatemUI相關View之後接着會調用startKeyguard方法開啟鎖屏流程

public void start() {
	...
	createAndAddWindows(result);
	...
	startKeyguard();
}
1
2
3
4
5
6
7
startKeyguard
protected void startKeyguard() {
        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
        ...
        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
                mStatusBarWindow.findViewById(R.id.lock_icon_container));
               
        ...
    }
1
2
3
4
5
6
7
8
9
首先擷取了一個鎖屏非常重要的類KeyguardViewMediator,這個類主要負責處理鎖屏相關事務,接着調用registerStatusBar方法,這裡傳了一個getBouncerContainer()的ViewGroup過去,這個ViewGroup就是StartBar中加載的SystemUI最頂層ViewGroup,布局為super_status_bar的StatusBarWindowView,後面建立的密碼鎖屏會動态添加到這裡面

keyguardViewMediator.registerStatusBar
 public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
            ViewGroup container, NotificationPanelView panelView,
            BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer) {
        mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
                biometricUnlockController, mDismissCallbackRegistry, lockIconContainer);
        return mStatusBarKeyguardViewManager;
    }
1
2
3
4
5
6
7
接着調用

StatusBarKeyguardViewManager.registerStatusBar
public void registerStatusBar(StatusBar statusBar,
            ViewGroup container,
            NotificationPanelView notificationPanelView,
            BiometricUnlockController biometricUnlockController,
            DismissCallbackRegistry dismissCallbackRegistry,
            ViewGroup lockIconContainer) {
        mStatusBar = statusBar;
        //StatusBar傳遞過來的SystemUI頂層ViewGroup
        mContainer = container;
        //鎖屏上承載lockIcon的ViewGroup
        mLockIconContainer = lockIconContainer;
        if (mLockIconContainer != null) {
            mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE;
        }
        //生物識别相關
        mBiometricUnlockController = biometricUnlockController;
        //建立密碼鎖屏Bouncer
        mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
                mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
                mExpansionCallback);
        mNotificationPanelView = notificationPanelView;
        //給滑動鎖屏界面設定監聽器
        notificationPanelView.setExpansionListener(this);
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
來看看Bouncer的建立

SystemUIFactory.createKeyguardBouncer
 public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
            LockPatternUtils lockPatternUtils,  ViewGroup container,
            DismissCallbackRegistry dismissCallbackRegistry,
            KeyguardBouncer.BouncerExpansionCallback expansionCallback) {
        return new KeyguardBouncer(context, callback, lockPatternUtils, container,
                dismissCallbackRegistry, FalsingManagerFactory.getInstance(context),
                expansionCallback, KeyguardUpdateMonitor.getInstance(context),
                new Handler(Looper.getMainLooper()));
    }
1
2
3
4
5
6
7
8
9
這裡直接new了一個Bouncer對象,我們跟進KeyguardBouncer這個類會發現它并沒有繼承View或者ViewGroup,說明它并不是真正的密碼鎖屏的View,KeyguardBouncer其實是用來管理密碼鎖屏的,從它提供的方法就能看出來,show,hide,inflateView等

public class KeyguardBouncer {
public KeyguardBouncer(Context context, ViewMediatorCallback callback,
            LockPatternUtils lockPatternUtils, ViewGroup container,
            DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager,
            BouncerExpansionCallback expansionCallback,
            KeyguardUpdateMonitor keyguardUpdateMonitor, Handler handler) {
        mContext = context;
        mCallback = callback;
        mLockPatternUtils = lockPatternUtils;
        mContainer = container;
        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
        mFalsingManager = falsingManager;
        mDismissCallbackRegistry = dismissCallbackRegistry;
        mExpansionCallback = expansionCallback;
        mHandler = handler;
        mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
    }
 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
到這裡我們發現從StatusBar.start->StatusBar.startKeyguard->KeyguardViewMediator.registerStatusBar->StatusBarKeyguardViewManager.registerStatusBar->SystemUIFactory.createKeyguardBouncer->new KeyguardBouncer
在KeyguardBouncer構造方法中也隻是做了些初始化,并沒有涉及到和密碼鎖屏的建立及添加相關的操作

其實不管是滑動鎖屏還是密碼鎖屏加載都是通過KeyguardViewMediator中的doKeyguardLocked方法,此方法非常重要,可以說是整個鎖屏的核心方法,任何形式的鎖屏,開機啟動鎖屏,點選power鍵鎖屏,SIM卡狀态變化鎖屏都會調用此方法,我們就從此方法為入口分析鎖屏加載流程

KeyguardViewMediator.doKeyguardLocked
private void doKeyguardLocked(Bundle options) {
       //省略一些不需要加載鎖屏的情況,如外部禁用,系統沒準備好等
       	....
        showLocked(options);
    }
1
2
3
4
5
private void showLocked(Bundle options) {
       
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);
    }
1
2
3
4
5
6
通過Handler發送消息

private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW:
                    handleShow((Bundle) msg.obj);
                    break;
1
2
3
4
5
6
7
調用handleShow方法

private void handleShow(Bundle options) {
		  ....
         mStatusBarKeyguardViewManager.show(options);
         ....
    }
1
2
3
4
5
StatusBarKeyguardViewManager.show
public void show(Bundle options) {
        mShowing = true;
        ....
        reset(true /* hideBouncerWhenShowing */);
    }
1
2
3
4
5
reset
public void reset(boolean hideBouncerWhenShowing) {
        if (mShowing) {
            //不需要顯示鎖屏的情況
            if (mOccluded && !mDozing) {
                ...
            } else {
                showBouncerOrKeyguard(hideBouncerWhenShowing);
            }
			...
        }
    }
1
2
3
4
5
6
7
8
9
10
11
接着調用showBouncerOrKeyguard方法,此方法中就是判斷顯示滑動鎖屏,還是顯示密碼鎖屏,參數hideBouncerWhenShowing代表是否隐藏Bouncer

showBouncerOrKeyguard
 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
        if (mBouncer.needsFullscreenBouncer() && !mDozing) {
            //隐藏滑動鎖屏
            mStatusBar.hideKeyguard();
            //顯示密碼鎖屏
            mBouncer.show(true /* resetSecuritySelection */);
        } else {
           //顯示滑動鎖屏
            mStatusBar.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
                mBouncer.prepare();
            }
        }
        updateStates();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
什麼情況下會直接顯示密碼鎖屏界面呢?

KeyguardBouncer.needsFullscreenBouncer
public boolean needsFullscreenBouncer() {
        ensureView();
        if (mKeyguardView != null) {
            SecurityMode mode = mKeyguardView.getSecurityMode();
            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
        }
        return false;
    }
1
2
3
4
5
6
7
8
目前擷取的Bouncer的類型是SimPin或者SimPuk時,通過mKeyguardView.getSecurityMode()擷取目前Bouncer的類型時最終是調到KeyguardSecurityModel的getSecurityMode方法,通過KeyguardUpdateMonitor這個類擷取目前SIM卡的狀态來判斷的,當狀态是PIN_REQUIRED或者PUK_REQUIRED則說明應該直接顯示類型為SecurityMode.SimPin或者SecurityMode.SimPuk的密碼鎖屏,是以當我們插入一張帶密碼的SIM卡時會立即顯示sim pin界面

if (mIsPukScreenAvailable && SubscriptionManager.isValidSubscriptionId(
                monitor.getNextSubIdForState(IccCardConstants.State.PUK_REQUIRED))) {
            return SecurityMode.SimPuk;
        }

        if (SubscriptionManager.isValidSubscriptionId(
                monitor.getNextSubIdForState(IccCardConstants.State.PIN_REQUIRED))) {
            return SecurityMode.SimPin;
        }
1
2
3
4
5
6
7
8
9
我們再來看看needsFullscreenBouncer中調用的ensureView方法

protected void ensureView() {
        ...
        //首次調用mRoot為空
        if (mRoot == null || forceRemoval) {
            inflateView();
        }
    }
1
2
3
4
5
6
7
inflateView
protected void inflateView() {
       //在初始化View之前先移除,以保持幹淨
        removeView();
        mHandler.removeCallbacks(mRemoveViewRunnable);
        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
        mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mCallback);
        mContainer.addView(mRoot, mContainer.getChildCount());
        mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
                com.android.systemui.R.dimen.status_bar_height);
        mRoot.setVisibility(View.INVISIBLE);
        mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());

        final WindowInsets rootInsets = mRoot.getRootWindowInsets();
        if (rootInsets != null) {
            mRoot.dispatchApplyWindowInsets(rootInsets);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
此方法代碼很明顯,就是加載布局,加載View,然後addView,mRoot是名為keyguard_bouncer的layout,這是Bouncer的根布局

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black"
    android:fitsSystemWindows="true">

    <include
        style="@style/BouncerSecurityContainer"
        layout="@layout/keyguard_host_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</FrameLayout>
1
2
3
4
5
6
7
8
9
10
11
12
這裡面直接include了一個名為keyguard_host_view的layout,KeyguardHostView是一個自定義ViewGroup,裡面包含KeyguardSecurityContainer,KeyguardSecurityContainer立馬包含KeyguardSecurityViewFlipper

<com.android.keyguard.KeyguardHostView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
    android:id="@+id/keyguard_host_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
                                                  from this view when bouncer is shown -->

    <com.android.keyguard.KeyguardSecurityContainer
        android:id="@+id/keyguard_security_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        androidprv:layout_maxHeight="@dimen/keyguard_security_max_height"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:padding="0dp"
        android:fitsSystemWindows="true"
        android:layout_gravity="center">
        <com.android.keyguard.KeyguardSecurityViewFlipper
            android:id="@+id/view_flipper"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipChildren="false"
            android:clipToPadding="false"
            android:paddingTop="@dimen/keyguard_security_view_top_margin"
            android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
            android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
            android:gravity="center">
        </com.android.keyguard.KeyguardSecurityViewFlipper>
    </com.android.keyguard.KeyguardSecurityContainer>

</com.android.keyguard.KeyguardHostView>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
接着通過addView将mRoot添加到mContainer,mContainer我們前面有分析過,它是StatusBar傳遞過來的SystemUI頂層ViewGroup,接着mRoot.setVisibility(View.INVISIBLE)讓mRoot暫時不可見
ensureView分析完了,此方法也隻是初始化一些layout

接着再回到showBouncerOrKeyguard中去

showBouncerOrKeyguard
 protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
        if (mBouncer.needsFullscreenBouncer() && !mDozing) {
            mStatusBar.hideKeyguard();
            mBouncer.show(true /* resetSecuritySelection */);
        } else {
            mStatusBar.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
                mBouncer.prepare();
            }
        }
        updateStates();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
我們分析了直接顯示Bouncer的情況,是在SIM卡狀态為PIN_REQUIRED或者PUK_REQUIRED時,如果是普通情況則會調用StatusBar.showKeyguard顯示滑動鎖屏

StatusBar.showKeyguard
public void showKeyguard() {
        ...
        updateIsKeyguard();
        ...
    }
1
2
3
4
5
updateIsKeyguard
private boolean updateIsKeyguard() {
        ...
        boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
                || keyguardForDozing) && !wakeAndUnlocking;
        if (shouldBeKeyguard) {
            if (isGoingToSleep()
                    && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF) {
                // Delay showing the keyguard until screen turned off.
            } else {
                showKeyguardImpl();
            }
        } else {
            return hideKeyguardImpl();
        }
        return false;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
滿足顯示Keyguard的條件shouldBeKeyguard則調用showKeyguardImpl

showKeyguardImpl
public void showKeyguardImpl() {
        ...
        updatePanelExpansionForKeyguard();
       	...
        }
    }
1
2
3
4
5
6
updatePanelExpansionForKeyguard
private void updatePanelExpansionForKeyguard() {
	//狀态為KEYGUARD,不是MODE_WAKE_AND_UNLOCK模式,不顯示Bouncer
        if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
            instantExpandNotificationsPanel();
        } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
            instantCollapseNotificationPanel();
        }
    }
1
2
3
4
5
6
7
8
9
instantExpandNotificationsPanel
@Override
    public void instantExpandNotificationsPanel() {
        makeExpandedVisible(true);
        //展開滑動鎖屏
        mNotificationPanel.expand(false /* animate */);
        
    }
1
2
3
4
5
6
7
makeExpandedVisible
void makeExpandedVisible(boolean force) {
        ...
        mStatusBarWindowController.setPanelVisible(true);
        ...
    }
1
2
3
4
5
StatusBarWindowController.setPanelVisible
public void setPanelVisible(boolean visible) {
        ...
        apply(mCurrentState);
    }
1
2
3
4
apply
private void apply(State state) {
        applyKeyguardFlags(state);
        applyForceStatusBarVisibleFlag(state);
        applyFocusableFlag(state);
        applyForceShowNavigationFlag(state);
        adjustScreenOrientation(state);
        applyHeight(state);
        applyUserActivityTimeout(state);
        applyInputFeatures(state);
        applyFitsSystemWindows(state);
        applyModalFlag(state);
        applyBrightness(state);
        applyHasTopUi(state);
        applyNotTouchable(state);
        applyStatusBarColorSpaceAgnosticFlag(state);
        if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
            mWindowManager.updateViewLayout(mStatusBarView, mLp);
        }
        if (mHasTopUi != mHasTopUiChanged) {
            try {
                mActivityManager.setHasTopUi(mHasTopUiChanged);
            } catch (RemoteException e) {
                Log.e(TAG, "Failed to call setHasTopUi", e);
            }
            mHasTopUi = mHasTopUiChanged;
        }
        notifyStateChangedCallbacks();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
設定了一些資料,接着調用mNotificationPanel.expand(true)展開滑動鎖屏,這樣我們就能看到鎖屏界面了,到此為止滑動鎖屏的加載已經分析完了,隻分析了一個大概流程,裡面有很多細節的東西需要實際應用到之後再去跟代碼

下一篇我們接着分析密碼鎖屏的建立以及滑動鎖屏上滑後顯示密碼鎖屏的的流程相關
————————————————