KeyguardBouncer呈現(xiàn)流程

本文將以開(kāi)機(jī)啟動(dòng),初次展示PIN碼解鎖界面為主線,介紹KeyguardService的組織結(jié)構(gòu)并分析密碼解鎖界面的呈現(xiàn)流程。

一.開(kāi)機(jī)啟動(dòng)到PhoneWindowManager

開(kāi)機(jī)啟動(dòng)init->zygote->systemserver進(jìn)程
systemserver入口是main(),實(shí)例化systemserver對(duì)象并調(diào)用其run()方法。
在run()方法中,我們此次重點(diǎn)關(guān)注startOtherServices();
在startOtherServices()啟動(dòng)了WindowManagerService,
截取部分代碼如下:
PhoneWindowManager.WindowManagerService:

private void startOtherServices() {
    WindowManagerService wm = null;
    wm = WindowManagerService.main(context, inputManager,
         mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
         !mFirstBoot, mOnlyCore);//啟動(dòng)服務(wù)
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);//注冊(cè)到ServiceManager,供其他進(jìn)程調(diào)用
        ......
    wm.systemReady();
}

WindowManagerService.systemReady():

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    final WindowManagerPolicy mPolicy = new PhoneWindowManager();//生成PhoneWindowManager實(shí)例
    public void systemReady() {
        mPolicy.systemReady();//調(diào)用PhoneWindowManager.systemReady()
}  

PhoneWindowManager.systemReady():

public void systemReady() {
    mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
    mKeyguardDelegate.onSystemReady();//實(shí)例鎖屏代理類(lèi)并調(diào)用其onSystemReady()
    

二.KeyguardService的組織結(jié)構(gòu)

這里先放一張整體的流程圖,方便大家查看分析:


KeyguardBouncer呈現(xiàn)流程圖.png

KeyguardServiceDelegate.onSystemReady():

protected KeyguardServiceWrapper mKeyguardService;//鎖屏服務(wù)包裝類(lèi)
public void onSystemReady() {
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
}

KeyguardServiceWrapper.onSystemReady():

private IKeyguardService mService;
public KeyguardServiceWrapper(Context context, IKeyguardService service) {
        mService = service;//IKeyguardService在KeyguardServiceWrapper的構(gòu)造函數(shù)中賦值
        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
public void onSystemReady() {
        try {
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }

可以看到KeyguardServiceWrapper對(duì)IKeyguardService進(jìn)行了封裝,其方法實(shí)現(xiàn)主要是對(duì)
IKeyguardService的調(diào)用。而IKeyguardService在在KeyguardServiceWrapper的構(gòu)造函數(shù)中賦值。
KeyguardServiceWrapper在哪被實(shí)例化的呢?
后頭看一下KeyguardServiceDelegate初始化的過(guò)程:

/**
* 使用bindService的方式來(lái)綁定服務(wù)。利用bindService的方式:
* 調(diào)用者與服務(wù)綁定在一起,調(diào)用者退出,服務(wù)即終止。
* ps => bind方式綁定服務(wù),服務(wù)的執(zhí)行順序?yàn)椋?* onCreate()->onBind()->onUnbind()->onDestroy()
*/
 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));
        //config_keyguardComponent->com.android.systemui/com.android.systemui.keyguard.KeyguardService
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        intent.setComponent(keyguardComponent);
        
        //這里將KeyguardServiceDelegate與KeyguardService綁定到了一起。
        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, mScrimHandler, UserHandle.SYSTEM)) {
            Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
            mKeyguardState.showing = false;
            mKeyguardState.showingAndNotOccluded = false;
            mKeyguardState.secure = false;
            synchronized (mKeyguardState) {
                // TODO: Fix synchronisation model in this class. The other state in this class
                // is at least self-healing but a race condition here can lead to the scrim being
                // stuck on keyguard-less devices.
                mKeyguardState.deviceHasKeyguard = false;
                hideScrim();
            }
        } else {
            if (DEBUG) Log.v(TAG, "*** Keyguard started");
        }
    }

    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
            //通過(guò)onServiceConnected()拿到KeyguardService的Binder代理對(duì)象,并創(chuàng)建KeyguardService包裝類(lèi)
            //實(shí)例化KeyguardServiceWrapper
            mKeyguardService = new KeyguardServiceWrapper(mContext,
                    IKeyguardService.Stub.asInterface(service));
           ......
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
            mKeyguardService = null;
        }
    };

可以看到KeyguardServiceDelegate去綁定KeyguardService,KeyguardServiceDelegate就相當(dāng)于一個(gè)客戶(hù)端,而
KeyguardService即為服務(wù)端。
看一下KeyguardService:

public class KeyguardService extends Service {
    static final String TAG = "KeyguardService";
    static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;

    private KeyguardViewMediator mKeyguardViewMediator;

    @Override
    public void onCreate() {
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
        mKeyguardViewMediator =
                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;//此返回值將返回到KeyguardServiceDelegate的onServiceConnected(),通過(guò)這個(gè)Binder對(duì)象,客戶(hù)端與服務(wù)端才能連接起來(lái)
    }
    
    
    //mBinder實(shí)例化,重寫(xiě)相關(guān)接口方法
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
    
        @Override // Binder interface
        public void onSystemReady() {
            checkPermission();
            mKeyguardViewMediator.onSystemReady();//實(shí)際KeyguardService調(diào)用KeyguardViewMediator的對(duì)應(yīng)方法
        }
        ......
    }
}

KeyguardViewMediator.onSystemReady()

public void onSystemReady() {
        synchronized (this) {
            ......
            doKeyguardLocked(null);//鎖屏調(diào)起的真正入口,進(jìn)行鎖屏預(yù)處理工作
            ......
        }
}

三.KeyguardBouncer呈現(xiàn)流程

上文調(diào)用如下:
PhoneWindowManager.systemReady()->KeyguardServiceDelegate.onSystemReady()
->KeyguardServiceWrapper.onSystemReady()->KeyguardService.onSystemReady()->
KeyguardViewMediator.onSystemReady().

KeyguardViewMediator.doKeyguardLocked():

private void doKeyguardLocked(Bundle options) {
        //如果其他應(yīng)用阻止我們顯示,那么就不顯示。。例如:接打電話
        if (!mExternallyEnabled || PowerOffAlarmManager.isAlarmBoot()) {
            return;
        }
        
        //如果鎖屏正在顯示,那我們就不去顯示
        if (mStatusBarKeyguardViewManager.isShowing()) {
            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
            resetStateLocked();
            if (DEBUG) {
                Log.d(TAG, "doKeyguard: not showing because it is already showing");
            }
            return;
        }

        ......
        //經(jīng)過(guò)上述判斷后,再去顯示鎖屏
        showLocked(options);
    }

KeyguardViewMediator.showLocked()

private void showLocked(Bundle options) {
        ......
        //獲取鎖屏鎖,不讓cpu進(jìn)入休眠,以完整的展示鎖屏
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);//發(fā)送SHOW消息
}

 public void handleMessage(Message msg) {
            switch (msg.what) {
                case SHOW:
                    handleShow((Bundle) msg.obj);
                    break;

KeyguardViewMediator.handleShow()

private void handleShow(Bundle options) {
        mStatusBarKeyguardViewManager =
                SystemUIFactory.getInstance().createStatusBarKeyguardViewManager(mContext,
                        mViewMediatorCallback, mLockPatternUtils);
        synchronized (KeyguardViewMediator.this) {
            ......
            mStatusBarKeyguardViewManager.show(options);//主要是調(diào)用了這里
            ......

StatusBarKeyguardViewManager.show():

public void show(Bundle options) {
        ......
        reset();
}

StatusBarKeyguardViewManager.reset():

public void reset() {
    if (mShowing) {
        if (mOccluded) {//是否有遮擋物,如果有就隱藏鎖屏,沒(méi)有則判斷顯示鎖屏還是密碼解鎖界面
                mPhoneStatusBar.hideKeyguard();
                mPhoneStatusBar.stopWaitingForKeyguardExit();
                mBouncer.hide(false /* destroyView */);
            } else {
                showBouncerOrKeyguard();//判斷顯示鎖屏還是密碼解鎖界面
            }
       KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
       updateStates();
    }
}

StatusBarKeyguardViewManager.showBouncerOrKeyguard():

protected void showBouncerOrKeyguard() {
    if (mBouncer.needsFullscreenBouncer()) {//是否需要顯示密碼鎖屏界面
            // The keyguard might be showing (already). So we need to hide it.
        mPhoneStatusBar.hideKeyguard();//隱藏鎖屏,顯示密碼解鎖界面
        mBouncer.show(true /* resetSecuritySelection */);
    } else {
        mPhoneStatusBar.showKeyguard();//顯示鎖屏,隱藏密碼解鎖界面
        mBouncer.hide(false /* destroyView */);
        mBouncer.prepare();
    }
}

Bouncer.needsFullscreenBouncer():

public boolean needsFullscreenBouncer() {
        ensureView();
        SecurityMode mode = mSecurityModel.getSecurityMode();//獲得當(dāng)前是哪一種安全模式
        return mode == SecurityMode.SimPinPukMe1
                || mode == SecurityMode.SimPinPukMe2
                || mode == SecurityMode.SimPinPukMe3
                || mode == SecurityMode.SimPinPukMe4
                || mode == SecurityMode.AntiTheft
                || mode == SecurityMode.AlarmBoot;
}

KeyguardSecurityModel.getSecurityMode():

public SecurityMode getSecurityMode() { 
        KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext);

        SecurityMode mode = SecurityMode.None;

        if (PowerOffAlarmManager.isAlarmBoot()) { /// M: add for power-off alarm
            mode = SecurityMode.AlarmBoot;
        } else {
            //檢查當(dāng)前sim卡的Pin/Puk/Me是否均已解鎖
            for (int i = 0; i < KeyguardUtils.getNumOfPhone(); i++) {
                if (isPinPukOrMeRequiredOfPhoneId(i)) {//判斷此卡是否需要進(jìn)行密碼解鎖
                    if (0 == i) {
                        mode = SecurityMode.SimPinPukMe1;
                    } else if (1 == i) {
                        mode = SecurityMode.SimPinPukMe2;
                    } else if (2 == i) {
                        mode = SecurityMode.SimPinPukMe3;
                    } else if (3 == i) {
                        mode = SecurityMode.SimPinPukMe4;
                    }
                    break;
                }
            }
        }
        //是否需要顯示防盜保護(hù)
        if (AntiTheftManager.isAntiTheftPriorToSecMode(mode)) {
            Log.d("KeyguardSecurityModel", "should show AntiTheft!") ;
            mode = SecurityMode.AntiTheft;
        }
        //如果當(dāng)前安全模式不是sim卡的Pin/Puk/Me也不是防盜保護(hù),則查看是PIN碼,密碼,還是手勢(shì)
        if (mode == SecurityMode.None) {
            final int security = mLockPatternUtils.getActivePasswordQuality(
                    KeyguardUpdateMonitor.getCurrentUser());
            switch (security) {
                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
                    return SecurityMode.PIN;

                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
                    return SecurityMode.Password;

                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
                    return SecurityMode.Pattern;
                case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
                    return SecurityMode.None;

                default:
                    throw new IllegalStateException("Unknown security quality:" + security);
            }
        }

        Log.d(TAG, "getSecurityMode() - mode = " + mode);
        return mode;
    }

本文以sim卡1的Pin碼解鎖為例,則getSecurityMode返回SecurityMode.SimPinPukMe1。至needsFullscreenBouncer(),
再至showBouncerOrKeyguard(),此時(shí)mBouncer.needsFullscreenBouncer()條件為真,隱藏鎖屏,顯示bouncer.
mBouncer.show(true /* resetSecuritySelection */);//重置安全選擇

public void show(boolean resetSecuritySelection) {
    ......
    show(resetSecuritySelection, false) ;
}

public void show(boolean resetSecuritySelection, boolean authenticated) {
        ......
        if (resetSecuritySelection) {//此時(shí)resetSecuritySelection為true
            // showPrimarySecurityScreen() updates the current security method. This is needed in
            // case we are already showing and the current security method changed.
            mKeyguardView.showPrimarySecurityScreen();
        }
        ......
}
    
public void showPrimarySecurityScreen() {
      mSecurityContainer.showPrimarySecurityScreen(false);
}

KeyguardSecurityContainer.showPrimarySecurityScreen();

void showPrimarySecurityScreen(boolean turningOff) {
        //獲取當(dāng)前安全模式,上文分析過(guò)
        SecurityMode securityMode = mSecurityModel.getSecurityMode();
        ......
        showSecurityScreen(securityMode);
    }

KeyguardSecurityContainer.showSecurityScreen:

//初次啟動(dòng)時(shí)mCurrentSecuritySelection為SecurityMode.Invalid
private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;

private void showSecurityScreen(SecurityMode securityMode) {
        //判斷此參數(shù)安全模式是否與當(dāng)前安全模式相同,如果相同則直接返回。
        if ((securityMode == mCurrentSecuritySelection)
                && (securityMode != SecurityMode.AntiTheft)) {
            return;
        }
        //如果不同,則通知安全模式的改變
        VoiceWakeupManager.getInstance().notifySecurityModeChange(
                mCurrentSecuritySelection, securityMode);
        
        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
       
        KeyguardSecurityView newView = getSecurityView(securityMode);//關(guān)鍵方法,根據(jù)安全模式獲得對(duì)應(yīng)的view

        ......
        //設(shè)置相關(guān)回調(diào)
        if (securityMode != SecurityMode.None) {
            newView.setKeyguardCallback(mCallback);
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
        }

        final int childCount = mSecurityViewFlipper.getChildCount();
        //尋找當(dāng)前安全模式對(duì)應(yīng)的view,并進(jìn)行展示。(此時(shí)PIN碼解鎖解鎖已在getSecurityView()中添加至mSecurityViewFlipper)
        //到這里view的展示也到達(dá)了本文流程的終點(diǎn)。
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
        for (int i = 0; i < childCount; i++) {
            if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
                mSecurityViewFlipper.setDisplayedChild(i);
                break;
            }
        }
        //更新當(dāng)前的安全選擇
        mCurrentSecuritySelection = securityMode;
        ......
}

KeyguardSecurityContainer.getSecurityView()

private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);//獲取安全模式對(duì)應(yīng)的view id
        KeyguardSecurityView view = null;
        final int children = mSecurityViewFlipper.getChildCount();
        //從mSecurityViewFlipper中取出此安全模式對(duì)應(yīng)view id的view,按照開(kāi)機(jī)初次抵達(dá)這里的情況,此時(shí)獲取的view為null
        for (int child = 0; child < children; child++) {
            if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
                view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
                break;
            }
        }
        //根據(jù)安全模式獲得對(duì)應(yīng)的layoutId
        int layoutId = getLayoutIdFor(securityMode);
        //如果mSecurityViewFlipper還沒(méi)有此view并且存在此安全模式對(duì)應(yīng)的layoutId
        if (view == null && layoutId != 0) {
            //inflater Layout
            final LayoutInflater inflater = LayoutInflater.from(mContext);
            View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);//view在這里被繪制,進(jìn)行各項(xiàng)初始化。
            view = (KeyguardSecurityView) v;//
            //如果是KeyguardSimPinPukMeView則需要設(shè)置phoneid,KeyguardSimPinPukMeView將根據(jù)此phoneid展示對(duì)應(yīng)資源
            if (view instanceof KeyguardSimPinPukMeView) {
                KeyguardSimPinPukMeView pinPukView = (KeyguardSimPinPukMeView) view;
                final int phoneId = mSecurityModel.getPhoneIdUsingSecurityMode(securityMode);
                pinPukView.setPhoneId(phoneId);
            }
            //將此view添加入mSecurityViewFlipper中
            mSecurityViewFlipper.addView(v);//在這里添加view至mSecurityViewFlipper
            updateSecurityView(v); //更新KeyguardSecurityView
        }
        return view;
}


private int getSecurityViewIdForMode(SecurityMode securityMode) {
        switch (securityMode) {
            case Pattern: return R.id.keyguard_pattern_view;
            case PIN: return R.id.keyguard_pin_view;
            case Password: return R.id.keyguard_password_view;
            case SimPinPukMe1:
            case SimPinPukMe2:
            case SimPinPukMe3:
            case SimPinPukMe4:
                return R.id.keyguard_sim_pin_puk_me_view ;
        }
        return 0;
}


protected int getLayoutIdFor(SecurityMode securityMode) {
        switch (securityMode) {
            case Pattern: return R.layout.keyguard_pattern_view;//手勢(shì)
            case PIN: return R.layout.keyguard_pin_view;//PIN碼
            case Password: return R.layout.keyguard_password_view;//密碼解鎖

            case SimPinPukMe1:
            case SimPinPukMe2:
            case SimPinPukMe3:
            case SimPinPukMe4:
                return R.layout.mtk_keyguard_sim_pin_puk_me_view;//sim_pin_puk_me
            
            default:
                return 0;
        }
}

到這里,view展示,其啟動(dòng)流程也到此結(jié)束。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容