Android4.0 4.1Keyguard锁屏流程梳理(转)

一直想要整理一下keyguard(锁屏)模块的相关流程,由于各种原因总是没真正着手开始做,一直拖也不是个办法,所以就索性开始了。

这篇内容会比较偏分析,所以闲话就少扯点了。

锁屏模块位于framework中,有别于一般的上层应用,它的逻辑代码和view视图,资源文件散布在framework的几处地方,这也给新手分析该模块带来也一点的麻烦。下面我会试着来捋捋这些散落的珠子。

1.文件目录:

a,逻辑是Frameworks/base/policy/src/com/android/internal/policy/ impl/目录下

 

b,视图view是在 Framework/base/core/java/com/android/internal/ widget/路径下:

 

文件夹multiwaveview就是从4.0开始加入的环形解锁视图及相应动画实现。

c,资源文件在Framework/base/core/res/res/下。

这个就不贴目录了,和一般android应用一样,图片资源,布局文件都很规矩的放在相应分辨率的文件夹下。大致了解了锁屏模块文件分布后,我们一般就要开始看源代码了。

2,keyguard锁屏流程图:

现在看不明白的没关系可以先跳过,先看下面,再更几遍源码就会发现该图就是个小菜了。


3,keyguard锁屏view层次图:

 


 

一般4.0真机都会有五种锁屏方式:

 

这里和2.3有明显区别了,2.3的view视图如下:


可以看出来以前的锁屏流程是分正常锁屏和图案锁屏方式。在选择图案解锁方式,是不会显示正常解锁slidingview的。但是选择密码解锁就会出现需要用户二次解锁的情况。三星2.2就对此进行了流程优化统一。本人也试着做了,有兴趣可以。。。

4.0以后该流程得到了官方的统一,选择任何锁屏方式,用户都只需要一次解锁。流程上也更直观了。相信Google,必须是越来越good。

4,keyguard锁屏重要类分析:

1,KeyguardScreenback.java和KeyguardViewCallback.java

说明:接口两个,等着被LockPatternKeyguardView.java实例化。注意Keyguard ViewCallback.java还偷偷捞外快,同时替KeyguardViewMediator.java服务。

  1. public interface KeyguardScreenCallback extends KeyguardViewCallback {  
  2.     void goToLockScreen();//Transition to the lock screen.   
  3.     void goToUnlockScreen();//Transition to the unlock screen.   
  4.     void forgotPattern(boolean isForgotten);// The user forgot their pattern   
  5.     boolean isSecure();//Whether the keyguard requires some sort of PIN.   
  6.     /** 
  7.      * @return Whether we are in a mode where we only want to verify the 
  8.      *   user can get past the keyguard. 
  9.      */  
  10.     boolean isVerifyUnlockOnly();  
  11.     /** 
  12.      * Stay on me, but recreate me (so I can use a different layout). 
  13.      */  
  14.     void recreateMe(Configuration config);  
  15.     void takeEmergencyCallAction();//Take action to send an emergency call   
  16.     void reportFailedUnlockAttempt();//user had a failed attempt to unlock   
  17.     void reportSuccessfulUnlockAttempt();//successfully entered their password   
  18.     /** 
  19.      * Report whether we there's another way to unlock the device. 
  20.      * @return true 
  21.      */  
  22.     boolean doesFallbackUnlockScreenExist();  
  23. }  
public interface KeyguardScreenCallback extends KeyguardViewCallback {
    void goToLockScreen();//Transition to the lock screen.
    void goToUnlockScreen();//Transition to the unlock screen.
    void forgotPattern(boolean isForgotten);// The user forgot their pattern
    boolean isSecure();//Whether the keyguard requires some sort of PIN.
    /**
     * @return Whether we are in a mode where we only want to verify the
     *   user can get past the keyguard.
     */
    boolean isVerifyUnlockOnly();
    /**
     * Stay on me, but recreate me (so I can use a different layout).
     */
    void recreateMe(Configuration config);
    void takeEmergencyCallAction();//Take action to send an emergency call
    void reportFailedUnlockAttempt();//user had a failed attempt to unlock
    void reportSuccessfulUnlockAttempt();//successfully entered their password
    /**
     * Report whether we there's another way to unlock the device.
     * @return true
     */
    boolean doesFallbackUnlockScreenExist();
}

  1. public interface KeyguardViewCallback {  
  2.     /** 
  3.      * Request the wakelock to be poked for the default amount of time. 
  4.      */  
  5.     void pokeWakelock();//使屏幕保持亮一段时间。   
  6.     void pokeWakelock(int millis);  
  7.     void keyguardDone(boolean authenticated);// Report keyguard is done.   
  8.     /** 
  9.      * Report that the keyguard is done drawing. 
  10.      */  
  11.     void keyguardDoneDrawing();//所有锁屏视图完成draw时调用该方法。   
  12. }  
public interface KeyguardViewCallback {
    /**
     * Request the wakelock to be poked for the default amount of time.
     */
    void pokeWakelock();//使屏幕保持亮一段时间。
    void pokeWakelock(int millis);
    void keyguardDone(boolean authenticated);// Report keyguard is done.
    /**
     * Report that the keyguard is done drawing.
     */
    void keyguardDoneDrawing();//所有锁屏视图完成draw时调用该方法。
}

google的注释实在是太优雅了,都翻译成中文反而会有所误导且影响美观,单词看不明白的,有道去。实在懒的话,意会也行的;)

2. KeyguardScreen.java

说明:接口一个,坐等LockScreen.java等具体锁屏方式来实现它。

  1. public interface KeyguardScreen {  
  2.     boolean needsInput();//是否需要键盘进行输入   
  3.     void onPause();//view不在最上层时被系统调用。   
  4.     void onResume();//view重新掌权时被系统调用   
  5.     void cleanUp();//view被扫地出门。   
  6. }  
public interface KeyguardScreen {
    boolean needsInput();//是否需要键盘进行输入
    void onPause();//view不在最上层时被系统调用。
    void onResume();//view重新掌权时被系统调用
    void cleanUp();//view被扫地出门。
}

3. KeyguardStatusViewManager.java

说明:这个类是4.0后新增加的,其实它是从2.3的LockScreen.java分离了出来,所以它还是摆脱不了命运的束缚,依然要为LockScreen.java服务,而且它比以前更累了,如果条件需要它还要服侍其他如密码解锁,图形解锁等方式。功能就是状态视图总管。

  1. /*** 
  2.  * Manages a number of views inside of LockScreen layouts. See below for a list of widgets 
  3. */  
  4. class KeyguardStatusViewManager implements OnClickListener {  
  5.    
  6.     public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,boolean showEmergencyButtonByDefault) {  
  7.         if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");  
  8.         mContainer = view; //视图容器   
  9.         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);//格式日期   
  10.         mLockPatternUtils = lockPatternUtils;  
  11.         mUpdateMonitor = updateMonitor;  
  12.         mCallback = callback;  
  13.         mCarrierView = (TextView) findViewById(R.id.carrier);//运营商标识   
  14.         mDateView = (TextView) findViewById(R.id.date);//日期   
  15.         mStatus1View = (TextView) findViewById(R.id.status1);//sim卡状态   
  16.         mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);//闹铃状态   
  17.         mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);  
  18.         mTransportView = (TransportControlView) findViewById(R.id.transport);  
  19.         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);  
  20.         mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;  
  21. //紧急呼叫按钮   
  22.         // Hide transport control view until we know we need to show it.   
  23.         if (mTransportView != null) {  
  24.             mTransportView.setVisibility(View.GONE);  
  25.         }  
  26.   
  27.         if (mEmergencyCallButton != null) {  
  28.             mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);  
  29.             mEmergencyCallButton.setOnClickListener(this);  
  30.             mEmergencyCallButton.setFocusable(false); // touch only!   
  31.         }  
  32.   
  33.         mTransientTextManager = new TransientTextManager(mCarrierView);  
  34.   
  35.         mUpdateMonitor.registerInfoCallback(mInfoCallback);  
  36.         mUpdateMonitor.registerSimStateCallback(mSimStateCallback);  
  37.   
  38.         resetStatusInfo();//更新电池状态信息   
  39.         refreshDate();//刷新时间   
  40.         updateOwnerInfo();//更新所有者的信息   
  41.   
  42.         // Required to get Marquee to work.   
  43.         final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,  
  44.                 mAlarmStatusView };  
  45.         for (View v : scrollableViews) {  
  46.             if (v != null) {  
  47.                 v.setSelected(true);  
  48.             }  
  49.         }  
  50.     }  
/***
 * Manages a number of views inside of LockScreen layouts. See below for a list of widgets
*/
class KeyguardStatusViewManager implements OnClickListener {
 
    public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,boolean showEmergencyButtonByDefault) {
        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
        mContainer = view; //视图容器
        mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);//格式日期
        mLockPatternUtils = lockPatternUtils;
        mUpdateMonitor = updateMonitor;
        mCallback = callback;
        mCarrierView = (TextView) findViewById(R.id.carrier);//运营商标识
        mDateView = (TextView) findViewById(R.id.date);//日期
        mStatus1View = (TextView) findViewById(R.id.status1);//sim卡状态
        mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);//闹铃状态
        mOwnerInfoView = (TextView) findViewById(R.id.propertyOf);
        mTransportView = (TransportControlView) findViewById(R.id.transport);
        mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
        mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;
//紧急呼叫按钮
        // Hide transport control view until we know we need to show it.
        if (mTransportView != null) {
            mTransportView.setVisibility(View.GONE);
        }

        if (mEmergencyCallButton != null) {
            mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
            mEmergencyCallButton.setOnClickListener(this);
            mEmergencyCallButton.setFocusable(false); // touch only!
        }

        mTransientTextManager = new TransientTextManager(mCarrierView);

        mUpdateMonitor.registerInfoCallback(mInfoCallback);
        mUpdateMonitor.registerSimStateCallback(mSimStateCallback);

        resetStatusInfo();//更新电池状态信息
        refreshDate();//刷新时间
        updateOwnerInfo();//更新所有者的信息

        // Required to get Marquee to work.
        final View scrollableViews[] = { mCarrierView, mDateView, mStatus1View, mOwnerInfoView,
                mAlarmStatusView };
        for (View v : scrollableViews) {
            if (v != null) {
                v.setSelected(true);
            }
        }
    }

4. LockScreen.java

说明:五种锁屏方式之一,为系统默认设置选用,名为滑动解锁,也就是4.0的那个带锁的圆。它继承于LinearLayout并实现了KeyguardScreen接口,所以他具备了接受视图的解锁事件并作出响应。

  1. /** 
  2.  * The screen within {@link LockPatternKeyguardView} that shows general 
  3.  * information about the device depending on its state, and how to get 
  4.  * past it, as applicable. 
  5.  */  
  6. class LockScreen extends LinearLayout implements KeyguardScreen {  
  7.     class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {  
  8.         private final SlidingTab mSlidingTab;  
  9.   
  10.         SlidingTabMethods(SlidingTab slidingTab) {  
  11.             mSlidingTab = slidingTab;  
  12.         }  
  13.   
  14.         public void updateResources() {  
  15.            .......  
  16.         }  
  17.         /** 解锁响应*/  
  18.         public void onTrigger(View v, int whichHandle) {  
  19.             if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {  
  20.                 mCallback.goToUnlockScreen();  
  21.             } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {  
  22.                 toggleRingMode();  
  23.                 mCallback.pokeWakelock();  
  24.             }  
  25.         }  
  26.   
  27.         /** {@inheritDoc} */  
  28.         public void onGrabbedStateChange(View v, int grabbedState) {  
  29.            .......  
  30.         }  
  31.         public View getView() {  
  32.             return mSlidingTab;  
  33.         }  
  34.         public void reset(boolean animate) {  
  35.             mSlidingTab.reset(animate);  
  36.         }  
  37.         public void ping() {  
  38.         }  
  39.     }  
  40.     class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {  
  41.         private final WaveView mWaveView;  
  42.         WaveViewMethods(WaveView waveView) {  
  43.             mWaveView = waveView;  
  44.         }  
  45.         /** {@inheritDoc} */  
  46.         public void onTrigger(View v, int whichHandle) {  
  47.             if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {  
  48.                 requestUnlockScreen();  
  49.             }  
  50.         }  
  51.         /** {@inheritDoc} */  
  52.         public void onGrabbedStateChange(View v, int grabbedState) {  
  53.             // Don't poke the wake lock when returning to a state where the handle is   
  54.             // not grabbed since that can happen when the system (instead of the user)   
  55.             // cancels the grab.   
  56.             if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {  
  57.                 mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);  
  58.             }  
  59.         }  
  60.   
  61.         public void updateResources() {  
  62.         }  
  63.   
  64.         public View getView() {  
  65.             return mWaveView;  
  66.         }  
  67.         public void reset(boolean animate) {  
  68.             mWaveView.reset();  
  69.         }  
  70.         public void ping() {  
  71.         }  
  72.     }  
  73.   
  74.     class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,  
  75.             UnlockWidgetCommonMethods {  
  76.         private final MultiWaveView mMultiWaveView;  
  77.         private boolean mCameraDisabled;  
  78.         MultiWaveViewMethods(MultiWaveView multiWaveView) {  
  79.             mMultiWaveView = multiWaveView;  
  80.             final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()  
  81.                     .getCameraDisabled(null);  
  82.             if (cameraDisabled) {  
  83.                 Log.v(TAG, "Camera disabled by Device Policy");  
  84.                 mCameraDisabled = true;  
  85.             } else {  
  86.                 // Camera is enabled if resource is initially defined for MultiWaveView   
  87.                 // in the lockscreen layout file   
  88.                 mCameraDisabled = mMultiWaveView.getTargetResourceId()  
  89.                         != R.array.lockscreen_targets_with_camera;  
  90.             }  
  91.         }  
/**
 * The screen within {@link LockPatternKeyguardView} that shows general
 * information about the device depending on its state, and how to get
 * past it, as applicable.
 */
class LockScreen extends LinearLayout implements KeyguardScreen {
    class SlidingTabMethods implements SlidingTab.OnTriggerListener, UnlockWidgetCommonMethods {
        private final SlidingTab mSlidingTab;

        SlidingTabMethods(SlidingTab slidingTab) {
            mSlidingTab = slidingTab;
        }

        public void updateResources() {
           .......
        }
        /** 解锁响应*/
        public void onTrigger(View v, int whichHandle) {
            if (whichHandle == SlidingTab.OnTriggerListener.LEFT_HANDLE) {
                mCallback.goToUnlockScreen();
            } else if (whichHandle == SlidingTab.OnTriggerListener.RIGHT_HANDLE) {
                toggleRingMode();
                mCallback.pokeWakelock();
            }
        }

        /** {@inheritDoc} */
        public void onGrabbedStateChange(View v, int grabbedState) {
           .......
        }
        public View getView() {
            return mSlidingTab;
        }
        public void reset(boolean animate) {
            mSlidingTab.reset(animate);
        }
        public void ping() {
        }
    }
    class WaveViewMethods implements WaveView.OnTriggerListener, UnlockWidgetCommonMethods {
        private final WaveView mWaveView;
        WaveViewMethods(WaveView waveView) {
            mWaveView = waveView;
        }
        /** {@inheritDoc} */
        public void onTrigger(View v, int whichHandle) {
            if (whichHandle == WaveView.OnTriggerListener.CENTER_HANDLE) {
                requestUnlockScreen();
            }
        }
        /** {@inheritDoc} */
        public void onGrabbedStateChange(View v, int grabbedState) {
            // Don't poke the wake lock when returning to a state where the handle is
            // not grabbed since that can happen when the system (instead of the user)
            // cancels the grab.
            if (grabbedState == WaveView.OnTriggerListener.CENTER_HANDLE) {
                mCallback.pokeWakelock(STAY_ON_WHILE_GRABBED_TIMEOUT);
            }
        }

        public void updateResources() {
        }

        public View getView() {
            return mWaveView;
        }
        public void reset(boolean animate) {
            mWaveView.reset();
        }
        public void ping() {
        }
    }

    class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
            UnlockWidgetCommonMethods {
        private final MultiWaveView mMultiWaveView;
        private boolean mCameraDisabled;
        MultiWaveViewMethods(MultiWaveView multiWaveView) {
            mMultiWaveView = multiWaveView;
            final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()
                    .getCameraDisabled(null);
            if (cameraDisabled) {
                Log.v(TAG, "Camera disabled by Device Policy");
                mCameraDisabled = true;
            } else {
                // Camera is enabled if resource is initially defined for MultiWaveView
                // in the lockscreen layout file
                mCameraDisabled = mMultiWaveView.getTargetResourceId()
                        != R.array.lockscreen_targets_with_camera;
            }
        }

这个类的主要作用就是提供了三种不同时期的滑动解锁方案重载,具体用哪种已经在keyguard_screen_tab_unlock.xml中配置好了。

5. KeyguardViewBase.java

说明:一个抽象类,里面封装了一些抽象方法,并完成对各种按键的监听。条件允许的话他还会拦截keyEvent,从中作梗。

  1. public abstract class KeyguardViewBase extends FrameLayout {  
  2.     public boolean dispatchKeyEvent(KeyEvent event) {  
  3.         if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {  
  4.             mCallback.pokeWakelock();  
  5.         }  
  6.         if (interceptMediaKey(event)) {  
  7.             return true;  
  8.         }  
  9.         return super.dispatchKeyEvent(event);  
  10.     }  
  11.     private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) {  
  12.         if (event.getAction() != KeyEvent.ACTION_DOWN) {  
  13.             return false;  
  14.         }  
  15.         switch (event.getKeyCode()) {  
  16.             case KeyEvent.KEYCODE_DPAD_DOWN:  
  17.             case KeyEvent.KEYCODE_DPAD_LEFT:  
  18.             case KeyEvent.KEYCODE_DPAD_RIGHT:  
  19.             case KeyEvent.KEYCODE_DPAD_UP:  
  20.                 return false;  
  21.             default:  
  22.                 return true;  
  23.         }  
  24.     }  
  25.     private boolean interceptMediaKey(KeyEvent event) {  
  26.         final int keyCode = event.getKeyCode();  
  27.         if (event.getAction() == KeyEvent.ACTION_DOWN) {  
  28.             switch (keyCode) {  
  29.                 case KeyEvent.KEYCODE_MEDIA_PLAY:  
  30.                 case KeyEvent.KEYCODE_MEDIA_PAUSE:  
  31.                 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:  
  32.             ......  
  33.     }  
public abstract class KeyguardViewBase extends FrameLayout {
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {
            mCallback.pokeWakelock();
        }
        if (interceptMediaKey(event)) {
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
    private boolean shouldEventKeepScreenOnWhileKeyguardShowing(KeyEvent event) {
        if (event.getAction() != KeyEvent.ACTION_DOWN) {
            return false;
        }
        switch (event.getKeyCode()) {
            case KeyEvent.KEYCODE_DPAD_DOWN:
            case KeyEvent.KEYCODE_DPAD_LEFT:
            case KeyEvent.KEYCODE_DPAD_RIGHT:
            case KeyEvent.KEYCODE_DPAD_UP:
                return false;
            default:
                return true;
        }
    }
    private boolean interceptMediaKey(KeyEvent event) {
        final int keyCode = event.getKeyCode();
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_MEDIA_PLAY:
                case KeyEvent.KEYCODE_MEDIA_PAUSE:
                case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            ......
    }

6.LockPatternKeyguardView.java

说明:1-6的最终boss,上面的零碎都直接或间接为它工作,他的作用呢,可以参考上面的锁屏view层次图。一句话它是锁屏的最高权威,该整那样,它说了算,鉴于它太过NB,这里就不贴代码了,读者必须亲自膜拜三遍。

7. KeyguardViewManager.java

说明:封装了WindowManager,可以随性改变锁屏视图的创建,显示,隐藏及重新设定。

  1. /** 
  2.  * Manages creating, showing, hiding and resetting the keyguard.  Calls back 
  3.  * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke 
  4.  * the wake lock and report that the keyguard is done, which is in turn, 
  5.  * reported to this class by the current {@link KeyguardViewBase}. 
  6.  */  
  7. public class KeyguardViewManager implements KeyguardWindowController {  
  8.     private final KeyguardViewProperties mKeyguardViewProperties;  
  9.     private final KeyguardUpdateMonitor mUpdateMonitor;  
  10.     private WindowManager.LayoutParams mWindowLayoutParams;  
  11.     private boolean mNeedsInput = false;  
  12.     private FrameLayout mKeyguardHost;  
  13.     private KeyguardViewBase mKeyguardView;  
  14.   .....  
  15.         protected void dispatchDraw(Canvas canvas) {  
  16.             super.dispatchDraw(canvas);  
  17.             mCallback.keyguardDoneDrawing();  
  18.         }  
  19.     }  
  20.     /** 
  21.      * Show the keyguard.  Will handle creating and attaching to the view manager 
  22.      * lazily. 
  23.      */  
  24.     public synchronized void show() {  
  25.        .....  
  26.             if (mScreenOn) {  
  27.                 mKeyguardView.show();  
  28.             }  
  29.         }  
  30.   
  31.         // Disable aspects of the system/status/navigation bars that are not appropriate or   
  32.         // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.   
  33.         // Other disabled bits are handled by the KeyguardViewMediator talking directly to the   
  34.         // status bar service.   
  35.         int visFlags =  
  36.                 ( View.STATUS_BAR_DISABLE_BACK  
  37.                 | View.STATUS_BAR_DISABLE_HOME  
  38.                 );  
  39.         mKeyguardHost.setSystemUiVisibility(visFlags);  
  40.         mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);  
  41.         mKeyguardHost.setVisibility(View.VISIBLE);  
  42.         mKeyguardView.requestFocus();  
  43.     }  
  44.   
  45.     public void setNeedsInput(boolean needsInput) {  
  46.       ...  
  47.     }  
  48.     /** 
  49.      * Reset the state of the view. 
  50.      */  
  51.     public synchronized void reset() {  
  52.     }  
  53.     public synchronized void onScreenTurnedOff() {  
  54.     }  
  55.     public synchronized void onScreenTurnedOn(  
  56.             final KeyguardViewManager.ShowListener showListener) {  
  57.             // Caller should wait for this window to be shown before turning   
  58.             // on the screen.   
  59.     }  
  60.     public synchronized void verifyUnlock() {  
  61.         if (DEBUG) Log.d(TAG, "verifyUnlock()");  
  62.         show();  
  63.         mKeyguardView.verifyUnlock();  
  64.     }  
  65.     /** 
  66.      * A key has woken the device.   
  67.      */  
  68.     public boolean wakeWhenReadyTq(int keyCode) {  
  69.       .....  
  70.     }  
  71.     /** 
  72.      * Hides the keyguard view 
  73.      */  
  74.     public synchronized void hide() {  
  75.        .....  
  76.     }  
  77.     /** 
  78.      * @return Whether the keyguard is showing 
  79.      */  
  80.     public synchronized boolean isShowing() {  
  81.         return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);  
  82.     }  
/**
 * Manages creating, showing, hiding and resetting the keyguard.  Calls back
 * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
 * the wake lock and report that the keyguard is done, which is in turn,
 * reported to this class by the current {@link KeyguardViewBase}.
 */
public class KeyguardViewManager implements KeyguardWindowController {
    private final KeyguardViewProperties mKeyguardViewProperties;
    private final KeyguardUpdateMonitor mUpdateMonitor;
    private WindowManager.LayoutParams mWindowLayoutParams;
    private boolean mNeedsInput = false;
    private FrameLayout mKeyguardHost;
    private KeyguardViewBase mKeyguardView;
  .....
        protected void dispatchDraw(Canvas canvas) {
            super.dispatchDraw(canvas);
            mCallback.keyguardDoneDrawing();
        }
    }
    /**
     * Show the keyguard.  Will handle creating and attaching to the view manager
     * lazily.
     */
    public synchronized void show() {
       .....
            if (mScreenOn) {
                mKeyguardView.show();
            }
        }

        // Disable aspects of the system/status/navigation bars that are not appropriate or
        // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
        // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
        // status bar service.
        int visFlags =
                ( View.STATUS_BAR_DISABLE_BACK
                | View.STATUS_BAR_DISABLE_HOME
                );
        mKeyguardHost.setSystemUiVisibility(visFlags);
        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
        mKeyguardHost.setVisibility(View.VISIBLE);
        mKeyguardView.requestFocus();
    }

    public void setNeedsInput(boolean needsInput) {
      ...
    }
    /**
     * Reset the state of the view.
     */
    public synchronized void reset() {
    }
    public synchronized void onScreenTurnedOff() {
    }
    public synchronized void onScreenTurnedOn(
            final KeyguardViewManager.ShowListener showListener) {
            // Caller should wait for this window to be shown before turning
            // on the screen.
    }
    public synchronized void verifyUnlock() {
        if (DEBUG) Log.d(TAG, "verifyUnlock()");
        show();
        mKeyguardView.verifyUnlock();
    }
    /**
     * A key has woken the device.  
     */
    public boolean wakeWhenReadyTq(int keyCode) {
      .....
    }
    /**
     * Hides the keyguard view
     */
    public synchronized void hide() {
       .....
    }
    /**
     * @return Whether the keyguard is showing
     */
    public synchronized boolean isShowing() {
        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
    }

8. KeyguardUpdateMonitor.java

说明:监听系统状态值的改变如时间、SIM卡状态、电池电量等,状态值的改变会回调监听了该状态信息的对象实例。如果只是关注功能的话只需要看hadle里面的每个消息调用的方法即可。

  1. /** 
  2.  * Watches for updates that may be interesting to the keyguard, and provides 
  3.  * the up to date information as well as a registration for callbacks that care 
  4.  * to be updated. 
  5.  * 
  6.  * Note: under time crunch, this has been extended to include some stuff that 
  7.  * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns 
  8.  * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()} 
  9.  * and {@link #clearFailedAttempts()}.  Maybe we should rename this 'KeyguardContext'... 
  10.  */  
  11. public class KeyguardUpdateMonitor {  
  12.     private Handler mHandler;  
  13.     private ContentObserver mContentObserver;  
  14.     private int mRingMode;  
  15.     private int mPhoneState;  
  16. ......  
  17.     
  18.     /** 
  19.      * SIM卡状态改变捕获赋值。 
  20.      * the intent and provide a {@link SimCard.State} result. 
  21.      */  
  22.     private static class SimArgs {  
  23.   
  24.         public final IccCard.State simState;  
  25.   
  26.         private SimArgs(Intent intent) {  
  27.             if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {  
  28.                 throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");  
  29.             }  
  30.             String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);  
  31.             if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {  
  32.                 final String absentReason = intent  
  33.                     .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);  
  34.   
  35.                 if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(  
  36.                         absentReason)) {  
  37.                     this.simState = IccCard.State.PERM_DISABLED;  
  38.                 } else {  
  39.                     this.simState = IccCard.State.ABSENT;  
  40.                 }  
  41.             } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {  
  42.                 this.simState = IccCard.State.READY;  
  43.             } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {  
  44.                 final String lockedReason = intent  
  45.                         .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);  
  46.                 if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {  
  47.                     this.simState = IccCard.State.PIN_REQUIRED;  
  48.                 } else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {  
  49.                     this.simState = IccCard.State.PUK_REQUIRED;  
  50.                 } else {  
  51.                     this.simState = IccCard.State.UNKNOWN;  
  52.                 }  
  53.             } else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {  
  54.                 this.simState = IccCard.State.NETWORK_LOCKED;  
  55.             } else {  
  56.                 this.simState = IccCard.State.UNKNOWN;  
  57.             }  
  58.         }  
  59.   
  60.         public String toString() {  
  61.             return simState.toString();  
  62.         }  
  63.     }  
  64.   
  65.     public KeyguardUpdateMonitor(Context context) {  
  66.         mContext = context;  
  67.   
  68.         mHandler = new Handler() {  
  69.             @Override  
  70.             public void handleMessage(Message msg) {  
  71.                 switch (msg.what) {  
  72.                     case MSG_TIME_UPDATE:  
  73.                         handleTimeUpdate();  
  74.                         break;  
  75.                     case MSG_BATTERY_UPDATE:  
  76.                         handleBatteryUpdate(msg.arg1,  msg.arg2);  
  77.                         break;  
  78.                     case MSG_CARRIER_INFO_UPDATE:  
  79.                         handleCarrierInfoUpdate();  
  80.                         break;  
  81.                     case MSG_SIM_STATE_CHANGE:  
  82.                         handleSimStateChange((SimArgs) msg.obj);  
  83.                         break;  
  84.                     case MSG_RINGER_MODE_CHANGED:  
  85.                         handleRingerModeChange(msg.arg1);  
  86.                         break;  
  87.                     case MSG_PHONE_STATE_CHANGED:  
  88.                         handlePhoneStateChanged((String)msg.obj);  
  89.                         break;  
  90.                     case MSG_CLOCK_VISIBILITY_CHANGED:  
  91.                         handleClockVisibilityChanged();  
  92.                         break;  
  93.                     case MSG_DEVICE_PROVISIONED:  
  94.                         handleDeviceProvisioned();  
  95.                         break;  
  96.                 }  
  97.             }  
  98.         };  
/**
 * Watches for updates that may be interesting to the keyguard, and provides
 * the up to date information as well as a registration for callbacks that care
 * to be updated.
 *
 * Note: under time crunch, this has been extended to include some stuff that
 * doesn't really belong here.  see {@link #handleBatteryUpdate} where it shutdowns
 * the device, and {@link #getFailedAttempts()}, {@link #reportFailedAttempt()}
 * and {@link #clearFailedAttempts()}.  Maybe we should rename this 'KeyguardContext'...
 */
public class KeyguardUpdateMonitor {
    private Handler mHandler;
    private ContentObserver mContentObserver;
    private int mRingMode;
    private int mPhoneState;
......
  
    /**
     * SIM卡状态改变捕获赋值。
     * the intent and provide a {@link SimCard.State} result.
     */
    private static class SimArgs {

        public final IccCard.State simState;

        private SimArgs(Intent intent) {
            if (!TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) {
                throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
            }
            String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
            if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
                final String absentReason = intent
                    .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);

                if (IccCard.INTENT_VALUE_ABSENT_ON_PERM_DISABLED.equals(
                        absentReason)) {
                    this.simState = IccCard.State.PERM_DISABLED;
                } else {
                    this.simState = IccCard.State.ABSENT;
                }
            } else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
                this.simState = IccCard.State.READY;
            } else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
                final String lockedReason = intent
                        .getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
                if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
                    this.simState = IccCard.State.PIN_REQUIRED;
                } else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
                    this.simState = IccCard.State.PUK_REQUIRED;
                } else {
                    this.simState = IccCard.State.UNKNOWN;
                }
            } else if (IccCard.INTENT_VALUE_LOCKED_NETWORK.equals(stateExtra)) {
                this.simState = IccCard.State.NETWORK_LOCKED;
            } else {
                this.simState = IccCard.State.UNKNOWN;
            }
        }

        public String toString() {
            return simState.toString();
        }
    }

    public KeyguardUpdateMonitor(Context context) {
        mContext = context;

        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_TIME_UPDATE:
                        handleTimeUpdate();
                        break;
                    case MSG_BATTERY_UPDATE:
                        handleBatteryUpdate(msg.arg1,  msg.arg2);
                        break;
                    case MSG_CARRIER_INFO_UPDATE:
                        handleCarrierInfoUpdate();
                        break;
                    case MSG_SIM_STATE_CHANGE:
                        handleSimStateChange((SimArgs) msg.obj);
                        break;
                    case MSG_RINGER_MODE_CHANGED:
                        handleRingerModeChange(msg.arg1);
                        break;
                    case MSG_PHONE_STATE_CHANGED:
                        handlePhoneStateChanged((String)msg.obj);
                        break;
                    case MSG_CLOCK_VISIBILITY_CHANGED:
                        handleClockVisibilityChanged();
                        break;
                    case MSG_DEVICE_PROVISIONED:
                        handleDeviceProvisioned();
                        break;
                }
            }
        };

9.KeyguardViewMediator.java

说明:也是boss级别的,虽然明面上不及LockPatternKeyguardView.java,但论实权,是个深藏不露的实力派。奈何可能有把柄在他人之手,所以他必须低调,任劳任怨,为PhoneWindowManager.java所各种差遣。看它的话先把开头的50来行英文注释整清楚,然后在跳到handle里面看一下每个消息对应的执行函数,这样对这个所谓调度者就有个大概的理解了。然后就可以具体功能流程具体分析了。

 

  1. /** 
  2.  *有关键盘锁请求的调度者。包括键盘锁状态的查询,power management事件影响键盘锁是否应该被显示或者重置,特定的回调函数来 
  3.  *通知window manager键盘锁是什么时候显示,以及接受view视图传过来的消息表明已经成功完成解锁。 
  4.  *请注意键盘锁是在灭屏后立即被调用显示的。这样当你点亮屏幕,锁屏才能第一时间显示出来。 
  5.  *例如外部事件调度锁屏视图流程:  
  6.  * 
  7.  *-灭屏动作-》重置锁屏并显示它为下次点亮屏幕做好准备。 
  8.  *-锁屏很自然流畅的打开了-》如果他不是安全的,隐藏之。 
  9.  * 
  10.  *来自于锁屏视图的事件: 
  11.  *-用户成功完成解锁条件-》隐藏锁屏视图,不再对输入事件进行拦截。 
  12.  *请再注意:第三方应用通过条用power managment实例可以屏蔽系统的键盘锁。 
  13.  * 
  14.  *线程和同步: 
  15.  *该类是由WindowManagerPolicy创建并运行在它的线程里,锁屏UI也是这个类的构造函数里面产生。这个apis也可以被其他线程所调用。 
  16.  *然而,这个类的方法手势同步的,同时任何一个锁屏视图都会发消息到handle来保证它是在锁屏UI线程里面执行的。 
  17.  */  
  18.   
  19. public class KeyguardViewMediator implements KeyguardViewCallback,  
  20.         KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback {  
  21. private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;  
  22. /** 
  23.      * This handler will be associated with the policy thread, which will also 
  24.      * be the UI thread of the keyguard.  Since the apis of the policy, and therefore 
  25.      * this class, can be called by other threads, any action that directly 
  26.      * interacts with the keyguard ui should be posted to this handler, rather 
  27.      * than called directly. 
  28.      */  
  29.     private Handler mHandler = new Handler() {  
  30.         @Override  
  31.         public void handleMessage(Message msg) {  
  32.             switch (msg.what) {  
  33.                 case TIMEOUT:  
  34.                     handleTimeout(msg.arg1);  
  35.                     return ;  
  36.                 case SHOW:  
  37.                     handleShow();  
  38.                     return ;  
  39.                 case HIDE:  
  40.                     handleHide();  
  41.                     return ;  
  42.                 case RESET:  
  43.                     handleReset();  
  44.                     return ;  
  45.                 case VERIFY_UNLOCK:  
  46.                     handleVerifyUnlock();  
  47.                     return;  
  48.                 case NOTIFY_SCREEN_OFF:  
  49.                     handleNotifyScreenOff();  
  50.                     return;  
  51.                 case NOTIFY_SCREEN_ON:  
  52.                     handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);  
  53.                     return;  
  54.                 case WAKE_WHEN_READY:  
  55.                     handleWakeWhenReady(msg.arg1);  
  56.                     return;  
  57.                 case KEYGUARD_DONE:  
  58.                     handleKeyguardDone(msg.arg1 != 0);  
  59.                     return;  
  60.                 case KEYGUARD_DONE_DRAWING:  
  61.                     handleKeyguardDoneDrawing();  
  62.                     return;  
  63.                 case KEYGUARD_DONE_AUTHENTICATING:  
  64.                     keyguardDone(true);  
  65.                     return;  
  66.                 case SET_HIDDEN:  
  67.                     handleSetHidden(msg.arg1 != 0);  
  68.                     break;  
  69.                 case KEYGUARD_TIMEOUT:  
  70.                     synchronized (KeyguardViewMediator.this) {  
  71.                         doKeyguardLocked();  
  72.                     }  
  73.                     break;  
  74.             }  
  75.         }  
  76.     };  
  77. private void adjustStatusBarLocked() {  
  78.        ......//控制是否能在锁屏界面下拉状态栏。   
  79.             }  
  80. }  
/**
 *有关键盘锁请求的调度者。包括键盘锁状态的查询,power management事件影响键盘锁是否应该被显示或者重置,特定的回调函数来
 *通知window manager键盘锁是什么时候显示,以及接受view视图传过来的消息表明已经成功完成解锁。
 *请注意键盘锁是在灭屏后立即被调用显示的。这样当你点亮屏幕,锁屏才能第一时间显示出来。
 *例如外部事件调度锁屏视图流程: 
 *
 *-灭屏动作-》重置锁屏并显示它为下次点亮屏幕做好准备。
 *-锁屏很自然流畅的打开了-》如果他不是安全的,隐藏之。
 *
 *来自于锁屏视图的事件:
 *-用户成功完成解锁条件-》隐藏锁屏视图,不再对输入事件进行拦截。
 *请再注意:第三方应用通过条用power managment实例可以屏蔽系统的键盘锁。
 *
 *线程和同步:
 *该类是由WindowManagerPolicy创建并运行在它的线程里,锁屏UI也是这个类的构造函数里面产生。这个apis也可以被其他线程所调用。
 *然而,这个类的方法手势同步的,同时任何一个锁屏视图都会发消息到handle来保证它是在锁屏UI线程里面执行的。
 */

public class KeyguardViewMediator implements KeyguardViewCallback,
        KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
/**
     * This handler will be associated with the policy thread, which will also
     * be the UI thread of the keyguard.  Since the apis of the policy, and therefore
     * this class, can be called by other threads, any action that directly
     * interacts with the keyguard ui should be posted to this handler, rather
     * than called directly.
     */
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case TIMEOUT:
                    handleTimeout(msg.arg1);
                    return ;
                case SHOW:
                    handleShow();
                    return ;
                case HIDE:
                    handleHide();
                    return ;
                case RESET:
                    handleReset();
                    return ;
                case VERIFY_UNLOCK:
                    handleVerifyUnlock();
                    return;
                case NOTIFY_SCREEN_OFF:
                    handleNotifyScreenOff();
                    return;
                case NOTIFY_SCREEN_ON:
                    handleNotifyScreenOn((KeyguardViewManager.ShowListener)msg.obj);
                    return;
                case WAKE_WHEN_READY:
                    handleWakeWhenReady(msg.arg1);
                    return;
                case KEYGUARD_DONE:
                    handleKeyguardDone(msg.arg1 != 0);
                    return;
                case KEYGUARD_DONE_DRAWING:
                    handleKeyguardDoneDrawing();
                    return;
                case KEYGUARD_DONE_AUTHENTICATING:
                    keyguardDone(true);
                    return;
                case SET_HIDDEN:
                    handleSetHidden(msg.arg1 != 0);
                    break;
                case KEYGUARD_TIMEOUT:
                    synchronized (KeyguardViewMediator.this) {
                        doKeyguardLocked();
                    }
                    break;
            }
        }
    };
private void adjustStatusBarLocked() {
       ......//控制是否能在锁屏界面下拉状态栏。
            }
}

10.        PhoneWindowManager.java

说明:在Android中的地位犹如封疆之王爷,此等人物,岂能一眼看透并妄加揣测。需时日翻阅各种资料假以研究才能得出个大概.......此乃后话,当另谋篇幅。

5,2.3keyguard锁屏解的几个小问题,贴上仅供娱乐:

后续待补充。

 

转自:http://blog.csdn.net/aaa2832/article/details/7727848

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值