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);
    }
相关推荐
雨白8 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹10 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空11 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭12 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日13 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安13 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑13 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟17 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡18 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0018 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体