Android6.0 keyguard lock screen loading process analysis

The loading of the lock screen interface is usually triggered in two ways in android: after the android system is turned on and screenOff (screen off), then screenOn;

First look

The lock screen loading process when the android system is turned on :
First, during the system startup process, it will enter the startOtherServices() method of SystemServer.java:

Initialize WindowManagerService;

wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
Call the systemReady() method to indicate that the system is ready to start;

try {
            wm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
Call the systemReady() method of WindowManagerPolicy.java
public void systemReady() {
        mPolicy.systemReady();
    }
And this mPolicy is constructed by the construction method of PhoneWindowManager.java;

final WindowManagerPolicy mPolicy = new PhoneWindowManager();
That is to say, the systemReady() method of PhoneWindowManager.java will eventually be called, the KeyguardServiceDelegate object is initialized in this method and the systemReady() method is called;

 mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
 mKeyguardDelegate.onSystemReady();
In the KeyguardServiceDelegate.java class, continue to call the systemReady() method of KeyguardServiceWrapper.java;

public void onSystemReady() {
        if (mKeyguardService != null) {
            mKeyguardService.onSystemReady();
        } else {
            mKeyguardState.systemIsReady = true;
        }
    }
Use aidl to call the onSystemReady() method of KeyguardService.java in KeyguardServiceWrapper.java;

    @Override // Binder interface
    public void onSystemReady() {
        try {
            mService.onSystemReady();
        } catch (RemoteException e) {
            Slog.w(TAG , "Remote Exception", e);
        }
    }
Call the onSystemReady() method of KeyguardViewMediator.java in KeyguardService.java;
        @Override // Binder interface
        public void onSystemReady() {
            checkPermission();
            mKeyguardViewMediator.onSystemReady();
        }

Finally, doKeyguardLocked() is called in the onSystemReady() method of KeyguardViewMediator.java to start the lock screen loading process;

    /**
     * Let us know that the system is ready after startup.
     */
    public void onSystemReady() {
        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
        synchronized (this) {
            if (DEBUG) Log.d(TAG, "onSystemReady");
            mSystemReady = true;
            doKeyguardLocked(null);
            mUpdateMonitor.registerCallback(mUpdateCallback);
        }
        // Most services aren't available until the system reaches the ready state, so we
        // send it here when the device first boots.
        maybeSendUserPresentBroadcast();
    }
The doKeyguardLocked() method of KeyguardViewMediator.java;

    /**
     * Enable the keyguard if the settings are appropriate.
     */
    private void doKeyguardLocked(Bundle options) {
        // if another app is disabling us, don't show
        if (!mExternallyEnabled) {
            return;
        }

        // if the keyguard is already showing, don't bother
        if (mStatusBarKeyguardViewManager.isShowing()) {
            resetStateLocked();
            return;
        }

        // if the setup wizard hasn't run yet, don't show
        final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false);
        final boolean absent = SubscriptionManager.isValidSubscriptionId(
                mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.ABSENT));
        final boolean disabled = SubscriptionManager.isValidSubscriptionId(
                mUpdateMonitor.getNextSubIdForState(IccCardConstants.State.PERM_DISABLED));
        final boolean lockedOrMissing = mUpdateMonitor.isSimPinSecure()
                || ((absent || disabled) && requireSim);

        if (!lockedOrMissing && shouldWaitForProvisioning()) {
            return;
        }

        if (mLockPatternUtils.isLockScreenDisabled(KeyguardUpdateMonitor.getCurrentUser())
                && !lockedOrMissing) {
            return;
        }

        if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
            // Without this, settings is not enabled until the lock screen first appears
            setShowingLocked(false);
            hideLocked();
            mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
            return;
        }
        showLocked(options);
    }
1. mExternallyEnabled; the default is true, if the keyguard is not displayed in other applications, return will not be displayed directly;
2. If the keyguard is currently displayed, just ignore it and reset;
3. If the installation wizard is not completed, the device is not displayed After completing initial binding and other operations, do not display the keyguard;
4. If the current screen is off, do not display the keyguard;
5. Without this, settings is not enabled until the lock screen first appears (I have no comparison here Good saying);
6. If the above conditions are not met, use the showLocked() method to start displaying the keyguard.


Send a message that msg is SHOW, and start to display keyguard;

    /**
     * Send message to keyguard telling it to show itself
     * @see #handleShow
     */
    private 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);
    }
Call the handleShow() method;

case SHOW:
    handleShow((Bundle) msg.obj);
    break;
Call the show() method of StatusBarKeyguardViewManager.java in the handleShow() method;

    /**
     * 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");
            }

            setShowingLocked(true);
            mStatusBarKeyguardViewManager.show(options);
            mHiding = false;
            mWakeAndUnlocking = false;
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            updateActivityLockScreenState();
            adjustStatusBarLocked();
            userActivity();

            mShowKeyguardWakeLock.release();
        }
        mKeyguardDisplayManager.show();
    }
Called into the show() method of StatusBarKeyguardViewManager.java

    public void show(Bundle options) {
        mShowing = true;
        mStatusBarWindowManager.setKeyguardShowing(true);
        mScrimController.abortKeyguardFadingOut();
        reset();
    }
StatusBarKeyguardViewManager.java is responsible for creating, displaying, hiding, and resetting the status bar of the keyguard in the status bar.
StatusBarWindowManager.java is responsible for the logical management of all status bar window
states1. The setKeyguardShowing() method of StatusBarKeyguardViewManager.java uses the apply() method to refresh the flag of mStatusBarView parameter;
    public void setKeyguardShowing(boolean showing) {
        mCurrentState.keyguardShowing = showing;
        apply(mCurrentState);
    }
2. Call the reset() method to reset the state of mStatusBarView, first look at the reset() method;

    /**
     * Reset the state of the view.
     */
    public void reset() {
        if (mShowing) {
            if (mOccluded) {
                mPhoneStatusBar.hideKeyguard();
                mPhoneStatusBar.stopWaitingForKeyguardExit();
                mBouncer.hide(false /* destroyView */);
            } else {
                showBouncerOrKeyguard();
            }
            KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
            updateStates();
        }
    }
In the reset() method, it will be judged whether the keyguard is interrupted by other windows mOccluded, if it is, the keyguard will not be displayed; otherwise, the showBouncerOrKeyguard() method will be executed; the
showBouncerOrKeyguard() method will use the needsFullscreenBouncer() method of KeyguardBouncer.java to determine the display of regular locks The screen is still Bouncer security lock screen (such as pattern lock screen, password lock screen, PIN code lock screen, etc.);

    /**
     * Shows the notification keyguard or the bouncer depending on
     * {@link KeyguardBouncer#needsFullscreenBouncer()}.
     */
    private 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();
        }
    }
1. The conventional lock screen is the sliding lock screen interface, which is generally unlocked by sliding, called the notification keyguard; this type of keyguard has been integrated with the statusbar and can be directly controlled by the object of PhoneStatusBar.java;
2. Bouncer Security lock screen; lock screen interface such as password, pattern, PIM code, PUK code, etc., start to control show() and hide() through KeyguardBouncer.java;
KeyguardBouncer.java的show()方法:
    public void show(boolean resetSecuritySelection) {
        ensureView();
        if (resetSecuritySelection) {
            // showPrimarySecurityScreen() updates the current security method. This is needed in
            // case we are already showing and the current security method changed.
            mKeyguardView.showPrimarySecurityScreen();
        }
        if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
            return;
        }

        // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
        // Keyguard. If we need to authenticate, show the bouncer.
        if (!mKeyguardView.dismiss()) {
            mShowingSoon = true;

            // Split up the work over multiple frames.
            DejankUtils.postAfterTraversal(mShowRunnable);
        }
    }
1. First call the ensureView() method to load the keyguard_bouncer view

    private void ensureView() {
        if (mRoot == null) {
            inflateView();
        }
    }

    private void inflateView() {
        removeView();
        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
        mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mCallback);
        mContainer.addView(mRoot, mContainer.getChildCount());
        mRoot.setVisibility(View.INVISIBLE);
        mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
    }
2. Call the showPrimarySecurityScreen() method of KeyguardHostView.java;

    /**
     * Called when the view needs to be shown.
     */
    public void showPrimarySecurityScreen() {
        if (DEBUG) Log.d(TAG, "show()");
        mSecurityContainer.showPrimarySecurityScreen(false);
    }
Continue to call the showPrimarySecurityScreen() method of KeyguardSecurityContainer.java to get the lock screen method first;

    /**
     * Shows the primary security screen for the user. This will be either the multi-selector
     * or the user's security method.
     * @param turningOff true if the device is being turned off
     */
    void showPrimarySecurityScreen(boolean turningOff) {
        SecurityMode securityMode = mSecurityModel.getSecurityMode();
        if (DEBUG) Log.v(TAG, "showPrimarySecurityScreen(turningOff=" + turningOff + ")");
        showSecurityScreen(securityMode);
    }
Continue to call the showSecurityScreen() method with the acquired lock screen securityMode as a parameter; this method is mainly used to display the lock screen view according to the securityMode.
    /**
     * Switches to the given security view unless it's already being shown, in which case
     * this is a no-op.
     *
     * @param securityMode
     */
    private void showSecurityScreen(SecurityMode securityMode) {
        if (DEBUG) Log.d(TAG, "showSecurityScreen(" + securityMode + ")");

        if (securityMode == mCurrentSecuritySelection) return;

        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) {
            newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
            newView.setKeyguardCallback(mCallback);
        }

        // 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;
        mSecurityCallback.onSecurityModeChanged(securityMode,
                securityMode != SecurityMode.None && newView.needsInput());
    }
1. First determine whether the incoming securityMode has been displayed;
2. Call the getSecurityView() method to obtain the given lock screen view;
3. Call the onPause() method of KeyguardSecurityView.java to pause the display of the old lock screen view, onResume() The method starts to display the new lock screen view; KeyguardSecurityView.java is an interface class, and its internal methods are abstract except that the declaration is not implemented, and the method implementations are all in the class inherited from this interface.
In the keyguard, KeyguardAbsKeyInputView.java, KeyguardPasswordView.java, KeyguardPatternView.java, etc. These classes inherit from this interface to implement its internal methods. These classes are the specific lock screen interface view display;


The summary of the keyguard displayed at boot:
1. Call doKeyguardLocked() in the onSystemReady() method of KeyguardViewMediator.java to start the lock screen loading process;
2. setKeyguardEnabled(); other applications or services can call the setKeyguardEnabled() method to request the lock screen;
3. KeyguardViewMediator.java plays the main scheduling role in keyguard, and is mainly responsible for
1) Query the lock screen status, whether it is currently locked or unlocked; in the locked screen state, input events will be restricted.
2) PhoneWindowManager.java enables KeyguardViewMediator.java through the mKeyguardDelegate object (KeyguardServiceDelegate.java), and calls its methods;
3) Respond to the SIM card status change and make corresponding adjustments to the lock screen interface onSimStateChanged();
4. Determine whether the keyguard is Is prohibited, whether the keyguard is currently being displayed, etc. That is, whether the keguard can be displayed currently, if it can be displayed, continue to call the showLocked() method;
5. Call the handleShow() method, and call the show() of StatusBarKeyguardViewManager.java to start displaying the keyguard lock screen interface;
6. Call the reset() method and call the showBouncerOrKeyguard() method to determine whether to display the normal lock screen interface or the security lock screen interface; if the normal lock screen is displayed, directly call the showKeyguard() or hideKeyguard() method of PhoneStatusBar.java; if the security lock is displayed The screen interface is transferred into the KeyguardBouncer.java class;
7.Call the show() method of KeyguardBouncer.java; use the ensureView() method to load the instantiation layout; call the showPrimarySecurityScreen() method of KeyguardHostView.java to display the security lock screen interface ;
8. The showPrimarySecurityScreen() method of KeyguardHostView.java will be transferred to the showPrimarySecurityScreen() method of KeyguardSecurityContainer.java;
9. Call the showSecurityScreen() method to load different lock screen views according to the lock screen method;
10. KeyguardSecurityView. Java is an interface class, and its internal methods are abstract except that the declaration is not implemented, and the method implementations are all in the class inherited from this interface.
In the keyguard, KeyguardAbsKeyInputView.java, KeyguardPasswordView.java, KeyguardPatternView.java, etc. Keyguard*View.java inherit from this interface to implement its internal methods. These classes are the specific lock screen interface view display; the system turns


off the screen. The keguard loading process after off:
The automatic screen-off process in the android system may be a little different from the screen-off process after the Power button, but since the main analysis is to load the keyguard after the screen is off, you only need to care about the loading process of the keguard after the system is off.
Here is an example of pressing the power button to turn off the screen to analyze the process:
when the Power button is pressed in the on-screen state, after a series of judgments, the mPowerManager.goToSleep() method will be called, that is, the gotoSleep of PowerManagerService.java will be called through aidl. ()method:

        @Override // Binder call
        public void goToSleep(long eventTime, int reason, int flags) {
            if (eventTime > SystemClock.uptimeMillis()) {
                throw new IllegalArgumentException("event time must not be in the future");
            }

            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);

            final int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
                goToSleepInternal(eventTime, reason, flags, uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
Continue to call the goToSleepInternal() method:

    private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
        synchronized (mLock) {
            if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
                updatePowerStateLocked();
            }
        }
    }
Call the updatePowerStateLocked() method, and then call the finishWakefulnessChangeIfNeededLocked() method in this method

    private void finishWakefulnessChangeIfNeededLocked() {
        if (mWakefulnessChanging && mDisplayReady) {
            if (mWakefulness == WAKEFULNESS_DOZING
                    && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
                return; // wait until dream has enabled dozing
            }
            mWakefulnessChanging = false;
            mNotifier.onWakefulnessChangeFinished();
        }
    }
At this time, call the onWakefulnessChangeFinished() method of Notifier.java:

    /**
     * Notifies that the device has finished changing wakefulness.
     */
    public void onWakefulnessChangeFinished() {
        if (DEBUG) {
            Slog.d(TAG, "onWakefulnessChangeFinished");
        }

        if (mInteractiveChanging) {
            mInteractiveChanging = false;
            handleLateInteractiveChange();
        }
    }
Call the handleLateInteractiveChange() method;

    /**
     * Handle late interactive state changes once they are finished so that the system can
     * finish pending transitions (such as turning the screen off) before causing
     * applications to change state visibly.
     */
    private void handleLateInteractiveChange() {
        synchronized (mLock) {
            if (mInteractive) {
                // Finished waking up...
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mPolicy.finishedWakingUp();
                    }
                });
            } else {
                // Finished going to sleep...
                // This is a good time to make transitions that we don't want the user to see,
                // such as bringing the key guard to focus.  There's no guarantee for this
                // however because the user could turn the device on again at any time.
                // Some things may need to be protected by other mechanisms that defer screen on.

                // Cancel pending user activity.
                if (mUserActivityPending) {
                    mUserActivityPending = false;
                    mHandler.removeMessages(MSG_USER_ACTIVITY);
                }

                // Tell the policy we finished going to sleep.
                final int why = translateOffReason(mInteractiveChangeReason);
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
                        mPolicy.finishedGoingToSleep(why);
                    }
                });

                // Send non-interactive broadcast.
                mPendingInteractiveState = INTERACTIVE_STATE_ASLEEP;
                mPendingGoToSleepBroadcast = true;
                updatePendingBroadcastLocked();
            }
        }
    }
There are two sentences that need to be paid attention to in this method: mPolicy.finishedWakingUp() and mPolicy.finishedGoingToSleep(); look at the comments and find that one is waking up and the other is sleep operation. Since the power is off the screen, it needs to be viewed as mPolicy. .finishedGoingToSleep() method. And mPolicy is the object of WindowManagerPolicy.java, this class is also an interface class, the interface implementation is in PhoneWindowManager.java class, so at this time transferred to the finishedGoingToSleep() method of PhoneWindowManager.java;

    // Called on the PowerManager's Notifier thread.
    @Override
    public void finishedGoingToSleep(int why) {
        EventLog.writeEvent(70000, 0);
        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")");
        MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000);

        // We must get this work done here because the power manager will drop
        // the wake lock and let the system suspend once this function returns.
        synchronized (mLock) {
            mAwake = false;
            updateWakeGestureListenerLp();
            updateOrientationListenerLp();
            updateLockScreenTimeout();
        }
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onFinishedGoingToSleep(why);
        }
    }
Analyze this method to see this sentence:

mKeyguardDelegate.onFinishedGoingToSleep(why);
That is to say, the onFinishedGoingToSleep() method of KeyguardServiceDelegate.java will be called; and in the above analysis process, it is known that PhoneWindowManager.java enables KeyguardViewMediator.java through the mKeyguardDelegate object (KeyguardServiceDelegate.java), and calls its methods; that is to say, through At this time, the logic of this sentence has been transferred to the onFinishedGoingToSleep() method of the KeyguardViewMediator.java class.

    public void onFinishedGoingToSleep(int why) {
        if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")");
        synchronized (this) {
            mDeviceInteractive = false;
            mGoingToSleep = false;

            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;

            notifyFinishedGoingToSleep();

            if (mPendingReset) {
                resetStateLocked();
                mPendingReset = false;
            }
            if (mPendingLock) {
                doKeyguardLocked(null);
                mPendingLock = false;
            }
        }
        KeyguardUpdateMonitor.getInstance(mContext).dispatchFinishedGoingToSleep(why);
    }

In this method, call the notifyFinishedGoingToSleep() method to send a message with msg as NOTIFY_FINISHED_GOING_TO_SLEEP to mHandler;

    private void notifyFinishedGoingToSleep() {
        if (DEBUG) Log.d(TAG, "notifyFinishedGoingToSleep");
        mHandler.sendEmptyMessage(NOTIFY_FINISHED_GOING_TO_SLEEP);
    }
After mHandler receives this message, it calls the handleNotifyFinishedGoingToSleep() method;

case NOTIFY_FINISHED_GOING_TO_SLEEP:
    handleNotifyFinishedGoingToSleep();
    break;
In this method, call the onFinishedGoingToSleep() method of StatusBarKeyguardViewManager.java;

    private void handleNotifyFinishedGoingToSleep() {
        synchronized (KeyguardViewMediator.this) {
            if (DEBUG) Log.d(TAG, "handleNotifyFinishedGoingToSleep");
            mStatusBarKeyguardViewManager.onFinishedGoingToSleep();
        }
    }
Let's look at the onFinishedGoingToSleep() method of StatusBarKeyguardViewManager.java:
    public void onFinishedGoingToSleep() {
        mDeviceInteractive = false;
        mPhoneStatusBar.onFinishedGoingToSleep();
        mBouncer.onScreenTurnedOff();
    }
1. Call onFinishedGoingToSleep() of PhoneStatusBar.java to notify PhoneStatusBar to update the current status;
2. Enter the onScreenTurnedOff() method of KeyguardBouncer.java to actually start the loading of keyguard;


Next, look at the onScreenTurnedOff() method of KeyguardBouncer.java:

    public void onScreenTurnedOff() {
        if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
            mKeyguardView.onPause();
        }
    }
Call the onPause() method of KeyguardHostView.java:
    /**
     * Called when the Keyguard is not actively shown anymore on the screen.
     */
    public void onPause() {
        if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
                Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
        mSecurityContainer.showPrimarySecurityScreen(true);
        mSecurityContainer.onPause();
        clearFocus();
    }
Continue to call the showPrimarySecurityScreen() method of KeyguardSecurityContainer.java. According to the above analysis, we know that we will first get the current lock screen method, and then load the lock screen interface according to the obtained lock screen method;
this completes the keyguard in the screen off state Loading process analysis;


Summary of the keyguard process when the screen is turned off normally:
1. Whether it is pressing the Power button or automatically turning off the screen, it will execute to the gotoSleep() method of PowerManagerService.java;
2. In this method, it is transferred to PhoneWindowManager.java through a series of calls.
FinishedGoingToSleep () method; 3. In the PhoneWindowManager.java class, enable KeyguardViewMediator.java through the object mKeyguardDelegate of the KeyguardServiceDelegate.java class;
4. And KeyguardViewMediator.java as the scheduler of the keyguard, start the loading of the keyguard from here;
5. Finally, load the lock screen interface according to the lock screen method in the showPrimarySecurityScreen() method of KeyguardSecurityContainer.java;


























Guess you like

Origin blog.csdn.net/Otaku_627/article/details/53769473