Android 锁屏界面启动流程

本文基于Android 7.1

在开机过程中,Systemserver 会启动 WindowManagerService,并调用其systemReady 方法。进而调用PhoneWindowManager的systemReady方法

java 复制代码
@Override
    public void systemReady() {
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                this::onKeyguardShowingStateChanged);
        mKeyguardDelegate.onSystemReady();

        boolean bindKeyguardNow;
        
        synchronized (mLock) {
            mSystemReady = true;

            bindKeyguardNow = mDeferBindKeyguard;
			Slog.d(TAG,"bindKeyguardNow:"+bindKeyguardNow);
        }

        if (bindKeyguardNow) {
            mKeyguardDelegate.bindService(mContext);
            mKeyguardDelegate.onBootCompleted();
        }

    }

首先初始化 KeyguardServiceDelegate 对象,并调用其 onSystemReady 方法。

java 复制代码
public void onSystemReady() {
		Slog.d(TAG,"mKeyguardService:"+mKeyguardService);
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
    }

值得注意的是:

  • PhoneWindowManager的 systemReady 方法中 ,bindKeyguardNow为false,所以并不会在这里 bindService
  • KeyguardServiceDelegate 的 onSystemReady 方法中,mKeyguardService还是为null ,所以在改方法中只是将 mKeyguardState.systemIsReady 变量置为true
java 复制代码
WindowManager: bindKeyguardNow:false
KeyguardServiceDelegate:mKeyguardService:null

真正bindService 的地方在 PhoneWindowManager 中的 systemBooted 方法。

java 复制代码
@Override
    public void systemBooted() {
		Log.d(TAG,"systemBooted:",new Exception());
        boolean bindKeyguardNow = false;
        synchronized (mLock) {
    
            if (mKeyguardDelegate != null) {
                bindKeyguardNow = true;
            } else {
                mDeferBindKeyguard = true;
            }
        }
        if (bindKeyguardNow) {//绑定服务
            mKeyguardDelegate.bindService(mContext);
            mKeyguardDelegate.onBootCompleted();
        }
        synchronized (mLock) {
            mSystemBooted = true;
        }
        ......
    }

在前面已经初始化了mKeyguardDelegate对象,所以这里不为null,bindKeyguardNow为true,调用 KeyguardServiceDelegate 的 bindService 方法去绑定服务

java 复制代码
public void bindService(Context context) {
        Intent intent = new Intent();
        final Resources resources = context.getApplicationContext().getResources();

        final ComponentName keyguardComponent = ComponentName.unflattenFromString(
                resources.getString(com.android.internal.R.string.config_keyguardComponent));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);

        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, mScrimHandler, UserHandle.SYSTEM)) {
            
           ......
        } 
    
    
    	......
    }

这里 keyguardComponent 为 com.android.systemui/com.android.systemui.keyguard.KeyguardService

xml 复制代码
<!-- Keyguard component -->
    <string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>

该服务在 SystemUI中

c 复制代码
<service
            android:name=".keyguard.KeyguardService"
            android:exported="true"
            android:enabled="@bool/config_enableKeyguardService" />

注意这里可以配置enable,不启动KeyguardService,即配置 config_enableKeyguardService 决定是否永远禁止锁屏界面.

绑定成功的话,会调用 mKeyguardConnection 的onServiceConnected 方法

java 复制代码
private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
            mKeyguardService = new KeyguardServiceWrapper(mContext,
                    IKeyguardService.Stub.asInterface(service), mShowingStateChangedCallback);
            if (mKeyguardState.systemIsReady) {
                // If the system is ready, it means keyguard crashed and restarted.
                mKeyguardService.onSystemReady();
                
                ......
        }
    };

前面已经将 mKeyguardState.systemIsReady 置为true 了,所以这里会调用 KeyguardServiceWrapper 的 onSystemReady方法, 最终 调用KeyguardViewMediator 的 onSystemReady 方法

java 复制代码
public void onSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            doKeyguardLocked(null);
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
    
      ......
    }

在 doKeyguardLocked 方法中,经过一系列的判断,决定是否需要显示锁屏界面,如果需要显示,则调用showLocked 方法去显示锁屏界面。值得注意的是,这里 读取了 数据库中 lockscreen.disabled 字符串的值,来决定是否显示锁屏界面。而该值可以通过 def_lockscreen_disabled 来配置。即可以通过 配置 def_lockscreen_disabled 的值,来决定是否出厂默认禁止锁屏界面(该方法是LockPatternUtils的 isLockScreenDisabled,感兴趣的话自行分析)。

java 复制代码
private void showLocked(Bundle options) {
        Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");
        if (DEBUG) Log.d(TAG, "showLocked");
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);
        Trace.endSection();
    }

private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW:
                    handleShow((Bundle) msg.obj);
                    break;
                    
                

在 handleShow 中 调用StatusBarKeyguardViewManager 的show 方法

java 复制代码
public void show(Bundle options) {
        mShowing = true;
        mStatusBarWindowManager.setKeyguardShowing(true);
        mScrimController.abortKeyguardFadingOut();
        reset();
    }


public void reset() {
        if (mShowing) {
            if (mOccluded) {
                ......
            } else {
                showBouncerOrKeyguard();
            }
            ......
        }
    }

protected void showBouncerOrKeyguard() {
        if (mBouncer.needsFullscreenBouncer()) {

           ......
        } else {
            ......
            mBouncer.prepare();
        }
    }

调用 KeyguardBouncer 的 prepare 方法

java 复制代码
public void prepare() {
        boolean wasInitialized = mRoot != null;
        ensureView();
        if (wasInitialized) {
            mKeyguardView.showPrimarySecurityScreen();
        }
        mBouncerPromptReason = mCallback.getBouncerPromptReason();
    }

最终调用打 KeyguardSecurityContainer 的 showPrimarySecurityScreen 方法 ,先得到 锁屏的模式,然后去显示锁屏界面

java 复制代码
void showPrimarySecurityScreen(boolean turningOff) {
        SecurityMode securityMode = mSecurityModel.getSecurityMode();
        if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
        showSecurityScreen(securityMode);//显示锁屏界面
    }
相关推荐
花生糖@1 小时前
Android XR 应用程序开发 | 从 Unity 6 开发准备到应用程序构建的步骤
android·unity·xr·android xr
是程序喵呀1 小时前
MySQL备份
android·mysql·adb
casual_clover1 小时前
Android 之 List 简述
android·list
锋风Fengfeng2 小时前
安卓15预置第三方apk时签名报错问题解决
android
User_undefined3 小时前
uniapp Native.js原生arr插件服务发送广播到uniapp页面中
android·javascript·uni-app
程序员厉飞雨4 小时前
Android R8 耗时优化
android·java·前端
丘狸尾5 小时前
[cisco 模拟器] ftp服务器配置
android·运维·服务器
van叶~7 小时前
探索未来编程:仓颉语言的优雅设计与无限可能
android·java·数据库·仓颉
Crossoads11 小时前
【汇编语言】端口 —— 「从端口到时间:一文了解CMOS RAM与汇编指令的交汇」
android·java·汇编·深度学习·网络协议·机器学习·汇编语言
li_liuliu12 小时前
Android4.4 在系统中添加自己的System Service
android