Android9.0 SystemUI代码走读__锁屏模块_01

这篇文章会采用代码走读的方式,结合简单的流程图,和大家一起看下Android9.0 上的锁屏模块相关代码,其它android版本应该也差不多,不过这篇文件的讲解是基于android9.0上的代码。

在了解某个模块的之前,我们经常是有疑问才去了解,在这之前,我也是有下面几个疑问:

         1)锁屏界面代码是包含在哪个模块的;

         2)亮屏、灭屏操作,锁屏界面显示流程是怎样的;

         3)锁屏界面上滑,显示登陆密码界面流程是怎样的;

         4)按power键开机的时候,为啥没有显示锁屏界面;

         5)我想修改锁屏界面内容,应该关注哪些类和布局可以快速修改;

         6)  遇到的一些问题以及分析解决;

    有疑问总是好事,这篇文章会针对上面的疑问来一步步展开讲解;

写在前面

在Android系统上,短按电源power键,会进入灭屏和亮屏。如果我们在设置中设置了屏幕锁定方式有密码的话,亮屏的时候,我们会看到如下图所示的锁屏界面,然后锁屏界面上滑,就是密码验证界面,输入正确密码后,才能进入系统界面。

image

一、锁屏界面代码是包含在哪个模块的

答:是在SystemUI模块。

二、锁屏界面显示流程是怎样的

锁屏界面的处理是在SystemUI中进行处理。下图是系统开机后,涉及到锁屏相关逻辑的简单流程图,我们先来有个大概的了解,起码知道涉及到哪些重要的类。

KeyguardViewMediator.java

StatusBarKeyguardViewManager.java

StatusBarWindowManager.java

StatusBar.java

KeyguardBouncer.java

KeyguardHostView.java

KeyguardSecurityContainer.java

流程图-01

面我们已经看到有一个很重要的类KeyguardViewMediator.java ,是的,我们首先就看下这个类的代码。

看代码之前,我们先看下这个类的最前面的注释吧,我们翻译下重要的来看下,方便整体的理解(本人英语水平有限,大伙可以直接看英文理解理解)。

/**
 * Mediates requests related to the keyguard.  This includes queries about the
 * state of the keyguard, power management events that effect whether the keyguard
 * should be shown or reset, callbacks to the phone window manager to notify
 * it of when the keyguard is showing, and events from the keyguard view itself
 * stating that the keyguard was succesfully unlocked.
 *  
 *    //Mediates(调解) 主要处理和锁屏相关的请求。这些内容包括查询锁屏的状态、根据Power 管理事 
 *    件决定锁屏是否显示或者重置、采用回调将当前是否是锁屏状态回调给phone window manager,以及 
 *    锁屏是否成功解锁这种来自锁屏自身的view的事件。
 *     
 *
 * Note that the keyguard view is shown when the screen is off (as appropriate)
 * so that once the screen comes on, it will be ready immediately.
 *   
 *   //注意了:锁屏界面是在灭屏的时候就显示处理了(视情况而定),这样方便屏幕一亮的时候,锁屏界面
 *     能快速的显示出来。
 *
 * Example external events that translate to keyguard view changes:
 * - screen turned off -> reset the keyguard, and show it so it will be ready
 *   next time the screen turns on
 * - keyboard is slid open -> if the keyguard is not secure, hide it
 *  
 *  //外部事件引起锁屏界面变化的例子:
 *    灭屏->锁屏重置,然后显示,这样下次亮屏的时候,锁屏是准备好的。
 *
 * Events from the keyguard view:
 * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
 *   restrict input events.
 *   
 *   //锁屏试图的事件传递:
 *    用户成功解锁锁屏->隐藏锁屏视图,不再限制输入事件
 *
 * Note: in addition to normal power managment events that effect the state of
 * whether the keyguard should be showing, external apps and services may request
 * that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}.  When
 * false, this will override all other conditions for turning on the keyguard.
 *  
 *  //注意:外部apps或者服务可能会使用setKeyguardEnabled(boolean)接口来设置是否需要显示锁屏,
 *    为了使来自power management的关于锁屏是否应该显示的事件调用标准化,当setKeyguardEnabled设 
 *    的值为false的时候,这个会是推翻其它打开锁屏的条件
 /

我们根据上面注释的描述,来走读下按键灭屏、亮屏这个流程:
screen turned off -> reset the keyguard, and show it so it will be ready next time the screen turns on

KeyguardViewMediator.java
----------------------------

 /**
   * 亮屏
   **/
  public void onScreenTurnedOn() {
        Trace.beginSection("KeyguardViewMediator#onScreenTurnedOn");
        notifyScreenTurnedOn();
        mUpdateMonitor.dispatchScreenTurnedOn();
        Trace.endSection();
  }

  /**
   * 灭屏
   **/
  public void onScreenTurnedOff() {
        notifyScreenTurnedOff();
        mUpdateMonitor.dispatchScreenTurnedOff();
  }

  ...

  private void handleNotifyScreenTurnedOff() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
            mStatusBarKeyguardViewManager.onScreenTurnedOff();
            mDrawnCallback = null;
        }
  }

三、 长按power键开机后,为啥不会显示锁屏界面

没有显示,那就是Android本来就这样设计的呗,哈哈,做开发的,很喜欢的一句话应该是“设计就是这样的啊”,然后摊摊手,表示无能为力。是不是设计就是如此,我们来看代码确认下吧。

我们来看下 KeyguardViewMediator.java中的具体实现:

1)系统起来的时候,会走onSystemReady()方法,然后通话发送handler信息进行处理,真正的处理就是在handleSystemReady()里面;

2)handleSystemReady()里面,我们重点看下doKeyguardLocked()方法,doKeyguradLocked()里面会有一些条件判断,条件不符合,则直接return掉;条件符合,才会走showLocked(options)方法进行锁屏界面的显示;

    /**
     * 系统起来会调用该方法通知系统起来了
     * 通过handler发送SYSTEM_READY信息进行一些事情的处理
     */
    public void onSystemReady() {
        Log.v(TAG,"--- onSystemReady();");
        mHandler.obtainMessage(SYSTEM_READY).sendToTarget();
    }

     private Handler mHandler = new Handler(Looper.myLooper(), null, true) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                  ......
                case SYSTEM_READY:
                    handleSystemReady();
                    break;
                  ......
            }
        }
    };

    private void handleSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            doKeyguardLocked(null);
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }

3)doKeyguardLocked()里面有个mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) 的判断,我们把这个的值打印下,会发现开机的时候,打印的值是false,lockedOrMissing和forceShow值默认为false,所以会直接return回去,没有继续走下面的流程了。

  1. 那我们现在知道了,是判断到lockScreen锁屏还没准备好,所以没有走显示锁屏的流程了。(这里具体没准备好的原因和判断条件,我还没有继续跟踪,我试过这里强制显示也是没有问题的,本来就是有个强制显示的参数forceShow,那说明这时需要强制显示也是可以的)
    private void doKeyguardLocked(Bundle options) {
             ......

            //------ 分析1  
            if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing && !forceShow) {
                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
                return;
            }

            ......
        }

        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
        showLocked(options);
    }

五、我想修改锁屏界面内容,应该关注哪些类和布局可以快速修改

1)登陆密码验证界面

i、这里涉及到2个重要的类 KeyguardAbsKeyInputView.java和 KeyguardPasswordView.java ,密码的授权验证在KeyguardAbsKeyInputView.java类中处理,界面的显示是在KeyguardPasswordView.java 中进行处理。 我们看下下图贴的代码 KeyguardPasswordView.java 里面的onEditorAction()里面的处理,有个verifyPasswordAndUnlock()的方法,就是跳转到KeyguardAbsKeyInputView.java中进行密码的验证了。

如果我们希望修改密码验证的逻辑的话,就可以修改KeyguardAbsKeyInputView.java中的verifyPasswordAndUnlock()里面的内容。

ii、密码验证对应的布局文件keyguard_password_view.xml,如果我们希望在布局上添加内容,就可以在这个布局文件上添加了。

--------KeyguardPasswordView.java --------

    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Check if this was the result of hitting the enter key
        final boolean isSoftImeEvent = event == null
                && (actionId == EditorInfo.IME_NULL
                || actionId == EditorInfo.IME_ACTION_DONE
                || actionId == EditorInfo.IME_ACTION_NEXT);
        final boolean isKeyboardEnterKey = event != null
                && KeyEvent.isConfirmKey(event.getKeyCode())
                && event.getAction() == KeyEvent.ACTION_DOWN;
        if (isSoftImeEvent || isKeyboardEnterKey) {
            verifyPasswordAndUnlock();
            return true;
        }
        return false;
    }

六、遇到的问题以及分析解决

i、点击密码登录输入框,有时没有正常腾出输入法

这个问题发现和在KeyguardViewMediator.java 中调用mStatusBarKeyguardViewManager.setNeedsInput(needsInput); 有关系。需要正常腾出输入法,首先需要确保setNeedInput设置的值为true。我后面的修改是,在KeyguardViewMediator.java中,onSystemReady()方法中,根据自己需要,重新去设置了下setNeedInput的值。

还有个地方得修改下,KeyguardPasswordView.java中,resetState()里面,如下图所示,屏蔽掉了些代码。屏蔽掉的代码是自动调用输入法的,每次进入密码登录界面,会走resetState()的流程,不过很奇怪,主动去调用一次,反而是没有正常调用出来。

    @Override
    protected void resetState() {
        mSecurityMessageDisplay.setMessage("");
        final boolean wasDisabled = mUserNameEntry.isEnabled();
        setPasswordEntryEnabled(true);
        setPasswordEntryInputEnabled(true);

        setUserNameEntryEnabled(true);
        setUserNameEntryInputEnabled(true);

       //屏蔽掉的代码
//        if (wasDisabled) {
//            mImm.showSoftInput(mUserNameEntry, InputMethodManager.SHOW_IMPLICIT);
//        }
    }

*本人从事Android Camera相关开发已有5年,
*目前在深圳上班,
*小伙伴记得点我头像,看【个人介绍】进行关注哦,希望和更多的小伙伴一起交流 ~
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352