SystemUI学习总结(三)

前面学习了SystemUI中状态栏模块相关内容,接下来学习锁屏模块相关内容,锁屏模块可以大致分为两个部分,一个是密码解锁,一个是页面加载,密码解锁是由KeyguardBouncer类控制,页面加载是在StatusBar中加载,个人认为页面之所以在StatusBar中加载是因为很多内容与状态栏重合
先从开机启动流程开始,手机开机后会启动SystemServer,后续调用startSystemUi方法

    public static void main(String[] args) {
        Log.d("sunyuke","启动SystemServer");
        new SystemServer().run();
    }
    
    static final void startSystemUi(Context context, WindowManagerService windowManager) {
        Log.d("sunyuke","启动systemUI");
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        windowManager.onSystemUiStarted();
    }

onSystemUiStarted方法实际是在PhoneWindowManager类中处理,手机按键大部分都是在PhoneWindowManager类中进行处理

    @Override
    public void onSystemUiStarted() {
        bindKeyguard();
    }
    
    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        mKeyguardDelegate.bindService(mContext);
    }

后面会调用到KeyguardServiceDelegate类中的bindService,对KeyguardService进行绑定

    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);
        Log.d("sunyuke","绑定KeyguardService :"+intent.getComponent().getClassName());
        if (!context.bindServiceAsUser(intent, mKeyguardConnection,
                Context.BIND_AUTO_CREATE, mHandler, 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;
            }
        } 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!)");
            Log.d("sunyuke","将KeyguardServicer传入KeyguardServiceWrapper");
            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();
                ...
            }
            ...
        }

绑定成功后在ServiceConnection中进行回调,调用KeyguardService中的onSystemReady方法,最终会调用KeyguardViewMediator中的handleSystemReady方法,doKeyguardLocked是启动锁屏界面的预处理方法。主要处理有
1.判断其他应用禁止锁屏呈现。
2.判断是否需要重置状态。
3.判断Settings中没有启用锁屏 。
4.判断是否设置了密码等。
5.符合条件,显示锁屏。

    private void handleSystemReady() {
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            Log.d("sunyuke","启动锁屏界面处理");
            doKeyguardLocked(null);
            mUpdateMonitor.registerCallback(mUpdateCallback);
            mPowerOffAlarmManager.onSystemReady();
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
    
    private void doKeyguardLocked(Bundle options) {
        ...
        //展示锁屏页面
        showLocked(options);
    }

    private void handleShow(Bundle options) {
        ...
        synchronized (KeyguardViewMediator.this) {
            ...
            //加载锁屏页面
            mStatusBarKeyguardViewManager.show(options);
            ...
        }
       ...
    }

跟着方法一路走下来最终会调用StatusBarKeyguardViewManager中的showBouncerOrKeyguard方法加载锁屏页面及密码解锁页面

    protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
        if (DEBUG) Log.d(TAG, "showBouncerOrKeyguard() is called.");
        if (mBouncer.needsFullscreenBouncer() && !mDozing) {
            if (DEBUG) {
                Log.d(TAG, "needsFullscreenBouncer() is true, show \"Bouncer\" view directly.");
            }
            Log.d("sunyuke","隐藏锁屏界面,显示密码解锁界面");
            // The keyguard might be showing (already). So we need to hide it.
            mStatusBar.hideKeyguard();
            mBouncer.show(true /* resetSecuritySelection */);
        } else {
            if (DEBUG) {
                Log.d(TAG, "needsFullscreenBouncer() is false,"
                    + "show \"Notification Keyguard\" view.");
            }
            Log.d("sunyuke","显示锁屏界面");
            mStatusBar.showKeyguard();
            if (hideBouncerWhenShowing) {
                hideBouncer(shouldDestroyViewOnReset() /* destroyView */);
                mBouncer.prepare();
            }
        }
        updateStates();
    }

调用KeyguardBouncer类中的needsFullscreenBouncer方法

    public boolean needsFullscreenBouncer() {
        ensureView();
        /*if (mKeyguardView != null) {
            SecurityMode mode = mKeyguardView.getSecurityMode();
            return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk;
        }
        return false;*/
        SecurityMode mode = mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser());
        return mode == SecurityMode.SimPinPukMe1
                || mode == SecurityMode.SimPinPukMe2
                || mode == SecurityMode.SimPinPukMe3
                || mode == SecurityMode.SimPinPukMe4
                || mode == SecurityMode.AntiTheft
                || mode == SecurityMode.AlarmBoot;
    }
    
    protected void ensureView() {
        //是否执行了移除密码view
        boolean forceRemoval = mHandler.hasCallbacks(mRemoveViewRunnable);
        //如果锁屏密码为空或进行了删除才往下执行
        if (mRoot == null || forceRemoval) {
            inflateView();
        }
    }

    protected void inflateView() {
        //确保没有重复的锁屏密码页面
        removeView();
        mHandler.removeCallbacks(mRemoveViewRunnable);
        //创建锁屏密码页面
        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
        mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
        // M: Add to show message for MTK FaceUnlock
        mMessageView = (TextView) mRoot.findViewById(R.id.face_secure_msg);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mCallback);
        mContainer.addView(mRoot, mContainer.getChildCount());
        mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
                com.android.systemui.R.dimen.status_bar_height);
        mRoot.setVisibility(View.INVISIBLE);
        mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());

        final WindowInsets rootInsets = mRoot.getRootWindowInsets();
        if (rootInsets != null) {
            mRoot.dispatchApplyWindowInsets(rootInsets);
        }
    }

KeyguardHostView就是锁屏密码View

    @Override
    protected void onFinishInflate() {
        Log.d("sunyuke","showPrimarySecurityScreen1");
        mSecurityContainer =
                findViewById(R.id.keyguard_security_container);
        mLockPatternUtils = new LockPatternUtils(mContext);
        mSecurityContainer.setLockPatternUtils(mLockPatternUtils);
        mSecurityContainer.setSecurityCallback(this);
        mSecurityContainer.showPrimarySecurityScreen(false);
        // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
    }

主要看showPrimarySecurityScreen方法,根据流程往下走,回执行KeyguardSecurityContainer类中的showSecurityScreen方法

/**
     * 切换到给定的密码解锁页面,除非它已经被显示
     * this is a no-op.
     *
     * @param securityMode 密码解锁类型 1.None没有锁屏密码 2. Pattern 图形密码 3.Password 普通的密码 4.PIN PIN密码
     */
    private void showSecurityScreen(SecurityMode securityMode) {
        if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");

        //判断是否加载过解锁密码页面
        if ((securityMode == mCurrentSecuritySelection)
                && (securityMode != SecurityMode.AntiTheft)) {
            return;
        }
        Log.d(TAG, "showSecurityScreen() - get oldview for" + mCurrentSecuritySelection
                + ", get newview for" + securityMode);
        KeyguardSecurityView oldView = getSecurityView(mCurrentSecuritySelection);
        KeyguardSecurityView newView = getSecurityView(securityMode);

        // Emulate Activity life cycle
        if (oldView != null) {
            oldView.onPause();
            oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
        }
        if (securityMode != SecurityMode.None) {
            /// M: fix ALPS01832185,
            ///    KeyguardAntiTheftView needs the latest mCallback before onResume.
            newView.setKeyguardCallback(mCallback);
            Log.d(TAG, "showSecurityScreen() - newview.setKeyguardCallback(mCallback)");
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
        }

        // Find and show this child.
        final int childCount = mSecurityViewFlipper.getChildCount();

        final int securityViewIdForMode = getSecurityViewIdForMode(securityMode);
        for (int i = 0; i < childCount; i++) {
            if (mSecurityViewFlipper.getChildAt(i).getId() == securityViewIdForMode) {
                mSecurityViewFlipper.setDisplayedChild(i);
                break;
            }
        }

        mCurrentSecuritySelection = securityMode;
        Log.d(TAG, "Before update, mCurrentSecuritySelection = " + securityMode
                + "After update, mCurrentSecuritySelection = " + mCurrentSecuritySelection);
        mSecurityCallback.onSecurityModeChanged(securityMode,
                securityMode != SecurityMode.None && newView.needsInput());
    }

这块儿有一个地方我目前还没搞明白,为什么要获取oldView,根据打印的日志来看,第二次锁屏的时候mCurrentSecuritySelection的值与securityMode值是一致的,也不会往下走,所以意义在哪里?
关于锁屏后的页面主要是NotificationPanelView类控制,我们看StatusBar类,在makeStatusBarView方法中就创建了锁屏的页面

//StatusBar
		protected void makeStatusBarView() {
      ...
        // 创建 NotificationPanelView
        mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
        mStackScroller = mStatusBarWindow.findViewById(R.id.notification_stack_scroller);
        mZenController.addCallback(this);
       ...
     	  //创建 KeyguardStatusBarView
        mKeyguardStatusBar = mStatusBarWindow.findViewById(R.id.keyguard_header);
//NotificationPanelView
@Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mKeyguardStatusBar = findViewById(R.id.keyguard_header);
        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);

        mNotificationContainerParent = findViewById(R.id.notification_container_parent);
        mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
        //填充锁屏图标的layout
        mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
        mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
        mLastOrientation = getResources().getConfiguration().orientation;

        initBottomArea();

        mQsFrame = findViewById(R.id.qs_frame);
    }
//KeyguardBottomArea
/**
 * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
 * text.
 */
public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
        UnlockMethodCache.OnUnlockMethodChangedListener,
        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
        ...
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值