• 解锁、锁屏界面状态改变、锁屏(开机锁屏、时间超时锁屏、按power键锁屏)(转)


     
    解锁、锁屏界面状态改变、锁屏(开机锁屏、时间超时锁屏、按power键锁屏)
    一、解锁。以划动解锁(LockScreen.java)为例

       1、划动解锁触发其控件监听方法onTrigger,onTrigger方法再调用对象mCallback.goToUnlockScreen()
       
       2、在LockPatternKeyguardView的构造函里创建一个KeyguardScreenCallback的对象mKeyguardScreenCallback,并实现KeyguardScreenCallback的所有抽象方法。
       
          LockPatternKeyguardView把mKeyguardScreenCallback当作LockScreen的构造函数的参数,LockScreen把该参数赋值给mCallback,所以mCallback==mKeyguardScreenCallback
          
       3、KeyguardScreenCallback的抽象方法goToUnlockScreen的具体实现是:getCallback().keyguardDone(false)
       
          KeyguardViewMediator当作KeyguardViewManager的构造函数的参数传给KeyguardViewManager,
          
          然后在创建LockPatternKeyguardView对象mKeyguardView(mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this))后,
          
          执行mKeyguardView.setCallback(mCallback);
          
          所以getCallback().keyguardDone(false)==KeyguardViewMediator.keyguardDone(false)
          
       4、KeyguardViewMediator.keyguardDone(false)通过传递消息ID(KEYGUARD_DONE),最终调用KeyguardViewManager.hide()方法把界面给View.setVisibility(View.GONE)方法把界面隐藏,
          并清除。之后进入到launcher界面。


    二、锁屏界面状态改变。以LockScreen界面的时间变化举例

        LockScreen是view类型,并实现接口 KeyguardUpdateMonitor.InfoCallback的onTimeChanged()方法。
        
        在LockScreen的构造函数里面通过执行updateMonitor.registerInfoCallback(this)把LockScreen注册到KeyguardUpdateMonitor的观察对象列表。
        
        KeyguardUpdateMonitor注册了一个BroadcastReceiver用于监听时间、信号、电量等界面信息的变化。当时间发生变化时,BroadcastReceiver接收到Intent.ACTION_TIME_CHANGED,
        
        之后发出消息MSG_TIME_UPDATE。Handler接收到MSG_TIME_UPDATE后执行handleTimeUpdate(),在handleTimeUpdate里面代码如下:
        
        for (int i = 0; i < mInfoCallbacks.size(); i++) {
           mInfoCallbacks.get(i).onTimeChanged();
         }循环调用观察对象的onTimeChanged方法。
         
    三、锁屏(开机锁屏、时间超时锁屏、按power键锁屏)
        A、开机锁屏
        
          当系统初始化完成后会调用wm(WindowManagerService.java).systemReady()函数,触发解锁界面。
          
          --->PhoneWindowManager.systemReady()--->mKeyguardMediator(KeyguardViewMediator.java).onSystemReady()
          
          -->mKeyguardMediator.doKeyguard()-->mKeyguardMediator.showLocked(){Message msg = mHandler.obtainMessage(Show)  mHandler.sendMessage(msg)}
          
          -->mKeyguardMediator.handleShow()-->mKeyguardViewManager(KeyguardViewManager.java).show()
          {创建锁屏界面类mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this),之后执行mKeyguardHost.addView(mKeyguardView, lp)就可以显示界面了}
          
       B、时间超时锁屏
       
         当PowerManagerService.java服务建立起来后,电源的状态循环则主要是通过Handler来实现的。
          
          PowerManagerService在初始化方法里面会启动mHandler消息循环来提供任务的延迟发送,通过mHandler.post(TimeoutTask.java,int delaytime)实现timeout机制。
          注:TimeoutTask.java是PowerManagerService.java的一个内部类,用于timeout控制。
          
         1、PowerManagerService.userActivity()里面在调用setPowerState之后会用setTimeoutLocked来设置timeout。
          
          然后在setTimeoutLocked里面会根据当前的状态来计算下一个状态以及时间,判断完再调用mHandler.postAtTime(mTimeoutTask, when)来post一个TimeoutTask。
          这样在when毫秒后就会执行TimeoutTask。
          
          在TimeoutTask里面则根据设定的状态来调用setPowerState来改变电源状态,然后再设定新的状态,
          
          比如现在是把屏幕从亮改暗了,那就再用setTimeoutLocked(now, SCREEN_OFF)来等下把屏幕完全关掉。如果这次已经是把屏幕关了,那这轮的timeout状态循环就算是结束了。
          
        2、在PowerManagerService.userActivity()方法的最后面执行 mPolicy.userActivity()===PhoneWindowManager.userActivity(),其代码如下:
           if (mLockScreenTimerActive) {
            // reset the timer
            mHandler.removeCallbacks(mScreenLockTimeout);
            mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
           }
           
           mLockScreenTimeout是settings里设置的屏幕超时时间,mScreenLockTimeout是一个runable,代码如下:
           Runnable mScreenLockTimeout = new Runnable() {
            public void run() {
                synchronized (this) {
                    if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                    mKeyguardMediator.doKeyguardTimeout();
                    mLockScreenTimerActive = false;
                }
            }
           };mKeyguardMediator.doKeyguardTimeout()是下发锁屏命令。
        
          总的来说,就是在用户活动例如点击触摸屏之后,通过执行PowerManagerService.userActivity()重新设置系统的电源状态之后,
          再通过执行mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout)设置在mLockScreenTimeout之后屏幕锁屏
          
        C、按power键锁屏
         WindowManagerService负责android系统显示的加载及事件的接收和分发。
         power键是一个比较特殊的按键,power键的所有相关动作在WindowManagerService的内部类KeyQ的预处理方法preprocessEvent()截获,并且不会把事件放到KeyQ的事件列表中去
         大致流程如下:
         preprocessEvent()-->mPowerManager.goToSleep(event.when){PowerManagerService.goToSleep(long time)}--->PowerManagerService.goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER)
         
         --->PowerManagerService.goToSleepLocked(long time, int reason)-->PowerManagerService.setPowerState(SCREEN_OFF, false, reason)
         
         --->PowerManagerService.sendNotificationLocked(true, -1)--->mHandler.post(mNotificationTask)--->policy.screenTurnedOff(why)
         policy即是PhoneWindowManager.java,接下去就会再去调用dokeyguard等方法进行锁屏
         
         总的来说就是WindowManagerService截获power事件,在preprocessEvent()预处理方法里通知PowerManagerService暗下去,在PowerManagerService在屏幕暗下去的过程中调用
         PhoneWindowManager去再创建锁屏界面
         注:在因power键创建锁屏的过程中,PhoneWindowManager会去把mScreenLockTimeout从消息对列中去掉,以免冲突代码如下:
        private void updateLockScreenTimeout() {
            synchronized (mScreenLockTimeout) {
                            Log.d("cai","6666666666666666666-------");
                boolean enable = (mAllowLockscreenWhenOn && mScreenOn && mKeyguardMediator.isSecure());
                if (mLockScreenTimerActive != enable) {
                    if (enable) {
                        if (localLOGV) Log.v(TAG, "setting lockscreen timer");
                        mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
                    } else {
                        if (true) Log.v("cai", "clearing lockscreen timer");
                        mHandler.removeCallbacks(mScreenLockTimeout);//把mScreenLockTimeout从消息对列中去掉
                    }
                    mLockScreenTimerActive = enable;//设置屏幕超时的timer失效
                }
            }
        }
         
  • 相关阅读:
    架构师养成记--19.netty
    架构师养成记--18.NIO
    架构师养成记--17.disrunptor 多生产者多消费者
    JS计算字符长度、字节数 -- 转
    BootStrap Modal 点击空白时自动关闭
    架构师养成记--16.disruptor并发框架中RingBuffer的使用
    架构师养成记--15.Disruptor并发框架
    架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
    049、Java中使用switch判断,不加入break时的操作
    048、Java中使用switch判断
  • 原文地址:https://www.cnblogs.com/jack2010/p/2542864.html
Copyright © 2020-2023  润新知