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.截图
>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);
//.
}