最近在2.3.7版本上添加一种新的锁屏方式,指纹识别。搞了两个多星期,总算搞定了,下面总结一下:
首先最让人头疼的就是android原生的锁屏框架--Keyguard 虽然到现在也没完全摸清楚这个框架,不过还是要简单记录一下,方便日后参考。
源文件路径主要有两个:
frameworks\base\policy\src\com\android\internal\policy\impl\ ---->锁屏框架
frameworks\base\core\java\com\android\internal\widget\ ----> 提供了一些的自定义View
锁屏界面有两种组成,一种是滑屏的 如下图
另外一种是需要图案、密码或者PIN来解锁
\frameworks\base\policy\src\com\android\internal\policy\impl\目录下
第一种界面是LockScreen.java类
第二种界面是UnLockScreen.java类 分为以下三种:
图案解锁----PatternUnlockScreen.java类
PIN开锁界面 ---- SimUnlockScreen.java 类
密码开锁界面 ---- PasswordUnlockScreen.java类
自定义LinearLayout 在frameworks\policies\base\core\res\res\layout下
当锁屏时候,首先显示LockScreen界面,接着判断是否开启了UnLockScreen界面,如果设置了UnLockScreen界面,则进入对应的
UnLockScreen界面去解锁,才算成功解锁。但,存在一种特殊的情况,就是假如我们选择了图案 UnLockScreen界面,是不会
显示LockScreen界面,而只会显示UnLockScreen界面。
我们知道, 任何一种界面都是由各种View/ViewGroup(当然包括自定义的)组成的,然后根据系统对应的状态值的改变去更新
这些View的显示状态,锁屏界面自然也是如此。锁屏界面的实现最顶层是采用了FrameLayout去控制的,当然内部也嵌套了很
多层,内嵌层数的增多的一点好处就是我们可以分开而治,具体针对每层去做相应的更新。难处就是看代码看的很头疼。
锁屏机制的类结构说明:
1、 LockPatternKeyguardView 继承至FrameLayout :作为LockScreen和UnLockScreen的载体,用来控制显示LockScreen还是UnLockScreen界面。
1、 KeyguardScreen 类 接口
功能:该接口的主要功能是为每个需要显示的界面:LockScreen或者UnLockScreen定义了四个方法,使其在不同的状态能够
得到相应处理。优点就是: 利用设计原则的面向接口编程,减少对具体对象的依赖。
路径:\frameworks\base\policy\src\com\android\internal\policy\impl\KeyguardScreen.java
其源代码释义如下:
- /**
- * Common interface of each {@link android.view.View} that is a screen of
- * {@link LockPatternKeyguardView}.
- */
- public interface KeyguardScreen {
- /** Return true if your view needs input, so should allow the soft
- * keyboard to be displayed. */
- boolean needsInput(); //View是否需要输入数值,即该界面需要键盘输入数值
- /** This screen is no longer in front of the user.*/
- void onPause();//当该界面不处于前台界面时调用,包括处于GONE或者该界面即将被remove掉
- /** This screen is going to be in front of the user. */
- void onResume();//相对于onPause()方法,当该界面不处于前台界面时调用,处于VISIBLE状态时调用
- /** This view is going away; a hook to do cleanup. */
- void cleanUp();//该界面即将被remove掉 ,即不在需要
- }
/**
* Common interface of each {@link android.view.View} that is a screen of
* {@link LockPatternKeyguardView}.
*/
public interface KeyguardScreen {
/** Return true if your view needs input, so should allow the soft
* keyboard to be displayed. */
boolean needsInput(); //View是否需要输入数值,即该界面需要键盘输入数值
/** This screen is no longer in front of the user.*/
void onPause();//当该界面不处于前台界面时调用,包括处于GONE或者该界面即将被remove掉
/** This screen is going to be in front of the user. */
void onResume();//相对于onPause()方法,当该界面不处于前台界面时调用,处于VISIBLE状态时调用
/** This view is going away; a hook to do cleanup. */
void cleanUp();//该界面即将被remove掉 ,即不在需要
}
2、KeyguardScreenCallback类 接口
功能:每个需要显示的界面:LockScreen或者UnLockScreen都保存了该对象的唯一实例,用来向控制界面汇报情况。
路径:frameworks\base\policy\src\com\android\internal\policy\impl\KeyguardScreenCallback.java
其源代码释义如下:
- /** Within a keyguard, there may be several screens that need a callback
- * to the host keyguard view.
- */
- public interface KeyguardScreenCallback extends KeyguardViewCallback {
- /** Transition to the lock screen*/
- void goToLockScreen(); //当前界面跳转为LockScreen ,而不是UnLockScreen
- /** Transition to the unlock screen.*/
- void goToUnlockScreen();//LockScreen成功开锁 ,是否需要显示UnLockScreen,否则,直接开锁成功。
- //忘记了开锁图案,即我们需要跳转到Google 账户去开锁。
- void forgotPattern(boolean isForgotten);
- boolean isSecure();//当前机器是否安全,例如:设置了图案、密码开锁等
- //该函数还不太懂,可能是是否只需要验证UnlockScreen界面,即可成功开锁。
- boolean isVerifyUnlockOnly();
- /**Stay on me, but recreate me (so I can use a different layout).*/
- void recreateMe(Configuration config); //重新根据手机当前状态,显示对应的Screen.
- /** Take action to send an emergency call. */
- void takeEmergencyCallAction(); //紧急呼叫时的处理行为.
- /** Report that the user had a failed attempt to unlock with password or pattern.*/
- void reportFailedUnlockAttempt(); //在UnLockScreen界面登陆失败时处理
- /** Report that the user successfully entered their password or pattern.*/
- void reportSuccessfulUnlockAttempt();//在UnLockScreen界面登陆成功时处理
- /** Report whether we there's another way to unlock the device.
- * @return true */
- boolean doesFallbackUnlockScreenExist();
- }
/** Within a keyguard, there may be several screens that need a callback
* to the host keyguard view.
*/
public interface KeyguardScreenCallback extends KeyguardViewCallback {
/** Transition to the lock screen*/
void goToLockScreen(); //当前界面跳转为LockScreen ,而不是UnLockScreen
/** Transition to the unlock screen.*/
void goToUnlockScreen();//LockScreen成功开锁 ,是否需要显示UnLockScreen,否则,直接开锁成功。
//忘记了开锁图案,即我们需要跳转到Google 账户去开锁。
void forgotPattern(boolean isForgotten);
boolean isSecure();//当前机器是否安全,例如:设置了图案、密码开锁等
//该函数还不太懂,可能是是否只需要验证UnlockScreen界面,即可成功开锁。
boolean isVerifyUnlockOnly();
/**Stay on me, but recreate me (so I can use a different layout).*/
void recreateMe(Configuration config); //重新根据手机当前状态,显示对应的Screen.
/** Take action to send an emergency call. */
void takeEmergencyCallAction(); //紧急呼叫时的处理行为.
/** Report that the user had a failed attempt to unlock with password or pattern.*/
void reportFailedUnlockAttempt(); //在UnLockScreen界面登陆失败时处理
/** Report that the user successfully entered their password or pattern.*/
void reportSuccessfulUnlockAttempt();//在UnLockScreen界面登陆成功时处理
/** Report whether we there's another way to unlock the device.
* @return true */
boolean doesFallbackUnlockScreenExist();
}
其唯一实现类位于LockPatternKeyguardView类的内部类(稍后讲到)。
3、KeyguardViewCallback类 接口
功能: 提供了一些接口用来接受用户操作Screen的结果。
路径:frameworks\base\policy\src\com\android\internal\policy\impl\KeyguardViewCallback.java
其源代码释义如下:
- /**
- * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
- * various things.
- */
- public interface KeyguardViewCallback {
- /** Request the wakelock to be poked for the default amount of time. */
- void pokeWakelock(); //保存屏幕在一定时间内处于亮屏状况 , 默认时间为5s或者10s
- /** Request the wakelock to be poked for a specific amount of time. */
- void pokeWakelock(int millis);//根据给定时间值,使屏幕在该事件段内保持亮屏状况
- /** Report that the keyguard is done.
- * @param authenticated Whether the user securely got past the keyguard.
- * the only reason for this to be false is if the keyguard was instructed
- * to appear temporarily to verify the user is supposed to get past the
- * keyguard, and the user fails to do so. */
- //成功的完成开锁,可以进入手机界面了。参数为ture表示是否正大光明的开锁,例如:图案正确,密码输入正确。
- void keyguardDone(boolean authenticated);
- /**Report that the keyguard is done drawing. */
- void keyguardDoneDrawing(); //整个锁屏界面draw()过程绘制完成时,回调该方法.
- }
/**
* The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
* various things.
*/
public interface KeyguardViewCallback {
/** Request the wakelock to be poked for the default amount of time. */
void pokeWakelock(); //保存屏幕在一定时间内处于亮屏状况 , 默认时间为5s或者10s
/** Request the wakelock to be poked for a specific amount of time. */
void pokeWakelock(int millis);//根据给定时间值,使屏幕在该事件段内保持亮屏状况
/** Report that the keyguard is done.
* @param authenticated Whether the user securely got past the keyguard.
* the only reason for this to be false is if the keyguard was instructed
* to appear temporarily to verify the user is supposed to get past the
* keyguard, and the user fails to do so. */
//成功的完成开锁,可以进入手机界面了。参数为ture表示是否正大光明的开锁,例如:图案正确,密码输入正确。
void keyguardDone(boolean authenticated);
/**Report that the keyguard is done drawing. */
void keyguardDoneDrawing(); //整个锁屏界面draw()过程绘制完成时,回调该方法.
}
其唯一实现类是 KeyguardViewMediator类(稍后讲到)
4、 KeyguardWindowController类 接口
功能:提供通用 接口,判断该界面是否需要显示输入法窗口。
其源代码释义如下:
- /**
- * Interface passed to the keyguard view, for it to call up to control
- * its containing window.
- */
- public interface KeyguardWindowController {
- /** Control whether the window needs input -- that is if it has
- * text fields and thus should allow input method interaction. */
- void setNeedsInput(boolean needsInput); //是否需要显示输入法,为true表示需要。该方法可以想上层报到是否需要显示输入法窗口
- }
/**
* Interface passed to the keyguard view, for it to call up to control
* its containing window.
*/
public interface KeyguardWindowController {
/** Control whether the window needs input -- that is if it has
* text fields and thus should allow input method interaction. */
void setNeedsInput(boolean needsInput); //是否需要显示输入法,为true表示需要。该方法可以想上层报到是否需要显示输入法窗口
}
其唯一实现类是KeyguardViewManager类(稍后讲到)。
5、KeyguardViewManager类
功能:包装了WindowManager功能了,提供了添加、删除锁屏界面的功能。
其源代码释义如下:
- public class KeyguardViewManager implements KeyguardWindowController {
- ...
- private WindowManager.LayoutParams mWindowLayoutParams;
- private boolean mNeedsInput = false; //是否需要输入法 , 默认不需要
- private FrameLayout mKeyguardHost; //该ViewGroup作为顶层View,作为WindowManager添加至窗口
- private KeyguardViewBase mKeyguardView; //具体窗口内容。
- //以上两种的关系相当于DecorView和我们Activity内设置的资源文件一样
- private boolean mScreenOn = false; //是否处于亮屏状态
- //构造函数,初始化各种属性
- public KeyguardViewManager(Context context, ViewManager viewManager,
- KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties, KeyguardUpdateMonitor updateMonitor) {
- ...
- }
- /**
- * Helper class to host the keyguard view.
- */
- private static class KeyguardViewHost extends FrameLayout {
- ... //KeyguardViewHost类
- }
- /**
- * Show the keyguard. Will handle creating and attaching to the view manager
- * lazily.
- */ //显示锁屏界面
- public synchronized void show() {
- if (mKeyguardHost == null) {
- ...
- mViewManager.addView(mKeyguardHost, lp);
- }
- if (mKeyguardView == null) {
- ...
- mKeyguardHost.addView(mKeyguardView, lp);
- if (mScreenOn) {
- mKeyguardView.onScreenTurnedOn();
- }
- }
- ...
- }
- ...
- /*** Hides the keyguard view */
- public synchronized void hide() { //隐藏锁屏界面,也就是说我们成功的解锁了
- if (mKeyguardHost != null) {
- mKeyguardHost.setVisibility(View.GONE);
- ...
- }
- }
- //锁屏界面是否处于显示状态
- public synchronized boolean isShowing() {
- return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
- }
- }
- }
public class KeyguardViewManager implements KeyguardWindowController {
...
private WindowManager.LayoutParams mWindowLayoutParams;
private boolean mNeedsInput = false; //是否需要输入法 , 默认不需要
private FrameLayout mKeyguardHost; //该ViewGroup作为顶层View,作为WindowManager添加至窗口
private KeyguardViewBase mKeyguardView; //具体窗口内容。
//以上两种的关系相当于DecorView和我们Activity内设置的资源文件一样
private boolean mScreenOn = false; //是否处于亮屏状态
//构造函数,初始化各种属性
public KeyguardViewManager(Context context, ViewManager viewManager,
KeyguardViewCallback callback, KeyguardViewProperties keyguardViewProperties, KeyguardUpdateMonitor updateMonitor) {
...
}
/**
* Helper class to host the keyguard view.
*/
private static class KeyguardViewHost extends FrameLayout {
... //KeyguardViewHost类
}
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
*/ //显示锁屏界面
public synchronized void show() {
if (mKeyguardHost == null) {
...
mViewManager.addView(mKeyguardHost, lp);
}
if (mKeyguardView == null) {
...
mKeyguardHost.addView(mKeyguardView, lp);
if (mScreenOn) {
mKeyguardView.onScreenTurnedOn();
}
}
...
}
...
/*** Hides the keyguard view */
public synchronized void hide() { //隐藏锁屏界面,也就是说我们成功的解锁了
if (mKeyguardHost != null) {
mKeyguardHost.setVisibility(View.GONE);
...
}
}
//锁屏界面是否处于显示状态
public synchronized boolean isShowing() {
return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
}
}
}
6、 KeyguardUpdateMonitor.java类
功能:该类的主要功能就是根据监视系统状态值的改变(例如:时间、SIM卡状态、电池电量;使用广播监听),根据这种状态
值的改变回调监听了该状态信息的对象实例。
其源代码释义如下:
- public class KeyguardUpdateMonitor {
- ...
- private int mFailedAttempts = 0; //当前登录事,已经失败的次数
- private ArrayList<InfoCallback> mInfoCallbacks; //保存所有监听对象 InfoCallback
- private ArrayList<SimStateCallback> mSimStateCallbacks ; //保存所有监听对象 SimStateCallback
- private static class SimArgs { //Sim状态信息
- ...
- }
- /**
- * Callback for general information relevant to lock screen.
- */
- interface InfoCallback {
- //电池电量信息改变:参数含义分别如下:是否显示电量信息 、 是否插入电影充电、 当前电池电量值
- void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel);
- void onTimeChanged(); //时间发生了改变
- //网络运营商状态发生了改变 ,例如从中国移动2G变为中国移动3G,或者无服务等 ;
- void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn);
- /** Called when the ringer mode changes. */
- void onRingerModeChanged(int state);
- /** 电话状态发生了改变 值可能为:EXTRA_STATE_IDLE、EXTRA_STATE_RINGING、EXTRA_STATE_OFFHOOK*/
- void onPhoneStateChanged(String newState);
- }
- /** Callback to notify of sim state change. */
- interface SimStateCallback {
- void onSimStateChanged(IccCard.State simState); //Sim卡信息发生了改变,例如有正常状况变为ABSENT/MISSING状态
- }
- /*** Register to receive notifications about general keyguard information
- * (see {@link InfoCallback}. */
- public void registerInfoCallback(InfoCallback callback) {
- if (!mInfoCallbacks.contains(callback)) {
- mInfoCallbacks.add(callback); //注册一个监听器
- } ...
- }
- ...
- }
public class KeyguardUpdateMonitor {
...
private int mFailedAttempts = 0; //当前登录事,已经失败的次数
private ArrayList<InfoCallback> mInfoCallbacks; //保存所有监听对象 InfoCallback
private ArrayList<SimStateCallback> mSimStateCallbacks ; //保存所有监听对象 SimStateCallback
private static class SimArgs { //Sim状态信息
...
}
/**
* Callback for general information relevant to lock screen.
*/
interface InfoCallback {
//电池电量信息改变:参数含义分别如下:是否显示电量信息 、 是否插入电影充电、 当前电池电量值
void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel);
void onTimeChanged(); //时间发生了改变
//网络运营商状态发生了改变 ,例如从中国移动2G变为中国移动3G,或者无服务等 ;
void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn);
/** Called when the ringer mode changes. */
void onRingerModeChanged(int state);
/** 电话状态发生了改变 值可能为:EXTRA_STATE_IDLE、EXTRA_STATE_RINGING、EXTRA_STATE_OFFHOOK*/
void onPhoneStateChanged(String newState);
}
/** Callback to notify of sim state change. */
interface SimStateCallback {
void onSimStateChanged(IccCard.State simState); //Sim卡信息发生了改变,例如有正常状况变为ABSENT/MISSING状态
}
/*** Register to receive notifications about general keyguard information
* (see {@link InfoCallback}. */
public void registerInfoCallback(InfoCallback callback) {
if (!mInfoCallbacks.contains(callback)) {
mInfoCallbacks.add(callback); //注册一个监听器
} ...
}
...
}
7, LockPatternKeyguardView类 (自定义ViewGroup)
功能:作为LockScreen和UnLockScreen界面的载体,控制显示哪个界面。
其源代码释义如下:
- public class LockPatternKeyguardView extends KeyguardViewBase {
- ...
- private View mLockScreen;
- private View mUnlockScreen;
- private boolean mScreenOn = false;//是否亮屏
- enum Mode {
- //当前显示界面的Mode Lock 或者UnLock
- }
- enum UnlockMode {
- ...//开锁界面的几种不同Mode
- }
- //构造函数
- public LockPatternKeyguardView( ...) {
- //KeyguardScreenCallback的实现对象
- mKeyguardScreenCallback = new KeyguardScreenCallback() {
- ...
- };
- ...
- }
- public void reset() {
- ...//重置显示界面
- }
- private void recreateLockScreen() {
- ...//重新构建LockScreen
- }
- private void recreateUnlockScreen() {
- ...//重新构建UnlockScreen
- }
- private void recreateScreens() {
- ...//重新构建该视图
- }
- public void verifyUnlock() {
- ...
- }
- public void cleanUp() {
- ... //清理资源对象
- }
- private boolean isSecure() {
- ...//手机设置是否处于安全状态
- }
- private void updateScreen(final Mode mode) {
- ...//根据参数(Lock/unLock),判断显示为LockScreen或者UnlockScreen界面
- }
- View createLockScreen() {
- ...//创建lockScreen
- }
- View createUnlockScreenFor(UnlockMode unlockMode) {
- ...//根据不同的Unlock Mode , 创建不同的UnlockScreen
- }
- private Mode getInitialMode() {
- ...//得到初始化的状态Mode (lock or unlock).
- }
- /** Given the current state of things, what should the unlock screen be? */
- private UnlockMode getUnlockMode() {
- ...//返回开锁的状态Unlock Mode
- }
- private void showTimeoutDialog() {
- ... //输入密码超过一定次数时,提示30s后在登录的对话框
- }
- private void showAlmostAtAccountLoginDialog() {
- ... //显示Google 账户登录对话框
- }
- }
public class LockPatternKeyguardView extends KeyguardViewBase {
...
private View mLockScreen;
private View mUnlockScreen;
private boolean mScreenOn = false;//是否亮屏
enum Mode {
//当前显示界面的Mode Lock 或者UnLock
}
enum UnlockMode {
...//开锁界面的几种不同Mode
}
//构造函数
public LockPatternKeyguardView( ...) {
//KeyguardScreenCallback的实现对象
mKeyguardScreenCallback = new KeyguardScreenCallback() {
...
};
...
}
public void reset() {
...//重置显示界面
}
private void recreateLockScreen() {
...//重新构建LockScreen
}
private void recreateUnlockScreen() {
...//重新构建UnlockScreen
}
private void recreateScreens() {
...//重新构建该视图
}
public void verifyUnlock() {
...
}
public void cleanUp() {
... //清理资源对象
}
private boolean isSecure() {
...//手机设置是否处于安全状态
}
private void updateScreen(final Mode mode) {
...//根据参数(Lock/unLock),判断显示为LockScreen或者UnlockScreen界面
}
View createLockScreen() {
...//创建lockScreen
}
View createUnlockScreenFor(UnlockMode unlockMode) {
...//根据不同的Unlock Mode , 创建不同的UnlockScreen
}
private Mode getInitialMode() {
...//得到初始化的状态Mode (lock or unlock).
}
/** Given the current state of things, what should the unlock screen be? */
private UnlockMode getUnlockMode() {
...//返回开锁的状态Unlock Mode
}
private void showTimeoutDialog() {
... //输入密码超过一定次数时,提示30s后在登录的对话框
}
private void showAlmostAtAccountLoginDialog() {
... //显示Google 账户登录对话框
}
}
8、KeyguardViewBase类 抽象类 (自定义ViewGroup)
功能:为LockPatternKeyguardView提供了一组通用的方法 。需要值得注意的方法就是他对某些KeyEvent的监听,
当他消费监听到这些KeyEvent,我们的App就监听不到这些KeyEvent了 。常用的有KEYEVENT_VOLUME_UP/DOWN等。
- public abstract class KeyguardViewBase extends FrameLayout {
- ...
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- ...
- if (interceptMediaKey(event)) {
- return true;
- }
- return super.dispatchKeyEvent(event);
- }
- private boolean interceptMediaKey(KeyEvent event) {
- final int keyCode = event.getKeyCode();
- if (event.getAction() == KeyEvent.ACTION_DOWN) {
- switch (keyCode) {
- ...//more keyevent
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN: {
- ...
- // Don't execute default volume behavior
- return true; //直接返回不在向下传递处理
- }
- }
- }
- return false;
- }
- }
public abstract class KeyguardViewBase extends FrameLayout {
...
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
...
if (interceptMediaKey(event)) {
return true;
}
return super.dispatchKeyEvent(event);
}
private boolean interceptMediaKey(KeyEvent event) {
final int keyCode = event.getKeyCode();
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
...//more keyevent
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN: {
...
// Don't execute default volume behavior
return true; //直接返回不在向下传递处理
}
}
}
return false;
}
}
9、 KeyguardViewProperties.java 接口
功能:提供了创建界面的通用方法。
- public interface KeyguardViewProperties {
- //创建一个KeyguardViewBase实例 , 实际是指LockPatternKeyguardView实例
- KeyguardViewBase createKeyguardView(Context context,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardWindowController controller);
- boolean isSecure();
- }
public interface KeyguardViewProperties {
//创建一个KeyguardViewBase实例 , 实际是指LockPatternKeyguardView实例
KeyguardViewBase createKeyguardView(Context context,
KeyguardUpdateMonitor updateMonitor,
KeyguardWindowController controller);
boolean isSecure();
}
其唯一实现类是是LockPatternKeyguardViewProperties类(稍后讲到)。
10、LockPatternKeyguardViewProperties类
源代码释义如下:
- public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
- ...
- //创建一个LockPatternKeyguardView对象
- public KeyguardViewBase createKeyguardView(Context context,
- KeyguardUpdateMonitor updateMonitor,
- KeyguardWindowController controller) {
- return new LockPatternKeyguardView(context, updateMonitor,
- mLockPatternUtils, controller);
- }
public class LockPatternKeyguardViewProperties implements KeyguardViewProperties {
...
//创建一个LockPatternKeyguardView对象
public KeyguardViewBase createKeyguardView(Context context,
KeyguardUpdateMonitor updateMonitor,
KeyguardWindowController controller) {
return new LockPatternKeyguardView(context, updateMonitor,
mLockPatternUtils, controller);
}
}
//=============================================
// OK ,我知道你看的很纠结了,具体需要时参考源代码看是最明智的。
//=============================================
我知道代码贴的太多了,没办法,谁让它理解起来就那么费劲呢 ? 你可别犯愁,真正核心的类可还没出来。。
12、KeyguardViewMediator核心类 ,该类是唯一实现了KeyguardViewCallback的类。
功能: 功能:该类提供了一些接口,由PhoneWindowManager)去访问控制Keyguard....
该类的初始化是在PolicyWindowManager的构造函数中创建的。如下:
- public class PhoneWindowManager implements WindowManagerPolicy {
- ...
- /** {@inheritDoc} */ //由SystemServer调用
- public void init(Context context, IWindowManager windowManager,
- LocalPowerManager powerManager) {
- ...//初始化该实例
- mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
- }
- }
public class PhoneWindowManager implements WindowManagerPolicy {
...
/** {@inheritDoc} */ //由SystemServer调用
public void init(Context context, IWindowManager windowManager,
LocalPowerManager powerManager) {
...//初始化该实例
mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
}
}
参照源代码,把一些重要的属性和方法的大意给分析下:
- public class KeyguardViewMediator implements KeyguardViewCallback, KeyguardUpdateMonitor.SimStateCallback {
- private boolean mSystemReady; //启动成功 由SystemServer调用
- /**Used to keep the device awake while to ensure the keyguard finishes opening before
- * we sleep.*/ //在需要显示锁屏界面时,保持屏幕在某个时间段内为暗屏状态
- private PowerManager.WakeLock mShowKeyguardWakeLock;
- private KeyguardViewManager mKeyguardViewManager; //KeyguardViewManager实例
- /** * External apps (like the phone app) can tell us to disable the keygaurd.*/
- //是否允许其他App禁止锁屏 , 例如来电时 禁止锁屏
- private boolean mExternallyEnabled = true;
- //处于锁屏状态 , 即显示锁屏
- private boolean mShowing = false;
- // true if the keyguard is hidden by another window
- private boolean mHidden = false; //被其他窗口掩盖 , 例如来电时锁屏被掩盖
- private boolean mScreenOn = false; // 是否亮屏
- public KeyguardViewMediator(Context context, PhoneWindowManager callback,
- LocalPowerManager powerManager) {
- ...
- //构造相关实例对象
- mKeyguardViewProperties = new LockPatternKeyguardViewProperties(
- new LockPatternUtils(mContext), mUpdateMonitor);
- mKeyguardViewManager = new KeyguardViewManager(
- context, WindowManagerImpl.getDefault(), this,
- mKeyguardViewProperties, mUpdateMonitor);
- //解锁成功后发送的Intent
- mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
- mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- }
- /** Called to let us know the screen was turned off.
- * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
- * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
- */
- //屏幕变灰暗 , 原因有如下:以及对应的逻辑处理。
- // 1、OFF_BECAUSE_OF_USER : 用户按下POWER键 , 当前是否处于锁屏界面,若是(mShowing)则重置显示界面,否则重新显示锁屏界面
- // 2、OFF_BECAUSE_OF_TIMEOUT : 屏幕超时,常见情况就是一段时间没有操作屏幕,手机处于灰暗状态。 处理行为:
- // 发送Action值为DELAYED_KEYGUARD_ACTION的广播,因为该类注册了该Intent广播,接受到时会调用doKeyguard()方法锁屏
- // 3、OFF_BECAUSE_OF_PROX_SENSOR:接打电话时,距离感应太近导致暗屏,此时由于PowerManager那儿已经处理了暗屏,不需要做任何事
- // 最后,如果以上逻辑都不成立,调用 doKeyguard()方法显示屏幕
- public void onScreenTurnedOff(int why) {
- ...
- }
- /**
- * Let's us know the screen was turned on.
- */
- public void onScreenTurnedOn() {
- synchronized (this) {
- ...
- notifyScreenOnLocked(); //通知亮屏
- }
- }
- /** Enable the keyguard if the settings are appropriate. */
- private void doKeyguard() {
- synchronized (this) {
- ...
- showLocked();//显示锁屏界面
- }
- }
- //该方法的调用时机就是当按下POWER键时,系统会回调该方法 keyCode值一般为 26
- public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) {
- //操作按键是否能唤醒屏幕
- if (isWakeKeyWhenKeyguardShowing(keyCode)) {
- // give the keyguard view manager a chance to adjust the state of the
- // keyguard based on the key that woke the device before poking
- // the wake lock
- wakeWhenReadyLocked(keyCode);//开始唤醒屏幕咯
- return true;
- } else {
- return false;
- }
- }
- /** {@inheritDoc} */ //在一定时间内保存屏幕为亮屏状态
- public void pokeWakelock(int holdMs) {
- ...
- }
- //表示成功得分完成了解锁操作
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- synchronized (this) {
- //发送给Handler 进行异步处理
- Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
- msg.arg1 = wakeup ? 1 : 0;
- mHandler.sendMessage(msg);
- if (authenticated) {
- mUpdateMonitor.clearFailedAttempts(); //清除错误登录次数
- }
- ...
- }
- }
- //Handler对象 , 异步处理
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- ... //异步处理
- }
- }
- };
- //异步处理完成开锁成功
- private void handleKeyguardDone(boolean wakeup) {
- handleHide(); //释放该Keyguard对应的窗口
- mWakeLock.release();
- mContext.sendBroadcast(mUserPresentIntent); //解锁成功,发送Intent信息
- }
- //显示锁屏界面
- private void handleShow() {
- synchronized (KeyguardViewMediator.this) {
- ...
- mKeyguardViewManager.show();
- mShowing = true;
- ...
- }
- }
- private void handleHide() {
- synchronized (KeyguardViewMediator.this) {
- //去除锁屏界面对应的窗口
- mKeyguardViewManager.hide();
- mShowing = false;
- ...
- }
- }
- //设置状态栏enable状态 , 例如:能否被下拉等
- private void adjustStatusBarLocked() {
- ...
- // if the keyguard is shown, allow the status bar to open
- // only if the keyguard is insecure and is covered by another window
- boolean enable = !mShowing || (mHidden && !isSecure());
- mStatusBarManager.disable(enable ?StatusBarManager.DISABLE_NONE : StatusBarManager.DISABLE_EXPAND);
- }
- }
- }
public class KeyguardViewMediator implements KeyguardViewCallback, KeyguardUpdateMonitor.SimStateCallback {
private boolean mSystemReady; //启动成功 由SystemServer调用
/**Used to keep the device awake while to ensure the keyguard finishes opening before
* we sleep.*/ //在需要显示锁屏界面时,保持屏幕在某个时间段内为暗屏状态
private PowerManager.WakeLock mShowKeyguardWakeLock;
private KeyguardViewManager mKeyguardViewManager; //KeyguardViewManager实例
/** * External apps (like the phone app) can tell us to disable the keygaurd.*/
//是否允许其他App禁止锁屏 , 例如来电时 禁止锁屏
private boolean mExternallyEnabled = true;
//处于锁屏状态 , 即显示锁屏
private boolean mShowing = false;
// true if the keyguard is hidden by another window
private boolean mHidden = false; //被其他窗口掩盖 , 例如来电时锁屏被掩盖
private boolean mScreenOn = false; // 是否亮屏
public KeyguardViewMediator(Context context, PhoneWindowManager callback,
LocalPowerManager powerManager) {
...
//构造相关实例对象
mKeyguardViewProperties = new LockPatternKeyguardViewProperties(
new LockPatternUtils(mContext), mUpdateMonitor);
mKeyguardViewManager = new KeyguardViewManager(
context, WindowManagerImpl.getDefault(), this,
mKeyguardViewProperties, mUpdateMonitor);
//解锁成功后发送的Intent
mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT);
mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
}
/** Called to let us know the screen was turned off.
* @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
* {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
* {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
*/
//屏幕变灰暗 , 原因有如下:以及对应的逻辑处理。
// 1、OFF_BECAUSE_OF_USER : 用户按下POWER键 , 当前是否处于锁屏界面,若是(mShowing)则重置显示界面,否则重新显示锁屏界面
// 2、OFF_BECAUSE_OF_TIMEOUT : 屏幕超时,常见情况就是一段时间没有操作屏幕,手机处于灰暗状态。 处理行为:
// 发送Action值为DELAYED_KEYGUARD_ACTION的广播,因为该类注册了该Intent广播,接受到时会调用doKeyguard()方法锁屏
// 3、OFF_BECAUSE_OF_PROX_SENSOR:接打电话时,距离感应太近导致暗屏,此时由于PowerManager那儿已经处理了暗屏,不需要做任何事
// 最后,如果以上逻辑都不成立,调用 doKeyguard()方法显示屏幕
public void onScreenTurnedOff(int why) {
...
}
/**
* Let's us know the screen was turned on.
*/
public void onScreenTurnedOn() {
synchronized (this) {
...
notifyScreenOnLocked(); //通知亮屏
}
}
/** Enable the keyguard if the settings are appropriate. */
private void doKeyguard() {
synchronized (this) {
...
showLocked();//显示锁屏界面
}
}
//该方法的调用时机就是当按下POWER键时,系统会回调该方法 keyCode值一般为 26
public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) {
//操作按键是否能唤醒屏幕
if (isWakeKeyWhenKeyguardShowing(keyCode)) {
// give the keyguard view manager a chance to adjust the state of the
// keyguard based on the key that woke the device before poking
// the wake lock
wakeWhenReadyLocked(keyCode);//开始唤醒屏幕咯
return true;
} else {
return false;
}
}
/** {@inheritDoc} */ //在一定时间内保存屏幕为亮屏状态
public void pokeWakelock(int holdMs) {
...
}
//表示成功得分完成了解锁操作
public void keyguardDone(boolean authenticated, boolean wakeup) {
synchronized (this) {
//发送给Handler 进行异步处理
Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
msg.arg1 = wakeup ? 1 : 0;
mHandler.sendMessage(msg);
if (authenticated) {
mUpdateMonitor.clearFailedAttempts(); //清除错误登录次数
}
...
}
}
//Handler对象 , 异步处理
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
... //异步处理
}
}
};
//异步处理完成开锁成功
private void handleKeyguardDone(boolean wakeup) {
handleHide(); //释放该Keyguard对应的窗口
mWakeLock.release();
mContext.sendBroadcast(mUserPresentIntent); //解锁成功,发送Intent信息
}
//显示锁屏界面
private void handleShow() {
synchronized (KeyguardViewMediator.this) {
...
mKeyguardViewManager.show();
mShowing = true;
...
}
}
private void handleHide() {
synchronized (KeyguardViewMediator.this) {
//去除锁屏界面对应的窗口
mKeyguardViewManager.hide();
mShowing = false;
...
}
}
//设置状态栏enable状态 , 例如:能否被下拉等
private void adjustStatusBarLocked() {
...
// if the keyguard is shown, allow the status bar to open
// only if the keyguard is insecure and is covered by another window
boolean enable = !mShowing || (mHidden && !isSecure());
mStatusBarManager.disable(enable ?StatusBarManager.DISABLE_NONE : StatusBarManager.DISABLE_EXPAND);
}
}
}
该类的很多方法都是由PhoneWindowManager调用访问的。