博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android8.1 SystemUI Keyguard之启动流程
阅读量:2071 次
发布时间:2019-04-29

本文共 11057 字,大约阅读时间需要 36 分钟。

今天开始梳理SystemUI Keyguard源码

话不多说首先从启动流程开始:

起点是在 SystemUI/src/com/android/systemui/SystemUIService.java

onCreate() -> ((SystemUIApplication) getApplication()).startServicesIfNeeded();

启动SystemUI各个模块

SystemUI/src/com/android/systemui/SystemUIApplication.java

public void startServicesIfNeeded() {        startServicesIfNeeded(SERVICES);    }    private void startServicesIfNeeded(Class
[] services) { .. startServicesIfNeeded()-> Object newService = SystemUIFactory.getInstance().createInstance(cl); .. mServices[i].start(); .. if (mBootCompleted) { mServices[i].onBootCompleted(); } }

我们这里主要关注KeyguardViewMediator:

SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

@Override    public void start() {        synchronized (this) {            setupLocked();        }        putComponent(KeyguardViewMediator.class, this);    }    private void setupLocked() {        // 获取PowerManager        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);        // 获取TrustManager        mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);        // 创建PARTIAL_WAKE_LOCK        mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");        // 设置WakeLock为不计数机制        mShowKeyguardWakeLock.setReferenceCounted(false);        // 注册广播监听        IntentFilter filter = new IntentFilter();        filter.addAction(DELAYED_KEYGUARD_ACTION);        filter.addAction(DELAYED_LOCK_PROFILE_ACTION);        filter.addAction(Intent.ACTION_SHUTDOWN);        mContext.registerReceiver(mBroadcastReceiver, filter);        mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, mViewMediatorCallback);        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);        // KeyguardUpdateMontitor注册一堆广播监听和Listener        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);        mLockPatternUtils = new LockPatternUtils(mContext);        KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());        // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard        // is disabled.        if (mContext.getResources().getBoolean(                com.android.keyguard.R.bool.config_enableKeyguardService)) {            setShowingLocked(!shouldWaitForProvisioning()                    && !mLockPatternUtils.isLockScreenDisabled(                            KeyguardUpdateMonitor.getCurrentUser()),                    mSecondaryDisplayShowing, true /* forceCallbacks */);        }        // 把statusbar和keyguard关联起来,将mViewMediatorCallback传给mStatusBarKeyguardViewManager        mStatusBarKeyguardViewManager =                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,                        mViewMediatorCallback, mLockPatternUtils);        final ContentResolver cr = mContext.getContentResolver();        /*  获取设备可交互状态            true : 包括dreaming            false: dozing或asleep          * The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on}         * or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast         * whenever the interactive state of the device changes.  For historical reasons,         * the names of these broadcasts refer to the power state of the screen         * but they are actually sent in response to changes in the overall interactive         * state of the device, as described by this method.*/        mDeviceInteractive = mPM.isInteractive();        // 加载锁屏解锁音频和音量        mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);        String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);        if (soundPath != null) {            mLockSoundId = mLockSounds.load(soundPath, 1);        }        ..        ..        int lockSoundDefaultAttenuation = mContext.getResources().getInteger(                com.android.internal.R.integer.config_lockSoundVolumeDb);        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);        // 加载动画 (仅用于获得动画时间偏移量)        mHideAnimation = AnimationUtils.loadAnimation(mContext,                com.android.internal.R.anim.lock_screen_behind_enter);        mWorkLockController = new WorkLockActivityController(mContext);    }

 

 

关于WakeLock:

android developer文档关于WakeLock的解释

 

WakeLock计数机制(setReferenceCounted):

在创建了PowerManager.WakeLock 后,有两种机制,第一种是不计数锁机制,另一种是计数锁机制。这可以通过setReferenceCounted( boolean value) 来指定,默认为计数机制。这两种机制的区别在于,前者无论acquire() 了多少次,只要通过一次release() 即可解锁。而后者正真解锁是在(--count == 0 )的时候,同样当(count == 0) 的时候才会去申请加锁,其他情况下isHeld 状态是不会改变的。所以PowerManager.WakeLock 的计数机制并不是正真意义上的对每次请求进行申请/释放每一把锁,它只是对同一把锁被申请/释放的次数进行了统计。


KeyguardService的启动:

frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java

@Override    /**     * Called when the system is done booting to the point where the     * user can start interacting with it.     */    public void systemBooted() {        bindKeyguard();        ..    }

frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.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, mHandler, UserHandle.SYSTEM)) {     .. } private final ServiceConnection mKeyguardConnection = new ServiceConnection() {     @Override     public void onServiceConnected(ComponentName name, IBinder service) {         if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");         // KeyguardServiceWrapper包装类调用KeyguardService的Binder实例         mKeyguardService = new KeyguardServiceWrapper(mContext,                 IKeyguardService.Stub.asInterface(service), mCallback);         if (mKeyguardState.systemIsReady) {             // If the system is ready, it means keyguard crashed and restarted.             mKeyguardService.onSystemReady();             if (mKeyguardState.currentUser != UserHandle.USER_NULL) {                 // There has been a user switch earlier                 mKeyguardService.setCurrentUser(mKeyguardState.currentUser);             }            // 调用KeyguardService的IPC接口            ..            ..     }     @Override     public void onServiceDisconnected(ComponentName name) {         if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");         mKeyguardService = null;         mKeyguardState.reset();         ..     } };

在绑定以后,PhoneWindowManager可以调用代理类KeyguardServiceDelegate间接调用KeyguardService的binder接口进行各种锁屏相关状态回调。


初次开机Keyguard showLock流程:

系统启动完成-->PhoneWindowManager.systemReady()-->mKeyguardDelegate.onSystemReady()

-->mKeyguardService.onSystemReady()-->KeyguardService.onSystemReady()

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java

@Override // Binder interface        public void onSystemReady() {            Trace.beginSection("KeyguardService.mBinder#onSystemReady");            checkPermission();            mKeyguardViewMediator.onSystemReady();            Trace.endSection();        }

frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java

public void onSystemReady() {        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();    }    /**     * Enable the keyguard if the settings are appropriate.     */    private void doKeyguardLocked(Bundle options) {        // 判断是不是安全启动        if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {            // Don't show keyguard during half-booted cryptkeeper stage.            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");            return;        }       ..       ..        // if the keyguard is already showing, don't bother        if (mStatusBarKeyguardViewManager.isShowing()) {            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");            resetStateLocked();            return;        }       ..       ..        if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");        showLocked(options);    }    /**     * Send message to keyguard telling it to show itself     * @see #handleShow     */    private void showLocked(Bundle options) {        // 持有mShowKeyguardWakeLock        // ensure we stay awake until we are finished displaying the keyguard        mShowKeyguardWakeLock.acquire();        Message msg = mHandler.obtainMessage(SHOW, options);        mHandler.sendMessage(msg);        Trace.endSection();    }    /**     * Handle message sent by {@link #showLocked}.     * @see #SHOW     */    private void handleShow(Bundle options) {        ..        synchronized (KeyguardViewMediator.this) {            ..            setShowingLocked(true);            //  显示keyguard            mStatusBarKeyguardViewManager.show(options);            ..            // 释放mShowKeyguardWakeLock            mShowKeyguardWakeLock.release();        }        mKeyguardDisplayManager.show();        Trace.endSection();    }

接下来就要处理Keyguard绘制的逻辑了,这部分主要是在StatusBarKeyguardViewManager中

调用showBouncerOrKeyguard()方法去显示notification keyguard还是bouncer,在灭屏的情况下,再次亮屏看到的一般是notification keyguard,就是有消息通知、时间之类的那个view,上滑才会显示密码解锁界面,也就是bouncer。接着就会调用showKeyguard(),当然由于还没有绘制内容,所以会进行keyguard的绘制。这里会调用hideBouncer()去隐藏已有的bouncer,因为下次亮屏的时候可能不是原来的锁屏方式。例如原来是PIN解锁,而我们在settings去重置了锁屏为pattern,那下次亮屏就应该显示pattern的view。

/**     * Show the keyguard.  Will handle creating and attaching to the view manager     * lazily.     */    public void show(Bundle options) {        mShowing = true;        mStatusBarWindowManager.setKeyguardShowing(true);        mScrimController.abortKeyguardFadingOut();        reset(true /* hideBouncerWhenShowing */);    }    /**     * Shows the notification keyguard or the bouncer depending on     * {@link KeyguardBouncer#needsFullscreenBouncer()}.     */    protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {        if (mBouncer.needsFullscreenBouncer() && !mDozing) {            // The keyguard might be showing (already). So we need to hide it.            mStatusBar.hideKeyguard();            mBouncer.show(true /* resetSecuritySelection */);        } else {            mStatusBar.showKeyguard();            if (hideBouncerWhenShowing) {                hideBouncer(false /* destroyView */);                mBouncer.prepare();            }        }        updateStates();    }

参考文档:

转载地址:http://npvmf.baihongyu.com/

你可能感兴趣的文章
BlockQueue 生产消费 不需要判断阻塞唤醒条件
查看>>
强引用 软引用 弱引用 虚引用
查看>>
数据类型 java转换
查看>>
"NetworkError: 400 Bad Request - http://172.16.47.117:8088/rhip/**/####t/approval?date=976
查看>>
mybatis 根据 数据库表 自动生成 实体
查看>>
win10将IE11兼容ie10
查看>>
checkbox设置字体颜色
查看>>
第一篇 HelloWorld.java重新学起
查看>>
ORACLE表空间扩张
查看>>
orcal 循环执行sql
查看>>
web.xml配置监听器,加载数据库信息配置文件ServletContextListener
查看>>
结构型模式之桥接模式(Bridge)
查看>>
行为型模式之状态模式(State)
查看>>
行为型模式之策略模式(Strategy)
查看>>
行为型模式之模板方法模式(TemplateMethod)
查看>>
行为型模式之访问者模式(Visitor)
查看>>
大小端详解
查看>>
source insight使用方法简介
查看>>
<stdarg.h>头文件的使用
查看>>
C++/C 宏定义(define)中# ## 的含义 宏拼接
查看>>