android13#systemUI#05unlock screen

303 阅读20分钟

1.简介

  • 学习设置屏幕锁以后,解锁屏幕的流程
  • 锁屏通知显示与隐藏有啥影响?显示锁屏通知,锁屏页面下拉会显示下拉状态栏。不显示锁屏通知,锁屏页面下拉会直接跳到bouncer页面,参考小节12

1.1.解锁容器

>1.super_notification_shade.xml

  • 下拉状态栏的布局,这里贴了部分相关布局
    <!-- Keyguard messages -->
    <LinearLayout
        android:id="@+id/keyguard_message_area_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_marginTop="@dimen/status_bar_height"
        android:layout_gravity="top|center_horizontal"
        android:gravity="center_horizontal">
        <!--这个好像是生物识别失败以后的提示-->
        <com.android.keyguard.KeyguardMessageArea
            android:id="@+id/keyguard_message_area"
            style="@style/Keyguard.TextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/keyguard_lock_padding"
            android:gravity="center"
            android:singleLine="true"
            android:ellipsize="marquee"
            android:focusable="true" />
     </LinearLayout>
     <!--显示密码输入的容器-->
  <FrameLayout android:id="@+id/keyguard_bouncer_container"
                     android:layout_height="0dp"
                     android:layout_width="match_parent"
                     android:layout_weight="1"
                     android:background="@android:color/transparent"
                     android:clipChildren="false"
                     android:clipToPadding="false" />

>2.container的获取

CentralSurfacesImpl.java

    public ViewGroup getBouncerContainer() {
        return mNotificationShadeWindowViewController.getBouncerContainer();
    }

NotificationShadeWindowViewController.java

  • 布局参考补充1
    public ViewGroup getBouncerContainer() {
        return mView.findViewById(R.id.keyguard_bouncer_container);
    }

1.2.KeyguardBouncerComponent

  • @RootView注解声明一个ViewGroup,到时候create方法里传递的参数会给补充1里同样注解的参数用
@Subcomponent(modules = {KeyguardBouncerModule.class})//实现类就是补充1
@KeyguardBouncerScope
public interface KeyguardBouncerComponent {
    /** Simple factory for {@link KeyguardBouncerComponent}. */
    @Subcomponent.Factory
    interface Factory {
        KeyguardBouncerComponent create(@BindsInstance @RootView ViewGroup bouncerContainer);
    }

    KeyguardHostViewController getKeyguardHostViewController();
}

>1.KeyguardBouncerModule

    @Provides
    @KeyguardBouncerScope
    //@RootView是上边Factory里的create方法里传递的
    static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView,
            LayoutInflater layoutInflater) {
         //帧布局,补充2
        KeyguardHostView hostView = (KeyguardHostView) layoutInflater.inflate(
                R.layout.keyguard_host_view, rootView, false);
        rootView.addView(hostView);
        return hostView;
    }

    @Provides
    @KeyguardBouncerScope
    //帧布局
    static KeyguardSecurityContainer providesKeyguardSecurityContainer(KeyguardHostView hostView) {
        return hostView.findViewById(R.id.keyguard_security_container);
    }

    @Provides
    @KeyguardBouncerScope
    static KeyguardSecurityViewFlipper providesKeyguardSecurityViewFlipper(
            KeyguardSecurityContainer containerView) {
        return containerView.findViewById(R.id.view_flipper);
    }

>2.keyguard_host_view.xml

  • 这个容器是动态添加到1.1小节里的容器里的
  • KeyguardSecurityViewFlipper到时候会根据不同的锁屏mode添加不同的view
<!--帧布局,控制器见小节6-->
<com.android.keyguard.KeyguardHostView
    android:id="@+id/keyguard_host_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false"
    android:clipToPadding="false"
    android:importantForAccessibility="yes"> <!-- Needed because TYPE_WINDOW_STATE_CHANGED is sent
                                                  from this view when bouncer is shown -->
<!--帧布局,小节5-->
    <com.android.keyguard.KeyguardSecurityContainer
        android:id="@+id/keyguard_security_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:padding="0dp"
        android:fitsSystemWindows="true"
        android:layout_gravity="center">
        <!--帧布局,可以滑动切换子类,小节8-->
        <com.android.keyguard.KeyguardSecurityViewFlipper
            android:id="@+id/view_flipper"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:clipChildren="false"
            android:clipToPadding="false"
            android:paddingTop="@dimen/keyguard_security_view_top_margin"
            android:layout_gravity="center"
            android:gravity="center">
        </com.android.keyguard.KeyguardSecurityViewFlipper>
    </com.android.keyguard.KeyguardSecurityContainer>

</com.android.keyguard.KeyguardHostView>

1.3.CentralSurfacesImpl

>1.startKeyguard

  • mKeyguardViewMediator就是StatusBarKeyguardViewManager,小节2
    protected void startKeyguard() {
//..参考1.4.1
        mKeyguardViewMediator.registerCentralSurfaces(
                /* statusBar= */ this,
                mNotificationPanelViewController,
                mPanelExpansionStateManager,
                mBiometricUnlockController,
                mStackScroller,
                mKeyguardBypassController);

    }

>2.dismissKeyguardThenExecute

隐藏keyguard并执行对应的action

    public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
            boolean afterKeyguardGone) {
        if (!action.willRunAnimationOnKeyguard()
                && mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
                && mKeyguardStateController.canDismissLockScreen()
                && !mStatusBarStateController.leaveOpenOnKeyguardHide()
                && mDozeServiceHost.isPulsing()) {
            //
            mBiometricUnlockController.startWakeAndUnlock(
                    BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
        }
        if (mKeyguardStateController.isShowing()) {
        //正在显示的话,隐藏并执行对应的action,参考2.6
            mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
                    afterKeyguardGone);
        } else {
            if (mKeyguardUpdateMonitor.isDreaming()) {
                awakenDreams();
            }//没有显示,直接执行对应的action
            action.onDismiss();
        }
    }

>3.isShadeDisabled

    public boolean isShadeDisabled() {
        return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
    }

>4.showBouncerWithDimissAndCancelIfKeyguard

有keyguard的话隐藏,并显示bouncer

    public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
            Runnable cancelAction) {
        if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
                && !mKeyguardViewMediator.isHiding()) {
                //参考2.6
            mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
                    false /* afterKeyguardGone */);
        } else if (cancelAction != null) {
            cancelAction.run();
        }
    }

1.4.KeyguardViewMediator

>1.registerCentralSurfaces

    public KeyguardViewController registerCentralSurfaces(CentralSurfaces centralSurfaces,
//..
        //参考补充2注解,get的对象就是小节2
        mKeyguardViewControllerLazy.get().registerCentralSurfaces(//2.1
                centralSurfaces,
                panelView,
                panelExpansionStateManager,
                biometricUnlockController,
                notificationContainer,
                bypassController);
        return mKeyguardViewControllerLazy.get();
    }

>2.ReferenceSystemUIModule

    @Binds
    abstract KeyguardViewController bindKeyguardViewController(
            StatusBarKeyguardViewManager statusBarKeyguardViewManager);

1.5.RedactionInterstitial.java

  • 设置锁屏密码,最后配置页面,看下不同选项都设置了啥
  • 加载的RedactionInterstitialFragment

>1.截图

image.png

>2.onCreateView

        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            return inflater.inflate(R.layout.redaction_interstitial, container, false);
        }

>3.onCheckedChanged

  • 3个RadioButton的点击事件如下
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            final boolean show = (checkedId == R.id.show_all);
            final boolean enabled = (checkedId != R.id.hide_all);

            Settings.Secure.putIntForUser(getContentResolver(),
                    LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0, mUserId);
            Settings.Secure.putIntForUser(getContentResolver(),
                    LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0, mUserId);

        }

2.StatusBarKeyguardViewManager.java

public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
        StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
        PanelExpansionListener, NavigationModeController.ModeChangedListener,
        KeyguardViewController, FoldAodAnimationController.FoldAodAnimationStatus {

2.1.registerCentralSurfaces

  • 参考1.3调用
    public void registerCentralSurfaces(CentralSurfaces centralSurfaces,
            NotificationPanelViewController notificationPanelViewController,
            PanelExpansionStateManager panelExpansionStateManager,
            BiometricUnlockController biometricUnlockController,
            View notificationContainer,
            KeyguardBypassController bypassController) {
        mCentralSurfaces = centralSurfaces;
        mBiometricUnlockController = biometricUnlockController;
        //容器获取参考1.1.2
        ViewGroup container = mCentralSurfaces.getBouncerContainer();
        //container传递给KeyguardBouncer的构造方法了,参考3.1.1
        mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback);
        
        mNotificationPanelViewController = notificationPanelViewController;
        if (panelExpansionStateManager != null) {//监听参考2.2
            panelExpansionStateManager.addExpansionListener(this);
        }
        mBypassController = bypassController;
        mNotificationContainer = notificationContainer;
        mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create(
            KeyguardMessageArea.findSecurityMessageDisplay(container));

        registerListeners();//注册一堆监听,参考补充代码
    }

>1.mUpdateMonitorCallback

  • 点击emergency按钮以后会走这里,参考10.3的点击事件
  • mOccluded只有在启动一个可以显示在锁屏页面之上的页面的时候才为true,也就是activity调用setShowWhenLocked(true)
//mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback);

    private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
            new KeyguardUpdateMonitorCallback() {
        @Override
        public void onEmergencyCallAction() {
            //mOccluded只有在启动一个可以显示在锁屏页面之上的页面的时候才为true
            if (mOccluded) {
                reset(true /* hideBouncerWhenShowing */);
            }
        }
    };

>2.onDozingChanged

//mStatusBarStateController.addCallback(this);

    public void onDozingChanged(boolean isDozing) {
        setDozing(isDozing);
    }
    private void setDozing(boolean dozing) {
        if (mDozing != dozing) {
            mDozing = dozing;
            if (dozing || mBouncer.needsFullscreenBouncer() || mOccluded) {
                reset(dozing /* hideBouncerWhenShowing */);
            }
            updateStates();

            if (!dozing) {
                launchPendingWakeupAction();
            }
        }
    }

>3.onThemeChanged

  • 主题改变,如果bouncer正在显示,那么销毁bouncer,并重新显示
//mConfigurationController.addCallback(this);

    public void onThemeChanged() {
        boolean wasShowing = mBouncer.isShowing();
        boolean wasScrimmed = mBouncer.isScrimmed();

        hideBouncer(true /* destroyView */);
        mBouncer.prepare();

        if (wasShowing) showBouncer(wasScrimmed);
    }
    public void onDensityOrFontScaleChanged() {
        hideBouncer(true /* destroyView */);
    }

2.2.onPanelExpansionChanged

  • Udfps:屏下指纹解锁装置
    public void onPanelExpansionChanged(PanelExpansionChangeEvent event) {
        float fraction = event.getFraction();
        boolean tracking = event.getTracking();
        // Avoid having the shade and the bouncer open at the same time over a dream.
        final boolean hideBouncerOverDream =
                mDreamOverlayStateController.isOverlayActive()
                        && (mNotificationPanelViewController.isExpanded()
                        || mNotificationPanelViewController.isExpanding());

        // 下边几种情况下我们不想进入密码界面:
        // 1,设备即将休眠
        //2,Keyguard阻塞中,因为我们正在一个标记了FLAG_SHOW_WHEN_LOCKED的activity中,需要保护原本的动画
        //3.用户快速多次点击屏幕,我们会在底部显示文字提示:"swipe up to unlock."
        // 4.特殊的action会隐藏keyguard ,比如: FLAG_DISMISS_KEYGUARD_ACTIVITY
        //5.全屏用户切换显示中
        if (mDozing && !mPulsing) {
            return;
        } else if (mNotificationPanelViewController.isUnlockHintRunning()) {
        //解锁完成中,不显示bouncer
            mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
        } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
                && mKeyguardUpdateManager.isUdfpsEnrolled()) {//有登记指纹
            //
            return;
        } else if (bouncerNeedsScrimming()) {//补充1
            mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
        } else if (mShowing && !hideBouncerOverDream) {
            if (!isWakeAndUnlocking()
                    && !mCentralSurfaces.isInLaunchTransition()
                    && !isUnlockCollapsing()) {
                mBouncer.setExpansion(fraction);
            }
            if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking
                    && !mKeyguardStateController.canDismissLockScreen()
                    && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
                    //显示,3.4
                mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
            }
        } else if (!mShowing && mBouncer.inTransit()) {
            // Keyguard is not visible anymore, but expansion animation was still running.
            // We need to keep propagating the expansion state to the bouncer, otherwise it will be
            // stuck in transit.
            mBouncer.setExpansion(fraction);
        } else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
            // Panel expanded while pulsing but didn't translate the bouncer (because we are
            // unlocked.) Let's simply wake-up to dismiss the lock screen.
            mCentralSurfaces.wakeUpIfDozing(
                    SystemClock.uptimeMillis(),
                    mCentralSurfaces.getBouncerContainer(),
                    "BOUNCER_VISIBLE");
        }
    }

>1.bouncerNeedsScrimming

    public boolean bouncerNeedsScrimming() {
        // When a dream overlay is active, scrimming will cause any expansion to immediately expand.
        return (mOccluded && !mDreamOverlayStateController.isOverlayActive())
                || mBouncer.willDismissWithAction() 
                || (mBouncer.isShowing() && mBouncer.isScrimmed())
                || mBouncer.isFullscreenBouncer();
    }

2.3.reset

隐藏bouncer,如果正在显示的话

    public void reset(boolean hideBouncerWhenShowing) {
        if (mShowing) {
            // Hide quick settings.
            mNotificationPanelViewController.resetViews(/* animate= */ true);
            // Hide bouncer and quick-quick settings.
            if (mOccluded && !mDozing) {
                mCentralSurfaces.hideKeyguard();
                if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
                    hideBouncer(false /* destroyView */);
                }
            } else {
                showBouncerOrKeyguard(hideBouncerWhenShowing);
            }
            resetAlternateAuth(false);
            mKeyguardUpdateManager.sendKeyguardReset();
            updateStates();
        }
    }

>1.showBouncerOrKeyguard

    protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
    //参考3.4.3两种sim模式下才为true
        if (mBouncer.needsFullscreenBouncer() && !mDozing) {
            // The keyguard might be showing (already). So we need to hide it.
            mCentralSurfaces.hideKeyguard();
            mBouncer.show(true /* resetSecuritySelection */);
        } else {
            mCentralSurfaces.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(false /* destroyView */);
                mBouncer.prepare();
            }
        }
        updateStates();
    }

>2.hideBouncer

    void hideBouncer(boolean destroyView) {
        if (mBouncer == null) {
            return;
        }
        mBouncer.hide(destroyView);
        if (mShowing) {
            // If we were showing the bouncer and then aborting, we need to also clear out any
            // potential actions unless we actually unlocked.
            cancelPostAuthActions();
        }
        cancelPendingWakeupAction();
    }

2.4.show

    public void show(Bundle options) {
        mShowing = true;

        mNotificationShadeWindowController.setKeyguardShowing(true);
                //参考11.1
        mKeyguardStateController.notifyKeyguardState(mShowing,
                mKeyguardStateController.isOccluded());
        reset(true /* hideBouncerWhenShowing */);
    }

2.5.hide

    public void hide(long startTime, long fadeoutDuration) {
        mShowing = false;
        //参考11.1
        mKeyguardStateController.notifyKeyguardState(mShowing,
                mKeyguardStateController.isOccluded());
        launchPendingWakeupAction();

        if (mKeyguardUpdateManager.needsSlowUnlockTransition()) {
            fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
        }
        long uptimeMillis = SystemClock.uptimeMillis();
        long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);

        if (mCentralSurfaces.isInLaunchTransition()
                || mKeyguardStateController.isFlingingToDismissKeyguard()) {
            final boolean wasFlingingToDismissKeyguard =
                    mKeyguardStateController.isFlingingToDismissKeyguard();
            mCentralSurfaces.fadeKeyguardAfterLaunchTransition(new Runnable() {
                @Override
                public void run() {
                    mNotificationShadeWindowController.setKeyguardShowing(false);
                    mNotificationShadeWindowController.setKeyguardFadingAway(true);
                    hideBouncer(true /* destroyView */);
                    updateStates();
                }
            }, /* endRunnable */ new Runnable() {
                @Override
                public void run() {
                    mCentralSurfaces.hideKeyguard();
                    mNotificationShadeWindowController.setKeyguardFadingAway(false);

                    if (wasFlingingToDismissKeyguard) {
                        mCentralSurfaces.finishKeyguardFadingAway();
                    }

                    mViewMediatorCallback.keyguardGone();
                    executeAfterKeyguardGoneAction();
                }
            }, /* cancelRunnable */ new Runnable() {
                @Override
                public void run() {
                    mNotificationShadeWindowController.setKeyguardFadingAway(false);
                    if (wasFlingingToDismissKeyguard) {
                        mCentralSurfaces.finishKeyguardFadingAway();
                    }
                    cancelPostAuthActions();
                }
            });
        } else {
            executeAfterKeyguardGoneAction();
            boolean wakeUnlockPulsing =
                    mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING;
            boolean needsFading = needsBypassFading();
            if (needsFading) {
                delay = 0;
                fadeoutDuration = KeyguardBypassController.BYPASS_FADE_DURATION;
            } else if (wakeUnlockPulsing) {
                delay = 0;
                fadeoutDuration = 240;
            }
            mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration, needsFading);
            mBiometricUnlockController.startKeyguardFadingAway();
            hideBouncer(true /* destroyView */);
            if (wakeUnlockPulsing) {
                if (needsFading) {
                    ViewGroupFadeHelper.fadeOutAllChildrenExcept(
                            mNotificationPanelViewController.getView(),
                            mNotificationContainer,
                            fadeoutDuration,
                                    () -> {
                        mCentralSurfaces.hideKeyguard();
                        onKeyguardFadedAway();
                    });
                } else {
                    mCentralSurfaces.fadeKeyguardWhilePulsing();
                }
                wakeAndUnlockDejank();
            } else {
                boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
                if (!staying) {
                    mNotificationShadeWindowController.setKeyguardFadingAway(true);
                    if (needsFading) {
                        ViewGroupFadeHelper.fadeOutAllChildrenExcept(
                                mNotificationPanelViewController.getView(),
                                mNotificationContainer,
                                fadeoutDuration,
                                () -> {
                                    mCentralSurfaces.hideKeyguard();
                                });
                    } else {
                        mCentralSurfaces.hideKeyguard();
                    }
                    // hide() will happen asynchronously and might arrive after the scrims
                    // were already hidden, this means that the transition callback won't
                    // be triggered anymore and StatusBarWindowController will be forever in
                    // the fadingAway state.
                    mCentralSurfaces.updateScrimController();
                    wakeAndUnlockDejank();
                } else {
                    mCentralSurfaces.hideKeyguard();
                    mCentralSurfaces.finishKeyguardFadingAway();
                    mBiometricUnlockController.finishKeyguardFadingAway();
                }
            }
            updateStates();
            mNotificationShadeWindowController.setKeyguardShowing(false);
            mViewMediatorCallback.keyguardGone();
        }
        SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
                SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
        Trace.endSection();
    }

2.6.dismissWithAction

    public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
            boolean afterKeyguardGone, String message) {
        if (mKeyguardStateController.isShowing()) {
            try {
                cancelPendingWakeupAction();
                //如果正在休眠中,并且非 唤醒解锁中,则等待唤醒再处理
                if (mDozing && !isWakeAndUnlocking()) {
                    mPendingWakeupAction = new DismissWithActionRequest(
                            r, cancelAction, afterKeyguardGone, message);
                    return;
                }

                mAfterKeyguardGoneAction = r;
                mKeyguardGoneCancelAction = cancelAction;
                mDismissActionWillAnimateOnKeyguard = r != null && r.willRunAnimationOnKeyguard();

                //如果有其他验证器,比如人脸识别,则显示人脸识别相关的验证
                if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
                    if (!afterKeyguardGone) {
                        mPrimaryBouncerInteractor.setDismissAction(mAfterKeyguardGoneAction,
                                mKeyguardGoneCancelAction);
                        mAfterKeyguardGoneAction = null;
                        mKeyguardGoneCancelAction = null;
                    }

                    updateAlternateBouncerShowing(mAlternateBouncerInteractor.show());
                    return;
                }

                if (afterKeyguardGone) {
                    // we'll handle the dismiss action after keyguard is gone, so just show the
                    // bouncer
                    //直接显示bouncer
                    mPrimaryBouncerInteractor.show(/* isScrimmed= */true);
                } else {
                    // after authentication success, run dismiss action with the option to defer
                    // hiding the keyguard based on the return value of the OnDismissAction
                    mPrimaryBouncerInteractor.setDismissAction(
                            mAfterKeyguardGoneAction, mKeyguardGoneCancelAction);
                    mPrimaryBouncerInteractor.show(/* isScrimmed= */true);
                    // bouncer will handle the dismiss action, so we no longer need to track it here
                    mAfterKeyguardGoneAction = null;
                    mKeyguardGoneCancelAction = null;
                }
            }
        }
        updateStates();
    }

3.KeyguardBouncer.java

    static final long BOUNCER_FACE_DELAY = 1200;
    public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f;
    public static final float EXPANSION_HIDDEN = 1f;
    public static final float EXPANSION_VISIBLE = 0f;

    private KeyguardHostViewController mKeyguardViewController;

3.1.Factory

    public static class Factory {

>1.create

创建一个实例

        public KeyguardBouncer create(ViewGroup container,
                BouncerExpansionCallback expansionCallback) {
            return new KeyguardBouncer(mContext, mCallback, container,
                    mDismissCallbackRegistry, mFalsingCollector, expansionCallback,
                    mKeyguardStateController, mKeyguardUpdateMonitor,
                    mKeyguardBypassController, mHandler, mKeyguardSecurityModel,
                    mKeyguardBouncerComponentFactory);
        }

3.2.inflateView

protected final ViewGroup mContainer;//构造方法里赋值
    protected void inflateView() {
        removeView();//清空mContainer的child
        mHandler.removeCallbacks(mRemoveViewRunnable);
//参考1.2,调用Factory的create方法
        KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create(mContainer);
        //注解获取
        mKeyguardViewController = component.getKeyguardHostViewController();
        mKeyguardViewController.init();

        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
        //设置容器mContainer不可见
        setVisibility(View.INVISIBLE);

        final WindowInsets rootInsets = mContainer.getRootWindowInsets();
        if (rootInsets != null) {
            mContainer.dispatchApplyWindowInsets(rootInsets);
        }
        mInitialized = true;
    }

3.3.setExpansion

    public void setExpansion(float fraction) {
        float oldExpansion = mExpansion;
        boolean expansionChanged = mExpansion != fraction;
        mExpansion = fraction;
        if (mKeyguardViewController != null && !mIsAnimatingAway) {
            mKeyguardViewController.setExpansion(fraction);
        }

        if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) {
        //完全显示
            onFullyShown();
            dispatchFullyShown();
        } else if (fraction == EXPANSION_HIDDEN && oldExpansion != EXPANSION_HIDDEN) {
        //完全隐藏
            onFullyHidden();
            dispatchFullyHidden();
        } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) {
        //旧的是完全显示,新的不是,那么开始隐藏
            dispatchStartingToHide();
            if (mKeyguardViewController != null) {
            //隐藏keyguard控件
                mKeyguardViewController.onStartingToHide();
            }
        }

        if (expansionChanged) {
            dispatchExpansionChanged();
        }
    }

>1.onFullyShown

    private void onFullyShown() {
        mFalsingCollector.onBouncerShown();
        if (mKeyguardViewController == null) {
        } else {
            mKeyguardViewController.onResume();
        }
    }

>2.onFullyHidden

    private void onFullyHidden() {
        cancelShowRunnable();
        setVisibility(View.INVISIBLE);//使容器不可见
        mFalsingCollector.onBouncerHidden();
        DejankUtils.postAfterTraversal(mResetRunnable);
    }

3.4.show

    public void show(boolean resetSecuritySelection) {
        show(resetSecuritySelection, true /* scrimmed */);
    }
    public void show(boolean resetSecuritySelection, boolean isScrimmed) {
        final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
        if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
            //系统用户和主用户是否是分开的,默认是false,也就是一体的
            return;
        }
        try {
            ensureView();//补充1
            mIsScrimmed = isScrimmed;

            if (isScrimmed) {
                setExpansion(EXPANSION_VISIBLE);//0f
            }

            if (resetSecuritySelection) {
                //更新当前的安全方法,已经显示并且安全方法发生变化的情况
                showPrimarySecurityScreen();
            }
            //容器已经显示或者即将显示
            if (mContainer.getVisibility() == View.VISIBLE || mShowingSoon) {
                //补充3
                if (needsFullscreenBouncer()) {
                    mKeyguardViewController.onResume();
                }
                return;
            }

            final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
            final boolean isSystemUser =
                UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
            final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;

            //允许退出keyguard并且可以退出(没有设置安全锁)6.3
            if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) {
                return;
            }

            mShowingSoon = true;

            // Split up the work over multiple frames.
            DejankUtils.removeCallbacks(mResetRunnable);
            //有人脸识别的,延迟显示
            if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer()
                && !mKeyguardUpdateMonitor.userNeedsStrongAuth()
                && !mKeyguardBypassController.getBypassEnabled()) {
                mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
            } else {
                DejankUtils.postAfterTraversal(mShowRunnable);//补充4
            }

            mKeyguardStateController.notifyBouncerShowing(true /* showing */);
            dispatchStartingToShow();
        }
    }

>1.ensureView

确保视图已经加载

    protected void ensureView() {
        boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
        if (!mInitialized || forceRemoval) {
            inflateView();//参考3.2
        }
    }

>2.showPrimarySecurityScreen

    private void showPrimarySecurityScreen() {
        mKeyguardViewController.showPrimarySecurityScreen();
    }

>3.needsFullscreenBouncer

安全模式是如下两种sim卡相关的,则需要全屏模式,其他的不需要

    public boolean needsFullscreenBouncer() {
        SecurityMode mode = mKeyguardSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser());
        return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
    }

>4.mShowRunnable

    private final Runnable mShowRunnable = new Runnable() {
        @Override
        public void run() {
            setVisibility(View.VISIBLE);//容器可见
            showPromptReason(mBouncerPromptReason);
            final CharSequence customMessage = mCallback.consumeCustomMessage();
            if (customMessage != null) {
                mKeyguardViewController.showErrorMessage(customMessage);
            }
            mKeyguardViewController.appear(mStatusBarHeight);
            mShowingSoon = false;
            if (mExpansion == EXPANSION_VISIBLE) {
                mKeyguardViewController.onResume();
                mKeyguardViewController.resetSecurityContainer();
                showPromptReason(mBouncerPromptReason);
            }
        }
    };

4.KeyguardSecurityContainerController

4.1.Factory

Factory注解生成的

    static class Factory {
        public KeyguardSecurityContainerController create(
                SecurityCallback securityCallback) {
            return new KeyguardSecurityContainerController(mView,
                    mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
                    mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
                    mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
                    mConfigurationController, mFalsingCollector, mFalsingManager,
                    mUserSwitcherController, mFeatureFlags, mGlobalSettings, mSessionTracker);
        }

4.2.onViewAttached

    protected void onViewAttached() {
        mUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
        mView.setSwipeListener(mSwipeListener);
        mView.addMotionEventListener(mGlobalTouchListener);
        mConfigurationController.addCallback(mConfigurationListener);
        mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
    }

>1.mSwipeListener

    private SwipeListener mSwipeListener = new SwipeListener() {
        @Override
        public void onSwipeUp() {
        //人脸识别没有启动,那么请求人脸识别
            if (!mUpdateMonitor.isFaceDetectionRunning()) {
                mUpdateMonitor.requestFaceAuth(true);
                mKeyguardSecurityCallback.userActivity();
                showMessage(null, null);
            }
            //人脸识别成功
            if (mUpdateMonitor.isFaceEnrolled()) {
                mUpdateMonitor.requestActiveUnlock(
                        ActiveUnlockConfig.ACTIVE_UNLOCK_REQUEST_ORIGIN.UNLOCK_INTENT,
                        "swipeUpOnBouncer");
            }
        }
    };

4.3.onResume

    public void onResume(int reason) {
        if (mCurrentSecurityMode != SecurityMode.None) {
            getCurrentSecurityController().onResume(reason);
        }
        //5.7
        mView.onResume(
                mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
                mKeyguardStateController.isFaceAuthEnabled());
    }

>1.getCurrentSecurityController

    private KeyguardInputViewController<KeyguardInputView> getCurrentSecurityController() {
        return mSecurityViewFlipperController
                .getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback);
    }

4.4.updateResources

5.3.1调用

    public void updateResources() {
        int newOrientation = getResources().getConfiguration().orientation;
        if (newOrientation != mLastOrientation) {//屏幕方向发生变化,更新mode
            mLastOrientation = newOrientation;
            configureMode();//4.5
        }
    }

4.5.configureMode

    private void configureMode() {
        boolean useSimSecurity = mCurrentSecurityMode == SecurityMode.SimPin
                || mCurrentSecurityMode == SecurityMode.SimPuk;
        int mode = KeyguardSecurityContainer.MODE_DEFAULT;
        //可以展示用户切换(补充1)并且非sim锁定
        if (canDisplayUserSwitcher() && !useSimSecurity) {
            mode = KeyguardSecurityContainer.MODE_USER_SWITCHER;
        } else if (canUseOneHandedBouncer()) {//补充2
            mode = KeyguardSecurityContainer.MODE_ONE_HANDED;
        }
        mView.initMode(mode, mGlobalSettings, mFalsingManager, mUserSwitcherController);
    }

>1.canDisplayUserSwitcher

  • 默认配置是false,就是是否一边显示user,一边显示bouncer
    private boolean canDisplayUserSwitcher() {
        return mFeatureFlags.isEnabled(Flags.BOUNCER_USER_SWITCHER);
    }

>2.canUseOneHandedBouncer

  • pattern 或者 pin 才可能支持单手模式,还得看配置
    private boolean canUseOneHandedBouncer() {
        if (!(mCurrentSecurityMode == SecurityMode.Pattern
                || mCurrentSecurityMode == SecurityMode.PIN)) {
            return false;
        }
    //竖屏是false,横屏是true
        return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
    }

4.6.showPrimarySecurityScreen

显示锁屏页面

    public void showPrimarySecurityScreen(boolean turningOff) {
    //获取锁屏模式
        SecurityMode securityMode = whitelistIpcs(() -> mSecurityModel.getSecurityMode(
                KeyguardUpdateMonitor.getCurrentUser()));
         //见4.7       
        showSecurityScreen(securityMode);
    }

4.7.showSecurityScreen

  • 有旧的就销毁旧的模式,加载新的模式
    void showSecurityScreen(SecurityMode securityMode) {

        if (securityMode == SecurityMode.Invalid || securityMode == mCurrentSecurityMode) {
            return;
        }

        KeyguardInputViewController<KeyguardInputView> oldView = getCurrentSecurityController();
    //销毁旧的
        if (oldView != null) {
            oldView.onPause();
        }

        KeyguardInputViewController<KeyguardInputView> newView = changeSecurityMode(securityMode);
        if (newView != null) {
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
            mSecurityViewFlipperController.show(newView);
            configureMode();
        }

        mSecurityCallback.onSecurityModeChanged(
                securityMode, newView != null && newView.needsInput());
    }

>1.changeSecurityMode

    private KeyguardInputViewController<KeyguardInputView> changeSecurityMode(
            SecurityMode securityMode) {
        mCurrentSecurityMode = securityMode;
        return getCurrentSecurityController();//参考4.3.1
    }

4.8.showNextSecurityScreenOrFinish

  • 如果有的话显示下一个安全屏幕
    public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
            boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {

        if (expectedSecurityMode != SecurityMode.Invalid
                && expectedSecurityMode != getCurrentSecurityMode()) {
//要显示的和当前的mode不一样
            return false;
        }

        boolean finish = false;
        boolean strongAuth = false;
        int eventSubtype = -1;
        BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;
        if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
            finish = true;
            eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;
        } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) {
            finish = true;
            eventSubtype = BOUNCER_DISMISS_BIOMETRIC;
            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;
        } else if (SecurityMode.None == getCurrentSecurityMode()) {//当前控制器的安全模式是空
            SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
            //系统安全模式是空
            if (SecurityMode.None == securityMode) {
                finish = true; // no security required
                eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
                uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;
            } else {//4.7
                showSecurityScreen(securityMode);
            }
        } else if (authenticated) {//已经验证成功
            switch (getCurrentSecurityMode()) {
                case Pattern:
                case Password:
                case PIN:
                    strongAuth = true;
                    finish = true;
                    eventSubtype = BOUNCER_DISMISS_PASSWORD;
                    uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;
                    break;

                case SimPin:
                case SimPuk:
                    SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
                    boolean isLockscreenDisabled = mLockPatternUtils.isLockScreenDisabled(
                            KeyguardUpdateMonitor.getCurrentUser())
                            || !mDeviceProvisionedController.isUserSetup(targetUserId);

                    if (securityMode == SecurityMode.None && isLockscreenDisabled) {
                        finish = true;
                        eventSubtype = BOUNCER_DISMISS_SIM;
                        uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
                    } else {
                        showSecurityScreen(securityMode);
                    }
                    break;

                default:
                    showPrimarySecurityScreen(false);
                    break;
            }
        }
        // Check for device admin specified additional security measures.
        if (finish && !bypassSecondaryLockScreen) {
            Intent secondaryLockscreenIntent =
                    mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId);
            if (secondaryLockscreenIntent != null) {
                mAdminSecondaryLockScreenController.show(secondaryLockscreenIntent);
                return false;
            }
        }

        if (finish) {
            mSecurityCallback.finish(strongAuth, targetUserId);
        }
        return finish;
    }

5.KeyguardSecurityContainer.java

5.1.Mode

三种mode,默认的,单手模式,用户切换模式

    @IntDef({MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
    public @interface Mode {}
    static final int MODE_DEFAULT = 0;
    static final int MODE_ONE_HANDED = 1;
    static final int MODE_USER_SWITCHER = 2;

>1.initMode

    void initMode(@Mode int mode, GlobalSettings globalSettings, FalsingManager falsingManager,
            UserSwitcherController userSwitcherController) {
        if (mCurrentMode == mode) return;
        mCurrentMode = mode;
        mViewMode.onDestroy();

        switch (mode) {
            case MODE_ONE_HANDED:
                mViewMode = new OneHandedViewMode();
                break;
            case MODE_USER_SWITCHER:
                mViewMode = new UserSwitcherViewMode();
                break;
            default:
                mViewMode = new DefaultViewMode();
        }
        mGlobalSettings = globalSettings;
        mFalsingManager = falsingManager;
        mUserSwitcherController = userSwitcherController;
        setupViewMode();//补充2
    }

>2.setupViewMode

  • 初始化对应的ViewMode
    private void setupViewMode() {
//.
        mViewMode.init(this, mGlobalSettings, mSecurityViewFlipper, mFalsingManager,
                mUserSwitcherController);
    }

下边简单看下3种模式的区别

5.2.OneHandedViewMode

  • 宽度是容器的一半,横屏模式从左侧往上滑显示在左侧,从右侧往上滑显示在右侧

>1.init

        public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
                @NonNull KeyguardSecurityViewFlipper viewFlipper,
                @NonNull FalsingManager falsingManager,
                @NonNull UserSwitcherController userSwitcherController) {
            mView = v;
            mViewFlipper = viewFlipper;
            mGlobalSettings = globalSettings;
        //更新重心
            updateSecurityViewGravity();
            //更新flipper控件的位置,参考补充2和3
            updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
        }

>2.isLeftAligned

是否左对齐,默认为true,可以修改settings值

        boolean isLeftAligned() {
            return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT)
                == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
        }

>3.updateSecurityViewLocation

  • 默认左对齐,啥也不干,右对齐的话,往右移动一定的距离
        private void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
            int targetTranslation = leftAlign
                    ? 0 : (int) (mView.getMeasuredWidth() - mViewFlipper.getWidth());
            if (animate) {
    //...
            } else {
                mViewFlipper.setTranslationX(targetTranslation);
            }
        }

>4.getChildWidthMeasureSpec

  • 单手模式,child的宽度是容器宽度的一半
        public int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
            return MeasureSpec.makeMeasureSpec(
                    MeasureSpec.getSize(parentWidthMeasureSpec) / 2,
                    MeasureSpec.EXACTLY);
        }

>5.updateSecurityViewGravity

  • 默认布局重心是 left|bottom,后边根据手势改变
        private void updateSecurityViewGravity() {
            FrameLayout.LayoutParams lp =
                    (FrameLayout.LayoutParams) mViewFlipper.getLayoutParams();
            lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
            mViewFlipper.setLayoutParams(lp);
        }

>6.updatePositionByTouchX

  • 根据触摸位置修改child的位置,触摸位置在容器的左侧,child显示在左边,触摸位置在容器的右侧,那么child显示在右侧
        public void updatePositionByTouchX(float x) {
        //容器宽度的一半,左边的话当左手,右边的话当右手
            boolean isTouchOnLeft = x <= mView.getWidth() / 2f;
            updateSideSetting(isTouchOnLeft);//补充7,更改settings值
            updateSecurityViewLocation(isTouchOnLeft, /* animate= */false);
        }

>7.updateSideSetting

        private void updateSideSetting(boolean leftAligned) {
            mGlobalSettings.putInt(
                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
                    leftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
                    : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
        }

>8.handleTap

  • 根据点击位置切换九宫格显示的位置
        public void handleTap(MotionEvent event) {
            float x = event.getX();
            boolean currentlyLeftAligned = isLeftAligned();
            //当前显示在左侧点击右侧 或者 当前显示在右侧点击左侧 ,切换显示
            if ((currentlyLeftAligned && (x > mView.getWidth() / 2f))
                    || (!currentlyLeftAligned && (x < mView.getWidth() / 2f))) {
                boolean willBeLeftAligned = !currentlyLeftAligned;
                updateSideSetting(willBeLeftAligned);
//补充3
                updateSecurityViewLocation(willBeLeftAligned, true /* animate */);
            }
        }

5.3.UserSwitcherViewMode

>1.init

        public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
                @NonNull KeyguardSecurityViewFlipper viewFlipper,
                @NonNull FalsingManager falsingManager,
                @NonNull UserSwitcherController userSwitcherController) {
            mView = v;
            mViewFlipper = viewFlipper;
            mFalsingManager = falsingManager;
            mUserSwitcherController = userSwitcherController;
            mResources = v.getContext().getResources();

            if (mUserSwitcherViewGroup == null) {
                LayoutInflater.from(v.getContext()).inflate(
                        R.layout.keyguard_bouncer_user_switcher,
                        mView,
                        true);
                mUserSwitcherViewGroup =  mView.findViewById(R.id.keyguard_bouncer_user_switcher);
            }

            updateSecurityViewLocation();

            mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
            setupUserSwitcher();
            mUserSwitcherController.addUserSwitchCallback(mUserSwitchCallback);
        }

>2.updateSecurityViewLocation

        public void updateSecurityViewLocation() {
            int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans);
//竖屏
            if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            //水平居中
                updateViewGravity(mViewFlipper, Gravity.CENTER_HORIZONTAL);
                updateViewGravity(mUserSwitcherViewGroup, Gravity.CENTER_HORIZONTAL);
            //一个往下移,一个往上移
                mUserSwitcherViewGroup.setTranslationY(yTrans);
                mViewFlipper.setTranslationY(-yTrans);
            } else {
            //右下角
                updateViewGravity(mViewFlipper, Gravity.RIGHT | Gravity.BOTTOM);
                //左侧垂直居中
                updateViewGravity(mUserSwitcherViewGroup, Gravity.LEFT | Gravity.CENTER_VERTICAL);

                //往上移动一点距离
                mUserSwitcherViewGroup.setTranslationY(-yTrans);
                mViewFlipper.setTranslationY(0);
            }
        }

        private void updateViewGravity(View v, int gravity) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
            lp.gravity = gravity;
            v.setLayoutParams(lp);
        }

5.4.DefaultViewMode

默认的mode是水平居中

>1.updateSecurityViewGroup

        private void updateSecurityViewGroup() {
            FrameLayout.LayoutParams lp =
                    (FrameLayout.LayoutParams) mViewFlipper.getLayoutParams();
            lp.gravity = Gravity.CENTER_HORIZONTAL;
            mViewFlipper.setLayoutParams(lp);
            mViewFlipper.setTranslationX(0);
        }

5.5.onInterceptTouchEvent

    public boolean onInterceptTouchEvent(MotionEvent event) {
    //先看一堆listener里有没有拦击触摸事件
        boolean result =  mMotionEventListeners.stream().anyMatch(
                listener -> listener.onInterceptTouchEvent(event))
                || super.onInterceptTouchEvent(event);

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                int pointerIndex = event.getActionIndex();
                mStartTouchY = event.getY(pointerIndex);
                mActivePointerId = event.getPointerId(pointerIndex);
                mVelocityTracker.clear();
                break;
            case MotionEvent.ACTION_MOVE:
                if (mIsDragging) {
                    return true;
                }
                if (!mSwipeUpToRetry) {
                    return false;
                }
                // Avoid dragging the pattern view
                if (mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) {
                    return false;
                }
                int index = event.findPointerIndex(mActivePointerId);
                float touchSlop = mViewConfiguration.getScaledTouchSlop() * SLOP_SCALE;
                if (index != -1 && mStartTouchY - event.getY(index) > touchSlop) {
                    mIsDragging = true;
                    return true;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mIsDragging = false;
                break;
        }
        return result;
    }

5.6.onTouchEvent

    public boolean onTouchEvent(MotionEvent event) {
        final int action = event.getActionMasked();
//循环所有的listener看是否处理了
        boolean result =  mMotionEventListeners.stream()
                .anyMatch(listener -> listener.onTouchEvent(event))
                || super.onTouchEvent(event);

        switch (action) {
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                int pointerIndex = event.findPointerIndex(mActivePointerId);
                float y = event.getY(pointerIndex);
                if (mLastTouchY != -1) {
                    float dy = y - mLastTouchY;
                    //上下滑动的时候会移动控件位置
                    setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
                }
                mLastTouchY = y;
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mActivePointerId = -1;
                mLastTouchY = -1;
                mIsDragging = false;
                startSpringAnimation(mVelocityTracker.getYVelocity());
                break;
            case MotionEvent.ACTION_POINTER_UP:
                int index = event.getActionIndex();
                int pointerId = event.getPointerId(index);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = index == 0 ? 1 : 0;
                    mLastTouchY = event.getY(newPointerIndex);
                    mActivePointerId = event.getPointerId(newPointerIndex);
                }
                break;
        }
        if (action == MotionEvent.ACTION_UP) {
        //判断往上移动是否超过10dp,是的话执行swipe up回调
            if (-getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    MIN_DRAG_SIZE, getResources().getDisplayMetrics())) {
                if (mSwipeListener != null) {
                    mSwipeListener.onSwipeUp();
                }
            } else {
                if (!mIsDragging) {
                    mViewMode.handleTap(event);//5.2.8切换显示位置
                }
            }
        }
        return true;
    }

5.7.onResume

更新安全模式以及人脸识别是否可用

    void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
        mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
        updateBiometricRetry(securityMode, faceAuthEnabled);//补充1
    }

>1.updateBiometricRetry

  • 上划是否重新尝试解锁,人脸认证可用并且安全模式不是如下3种
    private void updateBiometricRetry(SecurityMode securityMode, boolean faceAuthEnabled) {
        mSwipeUpToRetry = faceAuthEnabled
                && securityMode != SecurityMode.SimPin
                && securityMode != SecurityMode.SimPuk
                && securityMode != SecurityMode.None;
    }

6.KeyguardHostViewController

6.1.onInit

    public void onInit() {
        mKeyguardSecurityContainerController.init();
        updateResources();//补充1
    }

>1.updateResources

    public void updateResources() {
        int gravity;
        Resources resources = mView.getResources();
//根据can_use_one_handed_bouncer的值不同,重心不同
        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
            gravity = resources.getInteger(
                    R.integer.keyguard_host_view_one_handed_gravity);//0x51
        } else {//默认0x51,sw600dp的是0x11
            gravity = resources.getInteger(R.integer.keyguard_host_view_gravity);
        }
        mTranslationY = resources
                .getDimensionPixelSize(R.dimen.keyguard_host_view_translation_y);
        if (mView.getLayoutParams() instanceof FrameLayout.LayoutParams) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mView.getLayoutParams();
            if (lp.gravity != gravity) {
                lp.gravity = gravity;
                mView.setLayoutParams(lp);
            }
        }

        if (mKeyguardSecurityContainerController != null) {
            mKeyguardSecurityContainerController.updateResources();
        }
    }

6.2.onViewAttached

    protected void onViewAttached() {
        mView.setViewMediatorCallback(mViewMediatorCallback);
        // Update ViewMediator with the current input method requirements
        mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput());
        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
        mView.setOnKeyListener(mOnKeyListener);
        mKeyguardSecurityContainerController.showPrimarySecurityScreen(false);
    }

6.3.dismiss

    public boolean dismiss(int targetUserId) {
        return mSecurityCallback.dismiss(false, targetUserId, false,
                getCurrentSecurityMode());
    }

>1.mSecurityCallback

    private final SecurityCallback mSecurityCallback = new SecurityCallback() {

        @Override
        public boolean dismiss(boolean authenticated, int targetUserId,
                boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
                //
            return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
                    authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
        }

        @Override
        public void userActivity() {
            mViewMediatorCallback.userActivity();
        }

        @Override
        public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
            mViewMediatorCallback.setNeedsInput(needsInput);
        }

        /**
         * Authentication has happened and it's time to dismiss keyguard. This function
         * should clean up and inform KeyguardViewMediator.
         *
         * @param strongAuth whether the user has authenticated with strong authentication like
         *                   pattern, password or PIN but not by trust agents or fingerprint
         * @param targetUserId a user that needs to be the foreground user at the dismissal
         *                    completion.
         */
        @Override
        public void finish(boolean strongAuth, int targetUserId) {
            // If there's a pending runnable because the user interacted with a widget
            // and we're leaving keyguard, then run it.
            boolean deferKeyguardDone = false;
            if (mDismissAction != null) {
                deferKeyguardDone = mDismissAction.onDismiss();
                mDismissAction = null;
                mCancelAction = null;
            }
            if (mViewMediatorCallback != null) {
                if (deferKeyguardDone) {
                    mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
                } else {
                    mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
                }
            }
        }

        @Override
        public void reset() {
            mViewMediatorCallback.resetKeyguard();
        }

        @Override
        public void onCancelClicked() {
            mViewMediatorCallback.onCancelClicked();
        }
    };

7.KeyguardSecurityViewFlipperController

注解生成的

7.1.getSecurityView

根据给定的锁屏模式,返回对应模式的控制器

    KeyguardInputViewController<KeyguardInputView> getSecurityView(SecurityMode securityMode,
            KeyguardSecurityCallback keyguardSecurityCallback) {
        KeyguardInputViewController<KeyguardInputView> childController = null;
        //先查找集合里是否已有对应的controller
        for (KeyguardInputViewController<KeyguardInputView> child : mChildren) {
            if (child.getSecurityMode() == securityMode) {
                childController = child;
                break;
            }
        }

        if (childController == null
                && securityMode != SecurityMode.None && securityMode != SecurityMode.Invalid) {
    //集合里没有,这里创建新的,补充1
            int layoutId = getLayoutIdFor(securityMode);
            KeyguardInputView view = null;
            if (layoutId != 0) {
            //创建view
                view = (KeyguardInputView) mLayoutInflater.inflate(
                        layoutId, mView, false);
                mView.addView(view);
            //根据Factory获取对应的controller
                childController = mKeyguardSecurityViewControllerFactory.create(
                        view, securityMode, keyguardSecurityCallback);
                childController.init();
            //加入集合
                mChildren.add(childController);
            }
        }

        if (childController == null) {
        //走到这里说明没有设置安全锁,返回一个空的controller
            childController = new NullKeyguardInputViewController(
                    securityMode, keyguardSecurityCallback,
                    mEmergencyButtonControllerFactory.create(null));
        }

        return childController;
    }

>1.getLayoutIdFor

根据锁屏模式返回对应的布局

    private int getLayoutIdFor(SecurityMode securityMode) {
        switch (securityMode) {
            case Pattern: return R.layout.keyguard_pattern_view;
            case PIN: return R.layout.keyguard_pin_view;
            case Password: return R.layout.keyguard_password_view;
            case SimPin: return R.layout.keyguard_sim_pin_view;
            case SimPuk: return R.layout.keyguard_sim_puk_view;
            default:
                return 0;
        }
    }

>2.keyguard_pattern_view

  • KeyguardPatternView,继承的KeyguardInputView,线性布局
<com.android.keyguard.KeyguardPatternView
    android:id="@+id/keyguard_pattern_view"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    androidprv:layout_maxWidth="@dimen/keyguard_security_width"
    android:layout_gravity="center_horizontal|bottom"
    android:clipChildren="false"
    android:clipToPadding="false">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/pattern_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_weight="1"
        android:layoutDirection="ltr">
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/pattern_top_guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            androidprv:layout_constraintGuide_percent="0"
            android:orientation="horizontal" />

        <com.android.internal.widget.LockPatternView
            android:id="@+id/lockPatternView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            androidprv:layout_constraintTop_toBottomOf="@id/pattern_top_guideline"
            androidprv:layout_constraintBottom_toBottomOf="parent"
            androidprv:layout_constraintLeft_toLeftOf="parent"
            androidprv:layout_constraintRight_toRightOf="parent"
            androidprv:layout_constraintDimensionRatio="1.0"
            androidprv:layout_constraintVertical_bias="1.0"
            />
    </androidx.constraintlayout.widget.ConstraintLayout>
    <!-- 这个就是emergency按钮的布局,资源文件里定义的,指向另外的布局-->
    <include layout="@layout/keyguard_eca"
        android:id="@+id/keyguard_selector_fade_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_gravity="bottom|center_horizontal"
        android:layout_marginTop="@dimen/keyguard_eca_top_margin"
        android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
        android:gravity="center_horizontal" />

</com.android.keyguard.KeyguardPatternView>

7.2.show

    public void show(KeyguardInputViewController<KeyguardInputView> childController) {
        int index = childController.getIndexIn(mView);
        if (index != -1) {
            mView.setDisplayedChild(index);
        }
    }

8.KeyguardSecurityViewFlipper

ViewFlipper是系统控件,帧布局,就是多个child切换显示的,可以带动画的,一次只能显示一个。

public class KeyguardSecurityViewFlipper extends ViewFlipper {

8.1.onTouchEvent

  • 同步交给child看是否处理
    public boolean onTouchEvent(MotionEvent ev) {
        boolean result = super.onTouchEvent(ev);
        mTempRect.set(0, 0, 0, 0);
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child.getVisibility() == View.VISIBLE) {
                offsetRectIntoDescendantCoords(child, mTempRect);
                ev.offsetLocation(mTempRect.left, mTempRect.top);
                result = child.dispatchTouchEvent(ev) || result;
                ev.offsetLocation(-mTempRect.left, -mTempRect.top);
            }
        }
        return result;
    }

8.2.getSecurityView

getDisplayedChild()返回的就是当前展示的view的id

    KeyguardInputView getSecurityView() {
        View child = getChildAt(getDisplayedChild());
        if (child instanceof KeyguardInputView) {
            return (KeyguardInputView) child;
        }
        return null;
    }

9.KeyguardInputViewController

各种锁屏模式控制器的抽象类,具体参考9.1.1里的对象

9.1.Factory

>1.create

根据不同的keyguardInputView创建对应的controller

        public KeyguardInputViewController create(KeyguardInputView keyguardInputView,
                SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback) {
            EmergencyButtonController emergencyButtonController =
                    mEmergencyButtonControllerFactory.create(
                            keyguardInputView.findViewById(R.id.emergency_call_button));

            if (keyguardInputView instanceof KeyguardPatternView) {
                return new KeyguardPatternViewController((KeyguardPatternView) keyguardInputView,
                        mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                        keyguardSecurityCallback, mLatencyTracker, mFalsingCollector,
                        emergencyButtonController, mMessageAreaControllerFactory,
                        mDevicePostureController);
            } else if (keyguardInputView instanceof KeyguardPasswordView) {
                return new KeyguardPasswordViewController((KeyguardPasswordView) keyguardInputView,
                        mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                        keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                        mInputMethodManager, emergencyButtonController, mMainExecutor, mResources,
                        mFalsingCollector, mKeyguardViewController);

            } else if (keyguardInputView instanceof KeyguardPINView) {
                return new KeyguardPinViewController((KeyguardPINView) keyguardInputView,
                        mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                        keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                        mLiftToActivateListener, emergencyButtonController, mFalsingCollector,
                        mDevicePostureController);
            } else if (keyguardInputView instanceof KeyguardSimPinView) {
                return new KeyguardSimPinViewController((KeyguardSimPinView) keyguardInputView,
                        mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                        keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                        mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
                        emergencyButtonController);
            } else if (keyguardInputView instanceof KeyguardSimPukView) {
                return new KeyguardSimPukViewController((KeyguardSimPukView) keyguardInputView,
                        mKeyguardUpdateMonitor, securityMode, mLockPatternUtils,
                        keyguardSecurityCallback, mMessageAreaControllerFactory, mLatencyTracker,
                        mLiftToActivateListener, mTelephonyManager, mFalsingCollector,
                        emergencyButtonController);
            }

            throw new RuntimeException("Unable to find controller for " + keyguardInputView);
        }

10.EmergencyButtonController

10.1.onInit

    protected void onInit() {
        whitelistIpcs(this::updateEmergencyCallButton);
    }

>1.updateEmergencyCallButton

    private void updateEmergencyCallButton() {
        if (mView != null) {
            mView.updateEmergencyCallButton(//参考10.2
                    mTelecomManager != null && mTelecomManager.isInCall(),
                    getContext().getPackageManager().hasSystemFeature(
                            PackageManager.FEATURE_TELEPHONY),
                    mKeyguardUpdateMonitor.isSimPinVoiceSecure(),
                    isEmergencyCapable());
        }
    }

>2.isEmergencyCapable

是否有紧急通话的能力

    private boolean isEmergencyCapable() {
        return (!mKeyguardUpdateMonitor.isOOS()//是否无服务
                || mIsCellAvailable
                || (mServiceState !=null && mServiceState.isEmergencyOnly()));
    }

10.2.EmergencyButton

>1.updateEmergencyCallButton

设置可见性以及按钮文字

    public void updateEmergencyCallButton(boolean isInCall, boolean hasTelephonyRadio,
                                          boolean simLocked, boolean isEmergencyCapable) {
        boolean visible = false;//按钮默认不可见
        //有通话功能才可见
        if (hasTelephonyRadio) {
            if (isInCall) {
                visible = true; //通话中,可见
            } else {
                if (simLocked) {
                    //sim卡锁定的情况下,看配置是否允许emergency
                    visible = mEnableEmergencyCallWhileSimLocked;
                } else {
                    //有安全锁(pin,pattern,sim pin等)或者配置里默认显示的情况下可见
                    visible = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()) ||
                            mContext.getResources().getBoolean(R.bool.config_showEmergencyButton);
                }
            //kg_hide_emgcy_btn_when_oos:当无通话服务的时候隐藏紧急按钮,配置默认是false
                if (mContext.getResources().getBoolean(R.bool.kg_hide_emgcy_btn_when_oos)) {
                //如果为true,就要同步判断是否有通话能力
                    visible = visible && isEmergencyCapable;
                }
            }
        }
        if (visible) {
            setVisibility(View.VISIBLE);

            int textId;
            if (isInCall) {
                textId = com.android.internal.R.string.lockscreen_return_to_call;
            } else {
                textId = com.android.internal.R.string.lockscreen_emergency_call;
            }
            setText(textId);
        } else {
            setVisibility(View.GONE);
        }
    }

>2.onFinishInflate

长按事件需要配置的,默认是false,暂时就不看了

    protected void onFinishInflate() {
        super.onFinishInflate();
        mLockPatternUtils = new LockPatternUtils(mContext);
        if (mEmergencyAffordanceManager.needsEmergencyAffordance()) {
            setOnLongClickListener(v -> {
                if (!mLongPressWasDragged
                        && mEmergencyAffordanceManager.needsEmergencyAffordance()) {
                    mEmergencyAffordanceManager.performEmergencyCall();
                    return true;
                }
                return false;
            });
        }
    }

10.3.onViewAttached

    protected void onViewAttached() {
    //监听手机状态,回调里会刷新数据
        mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
        mConfigurationController.addCallback(mConfigurationListener);
        mView.setOnClickListener(v -> takeEmergencyCallAction());//点击事件
    }

>1.takeEmergencyCallAction

    public void takeEmergencyCallAction() {
        if (mPowerManager != null) {
            mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
        }
        mActivityTaskManager.stopSystemLockTaskMode();
        mShadeController.collapsePanel(false);//收起下拉面板
        //通话中
        if (mTelecomManager != null && mTelecomManager.isInCall()) {
            mTelecomManager.showInCallScreen(false);
            if (mEmergencyButtonCallback != null) {
                mEmergencyButtonCallback.onEmergencyButtonClickedWhenInCall();
            }
        } else {
        //回调,最终走到2.1.1
            mKeyguardUpdateMonitor.reportEmergencyCallAction(true /* bypassHandler */);
            if (mTelecomManager == null) {
                return;
            }
            //跳转到紧急拨号页面
            Intent emergencyDialIntent =
                    mTelecomManager.createLaunchEmergencyDialerIntent(null /* number*/)//参考补充2
                            .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                                    | Intent.FLAG_ACTIVITY_CLEAR_TOP)
                            .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
                                    EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);

            getContext().startActivityAsUser(emergencyDialIntent,
                    ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
                    new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
        }
    }

>2.TelecomServiceImpl.java

        public Intent createLaunchEmergencyDialerIntent(String number) {
        //配置的包名,如果集成了谷歌套件的话可能被重写
            String packageName = mContext.getApplicationContext().getString(
                    com.android.internal.R.string.config_emergency_dialer_package);
            Intent intent = new Intent(Intent.ACTION_DIAL_EMERGENCY)
                    .setPackage(packageName);
            ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0 /* flags*/);
            if (resolveInfo == null) {
                //没找到页面,那么把包名置空
                intent.setPackage(null);
            }
            //如果有提供纯数字号码,那么添加数据
            if (!TextUtils.isEmpty(number) && TextUtils.isDigitsOnly(number)) {
                intent.setData(Uri.parse("tel:" + number));
            }
            return intent;
        }

11.NotificationShadeWindowViewController

11.1.NotificationShadeWindowView

  • 触摸事件都交给这个handler处理了,参考11.2
    protected void setInteractionEventHandler(InteractionEventHandler listener) {
        mInteractionEventHandler = listener;
    }

>1.dispatchTouchEvent

    public boolean dispatchTouchEvent(MotionEvent ev) {
        Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);

        result = result != null ? result : super.dispatchTouchEvent(ev);

        mInteractionEventHandler.dispatchTouchEventComplete();

        return result;
    }

>2.onInterceptTouchEvent

    public boolean onInterceptTouchEvent(MotionEvent ev) {
        boolean intercept = mInteractionEventHandler.shouldInterceptTouchEvent(ev);
        if (!intercept) {
            intercept = super.onInterceptTouchEvent(ev);
        }
        if (intercept) {
            mInteractionEventHandler.didIntercept(ev);
        }

        return intercept;
    }

>3.onTouchEvent

    public boolean onTouchEvent(MotionEvent ev) {
        boolean handled = mInteractionEventHandler.handleTouchEvent(ev);

        if (!handled) {
            handled = super.onTouchEvent(ev);
        }

        if (!handled) {
            mInteractionEventHandler.didNotHandleTouchEvent(ev);
        }

        return handled;
    }

11.2.setupExpandedStatusBar

    public void setupExpandedStatusBar() {
//...
        GestureDetector.SimpleOnGestureListener gestureListener =
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onSingleTapConfirmed(MotionEvent e) {
                        if (mSingleTapEnabled && !mDockManager.isDocked()) {
                            mService.wakeUpIfDozing(
                                    SystemClock.uptimeMillis(), mView, "SINGLE_TAP");
                            return true;
                        }
                        return false;
                    }

                    @Override
                    public boolean onDoubleTap(MotionEvent e) {
                        if (mDoubleTapEnabled || mSingleTapEnabled) {
                            mService.wakeUpIfDozing(
                                    SystemClock.uptimeMillis(), mView, "DOUBLE_TAP");
                            return true;
                        }
                        return false;
                    }
                };
        mGestureDetector = new GestureDetector(mView.getContext(), gestureListener);

        mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {
            @Override
            public Boolean handleDispatchTouchEvent(MotionEvent ev) {
                if (mStatusBarViewController == null) {
                //statusBarView还没创建好,无视
                    return false;
                }
                boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
                boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
                boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;

                boolean expandingBelowNotch = mExpandingBelowNotch;
                if (isUp || isCancel) {
                    mExpandingBelowNotch = false;
                }

                //
                if (!isCancel && mService.shouldIgnoreTouch()) {
                    return false;
                }

                if (isDown) {
                    mTouchActive = true;
                    mTouchCancelled = false;
                } else if (ev.getActionMasked() == MotionEvent.ACTION_UP
                        || ev.getActionMasked() == MotionEvent.ACTION_CANCEL) {
                    mTouchActive = false;
                }
                if (mTouchCancelled || mExpandAnimationRunning) {
                    return false;
                }

                if (mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
                    // If the user was sliding their finger across the lock screen,
                    // we may have been intercepting the touch and forwarding it to the
                    // UDFPS affordance via mStatusBarKeyguardViewManager.onTouch (see below).
                    // If this touch ended up unlocking the device, we want to cancel the touch
                    // immediately, so we don't cause swipe or expand animations afterwards.
                    cancelCurrentTouch();
                    return true;
                }

                mFalsingCollector.onTouchEvent(ev);
                mGestureDetector.onTouchEvent(ev);
                mStatusBarKeyguardViewManager.onTouch(ev);
                if (mBrightnessMirror != null
                        && mBrightnessMirror.getVisibility() == View.VISIBLE) {
                    //亮度条可见,也就是你正在拖动亮度条,不允许新的手指按下
                    if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
                        return false;
                    }
                }
                if (isDown) {
                    mNotificationStackScrollLayoutController.closeControlsIfOutsideTouch(ev);
                }

                if (mStatusBarStateController.isDozing()) {
                    mService.extendDozePulse();
                }
                mLockIconViewController.onTouchEvent(
                        ev,
                        () -> mService.wakeUpIfDozing(
                                SystemClock.uptimeMillis(),
                                mView,
                                "LOCK_ICON_TOUCH"));

                // In case we start outside of the view bounds (below the status bar), we need to
                // dispatch
                // the touch manually as the view system can't accommodate for touches outside of
                // the
                // regular view bounds.
                if (isDown && ev.getY() >= mView.getBottom()) {
                    mExpandingBelowNotch = true;
                    expandingBelowNotch = true;
                }
                if (expandingBelowNotch) {
                    return mStatusBarViewController.sendTouchToView(ev);
                }

                if (!mIsTrackingBarGesture && isDown
                        && mNotificationPanelViewController.isFullyCollapsed()) {
                    float x = ev.getRawX();
                    float y = ev.getRawY();
                    if (mStatusBarViewController.touchIsWithinView(x, y)) {
                        if (mStatusBarWindowStateController.windowIsShowing()) {
                            mIsTrackingBarGesture = true;
                            return mStatusBarViewController.sendTouchToView(ev);
                        } else { // it's hidden or hiding, don't send to notification shade.
                            return true;
                        }
                    }
                } else if (mIsTrackingBarGesture) {
                    final boolean sendToStatusBar = mStatusBarViewController.sendTouchToView(ev);
                    if (isUp || isCancel) {
                        mIsTrackingBarGesture = false;
                    }
                    return sendToStatusBar;
                }

                return null;
            }

            @Override
            public void dispatchTouchEventComplete() {
                mFalsingCollector.onMotionEventComplete();
            }

            @Override
            public boolean shouldInterceptTouchEvent(MotionEvent ev) {
                if (mStatusBarStateController.isDozing() && !mService.isPulsing()
                        && !mDockManager.isDocked()) {
                    // Capture all touch events in always-on.
                    return true;
                }

                if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
                    // capture all touches if the alt auth bouncer is showing
                    return true;
                }
//那个小锁图标
                if (mLockIconViewController.onInterceptTouchEvent(ev)) {
                    // immediately return true; don't send the touch to the drag down helper
                    return true;
                }

                boolean intercept = false;
                if (mNotificationPanelViewController.isFullyExpanded()
                        && mDragDownHelper.isDragDownEnabled()
                        && !mService.isBouncerShowing()
                        && !mStatusBarStateController.isDozing()) {
                    intercept = mDragDownHelper.onInterceptTouchEvent(ev);
                }

                return intercept;

            }

            @Override
            public void didIntercept(MotionEvent ev) {
                MotionEvent cancellation = MotionEvent.obtain(ev);
                cancellation.setAction(MotionEvent.ACTION_CANCEL);
                mStackScrollLayout.onInterceptTouchEvent(cancellation);
                mNotificationPanelViewController.getView().onInterceptTouchEvent(cancellation);
                cancellation.recycle();
            }

            @Override
            public boolean handleTouchEvent(MotionEvent ev) {
                boolean handled = false;
                if (mStatusBarStateController.isDozing()) {
                    handled = !mService.isPulsing();
                }

                if (mStatusBarKeyguardViewManager.isShowingAlternateAuthOrAnimating()) {
                    // eat the touch
                    handled = true;
                }

                if ((mDragDownHelper.isDragDownEnabled() && !handled)
                        || mDragDownHelper.isDraggingDown()) {
                    // we still want to finish our drag down gesture when locking the screen
                    handled = mDragDownHelper.onTouchEvent(ev);
                }

                return handled;
            }

            @Override
            public void didNotHandleTouchEvent(MotionEvent ev) {
                final int action = ev.getActionMasked();
                if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                    mService.setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
                }
            }

            @Override
            public boolean interceptMediaKey(KeyEvent event) {
                return mService.interceptMediaKey(event);
            }

            @Override
            public boolean dispatchKeyEventPreIme(KeyEvent event) {
                return mService.dispatchKeyEventPreIme(event);
            }

            @Override
            public boolean dispatchKeyEvent(KeyEvent event) {
                boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_BACK:
                        if (!down) {
                            mService.onBackPressed();
                        }
                        return true;
                    case KeyEvent.KEYCODE_MENU:
                        if (!down) {
                            return mService.onMenuPressed();
                        }
                        break;
                    case KeyEvent.KEYCODE_SPACE:
                        if (!down) {
                            return mService.onSpacePressed();
                        }
                        break;
                    case KeyEvent.KEYCODE_VOLUME_DOWN:
                    case KeyEvent.KEYCODE_VOLUME_UP:
                        if (mStatusBarStateController.isDozing()) {
                            MediaSessionLegacyHelper.getHelper(mView.getContext())
                                    .sendVolumeKeyEvent(
                                            event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);
                            return true;
                        }
                        break;
                }
                return false;
            }
        });
//下滑事件基本交给这个helper处理了,参考12.1
        setDragDownHelper(mLockscreenShadeTransitionController.getTouchHelper());

        mDepthController.setRoot(mView);
        mPanelExpansionStateManager.addExpansionListener(mDepthController);
    }

12.LockscreenShadeTransitionController.kt

12.1.DragDownHelper

class DragDownHelper(
    private val falsingManager: FalsingManager,
    private val falsingCollector: FalsingCollector,
    private val dragDownCallback: LockscreenShadeTransitionController,
    context: Context
) : Gefingerpoken {

>1.onTouchEvent

  • 这里就简单学习下下拉松手以后干了啥
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!isDraggingDown) {
            return false
        }
        val x = event.x
        val y = event.y
        when (event.actionMasked) {
            MotionEvent.ACTION_MOVE -> {
                lastHeight = y - initialTouchY
                captureStartingChild(initialTouchX, initialTouchY)
                dragDownCallback.dragDownAmount = lastHeight + dragDownAmountOnStart
                if (startingChild != null) {
                    handleExpansion(lastHeight, startingChild!!)
                }
                if (lastHeight > minDragDistance) {
                    if (!draggedFarEnough) {
                        draggedFarEnough = true
                        dragDownCallback.onCrossedThreshold(true)
                    }
                } else {
                    if (draggedFarEnough) {
                        draggedFarEnough = false
                        dragDownCallback.onCrossedThreshold(false)
                    }
                }
                return true
            }
            MotionEvent.ACTION_UP -> if (!falsingManager.isUnlockingDisabled && !isFalseTouch &&
                    dragDownCallback.canDragDown()) {
                    //松手走这里,12.2
                dragDownCallback.onDraggedDown(startingChild, (y - initialTouchY).toInt())
                if (startingChild != null) {
                    expandCallback.setUserLockedChild(startingChild, false)
                    startingChild = null
                }
                isDraggingDown = false
            } else {
                stopDragging()
                return false
            }
            MotionEvent.ACTION_CANCEL -> {
                stopDragging()
                return false
            }
        }
        return false
    }

12.2.onDraggedDown

    private lateinit var nsslController: NotificationStackScrollLayoutController

    internal fun onDraggedDown(startingChild: View?, dragLengthY: Int) {
        if (canDragDown()) {
            val cancelRunnable = Runnable {
                setDragDownAmountAnimated(0f)
            }
            //补充1
            if (nsslController.isInLockedDownShade()) {
                statusBarStateController.setLeaveOpenOnKeyguardHide(true)
                //隐藏keyguard,参考1.3.2
                centralSurfaces.dismissKeyguardThenExecute(OnDismissAction {
                    nextHideKeyguardNeedsNoAnimation = true
                    false
                }, cancelRunnable, false /* afterKeyguardGone */)
            } else {
            //非休眠中 或者拖拽的child不为空
                if (!ambientState.isDozing() || startingChild != null) {
                //不需要显示bouncer的最后会执行这个
                    val animationHandler = //..
                    //补充2
                    goToLockedShadeInternal(startingChild, animationHandler, cancelRunnable)
                }
            }
        } else {
            setDragDownAmountAnimated(0f)
        }
    }

>1.isInLockedDownShade

NotificationStackScrollLayoutController.java

    public boolean isInLockedDownShade() {
        return mDynamicPrivacyController.isInLockedDownShade();//12.3
    }

>2.goToLockedShadeInternal

    private fun goToLockedShadeInternal(
        expandView: View?,
        animationHandler: ((Long) -> Unit)? = null,
        cancelAction: Runnable? = null
    ) {//参考1.3.3,是否禁掉了通知面板
        if (centralSurfaces.isShadeDisabled) {
            cancelAction?.run()
            return
        }
        var userId: Int = lockScreenUserManager.getCurrentUserId()
        var entry: NotificationEntry? = null
        if (expandView is ExpandableNotificationRow) {
            entry = expandView.entry
            //点击的是通知面板里的某条通知,这里展开
            entry.setUserExpanded(true /* userExpanded */, true /* allowChildExpansion */)
            
            entry.setGroupExpansionChanging(true)
            userId = entry.sbn.userId
        }
        //是否需要显示bouncer,显示锁屏通知的话为false,不显示锁屏通知的话为true
        var fullShadeNeedsBouncer = (//参考12.4.1,是否显示锁屏通知
                !lockScreenUserManager.shouldShowLockscreenNotifications() ||
                falsingCollector.shouldEnforceBouncer())
        if (keyguardBypassController.bypassEnabled) {//人脸识别解锁成功返回true
            fullShadeNeedsBouncer = false
        }
        //
        if (lockScreenUserManager.isLockscreenPublicMode(userId) && fullShadeNeedsBouncer) {
            statusBarStateController.setLeaveOpenOnKeyguardHide(true)
//..参考1.3.4
            centralSurfaces.showBouncerWithDimissAndCancelIfKeyguard(onDismissAction, cancelHandler)
            draggedDownEntry = entry
        } else {//不需要显示bouncer的
            if (statusBarStateController.isDozing) {
                // Make sure we don't go back to keyguard immediately again after waking up
                isWakingToShadeLocked = true
            }
            //先修改状态
            statusBarStateController.setState(StatusBarState.SHADE_LOCKED)
            //再执行对应的handler
            if (animationHandler != null) {
                animationHandler.invoke(0 /* delay */)
            } else {
                performDefaultGoToFullShadeAnimation(0)
            }
        }
    }

12.3.DynamicPrivacyController.java

>1.isInLockedDownShade

    public boolean isInLockedDownShade() {
    //keyguard没有显示 或者 非安全模式(没有设置pin,password,pattern.)
        if (!mKeyguardStateController.isShowing() || !mKeyguardStateController.isMethodSecure()) {
            return false;
        }
        int state = mStateController.getState();
        //就3种state,如果是KEYGUARD状态返回false
        if (state != StatusBarState.SHADE && state != StatusBarState.SHADE_LOCKED) {
            return false;
        }
        if (!isDynamicPrivacyEnabled() || isDynamicallyUnlocked()) {
            return false;
        }
        return true;
    }

>2.isDynamicPrivacyEnabled

    boolean isDynamicPrivacyEnabled() {
        return mLockscreenUserManager.userAllowsNotificationsInPublic(
                mLockscreenUserManager.getCurrentUserId());
    }

>3.isDynamicallyUnlocked

    public boolean isDynamicallyUnlocked() {
        return (mKeyguardStateController.canDismissLockScreen()
                || mKeyguardStateController.isKeyguardGoingAway()
                || mKeyguardStateController.isKeyguardFadingAway())
                && isDynamicPrivacyEnabled();
    }

12.4.NotificationLockscreenUserManagerImpl.java

>1.shouldShowLockscreenNotifications

锁屏界面是否显示通知

    public boolean shouldShowLockscreenNotifications() {
        return mShowLockscreenNotifications;
    }
    private void setShowLockscreenNotifications(boolean show) {
        mShowLockscreenNotifications = show;
    }

查下哪里设置的,有4处调用,用户改变,对应的settings发生变化

    protected void updateLockscreenNotificationSetting() {
    //参考1.5.3,锁屏界面是否显示通知,hide all的话为false,其他2个位true
        final boolean show = mSecureSettings.getIntForUser(
                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
                1,
                mCurrentUserId) != 0;
        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
                null /* admin */, mCurrentUserId);
        final boolean allowedByDpm = (dpmFlags
                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;

        setShowLockscreenNotifications(show && allowedByDpm);
//.
    }