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);//显示锁屏界面
    }
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui