android13#systemui#keyguard

1.简介

公司代码比较旧,导致restart以后,在开机后的锁屏界面上出现了白屏,就是通知栏后边那个白色的背景,所以整理下显示的流程,查找原因。

  • 主要修改的就是2.10以及2.7也就是mQsExpandImmediate的值

2.NotificationPanelViewController.java

这个就是下拉状态栏的根布局,具体布局内容见上篇1.3小节里的status_bar_expanded.xml布局

2.1.expand

开机后进入锁屏界面,这个是要展开的,因为锁屏界面显示的东西也在这个容器里

scss 复制代码
    public void expand(boolean animate) {
        //完全收缩状态或者正在收缩中
        if (isFullyCollapsed() || isCollapsing()) {
            mInstantExpanding = true;
            mAnimateAfterExpanding = animate;
            mUpdateFlingOnLayout = false;
            abortAnimations();
            if (mTracking) {
                // The panel is expanded after this call.
                onTrackingStopped(true /* expands */);
            }
            if (mExpanding) {
                notifyExpandingFinished();
            }
            //见补充1,使面板可见
            updatePanelExpansionAndVisibility();
            // Wait for window manager to pickup the change, so we know the maximum height of the
            // panel then.
            this.mView.getViewTreeObserver().addOnGlobalLayoutListener(
                    new ViewTreeObserver.OnGlobalLayoutListener() {
                        @Override
                        public void onGlobalLayout() {
                            if (!mInstantExpanding) {
                                mView.getViewTreeObserver().removeOnGlobalLayoutListener(
                                        this);
                                return;
                            }
                            if (mCentralSurfaces.getNotificationShadeWindowView()
                                    .isVisibleToUser()) {
                                mView.getViewTreeObserver().removeOnGlobalLayoutListener(
                                        this);
                                //走到这里会展开状态栏,if和else都是设置展开高度为panel最大值
                                if (mAnimateAfterExpanding) {
                                    notifyExpandingStarted();
                                    beginJankMonitoring();
                                    
                                    fling(0  /* expand */);
                                } else {
                                    mShadeHeightLogger.logFunctionCall("expand");
                                    setExpandedFraction(1f);
                                }
                                mInstantExpanding = false;
                            }
                        }
                    });
            // Make sure a layout really happens.
            this.mView.requestLayout();
        }

        setListening(true);
    }

>1.updatePanelExpansionAndVisibility

更新面板的可见性

typescript 复制代码
    public void updatePanelExpansionAndVisibility() {
    //这个类里其实是调用了一堆回调处理的
        mShadeExpansionStateManager.onPanelExpansionChanged(
                mExpandedFraction, isExpanded(), mTracking, mExpansionDragDownAmountPx);
        updateVisibility();
    }

    private void updateVisibility() {
        mView.setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
    }

    private boolean shouldPanelBeVisible() {
        boolean headsUpVisible = mHeadsUpAnimatingAway || mHeadsUpPinnedMode;
        return headsUpVisible || isExpanded() || mBouncerShowing;
    }

    public boolean isExpanded() {
        return mExpandedFraction > 0f
                || mInstantExpanding
                || isPanelVisibleBecauseOfHeadsUp()
                || mTracking
                || mHeightAnimator != null
                && !mIsSpringBackAnimation;
    }

>2.setExpandedFraction

arduino 复制代码
    public void setExpandedFraction(float frac) {
        setExpandedHeight(getMaxPanelHeight() * frac);
    }

>3.fling

scss 复制代码
    protected void fling(float vel, boolean expand, float collapseSpeedUpFactor,
            boolean expandBecauseOfFalsing) {
        float target = expand ? getMaxPanelHeight() : 0;
        if (!expand) {
            setIsClosing(true);
        }
        flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing);
    }

>4.setExpandedHeight

arduino 复制代码
    void setExpandedHeight(float height) {
        setExpandedHeightInternal(height);
    }

2.2.setExpandedHeightInternal

scss 复制代码
    private void setExpandedHeightInternal(float h) {
        //就是执行对应的run方法,完事刷新layout
        mNotificationShadeWindowController.batchApplyWindowLayoutParams
        (() -> {
            if (mExpandLatencyTracking && h != 0f) {
                DejankUtils.postAfterTraversal(
                        () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
                mExpandLatencyTracking = false;
            }
            float maxPanelHeight = getMaxPanelTransitionDistance();
            if (mHeightAnimator == null) {
                // Split shade has its own overscroll logic
                if (mTracking && !mSplitShadeEnabled) {
                    float overExpansionPixels = Math.max(0, h - maxPanelHeight);
                    setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
                }
            }
            //计算出面板的展开高度
            mExpandedHeight = Math.min(h, maxPanelHeight);
            // If we are closing the panel and we are almost there due to a slow decelerating
            // interpolator, abort the animation.
            if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
                mExpandedHeight = 0f;
                if (mHeightAnimator != null) {
                    mHeightAnimator.end();
                }
            }
            mExpansionDragDownAmountPx = h;
            mExpandedFraction = Math.min(1f,
                    maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
            mAmbientState.setExpansionFraction(mExpandedFraction);
            //见2.3,更新面板高度
            onHeightUpdated(mExpandedHeight);
            updatePanelExpansionAndVisibility();
        });
    }

>batchApplyWindowLayoutParams

就是执行对应的run方法,完事刷新layout

scss 复制代码
    public void batchApplyWindowLayoutParams(Runnable scope) {
        mDeferWindowLayoutParams++;
        scope.run();
        mDeferWindowLayoutParams--;
        applyWindowLayoutParams();
    }
csharp 复制代码
    private void applyWindowLayoutParams() {
        if (mDeferWindowLayoutParams == 0 && mLp != null && mLp.copyFrom(mLpChanged) != 0) {
            mWindowManager.updateViewLayout(mNotificationShadeView, mLp);
        }
    }

2.3.onHeightUpdated

scss 复制代码
    private void onHeightUpdated(float expandedHeight) {

        if (!mQsExpanded || mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted) {
            // Updating the clock position will set the top padding which might
            // trigger a new panel height and re-position the clock.
            // This is a circular dependency and should be avoided, otherwise we'll have
            // a stack overflow.
            if (mStackScrollerMeasuringPass > 2) {
                debugLog("Unstable notification panel height. Aborting.");
            } else {
                positionClockAndNotifications();
            }
        }
        // Below is true when QS are expanded and we swipe up from the same bottom of panel to
        // close the whole shade with one motion. Also this will be always true when closing
        // split shade as there QS are always expanded so every collapsing motion is motion from
        // expanded QS to closed panel
        boolean collapsingShadeFromExpandedQs = mQsExpanded && !mQsTracking
                && mQsExpansionAnimator == null && !mQsExpansionFromOverscroll;
        //主要是mQsExpandImmediate这个值决定的,具体见2.7
        boolean goingBetweenClosedShadeAndExpandedQs =
                mQsExpandImmediate || collapsingShadeFromExpandedQs;
        // in split shade we react when HUN is visible only if shade height is over HUN start
        // height - which means user is swiping down. Otherwise shade QS will either not show at all
        // with HUN movement or it will blink when touching HUN initially
        boolean qsShouldExpandWithHeadsUp = !mSplitShadeEnabled
                || (!mHeadsUpManager.isTrackingHeadsUp() || expandedHeight > mHeadsUpStartHeight);
        //判断qs是否要展开,老代码就是mQsExpandImmediate状态不对,导致进入下边的if方法,修改了qs的高度
        if (goingBetweenClosedShadeAndExpandedQs && qsShouldExpandWithHeadsUp) {
            float qsExpansionFraction;
            if (mSplitShadeEnabled) {
                qsExpansionFraction = 1;
            } else if (mKeyguardShowing) {
                // On Keyguard, interpolate the QS expansion linearly to the panel expansion
                qsExpansionFraction = expandedHeight / (getMaxPanelHeight());
            } else {
                // In Shade, interpolate linearly such that QS is closed whenever panel height is
                // minimum QS expansion + minStackHeight
                float panelHeightQsCollapsed =
                        mNotificationStackScrollLayoutController.getIntrinsicPadding()
                                + mNotificationStackScrollLayoutController.getLayoutMinHeight();
                float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
                qsExpansionFraction = (expandedHeight - panelHeightQsCollapsed)
                        / (panelHeightQsExpanded - panelHeightQsCollapsed);
            }
            float targetHeight = mQsMinExpansionHeight
                    + qsExpansionFraction * (mQsMaxExpansionHeight - mQsMinExpansionHeight);
            //见 2.4,
            setQsExpansionHeight(targetHeight);
        }
        //见2.5
        updateExpandedHeight(expandedHeight);
        //见补充1
        updateHeader();
        //见补充2
        updateNotificationTranslucency();
        //见补充4
        updatePanelExpanded();
        //见补充5
        updateGestureExclusionRect();
        if (DEBUG_DRAWABLE) {
            mView.invalidate();
        }
    }
    

>1.updateHeader

scss 复制代码
    private void updateHeader() {
        if (mBarState == KEYGUARD) {
            mKeyguardStatusBarViewController.updateViewState();
        }
        //见2.6
        updateQsExpansion();
    }

>2.updateNotificationTranslucency

ini 复制代码
    private void updateNotificationTranslucency() {
        if (mIsToLockscreenTransitionRunning) {
            return;
        }
        float alpha = 1f;
        if (mClosingWithAlphaFadeOut && !mExpandingFromHeadsUp
                && !mHeadsUpManager.hasPinnedHeadsUp()) {
            //见补充3
            alpha = getFadeoutAlpha();
        }
        if (mBarState == KEYGUARD && !mHintAnimationRunning
                && !mKeyguardBypassController.getBypassEnabled()) {
            alpha *= mClockPositionResult.clockAlpha;
        }
        //设置通知栏容器的透明度
        mNotificationStackScrollLayoutController.setAlpha(alpha);
    }

>3.getFadeoutAlpha

ini 复制代码
    private float getFadeoutAlpha() {
        float alpha;
        if (mQsMinExpansionHeight == 0) {
        //横屏模式或者锁屏下,透明度一直是1,也就是通知面板可见。
            return 1.0f;
        }
        alpha = getExpandedHeight() / mQsMinExpansionHeight;
        alpha = Math.max(0, Math.min(alpha, 1));
        alpha = (float) Math.pow(alpha, 0.75);
        return alpha;
    }

mQsMinExpansionHeight的值,可以看到,在锁屏界面或者横屏模式下,一直是0

ini 复制代码
    private void updateQSMinHeight() {
        float previousMin = mQsMinExpansionHeight;
        if (mKeyguardShowing || mSplitShadeEnabled) {
            mQsMinExpansionHeight = 0;
        } else {
            mQsMinExpansionHeight = mQs.getQsMinExpansionHeight();
        }
        if (mQsExpansionHeight == previousMin) {
            mQsExpansionHeight = mQsMinExpansionHeight;
        }
    }

>4.updatePanelExpanded

更新面板状态

scss 复制代码
    private void updatePanelExpanded () {
    //展开状态
        boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown;
        if (mPanelExpanded != isExpanded) {
            mPanelExpanded = isExpanded;
            mShadeExpansionStateManager.onShadeExpansionFullyChanged(isExpanded);
            if (!isExpanded && mQs != null && mQs.isCustomizing()) {
            //非展开状态,关闭qs编辑页面
                mQs.closeCustomizer();
            }
        }
    }

>5.updateGestureExclusionRect

java 复制代码
    private void updateGestureExclusionRect() {
        Rect exclusionRect = calculateGestureExclusionRect();
        mView.setSystemGestureExclusionRects(exclusionRect.isEmpty() ? Collections.emptyList()
                : Collections.singletonList(exclusionRect));
    }

    private Rect calculateGestureExclusionRect() {
        Rect exclusionRect = null;
        Region touchableRegion = mStatusBarTouchableRegionManager.calculateTouchableRegion();
        if (isFullyCollapsed() && touchableRegion != null) {
            // Note: The manager also calculates the non-pinned touchable region
            exclusionRect = touchableRegion.getBounds();
        }
        return exclusionRect != null ? exclusionRect : EMPTY_RECT;
    }

2.4.setQsExpansionHeight

修改qs展开高度

scss 复制代码
    void setQsExpansionHeight (float height) {
        height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
        mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
        boolean qsAnimatingAway = !mQsAnimatorExpand && mAnimatingQS;
        if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
                && !mDozing && !qsAnimatingAway) {
            setQsExpanded(true);
        } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
            setQsExpanded(false);
        }
        //更新qs展开高度
        mQsExpansionHeight = height;
        updateQsExpansion();
        requestScrollerTopPaddingUpdate(false /* animate */);
        mKeyguardStatusBarViewController.updateViewState();
        if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == KEYGUARD) {
        //锁屏页面手指往下滑,可以看到底部透明度改变,以及左侧的clock位置移动
            updateKeyguardBottomAreaAlpha();
            positionClockAndNotifications();
        }

        if (mAccessibilityManager.isEnabled()) {
            mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
        }

        if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded
                && mFalsingCollector.shouldEnforceBouncer()) {
            mCentralSurfaces.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
                    false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
        }
        if (DEBUG_DRAWABLE) {
            mView.invalidate();
        }
    }

2.5.updateExpandedHeight

scss 复制代码
    private void updateExpandedHeight(float expandedHeight) {
        if (mTracking) {
            mNotificationStackScrollLayoutController
                    .setExpandingVelocity(getCurrentExpandVelocity());
        }
        if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
            // The expandedHeight is always the full panel Height when bypassing
            expandedHeight = getMaxPanelHeight();
        }
        mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight);
        updateKeyguardBottomAreaAlpha();
        updateStatusBarIcons();
    }

2.6.updateQsExpansion

更新qs的展开状态

scss 复制代码
    private void updateQsExpansion() {
        if (mQs == null) return;
        final float squishiness;
        if ((mQsExpandImmediate || mQsExpanded) && !mSplitShadeEnabled) {
            squishiness = 1;
        } else if (mTransitioningToFullShadeProgress > 0.0f) {
            squishiness = mLockscreenShadeTransitionController.getQsSquishTransitionFraction();
        } else {
            squishiness = mNotificationStackScrollLayoutController
                    .getNotificationSquishinessFraction();
        }
        //计算qs展开比例
        final float qsExpansionFraction = computeQsExpansionFraction();
        final float adjustedExpansionFraction = mSplitShadeEnabled
                ? 1f : computeQsExpansionFraction();
        mQs.setQsExpansion(adjustedExpansionFraction, getExpandedFraction(), getHeaderTranslation(),
                squishiness);
        mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
        int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
        //这里修改scrim的状态
        mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
        setQSClippingBounds();

        if (mSplitShadeEnabled) {
            // In split shade we want to pretend that QS are always collapsed so their behaviour and
            // interactions don't influence notifications as they do in portrait. But we want to set
            // 0 explicitly in case we're rotating from non-split shade with QS expansion of 1.
            mNotificationStackScrollLayoutController.setQsExpansionFraction(0);
        } else {
            mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
        }

        mDepthController.setQsPanelExpansion(qsExpansionFraction);
        mStatusBarKeyguardViewManager.setQsExpansion(qsExpansionFraction);

        float shadeExpandedFraction = isOnKeyguard()
                ? getLockscreenShadeDragProgress()
                : getExpandedFraction();

        mLargeScreenShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
        mLargeScreenShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
        mLargeScreenShadeHeaderController.setQsVisible(mQsVisible);
    }

>1.computeQsExpansionFraction

csharp 复制代码
    private float computeQsExpansionFraction() {
        if (mQSAnimatingHiddenFromCollapsed) {
            // When hiding QS from collapsed state, the expansion can sometimes temporarily
            // be larger than 0 because of the timing, leading to flickers.
            return 0.0f;
        }
        return Math.min(
                1f, (mQsExpansionHeight - mQsMinExpansionHeight) / (mQsMaxExpansionHeight
                        - mQsMinExpansionHeight));
    }

2.7.mQsExpandImmediate

看下这个值是如何变化的

ini 复制代码
    void setQsExpandImmediate(boolean expandImmediate) {
        if (expandImmediate != mQsExpandImmediate) {
            mQsExpandImmediate = expandImmediate;
            mShadeExpansionStateManager.notifyExpandImmediateChange(expandImmediate);
        }
    }

所有调用的地方

scss 复制代码
//1=====//面板收缩,qs是展开状态,设置值为true
    public void collapse(boolean delayed, float speedUpFactor) {
        if (!canPanelBeCollapsed()) {
            return;
        }

        if (mQsExpanded) {
        
            setQsExpandImmediate(true);
            setShowShelfOnly(true);
        }

//2=====//面板关闭的时候,设置值为false
 public void closeQs() {
        cancelQsAnimation();
        setQsExpansionHeight(mQsMinExpansionHeight);
        // qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
        // middle of animation - we need to make sure that value is always false when shade if
        // fully collapsed or expanded
        
        setQsExpandImmediate(false);
    }

//3=====//展开面板带qs的时候,设置为true
    public void expandWithQs() {
        if (isQsExpansionEnabled()) {
            setQsExpandImmediate(true);
            setShowShelfOnly(true);
        }

//4=====//qs的触摸事件,
    private boolean handleQsTouch(MotionEvent event) {

        if (mTwoFingerQsExpandPossible && isOpenQsEvent(event) && event.getY(event.getActionIndex())
                < mStatusBarMinHeight) {
            mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1);
            setQsExpandImmediate(true);

//5=====//面板展开完成的,修改值为false
    private void onExpandingFinished() {

        if (mBarState != SHADE) {
            // updating qsExpandImmediate is done in onPanelStateChanged for unlocked shade but
            // on keyguard panel state is always OPEN so we need to have that extra update
            setQsExpandImmediate(false);
        }
//6=========
    private void onTrackingStarted() {
        if (mQsFullyExpanded) {
            setQsExpandImmediate(true);
            setShowShelfOnly(true);
        }
//7=====//面板状态改变的时候
    private void onPanelStateChanged(@PanelState int state) {
        updateQSExpansionEnabledAmbient();

        if (state == STATE_OPEN && mCurrentPanelState != state) {
            setQsExpandImmediate(false);
            mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
        }
        if (state == STATE_OPENING) {
            // we need to ignore it on keyguard as this is a false alarm - transition from unlocked
            // to locked will trigger this event and we're not actually in the process of opening
            // the shade, lockscreen is just always expanded
            if (mSplitShadeEnabled && !isOnKeyguard()) {
                setQsExpandImmediate(true);
            }
            mOpenCloseListener.onOpenStarted();
        }
        if (state == STATE_CLOSED) {
            setQsExpandImmediate(false);
            // Close the status bar in the next frame so we can show the end of the
            // animation.
            mView.post(mMaybeHideExpandedRunnable);
        }
        mCurrentPanelState = state;
    }

>log

我们的代码比较旧,开机会走下边的方法,上边的7,state为STATE_OPENING ,设置为true以后,没有再被修改成false,导致qs展开异常。

  • log的逻辑见小节3之后的代码
php 复制代码
at com.android.systemui.statusbar.phone.NotificationPanelViewController.onPanelStateChanged(NotificationPanelViewController.java:5199)
at com.android.systemui.statusbar.phone.NotificationPanelViewController.$r8$lambda$b5I6ELTIP2he3Ex7kHWUxblpoU4(Unknown Source:0)
at com.android.systemui.statusbar.phone.NotificationPanelViewController$$ExternalSyntheticLambda15.onPanelStateChanged(Unknown Source:2)
at com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager.updateStateInternal(PanelExpansionStateManager.kt:138)
at com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager.onPanelExpansionChanged(PanelExpansionStateManager.kt:98)
at com.android.systemui.statusbar.phone.PanelViewController.updatePanelExpansionAndVisibility(PanelViewController.java:1147)
at com.android.systemui.statusbar.phone.PanelViewController.expand(PanelViewController.java:952)
at com.android.systemui.statusbar.phone.NotificationPanelViewController.expand(NotificationPanelViewController.java:3382)
at com.android.systemui.statusbar.phone.ShadeControllerImpl.instantExpandNotificationsPanel(ShadeControllerImpl.java:79)
at com.android.systemui.statusbar.phone.CentralSurfacesImpl.updatePanelExpansionForKeyguard(CentralSurfacesImpl.java:3016)
at com.android.systemui.statusbar.phone.CentralSurfacesImpl.showKeyguardImpl(CentralSurfacesImpl.java:3009)
at com.android.systemui.statusbar.phone.CentralSurfacesImpl.updateIsKeyguard(CentralSurfacesImpl.java:2980)
at com.android.systemui.statusbar.phone.CentralSurfacesImpl.updateIsKeyguard(CentralSurfacesImpl.java:2953)
at com.android.systemui.statusbar.phone.CentralSurfacesImpl.showKeyguard(CentralSurfacesImpl.java:2941)
at com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.showBouncerOrKeyguard(StatusBarKeyguardViewManager.java:446)
at com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.reset(StatusBarKeyguardViewManager.java:595)
at com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager.show(StatusBarKeyguardViewManager.java:430)
at com.android.systemui.keyguard.KeyguardViewMediator.handleShow(KeyguardViewMediator.java:2322)
at com.android.systemui.keyguard.KeyguardViewMediator.-$$Nest$mhandleShow(Unknown Source:0)
at com.android.systemui.keyguard.KeyguardViewMediator$10.handleMessage(KeyguardViewMediator.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)

2.8.ShadeLayoutChangeListener

构造方法里添加的监听,监听布局的改变

ini 复制代码
        mView.addOnLayoutChangeListener(new ShadeLayoutChangeListener());
        mView.setOnTouchListener(createTouchHandler());
scss 复制代码
    private final class ShadeLayoutChangeListener implements View.OnLayoutChangeListener {
        @Override
        public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
                int oldTop, int oldRight, int oldBottom) {
        //见补充1,更新面板高度
            updateExpandedHeightToMaxHeight();
            mHasLayoutedSinceDown = true;
            if (mUpdateFlingOnLayout) {
                abortAnimations();
                fling(mUpdateFlingVelocity);
                mUpdateFlingOnLayout = false;
            }
            updateMaxDisplayedNotifications(!shouldAvoidChangingNotificationsCount());
            //通知面板和容器宽度一样,竖屏模式为true,横屏就不是了
            setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth());

            // Update Clock Pivot (used by anti-burnin transformations)
            mKeyguardStatusViewController.updatePivot(mView.getWidth(), mView.getHeight());

            // Calculate quick setting heights.
            int oldMaxHeight = mQsMaxExpansionHeight;
            if (mQs != null) {
            //更新qs最小展开高度
                updateQSMinHeight();
                mQsMaxExpansionHeight = mQs.getDesiredHeight();
                mNotificationStackScrollLayoutController.setMaxTopPadding(mQsMaxExpansionHeight);
            }
            //更新clock和通知的为主
            positionClockAndNotifications();
            if (mQsExpanded && mQsFullyExpanded) {
            //qs是完全展开状态
                mQsExpansionHeight = mQsMaxExpansionHeight;
                requestScrollerTopPaddingUpdate(false /* animate */);
                updateExpandedHeightToMaxHeight();

                // Size has changed, start an animation.
                if (mQsMaxExpansionHeight != oldMaxHeight) {
                    startQsSizeChangeAnimation(oldMaxHeight, mQsMaxExpansionHeight);
                }
            } else if (!mQsExpanded && mQsExpansionAnimator == null) {
                setQsExpansionHeight(mQsMinExpansionHeight + mLastOverscroll);
            } else {
                mShadeLog.v("onLayoutChange: qs expansion not set");
            }
            updateExpandedHeight(getExpandedHeight());
            updateHeader();

            // If we are running a size change animation, the animation takes care of the height
            // of the container. However, if we are not animating, we always need to make the QS
            // container the desired height so when closing the QS detail, it stays smaller after
            // the size change animation is finished but the detail view is still being animated
            // away (this animation takes longer than the size change animation).
            if (mQsSizeChangeAnimator == null && mQs != null) {
                mQs.setHeightOverride(mQs.getDesiredHeight());
            }
            updateMaxHeadsUpTranslation();
            updateGestureExclusionRect();
            if (mExpandAfterLayoutRunnable != null) {
                mExpandAfterLayoutRunnable.run();
                mExpandAfterLayoutRunnable = null;
            }
            
        }
    }

>1.updateExpandedHeightToMaxHeight

csharp 复制代码
    private void updateExpandedHeightToMaxHeight() {
    //见补充2
        float currentMaxPanelHeight = getMaxPanelHeight();

        if (isFullyCollapsed()) {
        //面板是完全收缩状态 mExpandedFraction <= 0.0f;
            return;
        }

        if (currentMaxPanelHeight == mExpandedHeight) {
        //高度未发生变化
            return;
        }

        if (mTracking && !isTrackingBlocked()) {
        //正在触摸滑动
            return;
        }

        if (mHeightAnimator != null && !mIsSpringBackAnimation) {
        //动画中
            mPanelUpdateWhenAnimatorEnds = true;
            return;
        }

       //最终走的2.2
        setExpandedHeight(currentMaxPanelHeight);
    }

>2.getMaxPanelHeight

获取面板最大高度

ini 复制代码
    int getMaxPanelHeight() {
    //默认是状态栏高度
        int min = mStatusBarMinHeight;
        if (!(mBarState == KEYGUARD)
                && mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
        //非锁屏界面并且通知数为0,取(qs最小展开高度和上边的min)最小值
            int minHeight = mQsMinExpansionHeight;
            min = Math.max(min, minHeight);
        }
        int maxHeight;
        if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted
                || mPulsing || mSplitShadeEnabled) {
            maxHeight = calculatePanelHeightQsExpanded();
        } else {
            maxHeight = calculatePanelHeightShade();
        }
        maxHeight = Math.max(min, maxHeight);
        return maxHeight;
    }

2.9.resetViews

重置view状态,关闭qs,通知栏状态重置

typescript 复制代码
    public void resetViews(boolean animate) {
        mGutsManager.closeAndSaveGuts(true /* leavebehind */, true /* force */,
                true /* controls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
        if (animate && !isFullyCollapsed()) {
            animateCloseQs(true /* animateAway */);
        } else {
            closeQs();
        }
        mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
                !animate /* cancelAnimators */);
        mNotificationStackScrollLayoutController.resetScrollPosition();
    }

2.10.StatusBarStateListener

java 复制代码
    private final class StatusBarStateListener implements StateListener {
        @Override
        public void onStateChanged(int statusBarState) {
            boolean goingToFullShade = mStatusBarStateController.goingToFullShade();
            boolean keyguardFadingAway = mKeyguardStateController.isKeyguardFadingAway();
            int oldState = mBarState;
            boolean keyguardShowing = statusBarState == KEYGUARD;

            if (mDozeParameters.shouldDelayKeyguardShow()
                    && oldState == StatusBarState.SHADE
                    && statusBarState == KEYGUARD) {
                // This means we're doing the screen off animation - position the keyguard status
                // view where it'll be on AOD, so we can animate it in.
                mKeyguardStatusViewController.updatePosition(
                        mClockPositionResult.clockX,
                        mClockPositionResult.clockYFullyDozing,
                        mClockPositionResult.clockScale,
                        false /* animate */);
            }

            mKeyguardStatusViewController.setKeyguardStatusViewVisibility(
                    statusBarState,
                    keyguardFadingAway,
                    goingToFullShade,
                    mBarState);

            setKeyguardBottomAreaVisibility(statusBarState, goingToFullShade);

            mBarState = statusBarState;
            mKeyguardShowing = keyguardShowing;
        //旧代码没有下边的逻辑,在closeQs()方法也里会修改2.7的字段为false
            boolean fromShadeToKeyguard = statusBarState == KEYGUARD
                    && (oldState == SHADE || oldState == SHADE_LOCKED);
            if (mSplitShadeEnabled && fromShadeToKeyguard) {
                // user can go to keyguard from different shade states and closing animation
                // may not fully run - we always want to make sure we close QS when that happens
                // as we never need QS open in fresh keyguard state
                closeQs();
            }

3.KeyguardViewMediator.java

  • 可以看到实现了CoreStartable,之前帖子讲过这个接口,SystemUi的服务启动的时候里边会查找所有这种接口,然后调用对应的start以及onBootCompleted方法
  • 其他方法是小节4里实例化的对象调用的
kotlin 复制代码
public class KeyguardViewMediator implements CoreStartable, Dumpable,
        StatusBarStateController.StateListener {

注解实例化的

less 复制代码
    @Binds
    @IntoMap
    @ClassKey(KeyguardViewMediator::class)
    abstract fun bindKeyguardViewMediator(sysui: KeyguardViewMediator): CoreStartable

3.1.start

csharp 复制代码
    public void start() {
        synchronized (this) {
            setupLocked();
        }
    }

>setupLocked

ini 复制代码
    private void setupLocked() {
        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
        mShowKeyguardWakeLock.setReferenceCounted(false);

        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SHUTDOWN);
        mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
        //注册广播监听
        final IntentFilter delayedActionFilter = new IntentFilter();
        delayedActionFilter.addAction(DELAYED_KEYGUARD_ACTION);
        delayedActionFilter.addAction(DELAYED_LOCK_PROFILE_ACTION);
        delayedActionFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter,
                SYSTEMUI_PERMISSION, null /* scheduler */,
                Context.RECEIVER_EXPORTED_UNAUDITED);

        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        KeyguardUpdateMonitor.setCurrentUser(mUserTracker.getUserId());

        // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
        // is disabled.
        //根据锁屏服务是否可用,决定是否显示keyguard
        if (isKeyguardServiceEnabled()) {
            setShowingLocked(!shouldWaitForProvisioning()
                    && !mLockPatternUtils.isLockScreenDisabled(
                            KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
        } else {
            // The system's keyguard is disabled or missing.
            setShowingLocked(false /* showing */, true /* forceCallbacks */);
        }

        final ContentResolver cr = mContext.getContentResolver();

        mDeviceInteractive = mPM.isInteractive();

        mLockSounds = new SoundPool.Builder()
                .setMaxStreams(1)
                .setAudioAttributes(
                        new AudioAttributes.Builder()
                                .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
                                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                                .build())
                .build();
        //锁屏声音的获取
        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);
        if (soundPath != null) {
            mLockSoundId = mLockSounds.load(soundPath, 1);
        }
        if (soundPath == null || mLockSoundId == 0) {
            Log.w(TAG, "failed to load lock sound from " + soundPath);
        }
        soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);
        if (soundPath != null) {
            mUnlockSoundId = mLockSounds.load(soundPath, 1);
        }
        if (soundPath == null || mUnlockSoundId == 0) {
            Log.w(TAG, "failed to load unlock sound from " + soundPath);
        }
        soundPath = Settings.Global.getString(cr, Settings.Global.TRUSTED_SOUND);
        if (soundPath != null) {
            mTrustedSoundId = mLockSounds.load(soundPath, 1);
        }
        if (soundPath == null || mTrustedSoundId == 0) {
            Log.w(TAG, "failed to load trusted sound from " + soundPath);
        }

        int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_lockSoundVolumeDb);
        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);

        mHideAnimation = AnimationUtils.loadAnimation(mContext,
                com.android.internal.R.anim.lock_screen_behind_enter);

        mWorkLockController = new WorkLockActivityController(mContext);
    }

3.2.onBootCompleted

scss 复制代码
    public void onBootCompleted() {
        synchronized (this) {
            if (mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_guestUserAutoCreated)) {
                //自动创建guest用户
                mUserSwitcherController.schedulePostBootGuestCreation();
            }
            mBootCompleted = true;
            //见补充1
            adjustStatusBarLocked(false, true);
            //这个值默认是false,需要执行过3.3的方法以后才会改为true
            if (mBootSendUserPresent) {
            //见3.3
                sendUserPresentBroadcast();
            }
        }
    }

>1.adjustStatusBarLocked

调整状态栏数据

ini 复制代码
    private void adjustStatusBarLocked(boolean forceHideHomeRecentsButtons,
            boolean forceClearFlags) {
        if (mStatusBarManager == null) {
            mStatusBarManager = (StatusBarManager)
                    mContext.getSystemService(Context.STATUS_BAR_SERVICE);
        }

        if (mStatusBarManager == null) {
            Log.w(TAG, "Could not get status bar manager");
        } else {

            int flags = StatusBarManager.DISABLE_NONE;
            if (forceClearFlags) {
                mStatusBarManager.disable(flags);
            }

            if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
                if (!mShowHomeOverLockscreen || !mInGestureNavigationMode) {
                    flags |= StatusBarManager.DISABLE_HOME;
                }
                flags |= StatusBarManager.DISABLE_RECENT;
            }
            mStatusBarManager.disable(flags);
        }
    }

3.3.sendUserPresentBroadcast

发送USER_PRESENT广播

ini 复制代码
    private void sendUserPresentBroadcast() {
        synchronized (this) {
            if (mBootCompleted) {
            //参考3.2可以知道,走这里需要bootComplte并且user present
                int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
                final UserHandle currentUser = new UserHandle(currentUserId);
                final UserManager um = (UserManager) mContext.getSystemService(
                        Context.USER_SERVICE);
                mUiBgExecutor.execute(() -> {
                    for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
                    //发送user present广播
                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
                    }
                    mLockPatternUtils.userPresent(currentUserId);
                });
            } else {
                mBootSendUserPresent = true;
            }
        }
    }

3.4.onSystemReady

这个方法里调用了显示keyguard的逻辑

scss 复制代码
    public void onSystemReady() {
        mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
    }
        //对应的handler方法
    private void handleSystemReady() {
        synchronized (this) {
            mSystemReady = true;
            //见3.5,显示keyguard
            doKeyguardLocked(null);
            mUpdateMonitor.registerCallback(mUpdateCallback);
            adjustStatusBarLocked();
            mDreamOverlayStateController.addCallback(mDreamOverlayStateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }

3.5.doKeyguardLocked

java 复制代码
    private void doKeyguardLocked(Bundle options) {
        if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
            // Don't show keyguard during half-booted cryptkeeper stage.
            return;
        }

        // if another app is disabling us, don't show
        if (!mExternallyEnabled) {
          //如果外部app不允许显示keyguard
            mNeedToReshowWhenReenabled = true;
            return;
        }

        // if the keyguard is already showing, don't bother. check flags in both files
        // to account for the hiding animation which results in a delay and discrepancy
        // between flags
        if (mShowing && mKeyguardStateController.isShowing()) {
            //已经在显示了
            resetStateLocked();
            return;
        }

        // In split system user mode, we never unlock system user.
        if (!mustNotUnlockCurrentUser()
                || !mUpdateMonitor.isDeviceProvisioned()) {

            // if the setup wizard hasn't run yet, don't show
            final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
            final boolean absent = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_ABSENT));
            final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                    mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PERM_DISABLED));
            final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
                    || ((absent || disabled) && requireSim);

            if (!lockedOrMissing && shouldWaitForProvisioning()) {
            //设备未分配完成并且sim没有锁或者丢失
                return;
            }

            boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
            if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
                    && !lockedOrMissing && !forceShow) {
              //禁止锁屏并且不强制显示
                return;
            }
        }

    //显示keyguard,见3.6
        showLocked(options);
    }

3.6.showLocked

显示keyguard

scss 复制代码
    private void showLocked(Bundle options) {
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        // Treat these messages with priority - This call can originate from #doKeyguardTimeout,
        // meaning the device should lock as soon as possible and not wait for other messages on
        // the thread to process first.
        mHandler.sendMessageAtFrontOfQueue(msg);
    }

>1.handleShow

handler最终调用这个方法处理

scss 复制代码
    private void handleShow(Bundle options) {
        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
        if (mLockPatternUtils.isSecure(currentUser)) {
            mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
        }
        synchronized (KeyguardViewMediator.this) {
            if (!mSystemReady) {
                return;
            }

            mHiding = false;
            mKeyguardExitAnimationRunner = null;
            mWakeAndUnlocking = false;
            setPendingLock(false);
            setShowingLocked(true);
            //这个就是StatusBarKeyguardViewManager
            mKeyguardViewControllerLazy.get().show(options);
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            adjustStatusBarLocked();
            userActivity();
            mUpdateMonitor.setKeyguardGoingAway(false);
            mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false);
            mShowKeyguardWakeLock.release();
        }
        mKeyguardDisplayManager.show();

        // schedule 4hr idle timeout after which non-strong biometrics (i.e. weak or convenience
        // biometric) can't be used to unlock device until unlocking with strong biometric or
        // primary auth (i.e. PIN/pattern/password)
        mLockPatternUtils.scheduleNonStrongBiometricIdleTimeout(
                KeyguardUpdateMonitor.getCurrentUser());

        Trace.endSection();
    }
java 复制代码
    @Binds
    abstract KeyguardViewController bindKeyguardViewController(
            StatusBarKeyguardViewManager statusBarKeyguardViewManager);

4.KeyguardService.java

可以看到,也是注解实例化的,构造方法里有KeyguardViewMediator参数

ini 复制代码
    @Inject
    public KeyguardService(KeyguardViewMediator keyguardViewMediator,
                           KeyguardLifecyclesDispatcher keyguardLifecyclesDispatcher,
                           ScreenOnCoordinator screenOnCoordinator,
                           ShellTransitions shellTransitions) {
        super();
        mKeyguardViewMediator = keyguardViewMediator;
        mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
        mScreenOnCoordinator = screenOnCoordinator;
        mShellTransitions = shellTransitions;
    }

4.1.mBinder

小节5.2里封装的mKeyguardService对象,里边调用的方法最终走的就是这里

java 复制代码
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {

5.KeyguardServiceDelegate.java

这个对象是在小节6里实例化的,方法也都是在小节6里调用的

ini 复制代码
    public KeyguardServiceDelegate(Context context, KeyguardStateMonitor.StateCallback callback) {
        mContext = context;
        mHandler = UiThread.getHandler();
        mCallback = callback;
    }

5.1.bindService

ini 复制代码
    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)) {
            Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
            mKeyguardState.showing = false;
            mKeyguardState.showingAndNotOccluded = false;
            mKeyguardState.secure = false;
            synchronized (mKeyguardState) {
                // TODO: Fix synchronisation model in this class. The other state in this class
                // is at least self-healing but a race condition here can lead to the scrim being
                // stuck on keyguard-less devices.
                mKeyguardState.deviceHasKeyguard = false;
            }
        }
    }

5.2.mKeyguardConnection

这里封装了一个KeyguardServiceWrapper对象,里边通过aidl的逻辑,其实最终调用的就是4.1里的binder的方法

scss 复制代码
    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
           //这里的service就是4.1里的binder了
            mKeyguardService = new KeyguardServiceWrapper(mContext,
                    IKeyguardService.Stub.asInterface(service), mCallback);
            if (mKeyguardState.systemIsReady) {
                // If the system is ready, it means keyguard crashed and restarted.
                mKeyguardService.onSystemReady();
                if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
                    // There has been a user switch earlier
                    mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
                }
                // This is used to hide the scrim once keyguard displays.
                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
                        || mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
                    mKeyguardService.onStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN,
                            false /* cameraGestureTriggered */);
                }
                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);
            }
            if (mKeyguardState.dreaming) {
                mKeyguardService.onDreamingStarted();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
            mKeyguardService = null;
            mKeyguardState.reset();
            mHandler.post(() -> {
                try {
                    ActivityTaskManager.getService().setLockScreenShown(true /* keyguardShowing */,
                            false /* aodShowing */);
                } catch (RemoteException e) {
                    // Local call.
                }
            });
        }
    };

5.3.onSystemReady

服务已经绑定了,直接调用对应的方法,没有的话修改状态,在服务绑定以后根据状态执行对应的方法,其他方法逻辑一样就不重述了。

csharp 复制代码
    public void onSystemReady() {
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
    }

6.PhoneWindowManager.java

这个对象是在SystemServe里初始化WindowManagerService的时候new了一个对象传递给构造方法里的参数的

ini 复制代码
            t.traceBegin("StartWindowManagerService");
            // WMS needs sensor service ready
            mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
            //这里。。。
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            t.traceEnd();

6.1.构造方法

typescript 复制代码
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                new StateCallback() {
                    @Override
                    public void onTrustedChanged() {
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                    }

                    @Override
                    public void onShowingChanged() {
                        mWindowManagerFuncs.onKeyguardShowingAndNotOccludedChanged();
                    }
                });

6.2.bindKeyguard

csharp 复制代码
    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        //见5.1
        mKeyguardDelegate.bindService(mContext);
    }

调用的地方有两处

>1.onSystemUiStarted

csharp 复制代码
    public void onSystemUiStarted() {
        bindKeyguard();
    }

>2.systemBooted

csharp 复制代码
    public void systemBooted() {
        bindKeyguard();

6.3.systemReady

scss 复制代码
    public void systemReady() {
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        //见5.3,最终
        mKeyguardDelegate.onSystemReady();

        mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
        if (mVrManagerInternal != null) {
            mVrManagerInternal.addPersistentVrModeStateListener(mPersistentVrModeListener);
        }

        readCameraLensCoverState();
        updateUiMode();
        mDefaultDisplayRotation.updateOrientationListener();
        synchronized (mLock) {
            mSystemReady = true;
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    updateSettings();
                }
            });
            // If this happens, for whatever reason, systemReady came later than systemBooted.
            // And keyguard should be already bound from systemBooted
            if (mSystemBooted) {
            //如果systemBoot先调用了,那这里直接调用bootCompleted
                mKeyguardDelegate.onBootCompleted();
            }
        }

        mAutofillManagerInternal = LocalServices.getService(AutofillManagerInternal.class);
        mGestureLauncherService = LocalServices.getService(GestureLauncherService.class);
    }

6.4.systemBooted

当系统完成引导到用户可以开始与之交互的点时调用

scss 复制代码
    public void systemBooted() {
        bindKeyguard();
        synchronized (mLock) {
            mSystemBooted = true;
            if (mSystemReady) {
            //比如在systemReady的情况下才走这里
                mKeyguardDelegate.onBootCompleted();
            }
        }
        mSideFpsEventHandler.onFingerprintSensorReady();
        startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
        finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);

        int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState();
        boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON;
        boolean defaultScreenTurningOn = mDefaultDisplayPolicy.getScreenOnListener() != null;
        if (defaultDisplayOn || defaultScreenTurningOn) {
            // Now that system is booted, wait for keyguard and windows to be drawn before
            // updating the orientation listener, stopping the boot animation and enabling screen.
            screenTurningOn(DEFAULT_DISPLAY, mDefaultDisplayPolicy.getScreenOnListener());
            screenTurnedOn(DEFAULT_DISPLAY);
        } else {
            // We're not turning the screen on, so don't wait for keyguard to be drawn
            // to dismiss the boot animation and finish booting
            mBootAnimationDismissable = true;
            enableScreen(null, false /* report */);
        }
    }

7.StatusBarKeyguardViewManager.java

7.1.show

typescript 复制代码
    /**
     * Show the keyguard.  Will handle creating and attaching to the view manager
     * lazily.
     */
    @Override
    public void show(Bundle options) {
        mNotificationShadeWindowController.setKeyguardShowing(true);
        //见8.1
        mKeyguardStateController.notifyKeyguardState(true,
                mKeyguardStateController.isOccluded());
        //见7.2
        reset(true /* hideBouncerWhenShowing */);
    }

7.2.reset

scss 复制代码
    public void reset(boolean hideBouncerWhenShowing) {
        if (mKeyguardStateController.isShowing()) {
            final boolean isOccluded = mKeyguardStateController.isOccluded();
            // Hide quick settings.见2.9
            mNotificationPanelViewController.resetViews(/* animate= */ !isOccluded);
            // Hide bouncer and quick-quick settings.
            if (isOccluded && !mDozing) {
                mCentralSurfaces.hideKeyguard();
                if (hideBouncerWhenShowing || needsFullscreenBouncer()) {
                    hideBouncer(false /* destroyView */);
                }
            } else {
            //见补充1
                showBouncerOrKeyguard(hideBouncerWhenShowing);
            }
            hideAlternateBouncer(false);
            mKeyguardUpdateManager.sendKeyguardReset();
            updateStates();
        }
    }

>1.showBouncerOrKeyguard

scss 复制代码
    protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
    //pin模式
        if (needsFullscreenBouncer() && !mDozing) {
            // The keyguard might be showing (already). So we need to hide it.
            mCentralSurfaces.hideKeyguard();
            if (mPrimaryBouncer != null) {
                mPrimaryBouncer.show(true /* resetSecuritySelection */);
            } else {
                mPrimaryBouncerInteractor.show(true);
            }
        } else {
        //正常走这里,见补充2
            mCentralSurfaces.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(false /* destroyView */);
                if (mPrimaryBouncer != null) {
                    mPrimaryBouncer.prepare();
                }
            }
        }
        updateStates();
    }

>2.CentralSurfaces.showKeyguard()

scss 复制代码
    public void showKeyguard() {
        mStatusBarStateController.setKeyguardRequested(true);
        mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
        updateIsKeyguard();
        mAssistManagerLazy.get().onLockscreenShown();
    }
//
    public boolean updateIsKeyguard() {
        return updateIsKeyguard(false /* forceStateChange */);
    }
//
    public boolean updateIsKeyguard(boolean forceStateChange) {
        boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();

        // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
        // there's no surface we can show to the user. Note that the device goes fully interactive
        // late in the transition, so we also allow the device to start dozing once the screen has
        // turned off fully.
        boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
                && (!mDeviceInteractive || (isGoingToSleep()
                    && (isScreenFullyOff()
                        || (mKeyguardStateController.isShowing() && !isOccluded()))));
        boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake();
        boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
                || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded;
        if (keyguardForDozing) {
            updatePanelExpansionForKeyguard();
        }
        if (shouldBeKeyguard) {
            if (mScreenOffAnimationController.isKeyguardShowDelayed()
                    || (isGoingToSleep()
                    && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) {
                // Delay showing the keyguard until screen turned off.
            } else {
            //正常走这里
                showKeyguardImpl();
            }
        } else {
            // During folding a foldable device this might be called as a result of
            // 'onScreenTurnedOff' call for the inner display.
            // In this case:
            //  * When phone is locked on folding: it doesn't make sense to hide keyguard as it
            //    will be immediately locked again
            //  * When phone is unlocked: we still don't want to execute hiding of the keyguard
            //    as the animation could prepare 'fake AOD' interface (without actually
            //    transitioning to keyguard state) and this might reset the view states
            if (!mScreenOffAnimationController.isKeyguardHideDelayed()
                    // If we're animating occluded, there's an activity launching over the keyguard
                    // UI. Wait to hide it until after the animation concludes.
                    && !mKeyguardViewMediator.isOccludeAnimationPlaying()) {
                return hideKeyguardImpl(forceStateChange);
            }
        }
        return false;
    }
//
    public void showKeyguardImpl() {
        if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
            mNotificationPanelViewController.cancelAnimation();
            onLaunchTransitionFadingEnded();
        }
        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
        if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) {
            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
        }
        updatePanelExpansionForKeyguard();

    }
//
    private void updatePanelExpansionForKeyguard() {
        if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
                //继续看补充3
            mShadeController.instantExpandShade();
        }
    }

>3.ShadeControllerImpl.java

csharp 复制代码
    public void instantExpandShade() {
        // Make our window larger and the panel expanded.
        makeExpandedVisible(true /* force */);
        //见小节2.1
        mNotificationPanelViewController.expand(false /* animate */);
        mCommandQueue.recomputeDisableFlags(mDisplayId, false /* animate */);
    }

8.KeyguardStateController

kotlin 复制代码
public class KeyguardStateControllerImpl implements KeyguardStateController, Dumpable {

8.1.notifyKeyguardState

scss 复制代码
    public void notifyKeyguardState(boolean showing, boolean occluded) {
        if (mShowing == showing && mOccluded == occluded) return;
        mShowing = showing;
        mOccluded = occluded;
        mKeyguardUpdateMonitor.setKeyguardShowing(showing, occluded);

        notifyKeyguardChanged();

        // Update the dismiss amount to the full 0f/1f if we explicitly show or hide the keyguard.
        // Otherwise, the dismiss amount could be left at a random value if we show/hide during a
        // dismiss gesture, canceling the gesture.
        notifyKeyguardDismissAmountChanged(showing ? 0f : 1f, false);
    }
相关推荐
拭心5 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王8 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡8 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道8 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库9 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道10 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe10 小时前
Android Hook - 动态加载so库
android
居居飒11 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He13 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗14 小时前
Android笔试面试题AI答之Android基础(1)
android