Android4.4 Keyguard锁屏机制分析

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);

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值