android锁屏创建流程

本文简单分析,android启动之后,锁屏界面启动过程。

android系统开机后会运行PhoneWindowManage管理系统相关按键和事件,

看下PhoneWindowManager锁屏相关

1.Pwm初始化KeyguardViewMediator类,用来接受PhoneWindowManager传递相关事件

2.系统启动完成会调用SystemReady函数,进入锁屏流程

/** {@inheritDoc} */
    public void systemReady() {
        // tell the keyguard
        mKeyguardMediator.onSystemReady();
        android.os.SystemProperties.set("dev.bootcomplete", "1"); 
        synchronized (mLock) {
            updateOrientationListenerLp();
            mSystemReady = true;
            mHandler.post(new Runnable() {
                public void run() {
                    updateSettings();
                }
            });
        }
    }


3.KeyguradMediator中onSystemReady函数 /**
     * Let us know that the system is ready after startup.
     */ public void onSystemReady() { synchronized (this) { if (DBG_WAKE) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            doKeyguardLocked(); } }


4.doKeyguardLocked进入锁屏判断,是否有第三方锁屏应用文件。
5.没有第三方锁屏应用或禁用锁屏,则进入showLocked函数 /**
     
 /**
     * Send message to keyguard telling it to show itself
     * @see #handleShow()
     */
    private void showLocked() {
        if (DEBUG) Xlog.d(TAG, "showLocked");
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW);
        
         if (isAlarmBoot() && !mChecked) {
            mChecked = true;
            Log.i(TAG, "it's alarm boot, delay 3s to show");
            mHandler.sendMessageDelayed(msg, 5000);
         } else {
            mHandler.sendMessage(msg);
         }
    }


6.showLocked函数通过handler,发送显示锁屏信息或延时处理,handler 接受消息,直接调用handleShow处理
 
 /**
     * Handle message sent by {@link #showLocked}.
     * @see #SHOW
     */
    private void handleShow() {
        synchronized (KeyguardViewMediator.this) {
            if (DEBUG) Xlog.d(TAG, "handleShow");
            if (!mSystemReady) return;
            if (mShowing == true) return;
            mShowCount++;
            //avoid the int overflow
            if (mShowCount == (int)Math.pow(2, 32)){
                mShowCount=2;
            }
            Xlog.d(TAG, "handleShow, count="+mShowCount);

            mKeyguardViewManager.show();
            mShowing = true;
            adjustUserActivityLocked();
            adjustStatusBarLocked();
            
            try {
                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
            } catch (RemoteException e) {
            }

            // Do this at the end to not slow down display of the keyguard.
            playSounds(true);

            mShowKeyguardWakeLock.release();
        }
    }


7.进入KeyguardViewManager中的show();KeyguardViewManager 是锁屏管理处理类,该类在KeyguraMeditor初始化
   
  /**
     * Show the keyguard.  Will handle creating and attaching to the view 
manager

     * lazily.
     */
    public synchronized void show() {
        if (DEBUG) Xlog.d(TAG, "show(); mKeyguardView==" + mKeyguardView);

        Resources res = mContext.getResources();
        boolean enableScreenRotation =
                SystemProperties.getBoolean("lockscreen.rot_override",false)
                || res.getBoolean(R.bool.config_enableLockScreenRotation);
        if (mKeyguardHost == null) {
            if (DEBUG) Xlog.d(TAG, "keyguard host is null, creating it...");

            mKeyguardHost = new KeyguardViewHost(mContext, mCallback);

            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
            int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
                    | WindowManager.LayoutParams.
FLAG_KEEP_SURFACE_WHILE_ANIMATING

                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
            if (mUpdateMonitor.DM_IsLocked()) {//in the first created
                flags &= ~WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
                flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
                flags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
            } else {
                flags &= ~WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
                flags &= ~WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
                flags |= WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
            }
            if (!mNeedsInput) {
                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            }
            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.
getSystemService(

                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
                flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
            }
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
                    flags, PixelFormat.TRANSLUCENT);
            lp.softInputMode = WindowManager.LayoutParams.
SOFT_INPUT_ADJUST_RESIZE;

            lp.windowAnimations = com.android.internal.R.style.
Animation_LockScreen;

            if (ActivityManager.isHighEndGfx(((WindowManager)mContext.
getSystemService(

                    Context.WINDOW_SERVICE)).getDefaultDisplay())) {
                lp.flags |= WindowManager.LayoutParams.
FLAG_HARDWARE_ACCELERATED;

                lp.privateFlags |=
                        WindowManager.LayoutParams.
PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;

            }

            lp.setTitle("Keyguard");
            mWindowLayoutParams = lp;

            mViewManager.addView(mKeyguardHost, lp);
        }

        if (enableScreenRotation || FeatureOption.MTK_TB_APP_LANDSCAPE_SUPPORT
) {

            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
            mWindowLayoutParams.screenOrientation = ActivityInfo.
SCREEN_ORIENTATION_SENSOR;

        } else {
            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
            mWindowLayoutParams.screenOrientation = ActivityInfo.
SCREEN_ORIENTATION_NOSENSOR;

        }

        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);

        if (mKeyguardView == null) {
            if (DEBUG) Xlog.d(TAG, "keyguard view is null, creating it...");
            mKeyguardView = mKeyguardViewProperties.createKeyguardView(
mContext, mUpdateMonitor, this);

            mKeyguardView.setId(R.id.lock_screen);
            mKeyguardView.setCallback(mCallback);

            final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);

            mKeyguardHost.addView(mKeyguardView, lp);

            if (mScreenOn) {
                mKeyguardView.show();
            }
        }

        // Disable aspects of the system/status/navigation bars that are not 
appropriate or

        // useful for the lockscreen 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_BACK
                | View.STATUS_BAR_DISABLE_HOME);
        
        mKeyguardHost.setSystemUiVisibility(visFlags);

        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
        mKeyguardHost.setVisibility(View.VISIBLE);
        mKeyguardView.requestFocus();
    }


show函数主要锁屏界面添加到ViewManager中显示,主要看下KeyguardView创建工程 

mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
看下mKeyguraViewProperties 通过源码可知KeyViewMediator初始化创建,传入

KeyguardViewManager mKeyguardViewProperties = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor); 

mKeyguardViewManager = new KeyguardViewManager( context, WindowManagerImpl.getDefault(), this, mKeyguardViewProperties, mUpdateMonitor);
8.LockPatternKeyguardViewProperties类中CreateKeyGuardView函数,初始化 LockPatternKeyguardView,LockPatternKeyguardView便是我们的锁屏界面

/**
 * Knows how to create a lock pattern keyguard view, and answer questions about
 * it (even if it hasn't been created, per the interface specs).
 */
public class LockPatternKeyguardViewProperties implements 
KeyguardViewProperties {


    private final LockPatternUtils mLockPatternUtils;
    private final KeyguardUpdateMonitor mUpdateMonitor;

    /**
     * @param lockPatternUtils Used to know whether the pattern enabled, and 
passed

     *   onto the keygaurd view when it is created.
     * @param updateMonitor Used to know whether the sim pin is enabled, and 
passed

     *   onto the keyguard view when it is created.
     */
    public LockPatternKeyguardViewProperties(LockPatternUtils lockPatternUtils,
            KeyguardUpdateMonitor updateMonitor) {
        mLockPatternUtils = lockPatternUtils;
        mUpdateMonitor = updateMonitor;
    }

    public KeyguardViewBase createKeyguardView(Context context,
            KeyguardUpdateMonitor updateMonitor,
            KeyguardWindowController controller) {
        return new LockPatternKeyguardView(context, updateMonitor,
                mLockPatternUtils, controller);
    }

    public boolean isSecure() {
        return mLockPatternUtils.isSecure() || isSimPinSecure();
    }

    private boolean isSimPinSecure() {
        final IccCard.State simState = mUpdateMonitor.getSimState(Phone.
GEMINI_SIM_1);

        final IccCard.State sim2State = mUpdateMonitor.getSimState(Phone.
GEMINI_SIM_2);

        return (simState == IccCard.State.PIN_REQUIRED
                || simState == IccCard.State.PUK_REQUIRED
                || simState == IccCard.State.PERM_DISABLED
                || sim2State == IccCard.State.PIN_REQUIRED
                || sim2State == IccCard.State.PUK_REQUIRED
                || sim2State == IccCard.State.PERM_DISABLED
                || simState == IccCard.State.ABSENT
                && sim2State == IccCard.State.ABSENT);
    }

}
9.看下LockPatternKeyguardView初始流程
    /**
     * @param context Used to inflate, and create views.
     * @param updateMonitor Knows the state of the world, and passed along to 
each

     *   screen so they can use the knowledge, and also register for callbacks
     *   on dynamic information.
     * @param lockPatternUtils Used to look up state of lock pattern.
     */
    public LockPatternKeyguardView(
            Context context,
            KeyguardUpdateMonitor updateMonitor,
            LockPatternUtils lockPatternUtils,
            KeyguardWindowController controller) {
        super(context);

        mHandler = new Handler(this);
        mConfiguration = context.getResources().getConfiguration();
        mEnableFallback = false;
        mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.
no_require_sim"));

        mUpdateMonitor = updateMonitor;
        mLockPatternUtils = lockPatternUtils;
        mWindowController = controller;
        mHasOverlay = false;

        mUpdateMonitor.registerDeviceInfoCallback(this);
        mUpdateMonitor.registerPhoneStateCallback(this);

        mKeyguardScreenCallback = new KeyguardScreenCallback() {

            public void goToLockScreen() {
                mForgotPattern = false;
                if (mIsVerifyUnlockOnly) {
                    // navigating away from unlock screen during verify mode 
means

                    // we are done and the user failed to authenticate.
                    mIsVerifyUnlockOnly = false;
                    getCallback().keyguardDone(false);
                } else {
                    updateScreen(Mode.LockScreen, false);
                }
            }

            public void goToUnlockScreen() {
                final IccCard.State simState = mUpdateMonitor.getSimState(
Phone.GEMINI_SIM_1);

                final IccCard.State sim2State = mUpdateMonitor.getSimState(
Phone.GEMINI_SIM_2);

                if (stuckOnLockScreenBecauseSimMissing()
                    || (simState == IccCard.State.PUK_REQUIRED 
                    && !mLockPatternUtils.isPukUnlockScreenEnable())
                    || (sim2State == IccCard.State.PUK_REQUIRED 
                    && !mLockPatternUtils.isPukUnlockScreenEnable())){
                    // stuck on lock screen when sim missing or
                    // puk'd but puk unlock screen is disabled
                    return;
                }
                if (!isSecure()) {
                    getCallback().keyguardDone(true);
                } else {
                    updateScreen(Mode.UnlockScreen, false);
                }
            }

            public void forgotPattern(boolean isForgotten) {
                if (mEnableFallback) {
                    mForgotPattern = isForgotten;
                    updateScreen(Mode.UnlockScreen, false);
                }
            }

            public boolean isSecure() {
                return LockPatternKeyguardView.this.isSecure();
            }

            public boolean isVerifyUnlockOnly() {
                return mIsVerifyUnlockOnly;
            }

            public void recreateMe(Configuration config) {
                removeCallbacks(mRecreateRunnable);
                post(mRecreateRunnable);
            }

            public void takeEmergencyCallAction() {
                mHasOverlay = true;

                // Continue showing FaceLock area until dialer comes up or 
call is resumed

                if (mLockPatternUtils.usingBiometricWeak() &&
                        mLockPatternUtils.isBiometricWeakInstalled() && 
mFaceLockServiceRunning) {

                    showFaceLockAreaWithTimeout(
FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);

                }

                // FaceLock must be stopped if it is running
                stopAndUnbindFromFaceLock();

                pokeWakelock(EMERGENCY_CALL_TIMEOUT);
                if (TelephonyManager.getDefault().getCallState()
                        == TelephonyManager.CALL_STATE_OFFHOOK) {
                    mLockPatternUtils.resumeCall();
                } else {
                    Intent intent = new Intent(ACTION_EMERGENCY_DIAL);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                    getContext().startActivity(intent);
                }
            }

            public void pokeWakelock() {
                getCallback().pokeWakelock();
            }

            public void pokeWakelock(int millis) {
                getCallback().pokeWakelock(millis);
            }

            public void keyguardDone(boolean authenticated) {
                getCallback().keyguardDone(authenticated);
                mSavedState = null; // clear state so we re-establish when 
locked again

            }

            public void keyguardDoneDrawing() {
                // irrelevant to keyguard screen, they shouldn't be calling 
this

            }

            public void reportFailedUnlockAttempt() {
                mUpdateMonitor.reportFailedAttempt();
                final int failedAttempts = mUpdateMonitor.getFailedAttempts();
                if (DEBUG) Xlog.d(TAG, "reportFailedPatternAttempt: #" + 
failedAttempts +

                    " (enableFallback=" + mEnableFallback + ")");

                final boolean usingPattern = mLockPatternUtils.
getKeyguardStoredPasswordQuality()

                        == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;

                final int failedAttemptsBeforeWipe = mLockPatternUtils.
getDevicePolicyManager()

                        .getMaximumFailedPasswordsForWipe(null);

                final int failedAttemptWarning = LockPatternUtils.
FAILED_ATTEMPTS_BEFORE_RESET

                        - LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT;

                final int remainingBeforeWipe = failedAttemptsBeforeWipe > 0 ?
                        (failedAttemptsBeforeWipe - failedAttempts)
                        : Integer.MAX_VALUE; // because DPM returns 0 if no 
restriction


                if (remainingBeforeWipe < LockPatternUtils.
FAILED_ATTEMPTS_BEFORE_WIPE_GRACE) {

                    // If we reach this code, it means the user has installed 
a DevicePolicyManager

                    // that requests device wipe after N attempts.  Once we 
get below the grace

                    // period, we'll post this dialog every time as a clear 
warning until the

                    // bombshell hits and the device is wiped.
                    if (remainingBeforeWipe > 0) {
                        showAlmostAtWipeDialog(failedAttempts, 
remainingBeforeWipe);

                    } else {
                        // Too many attempts. The device will be wiped shortly.
                        Slog.i(TAG, "Too many unlock attempts; device will be 
wiped!");

                        showWipeDialog(failedAttempts);
                    }
                } else {
                    boolean showTimeout =
                        (failedAttempts % LockPatternUtils.
FAILED_ATTEMPTS_BEFORE_TIMEOUT) == 0;

                    if (usingPattern && mEnableFallback) {
                        if (failedAttempts == failedAttemptWarning) {
                            showAlmostAtAccountLoginDialog();
                            showTimeout = false; // don't show both dialogs
                        } else if (failedAttempts >= LockPatternUtils.
FAILED_ATTEMPTS_BEFORE_RESET) {

                            mLockPatternUtils.setPermanentlyLocked(true);
                            updateScreen(mMode, false);
                            // don't show timeout dialog because we show 
account unlock screen next

                            showTimeout = false;
                        }
                    }
                    if (showTimeout) {
                        showTimeoutDialog();
                    }
                }
                mLockPatternUtils.reportFailedPasswordAttempt();
            }

            public boolean doesFallbackUnlockScreenExist() {
                return mEnableFallback;
            }

            public void reportSuccessfulUnlockAttempt() {
                mFailedFaceUnlockAttempts = 0;
                mLockPatternUtils.reportSuccessfulPasswordAttempt();
            }
        };

        /**
         * We'll get key events the current screen doesn't use. see
         * {@link KeyguardViewBase#onKeyDown(int, android.view.KeyEvent)}
         */
        setFocusableInTouchMode(true);
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);

        updateScreen(getInitialMode(), false);
        maybeEnableFallback(context);
    }

10.updateScreen,根据当前锁屏模式,更新显示相应的锁屏界面,

private void updateScreen(Mode mode, boolean force) {

        Log.v(TAG, "**** UPDATE SCREEN: mode=" + mode
                + " last mode=" + mMode + ", force = " + force);

        mMode = mode;

        // Re-create the lock screen if necessary
        if (mode == Mode.LockScreen || mShowLockBeforeUnlock) {
            if (force || mLockScreen == null) {
                recreateLockScreen();
            }
        }

        // Re-create the unlock screen if necessary. This is primarily 
required to properly handle

        // SIM state changes. This typically happens when this method is 
called by reset()

        if (mode == Mode.UnlockScreen) {
            final UnlockMode unlockMode = getUnlockMode();
            if (force || mUnlockScreen == null || unlockMode != 
mUnlockScreenMode) {

                recreateUnlockScreen(unlockMode);
            }
        }

        // visibleScreen should never be null
        final View goneScreen = (mode == Mode.LockScreen) ? mUnlockScreen : 
mLockScreen;

        final View visibleScreen = (mode == Mode.LockScreen) ? mLockScreen : 
mUnlockScreen;


        // do this before changing visibility so focus isn't requested before 
the input

        // flag is set
        mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).
needsInput());


        if (DEBUG_CONFIGURATION) {
            Xlog.v(TAG, "Gone=" + goneScreen);
            Xlog.v(TAG, "Visible=" + visibleScreen);
        }

        if (mScreenOn) {
            if (goneScreen != null && goneScreen.getVisibility() == View.
VISIBLE) {

                ((KeyguardScreen) goneScreen).onPause();
            }
            if (visibleScreen.getVisibility() != View.VISIBLE) {
                ((KeyguardScreen) visibleScreen).onResume();
            }
        }

        if (goneScreen != null) {
            goneScreen.setVisibility(View.GONE);
        }
        visibleScreen.setVisibility(View.VISIBLE);
        requestLayout();

        if (!visibleScreen.requestFocus()) {
            throw new IllegalStateException("keyguard screen must be able to 
take "

                    + "focus when shown " + visibleScreen.getClass().
getCanonicalName());

        }
    }


11.recreateLockScreen(),创建锁屏 

 

  private void recreateLockScreen() {
        Log.i(TAG, "recreateLockScreen");
        if (mLockScreen != null) {
            ((KeyguardScreen) mLockScreen).onPause();
            ((KeyguardScreen) mLockScreen).cleanUp();
            removeView(mLockScreen);
        }
        mLockScreen = createLockScreen();
        mLockScreen.setVisibility(View.INVISIBLE);
        addView(mLockScreen);
    }
















   

你可能感兴趣的:(android锁屏创建流程)