System UI
1.Introduction
1.0 注
梳理SystemUI - keyguard相关的代码执行流程,这里只梳理了一些关键方法的调用路径,可以提供一个参考,由于已经离职换了工作方向,相关的东西不会再有后续了~~
1.1 System UI
SystemUI: Android的系统界面,它包括了界面上方的状态栏status bar,下方的导航栏Navigation Bar,锁屏界面 Keyguard,电源界面PowerUI,近期任务界面Recent Task等。
1.2 代码路径
<source-code-path>/framework/base/packages/SystemUI
1.3 具体实现
- Status Bar 系统上方的状态栏
- Navigator Bar 系统下方的导航栏
- Keyguard 锁屏界面
- PowerUI 电源界面
- Recents Screen 近期任务界面
- VolumeUI 音量调节对话框
- Stack Divider 分屏功能调节器
- PipUI 画中画界面
- Screenshot 截屏界面
- RingtonePlayer 铃声播放器界面
- Settings Activity 系统设置中用到的一些界面,例如:NetworkOverLimitActivity,UsbDebuggingActivity等。
1.4 System UI 启动流程
framework/base/service/java/com/android/server/SystemServer.java
: main() -> SystemServer().run();- run() -> startBootstrapServices()
-> startOtherServices() -> mActivityManagerService.systemReady -> startSystemUi() 在该方法中启动SystemUI - startSystemUi() ->
framework/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
: onCreate() - onCreate() -> ((SystemUIApplication) getApplication()).startServicesIfNeeded()
- 读取service中预存的每个SystemUI相关类的反射,创建对应实例并启动相应的SystemUI进程
2. Keyguard
2.1 Keyguard
即Android 中处理锁屏(电源键按下、屏幕显示时间超时)、解锁(滑动、图案、指纹、声音、人脸、虹膜等)、锁屏下显示通知管理者。
2.2 KeyguardService的系统状态入口
void onStartedGoingToSleep(int pmSleepReason);
void onFinishedGoingToSleep(int pmSleepReason, boolean cameraGestureTriggered);
void onStartedWakingUp(int pmWakeReason, boolean cameraGestureTriggered);
void onFinishedWakingUp();
void onScreenTurningOn(IKeyguardDrawnCallback callback);
void onScreenTurnedOn();
void onScreenTurningOff();
void onScreenTurnedOff();
void onSystemReady();
void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
void onShortPowerPressedGoHome();
2.3 Keyguard启动 - onSystemReady
1.KeyguardService.onSystemReady()
public void onSystemReady() {
Trace.beginSection("KeyguardService.mBinder#onSystemReady");
checkPermission(); // 避免死锁并检查权限
mKeyguardViewMediator.onSystemReady(); // 进入锁屏入口
Trace.endSection();
}
2.KeyguardViewMediator.handleSystemReady()
private void handleSystemReady() {
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
doKeyguardLocked(null); // 锁屏预处理判断等操作
mUpdateMonitor.registerCallback(mUpdateCallback);
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
}
3.KeyguardViewMediator.doKeyguardLocked()
private void doKeyguardLocked(Bundle options) {
if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
// Don't show keyguard during half-booted cryptkeeper stage.
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");
return;
}
// if another app is disabling us, don't show
if (!mExternallyEnabled) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
mNeedToReshowWhenReenabled = true;
return;
}
// if the keyguard is already showing, don't bother. check flags in both files
// to account for the hiding animation which results in a delay and discrepancy
// between flags
if (mShowing && mKeyguardViewControllerLazy.get().isShowing()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
resetStateLocked();
return;
}
// In split system user mode, we never unlock system user.
if (!mustNotUnlockCurrentUser()
|| !mUpdateMonitor.isDeviceProvisioned()) {
// if the setup wizard hasn't run yet, don't show
final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
final boolean absent = SubscriptionManager.isValidSubscriptionId(
mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_ABSENT));
final boolean disabled = SubscriptionManager.isValidSubscriptionId(
mUpdateMonitor.getNextSubIdForState(TelephonyManager.SIM_STATE_PERM_DISABLED));
final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
|| ((absent || disabled) && requireSim);
if (!lockedOrMissing && shouldWaitForProvisioning()) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
+ " and the sim is not locked or missing");
return;
}
boolean forceShow = options != null && options.getBoolean(OPTION_FORCE_SHOW, false);
if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
&& !lockedOrMissing && !forceShow) {
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
return;
}
if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
setShowingLocked(false);
hideLocked();
return;
}
}
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
showLocked(options);
}
4.KeyguardViewMediator.showLocked()
private void showLocked(Bundle options) {
Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");
if (DEBUG) Log.d(TAG, "showLocked");
// ensure we stay awake until we are finished displaying the keyguard
mShowKeyguardWakeLock.acquire(); // 获取PARTIAL_WAKE_LOCK,不受电源键影响,不让CPU进入休眠状态
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg); // send SHOW类型的消息
Trace.endSection();
}
5.KeyguardViewMediator.handleMessage() -> handleShow()
private void handleShow(Bundle options) {
Trace.beginSection("KeyguardViewMediator#handleShow");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
}
synchronized (KeyguardViewMediator.this) {
if (!mSystemReady) {
if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
return;
} else {
if (DEBUG) Log.d(TAG, "handleShow");
}
mHiding = false;
mWakeAndUnlocking = false;
setShowingLocked(true);
mStatusBarKeyguardViewManager.show(options);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
mUpdateMonitor.setKeyguardGoingAway(false /* away */);
mStatusBarWindowController.setKeyguardGoingAway(false /* goingAway */);
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
Trace.endSection();
}
6.StatusBarKeyguardViewManager.show()
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowController.setKeyguardShowing(true);
mKeyguardMonitor.notifyKeyguardState(
mShowing, mKeyguardMonitor.isSecure(), mKeyguardMonitor.isOccluded());
reset(true /* hideBouncerWhenShowing */);
StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
}
7.StatusBarKeyguardViewManager.reset()
public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
if (mOccluded && !mDozing) {
mStatusBar.hideKeyguard();
if (hideBouncerWhenShowing || mBouncer.needsFullscreenBouncer()) {
hideBouncer(false /* destroyView */);
}
} else {
showBouncerOrKeyguard(hideBouncerWhenShowing);
}
KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
updateStates();
}
}
UpdateMonitor.handleKeyguardReset
private void handleKeyguardReset() {
if (DEBUG) Log.d(TAG, "handleKeyguardReset");
updateBiometricListeningState();
mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition();
}
8.StatusBarKeyguardViewManager.showBouncerOrKeyguard()
protected void showBouncerOrKeyguard() {
if (mBouncer.needsFullscreenBouncer()) {//是否需要显示密码锁屏界面
// The keyguard might be showing (already). So we need to hide it.
mPhoneStatusBar.hideKeyguard();//隐藏锁屏,显示密码解锁界面
mBouncer.show(true /* resetSecuritySelection */);
} else {
mPhoneStatusBar.showKeyguard();//显示锁屏,隐藏密码解锁界面
mBouncer.hide(false /* destroyView */);
mBouncer.prepare();
}
}
9.StatusBar.showKeyguard() / hideKeyguard()
public void showKeyguard() {
mStatusBarStateController.setKeyguardRequested(true);
mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
updateIsKeyguard();
mAssistManagerLazy.get().onLockscreenShown();
}
public boolean hideKeyguard() {
mStatusBarStateController.setKeyguardRequested(false);
return updateIsKeyguard();
}
10.KeyguardBouncer.show()
10.1 show
public void show(boolean resetSecuritySelection, boolean isScrimmed) {
final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
// In split system user mode, we never unlock system user.
return;
}
ensureView();
mIsScrimmed = isScrimmed;
// On the keyguard, we want to show the bouncer when the user drags up, but it's
// not correct to end the falsing session. We still need to verify if those touches
// are valid.
// Later, at the end of the animation, when the bouncer is at the top of the screen,
// onFullyShown() will be called and FalsingManager will stop recording touches.
if (isScrimmed) {
setExpansion(EXPANSION_VISIBLE);
}
if (resetSecuritySelection) {
// showPrimarySecurityScreen() updates the current security method. This is needed in
// case we are already showing and the current security method changed.
showPrimarySecurityScreen();
// ---> KeyguardViewController.showPrimarySecurityScreen();
// ---> KeyguardSecurityContainerController.showPrimarySecurityScreen(false);
// ---> KeyguardSecurityContainerController.showSecurityScreen()
}
if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
return;
}
final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
final boolean isSystemUser =
UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;
// If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
// set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) {
return;
}
// This condition may indicate an error on Android, so log it.
if (!allowDismissKeyguard) {
Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
}
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);
}
mCallback.onBouncerVisiblityChanged(true /* shown */);
dispatchStartingToShow();
}
10.2 KeyguardSecurityContainerController.showSecurityScreen
void showSecurityScreen(SecurityMode securityMode) {
if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
if (securityMode == SecurityMode.Invalid || securityMode == mCurrentSecurityMode) {
return;
}
KeyguardInputViewController<KeyguardInputView> oldView = getCurrentSecurityController();
// Emulate Activity life cycle
if (oldView != null) {
oldView.onPause();
}
KeyguardInputViewController<KeyguardInputView> newView = changeSecurityMode(securityMode);
if (newView != null) {
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
mSecurityViewFlipperController.show(newView);
mView.updateLayoutForSecurityMode(securityMode);
}
mSecurityCallback.onSecurityModeChanged(
securityMode, newView != null && newView.needsInput());
}
10.3 getCurrentSecurityController & changeSecurityMode
private KeyguardInputViewController<KeyguardInputView> getCurrentSecurityController() {
return mSecurityViewFlipperController
.getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback);
}
private KeyguardInputViewController<KeyguardInputView> changeSecurityMode(
SecurityMode securityMode) {
mCurrentSecurityMode = securityMode;
return getCurrentSecurityController();
}
11.KeyguardBouncer.hide()
public void hide(boolean destroyView) {
if (isShowing()) {
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
mDismissCallbackRegistry.notifyDismissCancelled();
}
mIsScrimmed = false;
mFalsingCollector.onBouncerHidden();
mCallback.onBouncerVisiblityChanged(false /* shown */);
cancelShowRunnable();
if (mKeyguardViewController != null) {
mKeyguardViewController.cancelDismissAction();
mKeyguardViewController.cleanUp();
}
mIsAnimatingAway = false;
if (mRoot != null) {
setVisibility(View.INVISIBLE);
if (destroyView) {
// We have a ViewFlipper that unregisters a broadcast when being detached, which may
// be slow because of AM lock contention during unlocking. We can delay it a bit.
mHandler.postDelayed(mRemoveViewRunnable, 50);
}
}
}
public void cleanUp() {
mKeyguardSecurityContainerController.onPause();
}
12.KeyguardBouncer.prepare()
public void prepare() {
boolean wasInitialized = mRoot != null;
ensureView();
if (wasInitialized) {
showPrimarySecurityScreen();
}
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
2.4 onStartGoingToSleep
1.KeyguardMediator.onStartedGoingToSleep
public void onStartedGoingToSleep(@WindowManagerPolicyConstants.OffReason int offReason) {
if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + offReason + ")");
synchronized (this) {
mDeviceInteractive = false;
mPowerGestureIntercepted = false;
mGoingToSleep = true;
// Lock immediately based on setting if secure (user has a pin/pattern/password).
// This also "locks" the device when not secure to provide easy access to the
// camera while preventing unwanted input.
int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final boolean lockImmediately =
mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
|| !mLockPatternUtils.isSecure(currentUser);
long timeout = getLockTimeout(KeyguardUpdateMonitor.getCurrentUser());
mLockLater = false;
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
if (!mExternallyEnabled) {
hideLocked();
}
} else if (mShowing) {
mPendingReset = true;
} else if (
(offReason == WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT
&& timeout > 0)
|| (offReason == WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER
&& !lockImmediately)) {
doKeyguardLaterLocked(timeout);
mLockLater = true;
} else if (!mLockPatternUtils.isLockScreenDisabled(currentUser)) {
mPendingLock = true;
}
if (mPendingLock) {
playSounds(true);
}
}
mUpdateMonitor.dispatchStartedGoingToSleep(offReason);
// Reset keyguard going away state so we can start listening for fingerprint. We
// explicitly DO NOT want to call
// mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false)
// here, since that will mess with the device lock state.
mUpdateMonitor.dispatchKeyguardGoingAway(false);
notifyStartedGoingToSleep();
}
2.KeyguardViewMediator.hideLocked
private void hideLocked() {
Trace.beginSection("KeyguardViewMediator#hideLocked");
if (DEBUG) Log.d(TAG, "hideLocked");
Message msg = mHandler.obtainMessage(HIDE);
mHandler.sendMessage(msg);
Trace.endSection();
}
3.KeyguardViewMediator.handleHide
private void handleHide() {
Trace.beginSection("KeyguardViewMediator#handleHide");
// It's possible that the device was unlocked in a dream state. It's time to wake up.
if (mAodShowing) {
PowerManager pm = mContext.getSystemService(PowerManager.class);
pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:BOUNCER_DOZING");
}
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleHide");
if (mustNotUnlockCurrentUser()) {
// In split system user mode, we never unlock system user. The end user has to
// switch to another user.
// TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
// still completes and makes the screen blank.
if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
mKeyguardExitAnimationRunner = null;
return;
}
mHiding = true;
if (mShowing && !mOccluded) {
mKeyguardGoingAwayRunnable.run();
} else {
// TODO(bc-unlock): Fill parameters
handleStartKeyguardExitAnimation(
SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */,
null /* nonApps */, null /* finishedCallback */);
}
}
Trace.endSection();
}
4.KeyguardGoingAwayRunnable.run
public void run() {
Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
if (DEBUG) Log.d(TAG, "keyguardGoingAway");
mKeyguardViewControllerLazy.get().keyguardGoingAway();
int flags = 0;
if (mKeyguardViewControllerLazy.get().shouldDisableWindowAnimationsForUnlock()
|| (mWakeAndUnlocking && !mPulsing)
|| isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) {
flags |= WindowManagerPolicyConstants
.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
}
if (mKeyguardViewControllerLazy.get().isGoingToNotificationShade()
|| (mWakeAndUnlocking && mPulsing)) {
flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
}
if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
flags |= KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
}
if (mKeyguardViewControllerLazy.get().shouldSubtleWindowAnimationsForUnlock()) {
flags |= WindowManagerPolicyConstants
.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
}
mUpdateMonitor.setKeyguardGoingAway(true); // 空实现
mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(true); // 设置局部变量,更新生物识别监听器状态
// Don't actually hide the Keyguard at the moment, wait for window
// manager until it tells us it's safe to do so with
// startKeyguardExitAnimation.
// Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
// order.
final int keyguardFlag = flags;
mUiBgExecutor.execute(() -> {
try {
ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag); // 调用 4.1
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
});
Trace.endSection();
}
4.1 KeyguardController.keyguardGoingAway
void keyguardGoingAway(int flags) {
if (!mKeyguardShowing) {
return;
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
mService.deferWindowLayout();
mKeyguardGoingAway = true;
try {
EventLogTags.writeWmSetKeyguardShown(
1 /* keyguardShowing */,
mAodShowing ? 1 : 0,
1 /* keyguardGoingAway */,
"keyguardGoingAway");
mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
TRANSIT_KEYGUARD_GOING_AWAY, convertTransitFlags(flags));
updateKeyguardSleepToken();
// Some stack visibility might change (e.g. docked stack)
mRootWindowContainer.resumeFocusedTasksTopActivities();
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mRootWindowContainer.addStartingWindowsForVisibleActivities();
mWindowManager.executeAppTransition();
} finally {
mService.continueWindowLayout();
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
5.keyguardViewMediator.handleStartKeyguardExitAnimation
private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, IRemoteAnimationFinishedCallback finishedCallback) {
Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
+ " fadeoutDuration=" + fadeoutDuration);
synchronized (KeyguardViewMediator.this) {
// Tell ActivityManager that we canceled the keyguard animation if
// handleStartKeyguardExitAnimation was called but we're not hiding the keyguard, unless
// we're animating the surface behind the keyguard and will be hiding the keyguard
// shortly.
if (!mHiding
&& !mSurfaceBehindRemoteAnimationRequested
&& !mKeyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture()) {
if (finishedCallback != null) {
// There will not execute animation, send a finish callback to ensure the remote
// animation won't hanging there.
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationFinished", e);
}
}
setShowingLocked(mShowing, true /* force */); // ---> 6
return;
}
mHiding = false;
IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner;
mKeyguardExitAnimationRunner = null;
if (mWakeAndUnlocking && mDrawnCallback != null) {
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
// the next draw from here so we don't have to wait for window manager to signal
// this to our ViewRootImpl.
mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
notifyDrawn(mDrawnCallback); //调用 mDawnCallback.onDrawn
mDrawnCallback = null;
}
LatencyTracker.getInstance(mContext)
.onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation && runner != null
&& finishedCallback != null) {
// Wrap finishedCallback to clean up the keyguard state once the animation is done.
IRemoteAnimationFinishedCallback callback =
new IRemoteAnimationFinishedCallback() {
@Override
public void onAnimationFinished() throws RemoteException {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationFinished", e);
}
onKeyguardExitFinished();
mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
0 /* fadeoutDuration */);
InteractionJankMonitor.getInstance()
.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
@Override
public IBinder asBinder() {
return finishedCallback.asBinder();
}
};
try {
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("RunRemoteAnimation"));
runner.onAnimationStart(WindowManager.TRANSIT_KEYGUARD_GOING_AWAY, apps,
wallpapers, nonApps, callback); // ---> 7
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onAnimationStart", e);
}
// When remaining on the shade, there's no need to do a fancy remote animation,
// it will dismiss the panel in that case.
} else if (KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()
&& apps != null && apps.length > 0) {
mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
mSurfaceBehindRemoteAnimationRunning = true;
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("DismissPanel"));
// Pass the surface and metadata to the unlock animation controller.
mKeyguardUnlockAnimationControllerLazy.get().notifyStartKeyguardExitAnimation(
apps[0], startTime, mSurfaceBehindRemoteAnimationRequested);
} else {
InteractionJankMonitor.getInstance().begin(
createInteractionJankMonitorConf("RemoteAnimationDisabled"));
mKeyguardViewControllerLazy.get().hide(startTime, fadeoutDuration);
mContext.getMainExecutor().execute(() -> {
if (finishedCallback == null) {
InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
return;
}
final SyncRtSurfaceTransactionApplier applier =
new SyncRtSurfaceTransactionApplier(
mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
final RemoteAnimationTarget primary = apps[0];
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
anim.setDuration(400 /* duration */);
anim.setInterpolator(Interpolators.LINEAR);
anim.addUpdateListener((ValueAnimator animation) -> {
SyncRtSurfaceTransactionApplier.SurfaceParams params =
new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(
primary.leash)
.withAlpha(animation.getAnimatedFraction())
.build();
applier.scheduleApply(params);
});
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException");
} finally {
InteractionJankMonitor.getInstance()
.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
}
@Override
public void onAnimationCancel(Animator animation) {
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException");
} finally {
InteractionJankMonitor.getInstance()
.cancel(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
}
}
});
anim.start();
});
onKeyguardExitFinished();
}
}
Trace.endSection();
}
6.KeyguardMediator.setShowingLocked
void setShowingLocked(boolean showing) {
setShowingLocked(showing, false /* forceCallbacks */);
}
private void setShowingLocked(boolean showing, boolean forceCallbacks) {
final boolean aodShowing = mDozing && !mWakeAndUnlocking;
final boolean notifyDefaultDisplayCallbacks = showing != mShowing
|| aodShowing != mAodShowing || forceCallbacks;
mShowing = showing;
mAodShowing = aodShowing;
if (notifyDefaultDisplayCallbacks) {
notifyDefaultDisplayCallbacks(showing); // 1.KeyguardStateCallback.onShowingStateChanged
// 2.updateInputRestrictedLocked
// 3.TrustManager.reportKeyguardShowingChanged
updateActivityLockScreenState(showing, aodShowing); // ActivityTaskManager.getService().setLockScreenShown
// ---> ActivityTaskManagerService
}
}
7.IRemoteAnimationRunner.onAnimationStart
// (in ActivityLaunchAnimator.kt)
override fun onAnimationStart(
@WindowManager.TransitionOldType transit: Int,
apps: Array<out RemoteAnimationTarget>?,
wallpapers: Array<out RemoteAnimationTarget>?,
nonApps: Array<out RemoteAnimationTarget>?,
iCallback: IRemoteAnimationFinishedCallback?
) {
removeTimeout()
// The animation was started too late and we already notified the controller that it
// timed out.
if (timedOut) {
iCallback?.invoke()
return
}
// This should not happen, but let's make sure we don't start the animation if it was
// cancelled before and we already notified the controller.
if (cancelled) {
return
}
context.mainExecutor.execute {
startAnimation(apps, nonApps, iCallback)
}
}
8.CarKeyguardViewController.hide
public void hide(long startTime, long fadeoutDuration) {
if (!mShowing) return;
mViewMediatorCallback.readyForKeyguardDone(); // if(mkeyguardDonePending) tryKeyguardGone()
mShowing = false;
mKeyguardStateController.notifyKeyguardState(mShowing, /* occluded= */ false);
mBouncer.hide(/* destroyView= */ true);
mCarSystemBarController.showAllNavigationButtons(/* isSetUp= */ true);
stop(); // 调用 mOverlayViewGlobalStateController.hideView
mKeyguardStateController.notifyKeyguardDoneFading(); // 调用callback的onKeyguardFadingAwayChanged
mMainExecutor.execute(mViewMediatorCallback::keyguardGone);
notifyKeyguardUpdateMonitor(); // KeyguardLifeController(kt).updateListeningState
}
KeyguardMediator.tryKeyguardDone
private void tryKeyguardDone() {
// if(DEBUG) ...
if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
handleKeyguardDone();
} else if (!mHideAnimationRun) {
if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
mHideAnimationRun = true;
mHideAnimationRunning = true;
mKeyguardViewControllerLazy.get() // 调用 Bouncer.startPreHideAnimation
.startPreHideAnimation(mHideAnimationFinishedRunnable);
}
}
KeyguardLifeController(kt).updateListeningState
private fun updateListeningState() {
// ...
if (shouldListen != isListening) {
isListening = shouldListen
if (shouldListen) {
asyncSensorManager.requestTriggerSensor(listener, pickupSensor)
} else {
asyncSensorManager.cancelTriggerSensor(listener, pickupSensor)
}
}
}
9.KeyguardViewMediator.onKeyguardExitFinished
private void onKeyguardExitFinished() {
// only play "unlock" noises if not on a call (since the incall UI
// disables the keyguard)
if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
playSounds(false);
}
setShowingLocked(false); // ---> 6
mWakeAndUnlocking = false;
mDismissCallbackRegistry.notifyDismissSucceeded();
resetKeyguardDonePendingLocked(); // mKeyguardDonePending = false;
// mHandler.removeMessages(KEYGUARD_DONE_PENDING_TIMEOUT);
mHideAnimationRun = false;
adjustStatusBarLocked(); // StatusBarManager.disable
sendUserPresentBroadcast();
}
2.5 onFinishedGoingToSleep
1. KeyguardViewMediator.onFinishedGoingToSleep
public void onFinishedGoingToSleep(
@WindowManagerPolicyConstants.OffReason int offReason, boolean cameraGestureTriggered) {
if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + offReason + ")");
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = false;
mWakeAndUnlocking = false;
mAnimatingScreenOff = mDozeParameters.shouldControlUnlockedScreenOff();
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
notifyFinishedGoingToSleep();
if (cameraGestureTriggered) {
// Just to make sure, make sure the device is awake.
mContext.getSystemService(PowerManager.class).wakeUp(SystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_CAMERA_LAUNCH,
"com.android.systemui:CAMERA_GESTURE_PREVENT_LOCK");
mPendingLock = false;
mPendingReset = false;
}
if (mPendingReset) {
resetStateLocked(); // ---> 2.3-7
mPendingReset = false;
}
maybeHandlePendingLock(); //if (mPendingLock && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying())
// doKeyguardLocked(null) ---> 2.3-3
if (!mLockLater && !cameraGestureTriggered) {
doKeyguardForChildProfilesLocked(); // 获取所有Enabled User Profile
// if (mLockPatternUtils.isSeparateProfileChallengeEnabled(profileId)) {
// lockProfile(profileId);
}
}
}
mUpdateMonitor.dispatchFinishedGoingToSleep(offReason);
// mHandler.sendMessage(mHandler.obtainMessage(MSG_FINISHED_GOING_TO_SLEEP, why (offReason), 0));
// ---> handleKeyguardReset (2.3-7)
}
private void notifyFinishedGoingToSleep() {
if (DEBUG) Log.d(TAG, "notifyFinishedGoingToSleep");
mHandler.sendEmptyMessage(NOTIFY_FINISHED_GOING_TO_SLEEP);
}
2.KeyguardViewMediator.handleNotifyFinishedGoingToSleep
private void handleNotifyFinishedGoingToSleep() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyFinishedGoingToSleep");
mKeyguardViewControllerLazy.get().onFinishedGoingToSleep();
}
}
3.CarKeyguardViewController.onFinishedGoingToSleep
public void onFinishedGoingToSleep() {
if (mBouncer != null) {
mBouncer.onScreenTurnedOff();
}
}
4.KeyguardBouncer.onScreenTurnedOff
public void onScreenTurnedOff() {
if (mKeyguardViewController != null
&& mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
mKeyguardViewController.onPause();
}
}
5.KeyguardHostViewController.onPause
public void onPause() {
if (DEBUG) {
Log.d(TAG, String.format("screen off, instance %s at %s",
Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
}
mKeyguardSecurityContainerController.showPrimarySecurityScreen(true);
mKeyguardSecurityContainerController.onPause();
mView.clearFocus();
}
6.KeyguardUpdateMonitor.handleFinishedGoingToSleep
protected void handleFinishedGoingToSleep(int arg1) {
Assert.isMainThread();
mGoingToSleep = false;
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onFinishedGoingToSleep(arg1);
}
}
updateBiometricListeningState();
}