锁屏相关的文件在android对应packagecom.android.internal.policy.impl

phoneWindowManager.java可以派发各种物理key,如PowerHomeVol+Vol-等等。那么,这个类是由谁启动的?

packagePolicy.java

publicPhoneWindowManagermakeNewWindowManager(){

returnnewPhoneWindowManager();

}

这个方法实现创建这个类。而在PolicyManager.java下调用这个方法实现对PhoneWindowManager的创建。

但是,PhoneWindowManager.java中有一个init()方法,这个是这个类的初始化方法,它调用PowerManagerwindowManagerKeyguardViewMediator等等实现对PhoneWindowManager。这个Init()是在WindowManagerService.java下的PolicyThread类下得Run方法中调用mPolicy.init(mContext,mService,mPM)

PhoneWindowManager.java这个类是非常重要的,这里注册了一个Orientation变化的监听类:

MyOrientationListenerextendsWindowOrientationListener,但是,它不能够自动进行更新,它的更新主要是依据接收广播进行的,此处大概就是JNI根据驱动获取相关Sensor消息然后发送消息。这里仅仅粗略说明在这个文件中有屏幕旋转的处理方法。

下面是锁屏的处理流程:

PhoneWindowManager.java中:

publicvoidsystemReady(){

//tellthekeyguard

mKeyguardMediator.onSystemReady();

android.os.SystemProperties.set("dev.bootcomplete","1");

synchronized(mLock){

updateOrientationListenerLp();

mSystemReady=true;

mHandler.post(newRunnable(){

publicvoidrun(){

updateSettings();

}

});

}

}

这个方法在开机时启动调用,然后mKeyguardMediator.onSystemReady()

在KeyGuardViewMeditor.java是一个非常重要的类,它用来响应电源键的处理(黑亮屏),查询解锁屏等等。

publicvoidonSystemReady(){

synchronized(this){

if(DEBUG)Log.d(TAG,"onSystemReady");

mSystemReady=true; //系统准备好了

doKeyguard(); //判断是否设定了锁

}

}

privatevoiddoKeyguard()主要功能:Enablethekeyguardifthesettingsareappropriate.意思就是如果在Setting里面设置了密码就激活keyguard。

1.如果设置了屏幕锁,黑屏后,在onScreenTurnedOff中doKeyguard()调用一次;

2.如果有SIM卡,且设置了PIN或PUK锁,那么调用doKeyguard();

3.TIMEROUT时调用doKeyguard();

4.接收到消息;DELAYED_KEYGUARD_ACTION或者TelephonyManager.ACTION_PHONE_STATE_CHANGED可能会调用

doKeyguard().

doKeyguard()方法最后调用了showLocked();

privatevoidshowLocked(){

if(DEBUG)Log.d(TAG,"showLocked");

//ensurewestayawakeuntilwearefinisheddisplayingthekeyguard

mShowKeyguardWakeLock.acquire();

Messagemsg=mHandler.obtainMessage(SHOW);

mHandler.sendMessage(msg);

}

实际上就是发送消息显示SHOW

Handler接收到SHOW这个Message,进行相关处理:

进入KeyguardViewManager.java:

publicsynchronizedvoidshow()方法中:

if(mKeyguardView==null){

if(DEBUG)Log.d(TAG,"keyguardviewisnull,creatingit...");

mKeyguardView=mKeyguardViewProperties.createKeyguardView(mContext,mUpdateMonitor,this);

mKeyguardView.setId(R.id.lock_screen);

……

}

mKeyguardView=mKeyguardViewProperties.createKeyguardView(mContext,mUpdateMonitor,this)这个就是KeyguardViewBase创建一个KeyguardViewBase的对象,也就是管理LockUnlock画面的类实例

在Setting里面设置各种锁屏之后,在按power键重新开启时会产生lock或者unlock界面,需要输入密码或者绘出Pattern等操作后才能进入界面。这个锁定和解锁界面是由LockPatternKeyguardView这个类实现的。下面便是这个class的构造函数。

publicLockPatternKeyguardView(

Contextcontext,

KeyguardUpdateMonitorupdateMonitor,

LockPatternUtilslockPatternUtils,

KeyguardWindowControllercontroller)

重要实现:

mConfiguration=context.getResources().getConfiguration();

这个函数是用来获取系统的一些配置,在此用来决定是横屏还是竖屏。

mMode=getInitialMode();

这个则是获取系统的mode了。

mMode是这样的类型:

enumMode{

LockScreen,

UnlockScreen

}

可以初步判断是lock还是unlock状态的flag枚举。获取这个状态是非常重要的,它决定初始化时究竟是显示unlock 界面还是lock界面。

privateModegetInitialMode(){

booleanisPukRequired=false;

for(inti=0;i<TelephonyManager.getPhoneCount();i++){

isPukRequired=isPukRequired||isSimPukLocked(i);

if(isPukRequired)break;

}

//这里是判断sim是否加入PUK锁或者sim卡不存在

if(stuckOnLockScreenBecauseSimMissing()||isPukRequired){

returnMode.LockScreen;

}else{

//ShowLockScreenfirstforanyscreenotherthanPatternunlock.

finalbooleanusingLockPattern=

mLockPatternUtils.getKeyguardStoredPasswordQuality()==DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;

if(isSecure()&&usingLockPattern){

returnMode.UnlockScreen;

}else{

returnMode.LockScreen;

}

}

}

对于isSecure这个函数,定义如下:

privatebooleanisSecure(){

UnlockModeunlockMode=getUnlockMode();

booleansecure=false;

switch(unlockMode){

casePattern:

secure=mLockPatternUtils.isLockPatternEnabled();

break;

caseSimPin:

for(inti=0;i<TelephonyManager.getPhoneCount();i++){

//CheckifsubscriptionisPIN/PUKlocked.

//isPinLockedreturnstrueifthestateisPIN_REQUIRED/PUK_REQUIRED.

secure=secure||getSimState(i).isPinLocked();

if(secure)break;

}

break;

caseAccount:

secure=true;

break;

casePassword:

secure=mLockPatternUtils.isLockPasswordEnabled();

break;

default:

thrownewIllegalStateException("unknownunlockmode"+unlockMode);

}

returnsecure;

很显然是判断,是否设置了解锁屏方式。是则返回true,否则false。

而usingLockPattern是判断是否是用pattern模式的。具体判断后面研究。

在获取相关初始状态后,就是一些回调函数的实现:

mKeyguardScreenCallback=newKeyguardScreenCallback(),这个是十分容易解决的。

在之后是:

//createboththelockandunlockscreensotheyarequicklyavailable

//whenthescreenturnson

mLockScreen=createLockScreen();

addView(mLockScreen);

finalUnlockModeunlockMode=getUnlockMode();

if(DEBUG)Log.d(TAG,

"LockPatternKeyguardViewctor:abouttocreateUnlockScreenFor;mEnableFallback="

+mEnableFallback);

mUnlockScreen=createUnlockScreenFor(unlockMode);

mUnlockScreenMode=unlockMode;

maybeEnableFallback(context);

addView(mUnlockScreen);

updateScreen(mMode);

由注释可知:其实就是创建lock和unlock界面,这样切换时就可以直接显示而不必先创建在切换,造成时间的缓冲。那么究竟显示lock还是unlock界面就是最后那个调用。具体函数:

privatevoidupdateScreen(finalModemode){

if(DEBUG_CONFIGURATION)Log.v(TAG,"****UPDATESCREEN:mode="+mode

+"lastmode="+mMode,newRuntimeException());

mMode=mode;

//Re-createtheunlockscreenifnecessary.Thisisprimarilyrequiredtoproperlyhandle

//SIMstatechanges.Thistypicallyhappenswhenthismethodiscalledbyreset()

if((mode==Mode.UnlockScreen&&mCurrentUnlockMode!=getUnlockMode())||

(getUnlockMode()==UnlockMode.SimPin)){

recreateUnlockScreen();

}

finalViewgoneScreen=(mode==Mode.LockScreen)?mUnlockScreen:mLockScreen;

finalViewvisibleScreen=(mode==Mode.LockScreen)?mLockScreen:mUnlockScreen;

//dothisbeforechangingvisibilitysofocusisn'trequestedbeforetheinput

//flagisset

mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());

if(DEBUG_CONFIGURATION){

Log.v(TAG,"Gone="+goneScreen);

Log.v(TAG,"Visible="+visibleScreen);

}

if(mScreenOn){

if(goneScreen.getVisibility()==View.VISIBLE){

((KeyguardScreen)goneScreen).onPause();

}

if(visibleScreen.getVisibility()!=View.VISIBLE){

((KeyguardScreen)visibleScreen).onResume();

}

}

goneScreen.setVisibility(View.GONE);

visibleScreen.setVisibility(View.VISIBLE);

requestLayout();

if(!visibleScreen.requestFocus()){

thrownewIllegalStateException("keyguardscreenmustbeabletotake"

+"focuswhenshown"+visibleScreen.getClass().getCanonicalName());

}

}

这里mMode=mode;之后

finalViewgoneScreen=(mode==Mode.LockScreen)?mUnlockScreen:mLockScreen;

finalViewvisibleScreen=(mode==Mode.LockScreen)?mLockScreen:mUnlockScreen;

很显然,这是根据mode决定显示lock还是unlock的。

关于在Unlock界面输入错误密码的提示流程:

当用户输入密码时,若不正确,此时就会报告错误:

在PasswordUnlockScreen.java中有一个函数verifyPasswordAndUnlock,如下:

privatevoidverifyPasswordAndUnlock(){

Stringentry=mPasswordEntry.getText().toString();

if(mLockPatternUtils.checkPassword(entry)){

mCallback.keyguardDone(true);

mCallback.reportSuccessfulUnlockAttempt();

}elseif(entry.length()>MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT){

mCallback.reportFailedUnlockAttempt();

//在这里,也就是输入次数是5的整数倍时,弹出报错对话框:

if(0==(mUpdateMonitor.getFailedAttempts()

%LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)){

longdeadline=mLockPatternUtils.setLockoutAttemptDeadline();

handleAttemptLockout(deadline);

}

}

mPasswordEntry.setText("");

}

那么这个错误如何显示的?

上面代码有一处:mCallback.reportFailedUnlockAttempt()

reportFailedUnlockAttempt()函数是在LockPatternKeyguardView.java中,

publicvoidreportFailedUnlockAttempt(){

mUpdateMonitor.reportFailedAttempt();

finalintfailedAttempts=mUpdateMonitor.getFailedAttempts();

finalbooleanusingLockPattern=mLockPatternUtils.getKeyguardStoredPasswordQuality()

==DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;

if(usingLockPattern&&mEnableFallback&&failedAttempts==

(LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET

-LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)){

showAlmostAtAccountLoginDialog();

}elseif(usingLockPattern&&mEnableFallback

&&failedAttempts>=LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET){

mLockPatternUtils.setPermanentlyLocked(true);

updateScreen(mMode);

}elseif((failedAttempts%LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)

==0){

showTimeoutDialog();

}

mLockPatternUtils.reportFailedPasswordAttempt();

}

showAlmostAtAccountLoginDialog和showTimeoutDialog()决定显示什么样的Message:

privatevoidshowTimeoutDialog(){

//Gettimetolockscreen

inttimeoutInSeconds=(int)LockPatternUtils.FAILED_ATTEMPT_TIMEOUT_MS/1000;

//Announceamessage

Stringmessage="";

//Getunlockmode

UnlockModeunlockMode=getUnlockMode();

if(unlockMode==UnlockMode.password){

message=mContext.getString(

R.string.lockscreen_too_many_failed_attempts_dialog_message,

mUpdateMonitor.getFailedAttempts(),

timeoutInSeconds);

}

else{

message=mContext.getString(

R.string.lockscreen_too_many_failed_attempts_dialog_message,

mUpdateMonitor.getFailedAttempts(),

timeoutInSeconds);

}

finalAlertDialogdialog=newAlertDialog.Builder(mContext)

.setTitle(null)

.setMessage(message)

.setNeutralButton(R.string.ok,null)

.create();

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);

if(!mContext.getResources().getBoolean(

com.android.internal.R.bool.config_sf_slowBlur)){

dialog.getWindow().setFlags(

WindowManager.LayoutParams.FLAG_BLUR_BEHIND,

WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

}

dialog.show();

}

更多相关文章

  1. Android第三方登录-----微信登录接入方法
  2. Android SDK Manager 更新方法
  3. android 实现时钟的简单方法
  4. Android Studio SVN 使用方法
  5. Android Virtual Device Manager 创建虚拟机出现SDK Manager NUL
  6. Android 登录界面调用输入法时让界面自动上移,使输入法不会遮挡到

随机推荐

  1. Android的Gradle插件
  2. 《Android深入透析》之Android事件分发机
  3. 如何在Android和iOS设备上录制游戏?
  4. 【转】有关Android线程的学习
  5. 如何在Android中使用OpenCV
  6. Android初学者入门 从入门到精通
  7. Android进程与线程基本知识
  8. Android安全机制(2) Android(安卓)Permissi
  9. Android(安卓)读取硬件信息技巧
  10. Android的专用驱动