android 锁屏界面处理

锁屏相关的文件在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();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值