Android6.0 keyguard锁屏加载流程分析
android6.0 keyguard锁屏加载流程分析,锁屏界面的加载通常在android中有两种方式触发:android开机和screenoff(灭屏)后,再screenon;
先来看
android系统开机时候的锁屏加载流程:
首先在系统启动过程中,会进入到systemserver.java的startotherservices()方法:
初始化windowmanagerservice;
[java]view plaincopy
wm=windowmanagerservice.main(context,inputmanager,
mfactorytestmode!=factorytest.factory_test_low_level,
!mfirstboot,monlycore); 调用systemready()方法,表示系统准备启动;
[java]view plaincopy
try{
wm.systemready();
}catch(throwablee){
reportwtf("makingwindowmanagerserviceready",e);
} 调用windowmanagerpolicy.java的systemready()方法
[java]view plaincopy
publicvoidsystemready(){
mpolicy.systemready();
} 而这个mpolicy 是由phonewindowmanager.java的构造方法构造出来的;
[java]view plaincopy
finalwindowmanagerpolicympolicy=newphonewindowmanager(); 也就是说最终会调用到phonewindowmanager.java的systemready()方法,在这个方法内初始化keyguardservicedelegate对象并调用systemready()方法;
[java]view plaincopy
mkeyguarddelegate=newkeyguardservicedelegate(mcontext);
mkeyguarddelegate.onsystemready(); 在keyguardservicedelegate.java类内,继续调用keyguardservicewrapper.java的systemready()方法;
[java]view plaincopy
publicvoidonsystemready(){
if(mkeyguardservice!=null){
mkeyguardservice.onsystemready();
}else{
mkeyguardstate.systemisready=true;
}
} 在keyguardservicewrapper.java内使用aidl调用keyguardservice.java的onsystemready()方法;
[java]view plaincopy
@override//binderinterface
publicvoidonsystemready(){
try{
mservice.onsystemready();
}catch(remoteexceptione){
slog.w(tag,"remoteexception",e);
}
} 在keyguardservice.java内调用keyguardviewmediator.java的onsystemready()方法;
[java]view plaincopy
@override//binderinterface
publicvoidonsystemready(){
checkpermission();
mkeyguardviewmediator.onsystemready();
}
最终在keyguardviewmediator.java的onsystemready()方法内调用dokeyguardlocked()开始锁屏加载流程;
[java]view plaincopy
/**
*letusknowthatthesystemisreadyafterstartup.
*/
publicvoidonsystemready(){
msearchmanager=(searchmanager)mcontext.getsystemservice(context.search_service);
synchronized(this){
if(debug)log.d(tag,"onsystemready");
msystemready=true;
dokeyguardlocked(null);
mupdatemonitor.registercallback(mupdatecallback);
}
//mostservicesaren'tavailableuntilthesystemreachesthereadystate,sowe
//senditherewhenthedevicefirstboots.
maybesenduserpresentbroadcast();
} keyguardviewmediator.java的dokeyguardlocked()方法;
[java]view plaincopy
/**
*enablethekeyguardifthesettingsareappropriate.
*/
privatevoiddokeyguardlocked(bundleoptions){
//ifanotherappisdisablingus,don'tshow
if(!mexternallyenabled){
return;
}
//ifthekeyguardisalreadyshowing,don'tbother
if(mstatusbarkeyguardviewmanager.isshowing()){
resetstatelocked();
return;
}
//ifthesetupwizardhasn'trunyet,don'tshow
finalbooleanrequiresim=!systemproperties.getboolean("keyguard.no_require_sim",false);
finalbooleanabsent=subscriptionmanager.isvalidsubscriptionid(
mupdatemonitor.getnextsubidforstate(icccardconstants.state.absent));
finalbooleandisabled=subscriptionmanager.isvalidsubscriptionid(
mupdatemonitor.getnextsubidforstate(icccardconstants.state.perm_disabled));
finalbooleanlockedormissing=mupdatemonitor.issimpinsecure()
||((absent||disabled)&&requiresim);
if(!lockedormissing&&shouldwaitforprovisioning()){
return;
}
if(mlockpatternutils.islockscreendisabled(keyguardupdatemonitor.getcurrentuser())
&&!lockedormissing){
return;
}
if(mlockpatternutils.checkvoldpassword(keyguardupdatemonitor.getcurrentuser())){
//withoutthis,settingsisnotenableduntilthelockscreenfirstappears
setshowinglocked(false);
hidelocked();
mupdatemonitor.reportsuccessfulstrongauthunlockattempt();
return;
}
showlocked(options);
} 1、mexternallyenabled;默认为true,如果其它应用设置keyguard不显示,则直接return不显示;
2、如果keyguard当前正在显示,则不用管它,重置;
3、如果安装向导未执行完毕,即设备未完成初始化绑定等操作,也不去显示keyguard;
4、如果当前屏幕为灭屏状态,也不去显示keyguard;
5、without this, settings is not enabled until the lock screen first appears(我这边没有比较好的说法);
6、如果上述条件都不满足则使用showlocked()方法开始显示keyguard。
发送msg为show的消息,开始显示keyguard;
[java]view plaincopy
/**
*sendmessagetokeyguardtellingittoshowitself
*@see#handleshow
*/
privatevoidshowlocked(bundleoptions){
if(debug)log.d(tag,"showlocked");
//ensurewestayawakeuntilwearefinisheddisplayingthekeyguard
mshowkeyguardwakelock.acquire();
messagemsg=mhandler.obtainmessage(show,options);
mhandler.sendmessage(msg);
} 调用handleshow()方法;
[java]view plaincopy
caseshow:
handleshow((bundle)msg.obj);
break; 在handleshow()方法中调用statusbarkeyguardviewmanager.java的show()方法;
[java]view plaincopy
/**
*handlemessagesentby{@link#showlocked}.
*@see#show
*/
privatevoidhandleshow(bundleoptions){
synchronized(keyguardviewmediator.this){
if(!msystemready){
if(debug)log.d(tag,"ignoringhandleshowbecausesystemisnotready.");
return;
}else{
if(debug)log.d(tag,"handleshow");
}
setshowinglocked(true);
mstatusbarkeyguardviewmanager.show(options);
mhiding=false;
mwakeandunlocking=false;
resetkeyguarddonependinglocked();
mhideanimationrun=false;
updateactivitylockscreenstate();
adjuststatusbarlocked();
useractivity();
mshowkeyguardwakelock.release();
}
mkeyguarddisplaymanager.show();
} 调入到statusbarkeyguardviewmanager.java的show()方法
[java]view plaincopy
publicvoidshow(bundleoptions){
mshowing=true;
mstatusbarwindowmanager.setkeyguardshowing(true);
mscrimcontroller.abortkeyguardfadingout();
reset();
} statusbarkeyguardviewmanager.java负责keyguard在status bar中创建、显示、隐藏、重置
statusbarwindowmanager.java负责所有的status bar窗口状态的逻辑管理
1、statusbarkeyguardviewmanager.java的setkeyguardshowing()方法去使用apply()方法刷新mstatusbarview的flag参数;
[java]view plaincopy
publicvoidsetkeyguardshowing(booleanshowing){
mcurrentstate.keyguardshowing=showing;
apply(mcurrentstate);
} 2、调用reset()方法去重置mstatusbarview的state,先来看reset()方法;
[java]view plaincopy
/**
*resetthestateoftheview.
*/
publicvoidreset(){
if(mshowing){
if(moccluded){
mphonestatusbar.hidekeyguard();
mphonestatusbar.stopwaitingforkeyguardexit();
mbouncer.hide(false/*destroyview*/);
}else{
showbouncerorkeyguard();
}
keyguardupdatemonitor.getinstance(mcontext).sendkeyguardreset();
updatestates();
}
} 在reset()方法中会去判断keyguard是否被其它的窗口中断moccluded,是则不显示keyguard;否则的就执行showbouncerorkeyguard()方法;
showbouncerorkeyguard()方法使用keyguardbouncer.java的needsfullscreenbouncer()方法判断显示常规锁屏还是bouncer安全锁屏(比如图案锁屏、密码锁屏、pin码锁屏等);
[java]view plaincopy
/**
*showsthenotificationkeyguardorthebouncerdependingon
*{@linkkeyguardbouncer#needsfullscreenbouncer()}.
*/
privatevoidshowbouncerorkeyguard(){
if(mbouncer.needsfullscreenbouncer()){
//thekeyguardmightbeshowing(already).soweneedtohideit.
mphonestatusbar.hidekeyguard();
mbouncer.show(true/*resetsecurityselection*/);
}else{
mphonestatusbar.showkeyguard();
mbouncer.hide(false/*destroyview*/);
mbouncer.prepare();
}
} 1、常规锁屏即为滑动锁屏界面,一般滑动即可解锁,称之为notification keyguard;这个类型的keyguard已经和statusbar融为一体了,可以通过phonestatusbar.java的对象直接进行控制;
2、bouncer安全锁屏;比如密码、图案、pim码、puk码等锁屏方式的锁屏界面,通过keyguardbouncer.java来开始控制show()和hide();
[java]view plaincopy
keyguardbouncer.java的show()方法:
publicvoidshow(booleanresetsecurityselection){
ensureview();
if(resetsecurityselection){
//showprimarysecurityscreen()updatesthecurrentsecuritymethod.thisisneededin
//casewearealreadyshowingandthecurrentsecuritymethodchanged.
mkeyguardview.showprimarysecurityscreen();
}
if(mroot.getvisibility()==view.visible||mshowingsoon){
return;
}
//trytodismissthekeyguard.ifnosecuritypatternisset,thiswilldismissthewhole
//keyguard.ifweneedtoauthenticate,showthebouncer.
if(!mkeyguardview.dismiss()){
mshowingsoon=true;
//splituptheworkovermultipleframes.
dejankutils.postaftertraversal(mshowrunnable);
}
} 1、首先调用ensureview()方法去加载keyguard_bouncer view
[java]view plaincopy
privatevoidensureview(){
if(mroot==null){
inflateview();
}
}
privatevoidinflateview(){
removeview();
mroot=(viewgroup)layoutinflater.from(mcontext).inflate(r.layout.keyguard_bouncer,null);
mkeyguardview=(keyguardhostview)mroot.findviewbyid(r.id.keyguard_host_view);
mkeyguardview.setlockpatternutils(mlockpatternutils);
mkeyguardview.setviewmediatorcallback(mcallback);
mcontainer.addview(mroot,mcontainer.getchildcount());
mroot.setvisibility(view.invisible);
mroot.setsystemuivisibility(view.status_bar_disable_home);
} 2、调用keyguardhostview.java的showprimarysecurityscreen()方法;
[java]view plaincopy
/**
*calledwhentheviewneedstobeshown.
*/
publicvoidshowprimarysecurityscreen(){
if(debug)log.d(tag,"show()");
msecuritycontainer.showprimarysecurityscreen(false);
} 继续调用keyguardsecuritycontainer.java的showprimarysecurityscreen()方法,先去获取锁屏方式;
[java]view plaincopy
/**
*showstheprimarysecurityscreenfortheuser.thiswillbeeitherthemulti-selector
*ortheuser'ssecuritymethod.
*@paramturningofftrueifthedeviceisbeingturnedoff
*/
voidshowprimarysecurityscreen(booleanturningoff){
securitymodesecuritymode=msecuritymodel.getsecuritymode();
if(debug)log.v(tag,"showprimarysecurityscreen(turningoff="+turningoff+")");
showsecurityscreen(securitymode);
} 继续往下将获取到的锁屏方式securitymode作为参数调用showsecurityscreen()方法;这个方法主要是用来根据securitymode显示锁屏view的。
[java]view plaincopy
/**
*switchestothegivensecurityviewunlessit'salreadybeingshown,inwhichcase
*thisisano-op.
*
*@paramsecuritymode
*/
privatevoidshowsecurityscreen(securitymodesecuritymode){
if(debug)log.d(tag,"showsecurityscreen("+securitymode+")");
if(securitymode==mcurrentsecurityselection)return;
keyguardsecurityviewoldview=getsecurityview(mcurrentsecurityselection);
keyguardsecurityviewnewview=getsecurityview(securitymode);
//emulateactivitylifecycle
if(oldview!=null){
oldview.onpause();
oldview.setkeyguardcallback(mnullcallback);//ignorerequestsfromoldview
}
if(securitymode!=securitymode.none){
newview.onresume(keyguardsecurityview.view_revealed);
newview.setkeyguardcallback(mcallback);
}
//findandshowthischild.
finalintchildcount=msecurityviewflipper.getchildcount();
finalintsecurityviewidformode=getsecurityviewidformode(securitymode);
for(inti=0;i if(msecurityviewflipper.getchildat(i).getid()==securityviewidformode){
msecurityviewflipper.setdisplayedchild(i);
break;
}
}
mcurrentsecurityselection=securitymode;
msecuritycallback.onsecuritymodechanged(securitymode,
securitymode!=securitymode.none&&newview.needsinput());
} 1、首先判断传入进来的securitymode是否已经被显示;
2、调用getsecurityview()方法获取给定的锁屏view;
3、调用keyguardsecurityview.java的onpause()方法暂停显示旧锁屏view,onresume()方法开始显示新的锁屏view;keyguardsecurityview.java是一个接口类,其内部方法都是抽象的只有声明没有实现,其方法实现都是在继承于这个接口的类中。
而在keyguard中主要是keyguardabskeyinputview.java、keyguardpasswordview.java、keyguardpatternview.java等等这些类继承于此接口实现其内部方法,这些类就是具体的锁屏界面view显示;
开机显示keyguard的总结:
1、在keyguardviewmediator.java的onsystemready()方法内调用dokeyguardlocked()开始锁屏加载流程;
2、setkeyguardenabled();其他应用程序或者服务可以调用setkeyguardenabled()方法请求禁止锁屏;
3、keyguardviewmediator.java在keyguard中起着主要调度的作用,主要负责
1)查询锁屏状态,当前是锁屏还是解锁状态;在锁屏状态下,会限制输入事件。
2)phonewindowmanager.java通过mkeyguarddelegate对象(keyguardservicedelegate.java)来使能keyguardviewmediator.java,调用其中的方法;
3)响应sim卡状态变化并对锁屏界面做相应的调整onsimstatechanged();
4、判断keyguard是否被禁止、keyguard当前是否正在显示等等即当前是否可以显示keguard,可以显示的话继续调用showlocked()方法;
5、调用handleshow()方法,调用statusbarkeyguardviewmanager.java的show()开始显示keyguard锁屏界面;
6、调用reset()方法,调用showbouncerorkeyguard()方法判断是显示正常锁屏界面还是安全锁屏界面;显示正常锁屏的话直接调用phonestatusbar.java的showkeyguard()或者hidekeyguard()方法;如果显示安全锁屏界面的话则调入keyguardbouncer.java类内;
7、调用keyguardbouncer.java的show()方法;使用ensureview()方法去加载实例化布局;调用keyguardhostview.java的showprimarysecurityscreen()方法去显示安全锁屏界面;
8、keyguardhostview.java的showprimarysecurityscreen()方法会调入到keyguardsecuritycontainer.java的showprimarysecurityscreen()方法中来;
9、调用showsecurityscreen()方法,根据锁屏方式来加载不同的锁屏view;
10、keyguardsecurityview.java是一个接口类,其内部方法都是抽象的只有声明没有实现,其方法实现都是在继承于这个接口的类中。
而在keyguard中主要是keyguardabskeyinputview.java、keyguardpasswordview.java、keyguardpatternview.java等等keyguard*view.java这些类继承于此接口实现其内部方法,这些类就是具体的锁屏界面view显示;
系统灭屏screen off之后的keguard加载流程:
android系统中的自动灭屏跟power按键之后灭屏流程可能有点区别,但是由于主要是分析灭屏之后keyguard加载,所以只需要关心keguard在系统灭屏之后的加载流程。
这里以按power键灭屏为例,分析其流程:
当亮屏状态下power键按下之后,经过一系列的判断之后会调用mpowermanager.gotosleep()方法,即通过aidl调用到powermanagerservice.java的gotosleep()方法:
[java]view plaincopy
@override//bindercall
publicvoidgotosleep(longeventtime,intreason,intflags){
if(eventtime>systemclock.uptimemillis()){
thrownewillegalargumentexception("eventtimemustnotbeinthefuture");
}
mcontext.enforcecallingorselfpermission(
android.manifest.permission.device_power,null);
finalintuid=binder.getcallinguid();
finallongident=binder.clearcallingidentity();
try{
gotosleepinternal(eventtime,reason,flags,uid);
}finally{
binder.restorecallingidentity(ident);
}
} 继续调用gotosleepinternal()方法:
[java]view plaincopy
privatevoidgotosleepinternal(longeventtime,intreason,intflags,intuid){
synchronized(mlock){
if(gotosleepnoupdatelocked(eventtime,reason,flags,uid)){
updatepowerstatelocked();
}
}
} 调用updatepowerstatelocked()方法,在这个方法内又去调用finishwakefulnesschangeifneededlocked()方法
[java]view plaincopy
privatevoidfinishwakefulnesschangeifneededlocked(){
if(mwakefulnesschanging&&mdisplayready){
if(mwakefulness==wakefulness_dozing
&&(mwakelocksummary&wake_lock_doze)==0){
return;//waituntildreamhasenableddozing
}
mwakefulnesschanging=false;
mnotifier.onwakefulnesschangefinished();
}
} 此时调用notifier.java的onwakefulnesschangefinished()方法:
[java]view plaincopy
/**
*notifiesthatthedevicehasfinishedchangingwakefulness.
*/
publicvoidonwakefulnesschangefinished(){
if(debug){
slog.d(tag,"onwakefulnesschangefinished");
}
if(minteractivechanging){
minteractivechanging=false;
handlelateinteractivechange();
}
} 调用handlelateinteractivechange()方法;
[java]view plaincopy
/**
*handlelateinteractivestatechangesoncetheyarefinishedsothatthesystemcan
*finishpendingtransitions(suchasturningthescreenoff)beforecausing
*applicationstochangestatevisibly.
*/
privatevoidhandlelateinteractivechange(){
synchronized(mlock){
if(minteractive){
//finishedwakingup...
mhandler.post(newrunnable(){
@override
publicvoidrun(){
mpolicy.finishedwakingup();
}
});
}else{
//finishedgoingtosleep...
//thisisagoodtimetomaketransitionsthatwedon'twanttheusertosee,
//suchasbringingthekeyguardtofocus.there'snoguaranteeforthis
//howeverbecausetheusercouldturnthedeviceonagainatanytime.
//somethingsmayneedtobeprotectedbyothermechanismsthatdeferscreenon.
//cancelpendinguseractivity.
if(museractivitypending){
museractivitypending=false;
mhandler.removemessages(msg_user_activity);
}
//tellthepolicywefinishedgoingtosleep.
finalintwhy=translateoffreason(minteractivechangereason);
mhandler.post(newrunnable(){
@override
publicvoidrun(){
eventlog.writeevent(eventlogtags.power_screen_state,0,why,0,0);
mpolicy.finishedgoingtosleep(why);
}
});
//sendnon-interactivebroadcast.
mpendinginteractivestate=interactive_state_asleep;
mpendinggotosleepbroadcast=true;
updatependingbroadcastlocked();
}
}
} 这个方法里面需要关注的有两句话:mpolicy.finishedwakingup()和mpolicy.finishedgoingtosleep();看其中的注释发现一个是唤醒另外一个是睡眠操作,由于当前是power灭屏,所以需要看得是mpolicy.finishedgoingtosleep()方法。而mpolicy是windowmanagerpolicy.java的对象,这个类又是一个接口类,接口实现是在phonewindowmanager.java类中,故此时调入到phonewindowmanager.java的finishedgoingtosleep()方法;
[java]view plaincopy
//calledonthepowermanager'snotifierthread.
@override
publicvoidfinishedgoingtosleep(intwhy){
eventlog.writeevent(70000,0);
if(debug_wakeup)slog.i(tag,"finishedgoingtosleep...(why="+why+")");
metricslogger.histogram(mcontext,"screen_timeout",mlockscreentimeout/1000);
//wemustgetthisworkdoneherebecausethepowermanagerwilldrop
//thewakelockandletthesystemsuspendoncethisfunctionreturns.
synchronized(mlock){
mawake=false;
updatewakegesturelistenerlp();
updateorientationlistenerlp();
updatelockscreentimeout();
}
if(mkeyguarddelegate!=null){
mkeyguarddelegate.onfinishedgoingtosleep(why);
}
} 分析这个方法看到这么一句话:
[java]view plaincopy
mkeyguarddelegate.onfinishedgoingtosleep(why); 也就是说会调用keyguardservicedelegate.java的onfinishedgoingtosleep()方法;而在上面的分析过程中知道,phonewindowmanager.java通过mkeyguarddelegate对象(keyguardservicedelegate.java)来使能keyguardviewmediator.java,调用其中的方法;也就是说通过这句话此时逻辑已经调入到了keyguardviewmediator.java类的onfinishedgoingtosleep()方法。
[java]view plaincopy
publicvoidonfinishedgoingtosleep(intwhy){
if(debug)log.d(tag,"onfinishedgoingtosleep("+why+")");
synchronized(this){
mdeviceinteractive=false;
mgoingtosleep=false;
resetkeyguarddonependinglocked();
mhideanimationrun=false;
notifyfinishedgoingtosleep();
if(mpendingreset){
resetstatelocked();
mpendingreset=false;
}
if(mpendinglock){
dokeyguardlocked(null);
mpendinglock=false;
}
}
keyguardupdatemonitor.getinstance(mcontext).dispatchfinishedgoingtosleep(why);
}
在这个方法中调用notifyfinishedgoingtosleep()方法,向mhandler中发送一个msg为notify_finished_going_to_sleep的消息;
[java]view plaincopy
privatevoidnotifyfinishedgoingtosleep(){
if(debug)log.d(tag,"notifyfinishedgoingtosleep");
mhandler.sendemptymessage(notify_finished_going_to_sleep);
} mhandler收到这个消息后,去调用handlenotifyfinishedgoingtosleep()方法;
[java]view plaincopy
casenotify_finished_going_to_sleep:
handlenotifyfinishedgoingtosleep();
break; 在这个方法中去调用statusbarkeyguardviewmanager.java的onfinishedgoingtosleep()方法;
[java]view plaincopy
privatevoidhandlenotifyfinishedgoingtosleep(){
synchronized(keyguardviewmediator.this){
if(debug)log.d(tag,"handlenotifyfinishedgoingtosleep");
mstatusbarkeyguardviewmanager.onfinishedgoingtosleep();
}
} 再来看statusbarkeyguardviewmanager.java的onfinishedgoingtosleep()方法:
[java]view plaincopy
publicvoidonfinishedgoingtosleep(){
mdeviceinteractive=false;
mphonestatusbar.onfinishedgoingtosleep();
mbouncer.onscreenturnedoff();
} 1、调用phonestatusbar.java的onfinishedgoingtosleep(),去通知phonestatusbar更新当前的状态;
2、进入keyguardbouncer.java的onscreenturnedoff()方法真正开始keyguard的加载;
接下来来看keyguardbouncer.java的onscreenturnedoff()方法:
[java]view plaincopy
publicvoidonscreenturnedoff(){
if(mkeyguardview!=null&&mroot!=null&&mroot.getvisibility()==view.visible){
mkeyguardview.onpause();
}
} 调用keyguardhostview.java的onpause()方法:
[java]view plaincopy
/**
*calledwhenthekeyguardisnotactivelyshownanymoreonthescreen.
*/
publicvoidonpause(){
if(debug)log.d(tag,string.format("screenoff,instance%sat%s",
integer.tohexstring(hashcode()),systemclock.uptimemillis()));
msecuritycontainer.showprimarysecurityscreen(true);
msecuritycontainer.onpause();
clearfocus();
} 继续调用keyguardsecuritycontainer.java的showprimarysecurityscreen()方法,根据上面的分析知道,此处先会去获取当前锁屏方式,然后根据得到的锁屏方式去加载锁屏界面;
至此完成keyguard在screen off状态下的加载流程分析;
正常灭屏显示keyguard流程总结:
1、不管是按power键还是自动灭屏,都会执行到powermanagerservice.java的gotosleep()方法;
2、在这个方法内通过一系列的调用,调入到phonewindowmanager.java的finishedgoingtosleep()方法;
3、在phonewindowmanager.java类中通过keyguardservicedelegate.java类的对象mkeyguarddelegate来使能keyguardviewmediator.java;
4、而keyguardviewmediator.java作为keyguard的调度者,从这里开始keyguard的加载;
5、最终在keyguardsecuritycontainer.java的showprimarysecurityscreen()方法内去实现根据锁屏方式加载锁屏界面;
上一篇: 大学时参加辩论比赛