KeyguardBouncer呈现流程

本文将以开机启动,初次展示PIN码解锁界面为主线,介绍KeyguardService的组织结构并分析密码解锁界面的呈现流程。

一.开机启动到PhoneWindowManager

开机启动init->zygote->systemserver进程
systemserver入口是main(),实例化systemserver对象并调用其run()方法。
在run()方法中,我们此次重点关注startOtherServices();
在startOtherServices()启动了WindowManagerService,
截取部分代码如下:
PhoneWindowManager.WindowManagerService:

private void startOtherServices() {
    WindowManagerService wm = null;
    wm = WindowManagerService.main(context, inputManager,
         mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
         !mFirstBoot, mOnlyCore);//启动服务
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);//注册到ServiceManager,供其他进程调用
        ......
    wm.systemReady();
}

WindowManagerService.systemReady():

public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
    final WindowManagerPolicy mPolicy = new PhoneWindowManager();//生成PhoneWindowManager实例
    public void systemReady() {
        mPolicy.systemReady();//调用PhoneWindowManager.systemReady()
}  

PhoneWindowManager.systemReady():

public void systemReady() {
    mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
    mKeyguardDelegate.onSystemReady();//实例锁屏代理类并调用其onSystemReady()
    

二.KeyguardService的组织结构

这里先放一张整体的流程图,方便大家查看分析:


KeyguardBouncer呈现流程图.png

KeyguardServiceDelegate.onSystemReady():

protected KeyguardServiceWrapper mKeyguardService;//锁屏服务包装类
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的构造函数中赋值
        mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
public void onSystemReady() {
        try {
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }

可以看到KeyguardServiceWrapper对IKeyguardService进行了封装,其方法实现主要是对
IKeyguardService的调用。而IKeyguardService在在KeyguardServiceWrapper的构造函数中赋值。
KeyguardServiceWrapper在哪被实例化的呢?
后头看一下KeyguardServiceDelegate初始化的过程:

/**
* 使用bindService的方式来绑定服务。利用bindService的方式:
* 调用者与服务绑定在一起,调用者退出,服务即终止。
* ps => bind方式绑定服务,服务的执行顺序为:
* 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!)");
            //通过onServiceConnected()拿到KeyguardService的Binder代理对象,并创建KeyguardService包装类
            //实例化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就相当于一个客户端,而
KeyguardService即为服务端。
看一下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(),通过这个Binder对象,客户端与服务端才能连接起来
    }
    
    
    //mBinder实例化,重写相关接口方法
    private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
    
        @Override // Binder interface
        public void onSystemReady() {
            checkPermission();
            mKeyguardViewMediator.onSystemReady();//实际KeyguardService调用KeyguardViewMediator的对应方法
        }
        ......
    }
}

KeyguardViewMediator.onSystemReady()

public void onSystemReady() {
        synchronized (this) {
            ......
            doKeyguardLocked(null);//锁屏调起的真正入口,进行锁屏预处理工作
            ......
        }
}

三.KeyguardBouncer呈现流程

上文调用如下:
PhoneWindowManager.systemReady()->KeyguardServiceDelegate.onSystemReady()
->KeyguardServiceWrapper.onSystemReady()->KeyguardService.onSystemReady()->
KeyguardViewMediator.onSystemReady().

KeyguardViewMediator.doKeyguardLocked():

private void doKeyguardLocked(Bundle options) {
        //如果其他应用阻止我们显示,那么就不显示。。例如:接打电话
        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;
        }

        ......
        //经过上述判断后,再去显示锁屏
        showLocked(options);
    }

KeyguardViewMediator.showLocked()

private void showLocked(Bundle options) {
        ......
        //获取锁屏锁,不让cpu进入休眠,以完整的展示锁屏
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);//发送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);//主要是调用了这里
            ......

StatusBarKeyguardViewManager.show():

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

StatusBarKeyguardViewManager.reset():

public void reset() {
    if (mShowing) {
        if (mOccluded) {//是否有遮挡物,如果有就隐藏锁屏,没有则判断显示锁屏还是密码解锁界面
                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();//获得当前是哪一种安全模式
        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 {
            //检查当前sim卡的Pin/Puk/Me是否均已解锁
            for (int i = 0; i < KeyguardUtils.getNumOfPhone(); i++) {
                if (isPinPukOrMeRequiredOfPhoneId(i)) {//判断此卡是否需要进行密码解锁
                    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;
                }
            }
        }
        //是否需要显示防盗保护
        if (AntiTheftManager.isAntiTheftPriorToSecMode(mode)) {
            Log.d("KeyguardSecurityModel", "should show AntiTheft!") ;
            mode = SecurityMode.AntiTheft;
        }
        //如果当前安全模式不是sim卡的Pin/Puk/Me也不是防盗保护,则查看是PIN码,密码,还是手势
        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(),此时mBouncer.needsFullscreenBouncer()条件为真,隐藏锁屏,显示bouncer.
mBouncer.show(true /* resetSecuritySelection */);//重置安全选择

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

public void show(boolean resetSecuritySelection, boolean authenticated) {
        ......
        if (resetSecuritySelection) {//此时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) {
        //获取当前安全模式,上文分析过
        SecurityMode securityMode = mSecurityModel.getSecurityMode();
        ......
        showSecurityScreen(securityMode);
    }

KeyguardSecurityContainer.showSecurityScreen:

//初次启动时mCurrentSecuritySelection为SecurityMode.Invalid
private SecurityMode mCurrentSecuritySelection = SecurityMode.Invalid;

private void showSecurityScreen(SecurityMode securityMode) {
        //判断此参数安全模式是否与当前安全模式相同,如果相同则直接返回。
        if ((securityMode == mCurrentSecuritySelection)
                && (securityMode != SecurityMode.AntiTheft)) {
            return;
        }
        //如果不同,则通知安全模式的改变
        VoiceWakeupManager.getInstance().notifySecurityModeChange(
                mCurrentSecuritySelection, securityMode);
        
        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
       
        KeyguardSecurityView newView = getSecurityView(securityMode);//关键方法,根据安全模式获得对应的view

        ......
        //设置相关回调
        if (securityMode != SecurityMode.None) {
            newView.setKeyguardCallback(mCallback);
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
        }

        final int childCount = mSecurityViewFlipper.getChildCount();
        //寻找当前安全模式对应的view,并进行展示。(此时PIN码解锁解锁已在getSecurityView()中添加至mSecurityViewFlipper)
        //到这里view的展示也到达了本文流程的终点。
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
        for (int i = 0; i < childCount; i++) {
            if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
                mSecurityViewFlipper.setDisplayedChild(i);
                break;
            }
        }
        //更新当前的安全选择
        mCurrentSecuritySelection = securityMode;
        ......
}

KeyguardSecurityContainer.getSecurityView()

private KeyguardSecurityView getSecurityView(SecurityMode securityMode) {
        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);//获取安全模式对应的view id
        KeyguardSecurityView view = null;
        final int children = mSecurityViewFlipper.getChildCount();
        //从mSecurityViewFlipper中取出此安全模式对应view id的view,按照开机初次抵达这里的情况,此时获取的view为null
        for (int child = 0; child < children; child++) {
            if (mSecurityViewFlipper.getChildAt(child).getId() == securityViewIdForMode) {
                view = ((KeyguardSecurityView)mSecurityViewFlipper.getChildAt(child));
                break;
            }
        }
        //根据安全模式获得对应的layoutId
        int layoutId = getLayoutIdFor(securityMode);
        //如果mSecurityViewFlipper还没有此view并且存在此安全模式对应的layoutId
        if (view == null && layoutId != 0) {
            //inflater Layout
            final LayoutInflater inflater = LayoutInflater.from(mContext);
            View v = inflater.inflate(layoutId, mSecurityViewFlipper, false);//view在这里被绘制,进行各项初始化。
            view = (KeyguardSecurityView) v;//
            //如果是KeyguardSimPinPukMeView则需要设置phoneid,KeyguardSimPinPukMeView将根据此phoneid展示对应资源
            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;//手势
            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展示,其启动流程也到此结束。

你可能感兴趣的:(KeyguardBouncer呈现流程)