android 锁屏代码分析,锁屏分析(Android9.0)
一、锁屏核心组成
Android锁屏流程分析,核心的类有KeyguardViewMediator、keyguardUpdateMonitor、keyguardBouncer等。
KeyguardViewMediator继承SystemUI,是锁屏的核心类,是交互的中转类,其它对象都通过KeyguardViewMediator对象相互交互。
keyguardUpdateMonitor是状态回调的管理类。
keyguardBouncer是锁屏view的通信交互类。
二、锁屏开机分析
锁屏keyguard属于SystemUI,锁屏开机大致分为两部分,第一部分是KeyguardViewMediator的启动;第二部分是从WindowManagerService开始,处理锁屏显示等流程。
KeyguardViewMediator继承SystemUI,所以KeyguardViewMediator的启动和SystemUI的启动一致。这里着重分析第二部分。
2.1 SystemServer
SystemServer在启动SystemUI的方法上,最后调用WindowManagerService的onSystemUiStarted方法。
1
2
3
4
5
6
7
8
9static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
2.2 WindowManagerService
WindowManagerService继承于IWindowManager.Stub, 作为Binder服务端。实际处理window的是PhoneWindowManager类,在SystemServer创建WindowManagerService时传入。
1
2
3
4
5
6
7
8wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
traceEnd();
WindowManagerService的onSystemUiStarted方法,实际调用的是PhoneWindowManager。
2.3 PhoneWindowManager
在PhoneWindowManager中会调用bindKeyguard,KeyguardServiceDelegate作为KeyguardService的委派。
1
2
3
4
5
6
7
8
9private void bindKeyguard() {
synchronized (mLock) {
if (mKeyguardBound) {
return;
}
mKeyguardBound = true;
}
mKeyguardDelegate.bindService(mContext);
}
2.4 KeyguardServiceDelegate
KeyguardServiceDelegate在bindService方法中绑定KeyguardService。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public void bindService(Context context) {
Intent intent = new Intent();
final Resources resources = context.getApplicationContext().getResources();
//从配置文件中获取KeyguardService
final ComponentName keyguardComponent = ComponentName.unflattenFromString(
resources.getString(com.android.internal.R.string.config_keyguardComponent));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
intent.setComponent(keyguardComponent);
//绑定KeyguardService
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;
synchronized (mKeyguardState) {
// TODO: Fix synchronisation model in this class. The other state in this class
// is at least self-healing but a race condition here can lead to the scrim being
// stuck on keyguard-less devices.
mKeyguardState.deviceHasKeyguard = false;
}
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
}
在ServiceConnection的连接成功回调中,创建KeyguardService包装类KeyguardServiceWrapper。包装类除了KeyguardService,还有KeyguardStateMonitor状态监视器。实际调用还是通过KeyguardService。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//将KeyguardServicer传入包装类
mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service), mCallback);
if (mKeyguardState.systemIsReady) {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
if (mKeyguardState.currentUser != UserHandle.USER_NULL) {
// There has been a user switch earlier
mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
}
// This is used to hide the scrim once keyguard displays.
if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
|| mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
mKeyguardService.onStartedWakingUp();
}
if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
mKeyguardService.onFinishedWakingUp();
}
if (mKeyguardState.screenState == SCREEN_STATE_ON
|| mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
mKeyguardService.onScreenTurningOn(
new KeyguardShowDelegate(mDrawnListenerWhenConnect));
}
if (mKeyguardState.screenState == SCREEN_STATE_ON) {
mKeyguardService.onScreenTurnedOn();
}
}
...
}
...
2.5 KeyguardService
KeyguardService内部由KeyguardViewMediator和KeyguardLifecyclesDispatcher组成,KeyguardViewMediator和windowmanager的通信实际是KeyguardService的IPC通信。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
private KeyguardViewMediator mKeyguardViewMediator;
private KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
@Override
public void onCreate() {
((SystemUIApplication) getApplication()).startServicesIfNeeded();
mKeyguardViewMediator =
((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(
Dependency.get(ScreenLifecycle.class),
Dependency.get(WakefulnessLifecycle.class));
}
在KeyguardService绑定成功后调用了onSystemReady方法。onSystemReady最终的处理流程是在KeyguardViewMediator的onSystemReady方法。
2.6 KeyguardViewMediator
onSystemReady方法发送了一条handler消息。经过消息传递会由handleSystemReady方法处理。handleSystemReady方法的关键调用是doKeyguardLocked。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public void onSystemReady() {
mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
}
----------------
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();
}
doKeyguardLocked是启动锁屏界面的预处理方法。主要处理有
判断其他应用禁止锁屏呈现。
判断是否需要重置状态。
判断Settings中没有启用锁屏 。
判断是否设置了密码等。
符合条件,显示锁屏。
1
2
3
4
5
6
7
8
9
10
11
12private void doKeyguardLocked(Bundle options) {
...
//1. 判断其他应用禁止锁屏呈现。
//2. 判断是否需要重置状态。
//3. 判断Settings中没有启用锁屏 。
//4. 判断是否设置了密码等。
...
//显示锁屏
if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
showLocked(options);
}
showLocked显示锁屏方法主要处理:请求CPU不休眠,发送显示锁屏消息。
1
2
3
4
5
6
7
8
9
10private 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
// 获取PARTIAL_WAKE_LOCK,不受电源键影响,不让CPU进入休眠状态
mShowKeyguardWakeLock.acquire();
Message msg = mHandler.obtainMessage(SHOW, options);
mHandler.sendMessage(msg);
Trace.endSection();
}
处理锁屏消息的方法在handleShow,在handleShow中调用StatusBarKeyguardViewManager方法,锁屏处理由KeyguardViewMediator转移到StatusBarKeyguardViewManager。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27private 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");
}
setShowingLocked(true, mAodShowing);
//展示锁屏界面
mStatusBarKeyguardViewManager.show(options);
mHiding = false;
mWakeAndUnlocking = false;
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
adjustStatusBarLocked();
userActivity();
mShowKeyguardWakeLock.release();
}
mKeyguardDisplayManager.show();
}
2.7 StatusBarKeyguardViewManager
show方法设置keyguard是否显示,通知statusbar显示锁屏,重置view的状态,进行锁屏。
1
2
3
4
5
6
7
8public void show(Bundle options) {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
//重置状态
reset(true /* hideBouncerWhenShowing */);
StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
}
reset方法,主要调用showBouncerOrKeyguard方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public 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();
}
}
showBouncerOrKeyguard方法,判断显示默认锁屏界面还是显示密码锁屏。默认锁屏界面由StatusBar管理,而密码解锁则调用KeyguardBouncer类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
//是否需要显示密码锁屏界面
if (mBouncer.needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
//隐藏锁屏,显示密码解锁界面
mStatusBar.hideKeyguard();
mBouncer.show(true /* resetSecuritySelection */);
} else {
mStatusBar.showKeyguard();
if (hideBouncerWhenShowing) {
hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
mBouncer.prepare();
}
}
updateStates();
}
2.8 KeyguardBouncer
在StatusBarKeyguardViewManager类中,StatusBar类则管理默认锁屏界面,KeyguardBouncer类控制密码解锁界面的,KeyguardBouncer会进行锁屏view的填充,KeyguardHostView是自定义容器,内部锁屏相关的处理在KeyguardSecurityContainer中。
1
2
3
4public void showPrimarySecurityScreen() {
if (DEBUG) Log.d(TAG, "show()");
mSecurityContainer.showPrimarySecurityScreen(false);
}
2.9 KeyguardSecurityContainer
在showSecurityScreen方法中会根据锁屏的类型获得锁屏的view,并添加到KeyguardSecurityViewFlipper 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57private void showSecurityScreen(SecurityMode securityMode) {
if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");
if (securityMode == mCurrentSecuritySelection) return;
KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
KeyguardSecurityView newView = getSecurityView(securityMode);
// Emulate Activity life cycle
if (oldView != null) {
oldView.onPause();
oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
}
if (securityMode != SecurityMode.None) {
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
newView.setKeyguardCallback(mCallback);
}
// Find and show this child.
final int childCount = mSecurityViewFlipper.getChildCount();
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
for (int i = 0; i < childCount; i++) {
if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
mSecurityViewFlipper.setDisplayedChild(i);
break;
}
}
mCurrentSecuritySelection = securityMode;
mSecurityCallback.onSecurityModeChanged(securityMode,
securityMode != SecurityMode.None && newView.needsInput());
}
private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
KeyguardSecurityView view = null;
final int children = mSecurityViewFlipper.getChildCount();
for (int child = 0; child < children; child++) {
if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
break;
}
}
int layoutId = getLayoutIdFor(securityMode);
if (view == null && layoutId != 0) {
final LayoutInflater inflater = LayoutInflater.from(mContext);
if (DEBUG) Log.v(TAG, "inflating id = " + layoutId);
View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);
mSecurityViewFlipper.addView(v);
updateSecurityView(v);
view = (KeyguardSecurityView)v;
}
return view;
}
2.10 StatusBar
StatusBar也是继承SystemUI,启动流程和SystemUI一致。并在star的时候添加创建StatusBar相关的view。
1
2
3
4
5
6
7
8
9protected void makeStatusBarView() {
...
// 创建 NotificationPanelView
mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
mZenController.addCallback(this);
...
//创建 KeyguardStatusBarView
mKeyguardStatusBar = mStatusBarWindow.findViewById(R.id.keyguard_header);
StatusBar管理锁屏状态的layout主要在NotificationPanelView,把KeyguardBottomAreaView添加到NotificationPanelView中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@Override
protected void onFinishInflate() {
super.onFinishInflate();
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
mNotificationContainerParent = findViewById(R.id.notification_container_parent);
mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
//填充锁屏图标的layout
mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
mLastOrientation = getResources().getConfiguration().orientation;
initBottomArea();
mQsFrame = findViewById(R.id.qs_frame);
}
KeyguardBottomAreaView是默认锁屏界面的底部view,包括锁图标、打开摄像头等自定义功能。
1
2
3
4
5
6
7
8
9/**
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
* text.
*/
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
UnlockMethodCache.OnUnlockMethodChangedListener,
AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
...
}
三、息屏分析
息屏的处理是从PowerManager开始,最终到锁屏的核心类KeyguardViewMediator,息屏处理的大致流程如下:
3.1 powerManager
powerManager是电源状态和power键处理的管理类。锁屏的息屏和亮屏都从powerManager类开始处理。按power键息屏会调用powerManager的goToSleep方法,而powerManager的处理是PowerManagerService类,所以是远程调用了PowerManagerService的goToSleep。
1
2
3
4
5
6
7public void goToSleep(long time, int reason, int flags) {
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
3.2 PowerManagerService
PowerManagerService对于goToSleep的处理流程如下。
goToSleep –> goToSleepInternal –> updatePowerStateLocked –> goToSleepNoUpdateLocked –>setWakefulnessLocked
经过一系列的调用,最终会走到setWakefulnessLocked方法,在方法内部调用了Notifier的
onWakefulnessChangeStarted方法。Notifier是PMS模块中用于进行“通知”的一个组件类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
...
try {
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@VisibleForTesting
void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
if (mNotifier != null) {
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
}
3.3 Notifier
在onWakefulnessChangeStarted方法中,分别对ActivityManager、InputManager进行通知以及调用handleEarlyInteractiveChange方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
mHandler.post(new Runnable() {
@Override
public void run() {
//ActivityManager处理 mActivityManagerInternal.onWakefulnessChanged(wakefulness);
}
});
if (mInteractive != interactive) {
//InputManager处理
mInputManagerInternal.setInteractive(interactive);
mInputMethodManagerInternal.setInteractive(interactive);
// Notify battery stats.
try {
mBatteryStats.noteInteractive(interactive);
} catch (RemoteException ex) { }
handleEarlyInteractiveChange();
}
}
handleEarlyInteractiveChange方法的核心是调用了WindowManagerPolicy方法,WindowManagerPolicy的实现类是PhoneWindowManager,所以处理转移到了PhoneWindowManager上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20private void handleEarlyInteractiveChange() {
synchronized (mLock) {
if (mInteractive) {
// Waking up...
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedWakingUp();
}
});
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedGoingToSleep(why);
}
});
}
}
}
3.4 PhoneWindowManager
startedGoingToSleep方法内调用了KeyguardServiceDelegate类,在锁屏开机流程的分析中已经知道KeyguardServiceDelegate最终会调用KeyguardViewMediator锁屏核心类,这里直接看
KeyguardViewMediator类的处理。
1
2
3
4
5
6
7
8
9
10
11@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
mGoingToSleep = true;
mRequestedOrGoingToSleep = true;
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
}
3.5 KeyguardViewMediator
KeyguardViewMediator的onStartedGoingToSleep方法会根据息屏的方式进行判断如是否为超时,是否需要播放锁屏音等。最后调用StatusBarKeyguardViewManager通知开始息屏。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public void onStartedGoingToSleep(int why) {
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = true;
...
if (!mExternallyEnabled) {
hideLocked();
}
...
//判断是否需要播放锁屏音
if (mPendingLock) {
playSounds(true);
}
}
//通知开始息屏
notifyStartedGoingToSleep();
3.6 StatusBarKeyguardViewManager
开始息屏的方法onStartedGoingToSleep,只是设置标志,KeyguardBouncer的操作是在完成息屏的方法上。完成息屏行为的发出要回到PowerManagerService上。
1
2
3
4
5
6
7
8
9public void onStartedGoingToSleep() {
mGoingToSleepVisibleNotOccluded = isShowing() && !isOccluded();
}
--------------------------
public void onFinishedGoingToSleep() {
mGoingToSleepVisibleNotOccluded = false;
mBouncer.onScreenTurnedOff();
}
3.7 PowerManagerService
在goToSleepInternal方法中,updatePowerStateLocked是更新电源状态的方法。
1
2
3
4
5
6
7
8private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
在updatePowerStateLocked方法内调用了finishWakefulnessChangeIfNeededLocked方法,而这个方法根据条件触发了Notifier的onWakefulnessChangeFinished。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17private void updatePowerStateLocked() {
...
// Phase 5: Send notifications, if needed.
finishWakefulnessChangeIfNeededLocked();
}
}
private void finishWakefulnessChangeIfNeededLocked() {
if (mWakefulnessChanging && mDisplayReady) {
if (mWakefulness == WAKEFULNESS_DOZING
&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
return; // wait until dream has enabled dozing
}
mNotifier.onWakefulnessChangeFinished();
}
}
3.8 Notifier
Notifier的onWakefulnessChangeFinished方法经过内部的调用最后会走到handleLateInteractiveChange方法上,方法内部调用了PhoneWindowManager的finishedGoingToSleep方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24private void handleLateInteractiveChange() {
synchronized (mLock) {
if (mInteractive) {
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.finishedWakingUp();
}
});
} else {
mHandler.post(new Runnable() {
@Override
public void run() {
//完成息屏
mPolicy.finishedGoingToSleep(why);
}
});
}
}
}
3.9 PhoneWindowManager
finishedGoingToSleep方法经过KeyguardServiceDelegate最终会调用KeyguardViewMediator锁屏核心类。
1
2
3
4
5
6public void finishedGoingToSleep(int why) {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onFinishedGoingToSleep(why,
mCameraGestureTriggeredDuringGoingToSleep);
}
}
3.10 KeyguardViewMediator
KeyguardViewMediator的onFinishedGoingToSleep方法会重置锁屏状态和重新处理doKeyguardLocked的流程。
doKeyguardLocked方法会调用showLocked方法进行锁屏展示。这和锁屏开机的流程大致相同,只是息屏的时候会先重置状态,等待亮屏时使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
synchronized (this) {
//重置锁屏状态
resetKeyguardDonePendingLocked();
//通知息屏完成
notifyFinishedGoingToSleep();
//重置锁屏状态
if (mPendingReset) {
resetStateLocked();
mPendingReset = false;
}
//重新处理锁屏View
if (mPendingLock) {
doKeyguardLocked(null);
mPendingLock = false;
}
}
}
四、亮屏分析
亮屏的处理也是从PowerManager开始,最终到锁屏的核心类KeyguardViewMediator,亮屏处理的大致流程如下:
4.1 PowerManager
按power键息屏会调用powerManager的wakeUp方法,而powerManager的处理是PowerManagerService类,所以是远程调用了PowerManagerService的wakeUp。
1
2
3
4
5
6
7public void wakeUp(long time) {
try {
mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
4.2 PowerManagerService
wakeUp方法主要调用了wakeUpInternal。
1
2
3
4
5
6
7
8public void wakeUp(long eventTime, String reason, String opPackageName) {
try {
//主要调用
wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
在wakeUpInternal方法中,主要看updatePowerStateLocked这个方法。
1
2
3
4
5
6
7
8
9private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
int opUid) {
synchronized (mLock) {
if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
//更新状态
updatePowerStateLocked();
}
}
}
在updatePowerStateLocked方法内调用了更新显示电源状态的方法。在updateDisplayPowerStateLocked方法内远程调用DisplayManagerService请求电源状态。
1
2
3
4
5
6
7
8
9private boolean updateDisplayPowerStateLocked(int dirty) {
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
//远程调用DisplayManagerService
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
...
return mDisplayReady && !oldDisplayReady;
}
4.3 DisplayManagerService
requestPowerState方法由接着调用DisplayPowerController。
1
2
3
4
5
6
7
8@Override
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
}
4.4 DisplayPowerController
在DisplayPowerController类的requestPowerState方法内主要发送更新电源状态的消息,消息的处理是在updatePowerState这个方法。updatePowerState这个方法处理比较复杂,不过会先后调用到PhoneWindowManager的screenTurningOn和screenTurnedOn。
1
2
3
4
5
6
7
8
9
10
11
12
13
14private boolean setScreenState(int state, boolean reportOnly){
...
//开始亮屏
mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
...
}
private void updatePowerState() {
...
//亮屏完成
mWindowManagerPolicy.screenTurnedOn();
...
}
4.5 PhoneWindowManager
PhoneWindowManager的screenTurningOn方法又调用了KeyguardServiceDelegate。
1
2
3
4
5
6@Override
public void screenTurningOn(final ScreenOnListener screenOnListener) {
...
mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
...
}
4.6 KeyguardServiceDelegate
onScreenTurningOn方法则经过KeyguardService最后回到锁屏核心类KeyguardViewMediator。
1
2
3
4
5public void onScreenTurningOn(final DrawnListener drawnListener) {
if (mKeyguardService != null) {
mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener));
}
}
4.7 KeyguardViewMediator
KeyguardViewMediator的onScreenTurningOn会发送消息,处理消息回到handleNotifyScreenTurningOn中。
1
2
3
4public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
//发送消息
notifyScreenOn(callback);
}
handleNotifyScreenTurningOn方法主要调用StatusBarKeyguardViewManager和进行通知绘制。
1
2
3
4
5
6
7
8
9
10
11
12
13
14private void handleNotifyScreenTurningOn(IKeyguardDrawnCallback callback) {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleNotifyScreenTurningOn");
mStatusBarKeyguardViewManager.onScreenTurningOn();
if (callback != null) {
if (mWakeAndUnlocking) {
mDrawnCallback = callback;
} else {
notifyDrawn(callback);
}
}
}
Trace.endSection();
}
开始亮屏ScreenTurningOn的大致流程到这里基本完成,screenTurnedOn的流程和ScreenTurningOn基本相同。
参考
android 锁屏代码分析,锁屏分析(Android9.0)相关推荐
- Windows 7 蓝屏代码大全 蓝屏全攻略
关于Windows 7.Vista等系统的蓝屏,之前都有很多文章讨论过,但是都是筛选的常见的一些问题,今天这个文章是个大全,希望大家看着别头痛,文章收藏下来以后待查即可. 一.蓝屏含义 1.故障检查信 ...
- xp系统蓝屏代码7b_7b蓝屏,win7系统蓝屏7b如何修复
操作e799bee5baa6e997aee7ad94e58685e5aeb9330系统是计算机系统中的 A.核心系统软件. 操作系统(英语:operating system,缩写作 OS)是管理计算 ...
- xp系统蓝屏代码7b_蓝屏代码7b怎么修复
大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答. 蓝屏代码7b的修复方法是: 1.修复系统引导,检查磁盘文件系统是否损坏: 2.重新安装系统,重建系统引导: 3.如果不能重装系统, ...
- W ndows7蓝屏0x00000024,Windows 7 蓝屏代码大全 蓝屏全攻略
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 三.Windows 7蓝屏代码含义 0 0x0000 作业完成. 1 0x0001 不正确的函数. 2 0x0002 系统找不到指定的档案. 3 0x00 ...
- 计算机蓝屏代码0x000000ED,蓝屏代码0x000000ed的4大解决方法详解!蓝屏0x000000ed的原因和解决方法!...
说到电脑问题,就不得不提蓝屏的问题.最近有位朋友的电脑开机的时候,并没有进入正常的启动程序,反而进入了蓝色界面,显示代码0x000000ed,不知道为什么会这样,也不知道如何去解决.下面就来看看蓝屏0 ...
- 计算机蓝屏代码0x000000ED,蓝屏代码0x000000ed,小编教你电脑蓝屏代码0x000000ed怎么解决...
蓝屏现象是我们在使用电脑中最常见的一种启动问题,也是很多人都非常头疼的问题,比如,我们在启动电脑的时候,它并没有正常地启动,屏幕反而一片蓝色,出现了一串奇怪的代码:0x000000ed.这一般是由于磁 ...
- android 投屏代码,视频投屏,支持网络投屏和本地投屏
//使用前先注册服务 ClingManager.getInstance().startClingService(); //得到当前搜索到的所有设备 private List clingDevices; ...
- html游戏全屏代码,HTML5全屏(Fullscreen)API详细介绍
在越来越真实的web应用程序中,JavaScript也变得越来越给力. FullScreen API 是一个新的JavaScript API,简单而又强大. FullScreen 让我们可以通过编程的 ...
- 计算机蓝屏代码0x0000007b,蓝屏代码0x0000007b的解决办法
=====原因===== 如果硬盘的主要磁盘组标识与存储在注册表中的主要磁盘组标识不 匹配,则会出现该错误信息.如果满足以下所有条件,就可能发生 此不匹配问题: • 在运行 Windows 2000 ...
- Android 动画之Gif动画的用法(适用于Android9.0以上和以下)
博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
最新文章
- C程序设计的抽象思维-递归过程-砝码称重
- css如何让背景透明,文字不透明
- Bootstrap3 Font Awesome 字体图标旋转或翻转图标
- RabbitMQ的六种工作模式(三)
- Tomcat默认端口,关闭不必要的安全隐患
- Windows虚拟桌面
- 独孤木专栏Delayed Project(中)
- 本机无法 正常连接到桌面端Ubuntu虚拟机
- java session logout_Spring Session Logout
- 皮卡丘(pikachu)文件包含
- 如何在中国制造网(made-in-china)上做生意
- discuz!代码内置颜色大全(收藏)
- 【微信小程序】云开发基础设置
- layui 父页面表格指定页码刷新
- 异常检测:综述(基本都是无监督算法)【时间序列算法:AR/MA/ARMA】【传统机器学习算法:孤独森林、One Class SVM】【深度学习算法:AutoEncoder、LSTM、DeepLog】
- 惠普服务器删除系统还原,惠普电脑系统还原的详细操作步骤
- 通过苹果设计和小米商业,重新理解互联网产品创新
- 成功解决xgboost.core.XGBoostError: b‘value 0 for Parameter num_class should be greater equal to 1‘
- 自行车存放管理系统c语言课程设计,基于51单片机的自行车智能辅助系统设计-(Proteus仿真图+源程序+论文)...
- 论文列表——EMNLP 2018
热门文章
- 「魔窗」问题终于解决了
- 消除macbook桌面快捷键图标上的箭头
- Windows 9X电脑经常出现bluescreen蓝屏怎么办?
- rtbeginreg.html文件,【答疑】安装3DMAX2014版本出现“Autodesk Licensing”的小窗口 - 视频教程线上学...
- 物联网平台具体都有哪些特点
- 面试经历---广州YY(欢聚时代)
- ios 图片合成幻灯片_为iPad构建iOS幻灯片应用程序
- PAT测试 cccc竞赛
- 有域名和服务器怎么建设网站新手,新手如何快速搭建一个新的网站【零基础】...
- 使用scrapy爬取图片