上滑解锁流程 - 安卓R

当用户在锁屏界面上滑时,在frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java中的onTrackingStopped方法被调用:

    public void onTrackingStopped(boolean expand) {
        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
            if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
                mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
            }
        }
    }

调用了frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java的showBouncer方法:

    /**
     * Shows the keyguard bouncer - the password challenge on the lock screen
     *
     * @param scrimmed true when the bouncer should show scrimmed, false when the user will be
     * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
     */
    public void showBouncer(boolean scrimmed) {
        if (mShowing && !mBouncer.isShowing()) {
            mBouncer.show(false /* resetSecuritySelection */, scrimmed);
        }
        updateStates();
    }

又调用了frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java的show方法:

    /**
     * Shows the bouncer.
     *
     * @param resetSecuritySelection Cleans keyguard view
     * @param isScrimmed true when the bouncer show show scrimmed, false when the user will be
     *                 dragging it and translation should be deferred.
     */
    public void show(boolean resetSecuritySelection, boolean isScrimmed) {
        final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
        if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
            // In split system user mode, we never unlock system user.
            return;
        }
        ensureView();
        mIsScrimmed = isScrimmed;

        // On the keyguard, we want to show the bouncer when the user drags up, but it's
        // not correct to end the falsing session. We still need to verify if those touches
        // are valid.
        // Later, at the end of the animation, when the bouncer is at the top of the screen,
        // onFullyShown() will be called and FalsingManager will stop recording touches.
        if (isScrimmed) {
            setExpansion(EXPANSION_VISIBLE);
        }

        if (resetSecuritySelection) {
            // showPrimarySecurityScreen() updates the current security method. This is needed in
            // case we are already showing and the current security method changed.
            showPrimarySecurityScreen();
        }

        if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
            return;
        }

        final int activeUserId = KeyguardUpdateMonitor.getCurrentUser();
        final boolean isSystemUser =
                UserManager.isSplitSystemUser() && activeUserId == UserHandle.USER_SYSTEM;
        final boolean allowDismissKeyguard = !isSystemUser && activeUserId == keyguardUserId;

        // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is
        // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer.
        if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) {
            return;
        }

        // This condition may indicate an error on Android, so log it.
        if (!allowDismissKeyguard) {
            Log.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
        }

        mShowingSoon = true;

        // Split up the work over multiple frames.
        DejankUtils.removeCallbacks(mResetRunnable);
        if (mKeyguardStateController.isFaceAuthEnabled() && !needsFullscreenBouncer()
                && !mKeyguardUpdateMonitor.userNeedsStrongAuth()
                && !mKeyguardBypassController.getBypassEnabled()) {
            mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
        } else {
            DejankUtils.postAfterTraversal(mShowRunnable);
        }

        mCallback.onBouncerVisiblityChanged(true /* shown */);
        mExpansionCallback.onStartingToShow();
    }

如果用户成功解锁或者没有设置锁屏密码,都会调用frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java的dismiss方法:

    /**
     * Dismisses the keyguard by going to the next screen or making it gone.
     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
     * @return True if the keyguard is done.
     */
    public boolean dismiss(int targetUserId) {
        return dismiss(false, targetUserId, false);
    }

    @Override
    public boolean dismiss(boolean authenticated, int targetUserId,
            boolean bypassSecondaryLockScreen) {
        return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId,
                bypassSecondaryLockScreen);
    }

又调用了frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java的showNextSecurityScreenOrFinish方法:

    /**
     * Shows the next security screen if there is one.
     * @param authenticated true if the user entered the correct authentication
     * @param targetUserId a user that needs to be the foreground user at the finish (if called)
     *     completion.
     * @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
     *     secondary lock screen requirement, if any.
     * @return true if keyguard is done
     */
    boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
            boolean bypassSecondaryLockScreen) {
        if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
        boolean finish = false;
        boolean strongAuth = false;
        int eventSubtype = -1;
        BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;
        if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
            finish = true;
            eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;
        } else if (mUpdateMonitor.getUserUnlockedWithBiometric(targetUserId)) {
            finish = true;
            eventSubtype = BOUNCER_DISMISS_BIOMETRIC;
            uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;
        } else if (SecurityMode.None == mCurrentSecuritySelection) {
            SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
            if (SecurityMode.None == securityMode) {
                finish = true; // no security required
                eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
                uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;
            } else {
                showSecurityScreen(securityMode); // switch to the alternate security view
            }
        } else if (authenticated) {
            switch (mCurrentSecuritySelection) {
                case Pattern:
                case Password:
                case PIN:
                    strongAuth = true;
                    finish = true;
                    eventSubtype = BOUNCER_DISMISS_PASSWORD;
                    uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;
                    break;

                case SimPin:
                case SimPuk:
                    // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
                    SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
                    if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
                            KeyguardUpdateMonitor.getCurrentUser())) {
                        finish = true;
                        eventSubtype = BOUNCER_DISMISS_SIM;
                        uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;
                    } else {
                        showSecurityScreen(securityMode);
                    }
                    break;

                default:
                    Log.v(TAG, "Bad security screen " + mCurrentSecuritySelection + ", fail safe");
                    showPrimarySecurityScreen(false);
                    break;
            }
        }
        // Check for device admin specified additional security measures.
        if (finish && !bypassSecondaryLockScreen) {
            Intent secondaryLockscreenIntent =
                    mUpdateMonitor.getSecondaryLockscreenRequirement(targetUserId);
            if (secondaryLockscreenIntent != null) {
                mSecondaryLockScreenController.show(secondaryLockscreenIntent);
                return false;
            }
        }
        if (eventSubtype != -1) {
            mMetricsLogger.write(new LogMaker(MetricsEvent.BOUNCER)
                    .setType(MetricsEvent.TYPE_DISMISS).setSubtype(eventSubtype));
        }
        if (uiEvent != BouncerUiEvent.UNKNOWN) {
            sUiEventLogger.log(uiEvent);
        }
        if (finish) {
            mSecurityCallback.finish(strongAuth, targetUserId);
        }
        return finish;
    }

解锁成功会调用frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java的finish方法:

    /**
     * Authentication has happened and it's time to dismiss keyguard. This function
     * should clean up and inform KeyguardViewMediator.
     *
     * @param strongAuth whether the user has authenticated with strong authentication like
     *                   pattern, password or PIN but not by trust agents or fingerprint
     * @param targetUserId a user that needs to be the foreground user at the dismissal completion.
     */
    @Override
    public void finish(boolean strongAuth, int targetUserId) {
        // If there's a pending runnable because the user interacted with a widget
        // and we're leaving keyguard, then run it.
        boolean deferKeyguardDone = false;
        if (mDismissAction != null) {
            deferKeyguardDone = mDismissAction.onDismiss();
            mDismissAction = null;
            mCancelAction = null;
        }
        if (mViewMediatorCallback != null) {
            if (deferKeyguardDone) {
                mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId);
            } else {
                mViewMediatorCallback.keyguardDone(strongAuth, targetUserId);
            }
        }
    }

调用了frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java的成员变量mViewMediatorCallback的keyguardDone方法:

    ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
		......
        @Override
        public void keyguardDone(boolean strongAuth, int targetUserId) {
            if (targetUserId != ActivityManager.getCurrentUser()) {
                return;
            }
            if (DEBUG) Log.d(TAG, "keyguardDone");
            tryKeyguardDone();
        }
		......
	}

调用了KeyguardViewMediator的tryKeyguardDone方法:

    private void tryKeyguardDone() {
        if (DEBUG) {
            Log.d(TAG, "tryKeyguardDone: pending - " + mKeyguardDonePending + ", animRan - "
                    + mHideAnimationRun + " animRunning - " + mHideAnimationRunning);
        }
        if (!mKeyguardDonePending && mHideAnimationRun && !mHideAnimationRunning) {
            handleKeyguardDone();
        } else if (!mHideAnimationRun) {
            if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation");
            mHideAnimationRun = true;
            mHideAnimationRunning = true;
            mKeyguardViewControllerLazy.get()
                    .startPreHideAnimation(mHideAnimationFinishedRunnable);
        }
    }

又调用了KeyguardViewMediator的handleKeyguardDone方法:

    /**
     * @see #keyguardDone
     * @see #KEYGUARD_DONE
     */
    private void handleKeyguardDone() {
        Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
        final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
        mUiBgExecutor.execute(() -> {
            if (mLockPatternUtils.isSecure(currentUser)) {
                mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
            }
        });
        if (DEBUG) Log.d(TAG, "handleKeyguardDone");
        synchronized (this) {
            resetKeyguardDonePendingLocked();
        }


        if (mGoingToSleep) {
            mUpdateMonitor.clearBiometricRecognized();
            Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
            return;
        }
        if (mExitSecureCallback != null) {
            try {
                mExitSecureCallback.onKeyguardExitResult(true /* authenciated */);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to call onKeyguardExitResult()", e);
            }

            mExitSecureCallback = null;

            // after succesfully exiting securely, no need to reshow
            // the keyguard when they've released the lock
            mExternallyEnabled = true;
            mNeedToReshowWhenReenabled = false;
            updateInputRestricted();
        }

        handleHide();
        mUpdateMonitor.clearBiometricRecognized();
        Trace.endSection();
    }

调用了KeyguardViewMediator的handleHide方法:

    /**
     * Handle message sent by {@link #hideLocked()}
     * @see #HIDE
     */
    private void handleHide() {
        Trace.beginSection("KeyguardViewMediator#handleHide");

        // It's possible that the device was unlocked in a dream state. It's time to wake up.
        if (mAodShowing) {
            PowerManager pm = mContext.getSystemService(PowerManager.class);
            pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                    "com.android.systemui:BOUNCER_DOZING");
        }

        synchronized (KeyguardViewMediator.this) {
            if (DEBUG) Log.d(TAG, "handleHide");

            if (mustNotUnlockCurrentUser()) {
                // In split system user mode, we never unlock system user. The end user has to
                // switch to another user.
                // TODO: We should stop it early by disabling the swipe up flow. Right now swipe up
                // still completes and makes the screen blank.
                if (DEBUG) Log.d(TAG, "Split system user, quit unlocking.");
                return;
            }
            mHiding = true;

            if (mShowing && !mOccluded) {
                mKeyguardGoingAwayRunnable.run();
            } else {
                handleStartKeyguardExitAnimation(
                        SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
                        mHideAnimation.getDuration());
            }
        }
        Trace.endSection();
    }

调用了KeyguardViewMediator的成员变量mKeyguardGoingAwayRunnable的run方法:

    private final Runnable mKeyguardGoingAwayRunnable = new Runnable() {
        @Override
        public void run() {
            Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
            if (DEBUG) Log.d(TAG, "keyguardGoingAway");
            mKeyguardViewControllerLazy.get().keyguardGoingAway();

            int flags = 0;
            if (mKeyguardViewControllerLazy.get().shouldDisableWindowAnimationsForUnlock()
                    || (mWakeAndUnlocking && !mPulsing)) {
                flags |= WindowManagerPolicyConstants
                        .KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
            }
            if (mKeyguardViewControllerLazy.get().isGoingToNotificationShade()
                    || (mWakeAndUnlocking && mPulsing)) {
                flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
            }
            if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
                flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
            }
            if (mKeyguardViewControllerLazy.get().shouldSubtleWindowAnimationsForUnlock()) {
                flags |= WindowManagerPolicyConstants
                        .KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
            }

            mUpdateMonitor.setKeyguardGoingAway(true);
            mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(true);

            // Don't actually hide the Keyguard at the moment, wait for window
            // manager until it tells us it's safe to do so with
            // startKeyguardExitAnimation.
            // Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
            // order.
            final int keyguardFlag = flags;
            mUiBgExecutor.execute(() -> {
                try {
                    ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error while calling WindowManager", e);
                }
            });
            Trace.endSection();
        }
    };

通过binder调用了frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java的keyguardGoingAway方法:

    @Override
    public void keyguardGoingAway(int flags) {
        enforceNotIsolatedCaller("keyguardGoingAway");
        final long token = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
                mKeyguardController.keyguardGoingAway(flags);
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

调用了frameworks/base/services/core/java/com/android/server/wm/KeyguardController.java的keyguardGoingAway方法:

    /**
     * Called when Keyguard is going away.
     *
     * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
     *              etc.
     */
    void keyguardGoingAway(int flags) {
        if (!mKeyguardShowing) {
            return;
        }
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
        mService.deferWindowLayout();
        try {
            setKeyguardGoingAway(true);
            EventLogTags.writeWmSetKeyguardShown(
                    1 /* keyguardShowing */,
                    mAodShowing ? 1 : 0,
                    1 /* keyguardGoingAway */,
                    "keyguardGoingAway");
            mRootWindowContainer.getDefaultDisplay().mDisplayContent
                    .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
                            false /* alwaysKeepCurrent */, convertTransitFlags(flags),
                            false /* forceOverride */);
            updateKeyguardSleepToken();

            // Some stack visibility might change (e.g. docked stack)
            mRootWindowContainer.resumeFocusedStacksTopActivities();
            mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
            mRootWindowContainer.addStartingWindowsForVisibleActivities();
            mWindowManager.executeAppTransition();
        } finally {
            mService.continueWindowLayout();
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

此时会打印event log:“wm_set_keyguard_shown: [1,0,1,keyguardGoingAway]”,其中1,0,1分别表示keyguard正在显示、AOD没有显示、keyguard正在消失。然后调用了mRootWindowContainer的resumeFocusedStacksTopActivities方法要前台app进入resume状态。

在准备解锁流程完成后,经过从systemserver通过binder回调到systemui进程后(此过程比较繁琐就先跳过了),调用了frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java的handleStartKeyguardExitAnimation方法:

    private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
        Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
        if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
                + " fadeoutDuration=" + fadeoutDuration);
        synchronized (KeyguardViewMediator.this) {

            if (!mHiding) {
                // Tell ActivityManager that we canceled the keyguardExitAnimation.
                setShowingLocked(mShowing, true /* force */);
                return;
            }
            mHiding = false;

            if (mWakeAndUnlocking && mDrawnCallback != null) {

                // Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
                // the next draw from here so we don't have to wait for window manager to signal
                // this to our ViewRootImpl.
                mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
                notifyDrawn(mDrawnCallback);
                mDrawnCallback = null;
            }

            // only play "unlock" noises if not on a call (since the incall UI
            // disables the keyguard)
            if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)) {
                playSounds(false);
            }

            setShowingLocked(false);
            mWakeAndUnlocking = false;
            mDismissCallbackRegistry.notifyDismissSucceeded();
            mKeyguardViewControllerLazy.get().hide(startTime, fadeoutDuration);
            resetKeyguardDonePendingLocked();
            mHideAnimationRun = false;
            adjustStatusBarLocked();
            sendUserPresentBroadcast();
        }
        Trace.endSection();
    }

调用了KeyguardViewMediator的setShowingLocked方法:

    private void setShowingLocked(boolean showing) {
        setShowingLocked(showing, false /* forceCallbacks */);
    }

    private void setShowingLocked(boolean showing, boolean forceCallbacks) {
        final boolean aodShowing = mDozing && !mWakeAndUnlocking;
        final boolean notifyDefaultDisplayCallbacks = showing != mShowing
                || aodShowing != mAodShowing || forceCallbacks;
        mShowing = showing;
        mAodShowing = aodShowing;
        if (notifyDefaultDisplayCallbacks) {
            notifyDefaultDisplayCallbacks(showing);
            updateActivityLockScreenState(showing, aodShowing);
        }
    }

调用了KeyguardViewMediator的updateActivityLockScreenState方法:

    private void updateActivityLockScreenState(boolean showing, boolean aodShowing) {
        mUiBgExecutor.execute(() -> {
            if (DEBUG) {
                Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
            }
            try {
                ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing);
            } catch (RemoteException e) {
            }
        });
    }

通过binder调用了frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java的setLockScreenShown方法:

    @Override
    public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing) {
        if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
                != PackageManager.PERMISSION_GRANTED) {
            throw new SecurityException("Requires permission "
                    + android.Manifest.permission.DEVICE_POWER);
        }

        synchronized (mGlobalLock) {
            long ident = Binder.clearCallingIdentity();
            if (mKeyguardShown != keyguardShowing) {
                mKeyguardShown = keyguardShowing;
                final Message msg = PooledLambda.obtainMessage(
                        ActivityManagerInternal::reportCurKeyguardUsageEvent, mAmInternal,
                        keyguardShowing);
                mH.sendMessage(msg);
            }
            try {
                mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        mH.post(() -> {
            for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
                mScreenObservers.get(i).onKeyguardStateChanged(keyguardShowing);
            }
        });
    }

调用了frameworks/base/services/core/java/com/android/server/wm/KeyguardController.java的setKeyguardShown方法:

    /**
     * Update the Keyguard showing state.
     */
    void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
        final boolean aodChanged = aodShowing != mAodShowing;
        // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
        // Do not reset keyguardChanged status if this is aodChanged.
        final boolean keyguardChanged = (keyguardShowing != mKeyguardShowing)
                || (mKeyguardGoingAway && keyguardShowing && !aodChanged);
        if (!keyguardChanged && !aodChanged) {
            return;
        }
        EventLogTags.writeWmSetKeyguardShown(
                keyguardShowing ? 1 : 0,
                aodShowing ? 1 : 0,
                mKeyguardGoingAway ? 1 : 0,
                "setKeyguardShown");
        mKeyguardShowing = keyguardShowing;
        mAodShowing = aodShowing;
        mWindowManager.setAodShowing(aodShowing);

        if (keyguardChanged) {
            // Irrelevant to AOD.
            dismissDockedStackIfNeeded();
            setKeyguardGoingAway(false);
            if (keyguardShowing) {
                mDismissalRequested = false;
            }
        }
        // TODO(b/113840485): Check usage for non-default display
        mWindowManager.setKeyguardOrAodShowingOnDefaultDisplay(
                isKeyguardOrAodShowing(DEFAULT_DISPLAY));

        // Update the sleep token first such that ensureActivitiesVisible has correct sleep token
        // state when evaluating visibilities.
        updateKeyguardSleepToken();
        mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
    }

此时会打印event log:“wm_set_keyguard_shown: [0,0,1,setKeyguardShown]”,并且此时keyguardChanged也会为true,会调用setKeyguardGoingAway(false)方法将KeyguardController和WindowManagerService的mKeyguardGoingAway都设为false。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSSxCCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值