锁屏分析(Android9.0)

Posted by Haiden on June 10, 2019

一、锁屏核心组成

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
9
   static 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
8
   wm = 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
9
    private 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
25
  public 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
34
 private 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
16
    static 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
16
    public 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是启动锁屏界面的预处理方法。主要处理有

  1. 判断其他应用禁止锁屏呈现。
  2. 判断是否需要重置状态。
  3. 判断Settings中没有启用锁屏 。
  4. 判断是否设置了密码等。
  5. 符合条件,显示锁屏。
1
2
3
4
5
6
7
8
9
10
11
12
 private 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
10
    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
        // 获取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
27
    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");
            }

            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
8
   public 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
15
    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();
        }
    }

showBouncerOrKeyguard方法,判断显示默认锁屏界面还是显示密码锁屏。默认锁屏界面由StatusBar管理,而密码解锁则调用KeyguardBouncer类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    protected 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
4
    public 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
57
  private 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
9
    protected 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
7
    public 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
23
   public 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
20
    private 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
17
 public 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
9
    public void onStartedGoingToSleep() {
        mGoingToSleepVisibleNotOccluded = isShowing() && !isOccluded();
    }
    
    --------------------------
    public void onFinishedGoingToSleep() {
        mGoingToSleepVisibleNotOccluded = false;
        mBouncer.onScreenTurnedOff();
    }
3.7 PowerManagerService

在goToSleepInternal方法中,updatePowerStateLocked是更新电源状态的方法。

1
2
3
4
5
6
7
8
   private 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
17
  private 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
24
  private 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
6
 public 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
19
 public 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
7
   public 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
8
        public 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
9
    private 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
9
 private 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
14
private 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
5
    public void onScreenTurningOn(final DrawnListener drawnListener) {
        if (mKeyguardService != null) {
            mKeyguardService.onScreenTurningOn(new KeyguardShowDelegate(drawnListener));
        } 
    }
4.7 KeyguardViewMediator

KeyguardViewMediator的onScreenTurningOn会发送消息,处理消息回到handleNotifyScreenTurningOn中。

1
2
3
4
   public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
        //发送消息
        notifyScreenOn(callback);
    }

handleNotifyScreenTurningOn方法主要调用StatusBarKeyguardViewManager和进行通知绘制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    private 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中Keyguard解析

SystemUI Keyguard之滑动解锁流程