一、锁屏核心组成

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)相关推荐

  1. Windows 7 蓝屏代码大全 蓝屏全攻略

    关于Windows 7.Vista等系统的蓝屏,之前都有很多文章讨论过,但是都是筛选的常见的一些问题,今天这个文章是个大全,希望大家看着别头痛,文章收藏下来以后待查即可. 一.蓝屏含义 1.故障检查信 ...

  2. xp系统蓝屏代码7b_7b蓝屏,win7系统蓝屏7b如何修复

    操作e799bee5baa6e997aee7ad94e58685e5aeb9330系统是计算机系统中的  A.核心系统软件. 操作系统(英语:operating system,缩写作 OS)是管理计算 ...

  3. xp系统蓝屏代码7b_蓝屏代码7b怎么修复

    大家好,我是时间财富网智能客服时间君,上述问题将由我为大家进行解答. 蓝屏代码7b的修复方法是: 1.修复系统引导,检查磁盘文件系统是否损坏: 2.重新安装系统,重建系统引导: 3.如果不能重装系统, ...

  4. W ndows7蓝屏0x00000024,Windows 7 蓝屏代码大全 蓝屏全攻略

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 三.Windows 7蓝屏代码含义 0 0x0000 作业完成. 1 0x0001 不正确的函数. 2 0x0002 系统找不到指定的档案. 3 0x00 ...

  5. 计算机蓝屏代码0x000000ED,蓝屏代码0x000000ed的4大解决方法详解!蓝屏0x000000ed的原因和解决方法!...

    说到电脑问题,就不得不提蓝屏的问题.最近有位朋友的电脑开机的时候,并没有进入正常的启动程序,反而进入了蓝色界面,显示代码0x000000ed,不知道为什么会这样,也不知道如何去解决.下面就来看看蓝屏0 ...

  6. 计算机蓝屏代码0x000000ED,蓝屏代码0x000000ed,小编教你电脑蓝屏代码0x000000ed怎么解决...

    蓝屏现象是我们在使用电脑中最常见的一种启动问题,也是很多人都非常头疼的问题,比如,我们在启动电脑的时候,它并没有正常地启动,屏幕反而一片蓝色,出现了一串奇怪的代码:0x000000ed.这一般是由于磁 ...

  7. android 投屏代码,视频投屏,支持网络投屏和本地投屏

    //使用前先注册服务 ClingManager.getInstance().startClingService(); //得到当前搜索到的所有设备 private List clingDevices; ...

  8. html游戏全屏代码,HTML5全屏(Fullscreen)API详细介绍

    在越来越真实的web应用程序中,JavaScript也变得越来越给力. FullScreen API 是一个新的JavaScript API,简单而又强大. FullScreen 让我们可以通过编程的 ...

  9. 计算机蓝屏代码0x0000007b,蓝屏代码0x0000007b的解决办法

    =====原因===== 如果硬盘的主要磁盘组标识与存储在注册表中的主要磁盘组标识不 匹配,则会出现该错误信息.如果满足以下所有条件,就可能发生 此不匹配问题: • 在运行 Windows 2000 ...

  10. Android 动画之Gif动画的用法(适用于Android9.0以上和以下)

    博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,

最新文章

  1. C程序设计的抽象思维-递归过程-砝码称重
  2. css如何让背景透明,文字不透明
  3. Bootstrap3 Font Awesome 字体图标旋转或翻转图标
  4. RabbitMQ的六种工作模式(三)
  5. Tomcat默认端口,关闭不必要的安全隐患
  6. Windows虚拟桌面
  7. 独孤木专栏Delayed Project(中)
  8. 本机无法 正常连接到桌面端Ubuntu虚拟机
  9. java session logout_Spring Session Logout
  10. 皮卡丘(pikachu)文件包含
  11. 如何在中国制造网(made-in-china)上做生意
  12. discuz!代码内置颜色大全(收藏)
  13. 【微信小程序】云开发基础设置
  14. layui 父页面表格指定页码刷新
  15. 异常检测:综述(基本都是无监督算法)【时间序列算法:AR/MA/ARMA】【传统机器学习算法:孤独森林、One Class SVM】【深度学习算法:AutoEncoder、LSTM、DeepLog】
  16. 惠普服务器删除系统还原,惠普电脑系统还原的详细操作步骤
  17. 通过苹果设计和小米商业,重新理解互联网产品创新
  18. 成功解决xgboost.core.XGBoostError: b‘value 0 for Parameter num_class should be greater equal to 1‘
  19. 自行车存放管理系统c语言课程设计,基于51单片机的自行车智能辅助系统设计-(Proteus仿真图+源程序+论文)...
  20. 论文列表——EMNLP 2018

热门文章

  1. 「魔窗」问题终于解决了
  2. 消除macbook桌面快捷键图标上的箭头
  3. Windows 9X电脑经常出现bluescreen蓝屏怎么办?
  4. rtbeginreg.html文件,【答疑】安装3DMAX2014版本出现“Autodesk Licensing”的小窗口 - 视频教程线上学...
  5. 物联网平台具体都有哪些特点
  6. 面试经历---广州YY(欢聚时代)
  7. ios 图片合成幻灯片_为iPad构建iOS幻灯片应用程序
  8. PAT测试 cccc竞赛
  9. 有域名和服务器怎么建设网站新手,新手如何快速搭建一个新的网站【零基础】...
  10. 使用scrapy爬取图片