Android4.4 Keyguard锁屏机制分析
一.Keyguard启动流程:
1.当系统服务开启后,重要的一个服务是WindowManagerService来管理系统窗口,同时启动手机锁屏Keyguard.在初始化WindowManagerService时,会调用initPolicy(UiThread.getHandler())这个方法。(WindowManagerService.java)
//初始化值
private void intePolicy(UiThread.getHandler){
...
mPolicy.init(mContext,WindowManagerService.this,WindowManagerService.this);
...
}
...
//初始化相关值后开始执行
public void systemReady(){
mPolicy.SystemReady();
}
2.PhoneWindowManager是唯一实现WindowManagerPolicy的类,所以上面的调用,在这里真正执行。(PhoneWindowManager.java)
//先得到boolean值mHeadless
public void init(){
...
//手机上这个值一般是false
mHeadless = "1".equals(SystemProperties.get("ro.xxxx","0"));
...
}
//调用Keyguard的代理类中方法onSystemReady()
public void systemReady(){
if(!mHeadless){
mkeyguardDelegate = new KeyguardServiceDelegate(mContext,null);
mKeyguardDelegate.onSystemReady();
}
}
3.因为KeygaurdServiceDelegate类绑定了KeyguardService服务,而这得到的IBinder是KeyguardServiceWrapper,它是一个实现了IkeyguardSerivice接口的类。此类是锁屏从4.4之后分离成单独apk后出现的对Keyguard的一个代理类。(KeygaurdServiceDelegate.java)
//KeyguardServiceDelegate初始化时绑定服务
public KeyguardServiceDelegate(Context context,LockPatternUtils lockPatternUtils){
...
Intent intent = new Intent();
intent.setClass("com.android.keyguard","com.android.keyguard.KeyguardService");
//开始绑定服务
if(content.binderServiceAsUser(intent,mKeyguardConn,Context.BIND_AUTO_CREATE,UserHanlder.OWNER)){
}
...
}
//绑定后得到的IBinder对象
mKeyguardService = new KeyguardServiceWrapper(IKeyguardService.Stub.adInterface(service))
//接着调用KeyguardServiceWrapper中的方法
public void onSystemReady(){
...
mKeyguardService.onSystemReady();
...
}
4.顾名思义,KeyguardServiceWrapper类是对KeyguardService的一个包装类。看里面的代码确是这样。(KeyguardServiceWrapper.java)
//mService是上面第三步中绑定后得到的IBinder对象中传入方法的参数IKeyguardService.Stub.adInterface
public void onSystemReady(){
...
mService.onSystemReady();
...
}
5.真正实现IKeyguardService接口中的方法是在KeyguardService类中,上面二步都是通过层层代理包装最后调用到里面的方法,在它的onCreate()方法中会初始化KeyguardViewMediator(KeyguardService.java)
//初始化KeyguardViewMediator
public void onCreate(){
if(mkeyguardViewMediator == null){
mKeyguardViewMediator = new KeyguardViewMediator(KeyguardService.this,new LockPatternUtils(KeyguardService.this));
}
}
//当别人绑定这个服务时返回的IBinder对象
public IBinder onBind(Intent intent){
return mBinde;
}
//这是正在实现IKeyguardService中的方法,它又是通过调用KeygaurdViewMediator来实现的
private final IKeyguardService.Stub mBinde = new IKeyguardService.Stub(){
public boolean isShowing(){
return mKeyguardViewMediator.isShowing();
}
...
//接着调用KeyguardViewMediator中的方法,这又回到了老版本中的锁屏流程
public void onSystemReady(){
checkPermission();
mKeyguardViewMeditor.onSystemReady();
}
...
public void onCompleted(){
checkPermission();
mKeyguardViewMediator();
}
}
6.从系统服务初始化到上一步都还没真正执行锁屏的功能,而KeyguardViewMediator类就开始锁屏的行为(KeyguardViewMediator.java)
//初始化KeyguardViewManager
public KeyguardViewMediator(Context context,LockPatternUtils lockPatternUtils){
//初始化需要的服务
...
//WindowManager接口继承ViewManager,传到下面用于添锁屏界面的根结点
WindowManager wm = (WindowManager)context.getSystemServie(Context.WINDOW_SERVICE);
mKeyguardViewManager = new KeyguardViewManager(context,wm,mViewMediatorCallback);
...
}
//开始执行锁屏功能
public void onSystemReady(){
...
Synchronized(this){
...
doKeyguardLocked(null);
...
}
...
}
private void doKeyguardLocked(Bunder options){
//如果别的应用隐藏了锁屏功能,则返回不显示系统锁屏
if(!ExternallyEnable){
return
}
//如果锁屏已经正在显示,也返回
if(mKeyguardViewManager.isShowing()){
return;
}
//如果是首次开机进入到设置界面也返回
...
showLocked(options);
}
//showLocked(options)方法是向Handler发送一个打开锁屏界面的消息
private void showLocked(Bundle options){
mShowKeyguardAwakeLock.acquire();
Message message = mHandler.obtainMessage(SHOW,options);
mHandler.sendMessage(message);
}
//看看mHandler中处理消息的方法
private Handler mHandler = new Handler(Looper.myLooper(),null,true){
@Override
public void handleMessage(Message message){
switch(message.what){
...
case SHOW:
handleShow((Bundle)message.obj);
break;
}
}
};
//private void handleShow(Bundle options){
Synchronized(KeyguardViewMediator.this){
//如果系统没准备好则返回
if(!mSystemReady){
}
//A.调用KeyguardViewManager类中的show()方法,这是锁屏启动的重要方法
mKeyguardViewManager.show(options);
}
}
7.下面咱们从第6步的handlerShow方法来接着往下分析.(KeyguardViewManager.java)
//初始化WindowManager
public KeyguardViewManager(Context context,ViewManager viewManager,KeyguardViewMediator.ViewMediatorCallback callback,LockPatternUtils lockPatternUtils){
...
mViewManager = viewManager;
...
}
//KeyguardView中的show方法
public void show(Bundle options){
...
//A-1,下面分析这个方法:
maybeCreateKeyguardLocked(enableScreenRotation,false,options);
}
private void maybeCreateKeyguardLocked(boolean enableScreenRotion,boolean foce,Bundle options){
if(mKeyguardHost != null){
mKeyguardHost.saveHierarchyState(mStatContainer);
}
//第一次开机时ViewManagerHost为null
if(mKeyguardHost == null){
//创建一个用于锁屏界面的根结点ViewManagerHost
mKeyguardHost = new ViewManagerHost(mContext);
...
//中间设置合适的WindowManager.LayoutParames值
...
WindowManager.LayoutParames lp = new WindowManager.LayoutParames(xxx);
//告诉wms通过surface给应用添加一个界面
mViewManager.add(mKeyguardHost,lp);
//通过KeyguardUpdateMonitor注册一个回调
KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
}
//mKeyguardView便是KeyguardHostView,因为是第一次开机,所以它为null
if(foce || mkeyguardView == null){
...
//A-1,下面分析这个方法:
inflateKeyguardView(options);
...
}
}
private void inflateKeyguardView(Bundle options){
View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
if(v != null){
mKeyguardHost.removeView(v);
}
final LayoutInflater inflater = LayoutInflater.from(mContext);
//A-1,下面分析KeyguardHostView中的onFinishInflate()方法.通过打气筒将KeyguardHostView这个布局填充到ViewManagerHost,这个方法执行完后会执行KeyguardHostView中的onFinishInflate()方法
inflater.inflat(R.layout.keyguard_host_view,mKeyguardHostView,true);
}
8.KeyguardHostView这个类是锁屏中非常重要的一个成员,用户设置的所有锁屏样式都是在由它直接控制的。(KeyguardHostView.java)
protected void onFinishInflate(){\
...
//找到KeyguardHostView中对应的布局,4.2之后加了添加widget的功能
...
//A-1,下面分析这个方法:
showPrimarySecurityScreen(false);
}
void showPrimarySecurityScreen(boolean turningOff){
//从数据库中得到用户之前的锁屏模式,一般有滑动,图案,PIN码
SecurityMode securityMode = mSecurityModel.getSecurityMode();
...
//A-1,下面分析这个方法:
showSecurityScreen(securityMode);
}
//这个就是最终呈现锁屏界面的方法
private void showSecurityScreen(SecurityMode securityMode){
//如果现在的锁屏模式和上次是一样的话那么返回,不在加载一样的布局
if(securityMode == mCurrentSecuritySelection) return
//第一次调用时mCurrentSecuritySelection为invalide
View oldView = getSecurityView(mCurrentSecuritySelection);
//锁屏中的界面都是通过下面这个方法加载的
View newView = getSecurityView(sercurityMode);
...
}
private KeyguardSecurityView getSecurityView(SecurityMode securityMode){
//通过锁屏模式的不同得到对应的view的id值
final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
KeyguardSecurityView view = null
//咱们分析开机后第一次启动锁屏的流程
...
//通过锁屏模式的不同得到对应的布局id值
int layoutId = getLayoutIdFor(securityMode);
if(view == null && layoutId != 0){
final LayoutInflater infalter = LayoutInflater.from(mContext);
View v = inflater.inflate(layoutId,mSecurityContainer,false);
...
//这一步就成功添加锁屏界面啦!!!
mSecurityViewContanier.addView(v);
...
}
...
return view;
}
这里顺便说一下这个mSecurityContainer,它是ViewFlipper的一个子类:
KeyguardSecutiyViewFlipper mSecutiyContainer = (KeyguardSecurityViewFlipper)findViewById(R.id.view_flipper);