android 锁屏框架流程分析

android 4.2以上系统锁屏框架

主要类:
 工作路径: frameworks/base/packages/keyguard

-->   KeyguardViewModiator.java  
  
   调度器中开始执行锁屏动作
    doKeyguardLocked(Bundle options)--> showLocked(options) 
    --> 
    /**
     * Send message to keyguard telling it to show itself
     * @see #handleShow()
     */
    void showLocked(Bundle options) {
        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);
    }
查找Handler消息处理中心调用,handleShow((Bundle) msg.obj);

   /**
     * Handle message sent by {@link #showLocked}.
     * @see #SHOW
     */
    private void handleShow(Bundle options) {
        synchronized (KeyguardViewMediator.this) {
            if (!mSystemReady) {
                if (DEBUG) Log.d(TAG, "ignoring handleShow because system is not ready.");
                return;
            } else {
                if (DEBUG) Log.d(TAG, "handleShow");
            }


            mKeyguardViewManager.show(options);
            if (DEBUG) KeyguardUtils.xlogD(TAG, "handleShow mKeyguardViewManager Show done");
            
            mShowing = true;
            mKeyguardDonePending = false;
            updateActivityLockScreenState();
            adjustStatusBarLocked();
            userActivity();
            ///M: [ALPS01268903] delay to finish to avoid flashing the below activity
            mHandler.postDelayed(new Runnable() {
                public void run() {
                    try {
                        ActivityManagerNative.getDefault().closeSystemDialogs("lock");
                    } catch (RemoteException e) {
                    }
                }
            }, 500);


            // Do this at the end to not slow down display of the keyguard.
            /// M: power off alarm
            if (!PowerOffAlarmManager.isAlarmBoot()) {
                playSounds(true);
            } else {
                mPowerOffAlarmManager.startAlarm();
            }


            mShowKeyguardWakeLock.release();
            if (DEBUG) KeyguardUtils.xlogD(TAG, "handleShow exit");
        }


        if (mKeyguardDisplayManager != null) {
            mKeyguardDisplayManager.show();
        }
    }

  在上述中有给出一系列的判断是否锁屏,比如在用户按下PowerOff的时候,会给出一定缓冲时间来避免用户执行后悔动作。处理了闹钟事件下的动作。
  调用视图显示:
          
	 mKeyguardViewManager.show(options);
 
--> KeyguardViewManager.java

   
  /**
     * Show the keyguard.  Will handle creating and attaching to the view manager
     * lazily.
     */
    public synchronized void show(Bundle options) {
        if (DEBUG) Log.d(TAG, "show(); mKeyguardView=" + mKeyguardView);


        boolean enableScreenRotation = KeyguardUtils.shouldEnableScreenRotation(mContext);
        if (DEBUG) Log.d(TAG, "show() query screen rotation after");


        /// M: Incoming Indicator for Keyguard Rotation @{
        KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();
        /// @}
        maybeCreateKeyguardLocked(enableScreenRotation, false, options);
        
        if (DEBUG) Log.d(TAG, "show() maybeCreateKeyguardLocked finish");
        
        maybeEnableScreenRotation(enableScreenRotation);


        // Disable common aspects of the system/status/navigation bars that are not appropriate or
        // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
        // activities. Other disabled bits are handled by the KeyguardViewMediator talking
        // directly to the status bar service.
        int visFlags = View.STATUS_BAR_DISABLE_HOME;
        if (shouldEnableTranslucentDecor()) {
            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                                       | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
        }
        if (DEBUG) Log.d(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
        mKeyguardHost.setSystemUiVisibility(visFlags);


        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
        mKeyguardHost.setVisibility(View.VISIBLE);
        mKeyguardView.show();
        mKeyguardView.requestFocus();
        if (DEBUG) Log.d(TAG, "show() exit; mKeyguardView=" + mKeyguardView);
    }
    这个方法就是将锁屏视图显示出来了,并抢占焦点。初始化时在maybeCreateKeyguardLocked时完成的
    
private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
            Bundle options) {
        if (mKeyguardHost != null) {
            mKeyguardHost.saveHierarchyState(mStateContainer);
        }


        if (mKeyguardHost == null) {
            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");


            mKeyguardHost = new ViewManagerHost(mContext);


            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;


            if (!mNeedsInput) {
                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            }


            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
            final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
            lp.windowAnimations = R.style.Animation_LockScreen;
            lp.screenOrientation = enableScreenRotation ?
                    ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;


            if (ActivityManager.isHighEndGfx()) {
                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                lp.privateFlags |=
                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
            }
            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
            /// M: Poke user activity when operating Keyguard
            //lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
            lp.setTitle("Keyguard");
            mWindowLayoutParams = lp;
            ///M: skip add KeyguardHost into viewManager in AT case
            if (!KeyguardViewMediator.isKeyguardInActivity) {
                mViewManager.addView(mKeyguardHost, lp);
            } else {
                if (DEBUG) Log.d(TAG, "skip add mKeyguardHost into mViewManager for testing");
            }
            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
        }


       /// M: If force and keyguardView is not null, we should relase memory hold by old keyguardview
        if (force && mKeyguardView != null) {
            mKeyguardView.cleanUp();
        }


        if (force || mKeyguardView == null) {
            mKeyguardHost.setCustomBackground(null);
            mKeyguardHost.removeAllViews();
            inflateKeyguardView(options);
            mKeyguardView.requestFocus();
        }
        updateUserActivityTimeoutInWindowLayoutParams();
        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);


        mKeyguardHost.restoreHierarchyState(mStateContainer);
    }

上述中可以看到,其实系统锁屏也是通过全屏的悬浮视图贴在窗口视图的最顶层,实现方式类似于我们开发工具类应用悬浮窗的方式, 锁屏视图类型由一下方法决定:

 private void inflateKeyguardView(Bundle options) {
        /// M: add for power-off alarm @{
        int resId = R.id.keyguard_host_view;
        int layoutId = R.layout.keyguard_host_view;
        if(PowerOffAlarmManager.isAlarmBoot()){
            resId = R.id.power_off_alarm_host_view;
            layoutId = R.layout.mtk_power_off_alarm_host_view;
        }
        /// @}
        View v = mKeyguardHost.findViewById(resId);
        if (v != null) {
            mKeyguardHost.removeView(v);
        }
        /// M: Save new orientation
        mCreateOrientation = mContext.getResources().getConfiguration().orientation;
        mCreateScreenWidthDp = mContext.getResources().getConfiguration().screenWidthDp;
        mCreateScreenHeightDp = mContext.getResources().getConfiguration().screenHeightDp;
        
        final LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(layoutId, mKeyguardHost, true);
        mKeyguardView = (KeyguardHostView) view.findViewById(resId);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
        mKeyguardView.initializeSwitchingUserState(options != null &&
                options.getBoolean(IS_SWITCHING_USER));


        // HACK
        // The keyguard view will have set up window flags in onFinishInflate before we set
        // the view mediator callback. Make sure it knows the correct IME state.
        if (mViewMediatorCallback != null) {
            KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
                    R.id.keyguard_password_view);


            if (kpv != null) {
                mViewMediatorCallback.setNeedsInput(kpv.needsInput());
            }
        }


        if (options != null) {
            int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
                mKeyguardView.goToWidget(widgetToShow);
            }
        }
    }
  然後在不同的视图类来实现解锁动作。



猜你喜欢

转载自blog.csdn.net/zjfengdou30/article/details/42775363