该系列文章总纲链接:专题分纲目录 Android SystemUI组件
本章关键点总结 & 说明:
说明:本章节持续迭代之前章节的思维导图,主要关注左侧上方锁屏分析部分 应用入口处理流程解读 即可。
在 Android 系统中,禁用锁屏(Keyguard)通常需要 DISABLE_KEYGUARD
权限。但是,这个权限属于签名权限,只能由系统应用或者具有系统签名的应用使用,比如Setting、Launcher等。
对于普通应用来说,通常不允许禁用锁屏,因为这会降低设备的安全性。然而,有些情况下,比如在设置应用或者需要解锁功能的其他预装应用中,可能需要这个权限。在 AndroidManifest.xml 文件中声明权限的示例:
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
但是,即使声明了这个权限,普通应用也无法获得这个权限,系统会忽略它们的请求。对于系统应用或者具有系统权限的应用,使用 KeyguardManager
禁用锁屏和重新启用锁屏的代码如下:
//获取系统服务
KeyguardManager keyguardManager = (KeyguardManager)getSystemService(Context.KEYGUARD_SERVICE);
//创建一个KeyguardLock对象,这个对象提供了控制锁屏(Keyguard)行为的方法。
//参数"UNIQUE_LOCK_INSTANCE"是一个标识符,用于区分不同的锁屏控制实例
KeyguardManager.KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("UNIQUE_LOCK_INSTANCE");
//常用操作:禁用锁屏
keyguardLock.disableKeyguard();
//常用操作:重新启用锁屏
keyguardLock.reenableKeyguard();
接下来从KeyguardManager的2个关键API disableKeyguard和reenableKeyguard来继续分析。
1 disableKeyguard和reenableKeyguard方法入手分析
disableKeyguard和reenableKeyguard的代码实现如下:
public class KeyguardManager {
private IWindowManager mWM;
private ITrustManager mTrustManager;
//...
public void disableKeyguard() {
try {
mWM.disableKeyguard(mToken, mTag);
} catch (RemoteException ex) {
}
}
public void reenableKeyguard() {
try {
mWM.reenableKeyguard(mToken);
} catch (RemoteException ex) {
}
}
//...
}
IWindowManager
是一个Binder接口,它定义了一系列管理窗口的方法。在Android系统中,服务通常是通过Binder IPC(进程间通信)机制进行通信的。IWindowManager
接口的实现类是WindowManagerService
,它运行在系统的服务端,并管理所有窗口的状态和行为。
当KeyguardManager
的disableKeyguard()
或reenableKeyguard()
方法被调用时,它们会通过mWM
(即IWindowManager
的实例)向WindowManagerService
发送请求,以禁用或重新启用锁屏。具体代码实现如下:
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
static final String TAG = "WindowManager";
//...
@Override
public void disableKeyguard(IBinder token, String tag) {
//权限检查
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
if (token == null) {
throw new IllegalArgumentException("token == null");
}
mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
KeyguardDisableHandler.KEYGUARD_DISABLE, new Pair<IBinder, String>(token, tag)));
}
@Override
public void reenableKeyguard(IBinder token) {
//权限检查
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires DISABLE_KEYGUARD permission");
}
if (token == null) {
throw new IllegalArgumentException("token == null");
}
mKeyguardDisableHandler.sendMessage(mKeyguardDisableHandler.obtainMessage(
KeyguardDisableHandler.KEYGUARD_REENABLE, token));
}
//...
}
针对这KeyguardDisableHandler的sendMessage的消息处理,代码实现如下:
public class KeyguardDisableHandler extends Handler {
private static final String TAG = "KeyguardDisableHandler";
//...
// Message.what constants
static final int KEYGUARD_DISABLE = 1;
static final int KEYGUARD_REENABLE = 2;
static final int KEYGUARD_POLICY_CHANGED = 3;
//...
@Override
public void handleMessage(Message msg) {
if (mKeyguardTokenWatcher == null) {
mKeyguardTokenWatcher = new KeyguardTokenWatcher(this);
}
switch (msg.what) {
case KEYGUARD_DISABLE:
final Pair<IBinder, String> pair = (Pair<IBinder, String>)msg.obj;
mKeyguardTokenWatcher.acquire(pair.first, pair.second);
break;
case KEYGUARD_REENABLE:
mKeyguardTokenWatcher.release((IBinder)msg.obj);
break;
case KEYGUARD_POLICY_CHANGED:
mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
if (mKeyguardTokenWatcher.isAcquired()) {
// If we are currently disabled we need to know if the keyguard
// should be re-enabled, so determine the allow state immediately.
mKeyguardTokenWatcher.updateAllowState();
if (mAllowDisableKeyguard != ALLOW_DISABLE_YES) {
mPolicy.enableKeyguard(true);
}
} else {
// lazily evaluate this next time we're asked to disable keyguard
mPolicy.enableKeyguard(true);
}
break;
}
}
//...
}
接下来着重分析mKeyguardTokenWatcher.acquire和mKeyguardTokenWatcher.release的实现,代码具体实现如下:
class KeyguardTokenWatcher extends TokenWatcher {
public KeyguardTokenWatcher(final Handler handler) {
super(handler, TAG);
}
//更新是否允许禁用锁屏的状态。这是通过查询DevicePolicyManager服务来实现的,
//它管理设备策略,包括密码质量要求等。
public void updateAllowState() {
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (dpm != null) {
try {
//检查当前用户是否有密码质量要求,如果返回PASSWORD_QUALITY_UNSPECIFIED,
//则表示没有密码要求,允许禁用锁屏(ALLOW_DISABLE_YES);
//否则,不允许禁用锁屏(ALLOW_DISABLE_NO)。
mAllowDisableKeyguard = dpm.getPasswordQuality(null,
ActivityManagerNative.getDefault().getCurrentUser().id)
== DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
} catch (RemoteException re) {
// Nothing much we can do
}
}
}
//获取到一个令牌时(请求禁用锁屏)
@Override
public void acquired() {
if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
updateAllowState();
}
if (mAllowDisableKeyguard == ALLOW_DISABLE_YES) {
mPolicy.enableKeyguard(false);
} else {
Log.v(TAG, "Not disabling keyguard since device policy is enforced");
}
}
//释放一个令牌时(请求要启用锁屏)
@Override
public void released() {
mPolicy.enableKeyguard(true);
}
}
这里的关键方法为:mPolicy.enableKeyguard,代码具体实现如下:
public class PhoneWindowManager implements WindowManagerPolicy {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
//...
/** {@inheritDoc} */
@Override
public void enableKeyguard(boolean enabled) {
if (mKeyguardDelegate != null) {
mKeyguardDelegate.setKeyguardEnabled(enabled);
}
}
//...
}
这里继续分析mKeyguardDelegate.setKeyguardEnabled,代码实现如下:
public class KeyguardServiceDelegate {
public static final String KEYGUARD_PACKAGE = "com.android.systemui";
public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
private static final String TAG = "KeyguardServiceDelegate";
private static final boolean DEBUG = true;
protected KeyguardServiceWrapper mKeyguardService;
//...
public void setKeyguardEnabled(boolean enabled) {
if (mKeyguardService != null) {
mKeyguardService.setKeyguardEnabled(enabled);
}
mKeyguardState.enabled = enabled;
}
//...
}
注意:这里的mKeyguardState.enabled状态的目的是为了维护一个本地副本,以便快速检查锁屏(Keyguard)是否当前被启用或禁用,而不需要每次都调用KeyguardService来获取这个状态。接下来继续分析mKeyguardService.setKeyguardEnabled,代码实现如下:
public class KeyguardServiceWrapper implements IKeyguardService {
private KeyguardStateMonitor mKeyguardStateMonitor;
private IKeyguardService mService;
private String TAG = "KeyguardServiceWrapper";
//...
@Override // Binder interface
public void setKeyguardEnabled(boolean enabled) {
try {
mService.setKeyguardEnabled(enabled);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
//...
}
继续分析mService.setKeyguardEnabled,代码实现如下:
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
//...
private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
//...
@Override // Binder interface
public void setKeyguardEnabled(boolean enabled) {
checkPermission();//权限检查
mKeyguardViewMediator.setKeyguardEnabled(enabled);
}
//...
}
//...
}
KeyguardViewMediator的setKeyguardEnabled,终于到了真正实现功能的部分了。
2 功能实现 KeyguardViewMediator.setKeyguardEnabled方法
接下来继续分析代码,主要关注逻辑功能的实现,代码实现如下:
public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
private static final boolean DEBUG = KeyguardConstants.DEBUG;
//...
public void setKeyguardEnabled(boolean enabled) {
synchronized (this) {
// 设置锁屏是否被外部启用
mExternallyEnabled = enabled;
// 如果请求禁用锁屏(enabled为false)且锁屏当前正在显示
if (!enabled && mShowing) {
// 如果当前有正在进行的解锁操作,则忽略禁用请求
if (mExitSecureCallback != null) {
return;
}
// 标记需要在锁屏重新启用时重新显示
mNeedToReshowWhenReenabled = true;
// 更新输入限制状态
updateInputRestrictedLocked();
// 隐藏锁屏
hideLocked();
} else if (enabled && mNeedToReshowWhenReenabled) {
// 如果请求启用锁屏且之前有标记需要重新显示
mNeedToReshowWhenReenabled = false;
// 更新输入限制状态
updateInputRestrictedLocked();
// 如果当前有解锁操作的回调,则处理解锁结果
if (mExitSecureCallback != null) {
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
// 重置状态
resetStateLocked();
} else {
// 显示锁屏
showLocked(null);
// 标记正在等待锁屏变为可见状态
mWaitingUntilKeyguardVisible = true;
// 延迟发送消息,以便在超时后继续执行
mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
// 等待锁屏变为可见状态
while (mWaitingUntilKeyguardVisible) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
}
//...
}
这段代码的逻辑确保了锁屏的显示和隐藏能够根据请求和当前状态正确地进行,同时处理了解锁操作的回调和状态同步。整体逻辑可拆解为4个部分:
-
锁屏状态更新:首先,方法同步并更新锁屏的外部启用状态。
-
处理禁用请求:如果请求是禁用锁屏,并且锁屏当前正在显示,会检查是否有正在进行的解锁操作。如果没有,将标记需要在锁屏重新启用时重新显示,并隐藏锁屏。
-
处理启用请求:如果请求是启用锁屏,并且之前有标记需要重新显示,会清除该标记,并根据是否有解锁操作的回调来处理。如果有回调,会处理解锁结果并重置状态。如果没有回调,会显示锁屏,并等待锁屏变为可见状态。
-
等待锁屏可见:在启用锁屏后,通过发送延迟消息和等待机制确保锁屏已经绘制完成,避免在锁屏未完全显示时用户操作导致的问题。
接下来分析两个重要的锁屏功能API:显示锁屏showLocked 和 隐藏锁屏hideLocked。这部分代码向下的分析参考了文章Android SystemUI组件(07)锁屏KeyguardViewMediator分析 的后半部分。代码实现如下:
public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
private static final boolean DEBUG = KeyguardConstants.DEBUG;
//...handler 发送消息 SHOW/HIDE
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);
}
private void hideLocked() {
if (DEBUG) Log.d(TAG, "hideLocked");
Message msg = mHandler.obtainMessage(HIDE);
mHandler.sendMessage(msg);
}
//...handler处理
private Handler mHandler = new Handler(Looper.myLooper(), null, true /*async*/) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW:
handleShow((Bundle) msg.obj);
break;
case HIDE:
handleHide();
break;
//...
}
}
};
//handler关键处理方法handleShow
private void handleShow(Bundle options) {
synchronized (KeyguardViewMediator.this) {
// 如果系统还没有准备好,忽略显示锁屏的请求
if (!mSystemReady) {
return;
}
// 标记锁屏为显示状态
setShowingLocked(true);
// 调用状态栏锁屏视图管理器显示锁屏
mStatusBarKeyguardViewManager.show(options);
// 标记锁屏不是在隐藏状态
mHiding = false;
// 重置锁屏完成挂起的状态
resetKeyguardDonePendingLocked();
// 标记没有运行隐藏动画
mHideAnimationRun = false;
// 更新活动锁屏状态
updateActivityLockScreenState();
// 调整状态栏
adjustStatusBarLocked();
// 用户活动事件
userActivity();
// 在最后执行,以免延迟锁屏显示
playSounds(true);
// 释放锁屏显示时持有的WakeLock
mShowKeyguardWakeLock.release();
}
// 显示锁屏管理器
mKeyguardDisplayManager.show();
}
private final Runnable mKeyguardGoingAwayRunnable = new Runnable() {
@Override
public void run() {
try {
// 通知窗口管理器锁屏正在消失
mWM.keyguardGoingAway(
mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock(),
mStatusBarKeyguardViewManager.isGoingToNotificationShade());
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
}
};
//handler关键处理方法handleHide
private void handleHide() {
synchronized (KeyguardViewMediator.this) {
mHiding = true; // 标记锁屏正在隐藏
// 如果锁屏当前正在显示并且没有被遮挡
if (mShowing && !mOccluded) {
// 如果还没有运行隐藏动画
if (!mHideAnimationRun) {
// 开始执行预隐藏动画,并在动画结束后执行mKeyguardGoingAwayRunnable
mStatusBarKeyguardViewManager.startPreHideAnimation(mKeyguardGoingAwayRunnable);
} else {
// 如果已经在运行隐藏动画,则直接执行mKeyguardGoingAwayRunnable
mKeyguardGoingAwayRunnable.run();
}
} else {
// 如果锁屏没有显示,或者被遮挡,不依赖于WindowManager来启动退出动画
// 直接处理开始退出动画
handleStartKeyguardExitAnimation(
SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(),
mHideAnimation.getDuration());
}
}
}
//...
}
接下来总结下2个关键流程内容:
handleShow
方法,它负责处理显示锁屏的逻辑。具体如下:
- 设置锁屏状态:如果系统已准备好,标记锁屏为显示状态,并调用
mStatusBarKeyguardViewManager.show(options)
来显示锁屏。 - 重置状态:重置锁屏完成挂起的状态,标记没有运行隐藏动画,更新活动锁屏状态,调整状态栏,记录用户活动事件。
- 播放声音:在锁屏显示后播放声音,这通常包括锁屏出现的声音。
- 释放WakeLock:释放在显示锁屏时持有的
mShowKeyguardWakeLock
,以允许设备在锁屏显示后进入休眠状态。 - 显示锁屏管理器:调用
mKeyguardDisplayManager.show()
来显示锁屏管理器。
handleShow
方法的目的是确保在需要时显示锁屏界面,更新系统状态以反映锁屏的显示,并通过播放声音或振动向用户提供反馈,同时保持设备的安全性和良好的用户体验。
handleHide
方法,它负责处理隐藏锁屏的逻辑。具体如下:
- 设置隐藏标志:将
mHiding
标志设置为true
,表示锁屏正在被隐藏。 - 检查锁屏状态:检查锁屏是否正在显示并且没有被遮挡。
- 处理没有显示的锁屏:如果锁屏没有显示或者被遮挡,不依赖于WindowManager来启动退出动画,而是直接调用
handleStartKeyguardExitAnimation
方法来处理开始退出动画。
handleHide
方法的目的是确保在锁屏隐藏时能够正确地执行动画和相关的清理工作。它根据锁屏的当前状态来决定是否启动动画,以及是否直接处理退出动画。这种方法确保了锁屏隐藏过程的平滑和一致性,同时避免了不必要的依赖和潜在的冲突。
接下来我们专注分析show的逻辑实现,这里调用了mStatusBarKeyguardViewManager的show方法,代码具体实现如下:
public class StatusBarKeyguardViewManager {
//step1 显示锁屏
public void show(Bundle options) {
mShowing = true; // 标记锁屏为显示状态
mStatusBarWindowManager.setKeyguardShowing(true); // 通知状态栏窗口管理器锁屏正在显示
reset(); // 调用reset方法来重置锁屏状态
}
//step2 重置锁屏状态
public void reset() {
if (mShowing) {
if (mOccluded) {
mPhoneStatusBar.hideKeyguard(); // 如果锁屏被遮挡,隐藏锁屏
mBouncer.hide(false /* destroyView */); // 隐藏解锁界面(Bouncer)
} else {
showBouncerOrKeyguard(); // 显示解锁界面或锁屏
}
updateStates(); // 更新锁屏状态
}
}
//step3 显示解锁界面或锁屏
private void showBouncerOrKeyguard() {
if (mBouncer.needsFullscreenBouncer()) {
mPhoneStatusBar.hideKeyguard(); // 需要全屏解锁界面时,隐藏锁屏
mBouncer.show(true); // 显示解锁界面(Bouncer)
} else {
mPhoneStatusBar.showKeyguard(); // 不需要全屏解锁界面时,显示锁屏
mBouncer.hide(false); // 隐藏解锁界面(Bouncer)
mBouncer.prepare(); // 准备解锁界面(Bouncer)
}
}
}
接下来主要解读mBouncer.show和hide的实现及相关流程。主要以show方法(加载视图)为主。接下来继续分析KeyguardBouncer的show方法和hide方法流程,代码具体实现如下:
public class KeyguardBouncer {
private Context mContext;
//...
private final Runnable mShowRunnable = new Runnable() {
@Override
public void run() {
// 设置锁屏视图的可见性为可见
mRoot.setVisibility(View.VISIBLE);
// 恢复锁屏视图的活动状态
mKeyguardView.onResume();
// 开始锁屏视图的显示动画
mKeyguardView.startAppearAnimation();
// 清除锁屏即将显示的标志
mShowingSoon = false;
}
};
//...
//加载及锁屏界面关键流程
//step1 显示锁屏界面
public void show() {
// 确保锁屏视图已经创建,锁屏View的加载
ensureView();
// 如果锁屏视图已经是可见的或者即将显示,则不需要再次显示
if (mRoot.getVisibility() == View.VISIBLE || mShowingSoon) {
// 更新当前的安全方法,这在锁屏已经显示但当前安全方法发生变化时是必要的
mKeyguardView.show();
return;
}
// 尝试dismiss锁屏。如果没有设置安全模式,这将dismiss整个锁屏。
// 如果需要认证,则显示解锁界面(Bouncer)。
if (!mKeyguardView.dismiss()) {
// 设置标志,表示锁屏即将显示
mShowingSoon = true;
// 在多个帧上分散工作
mChoreographer.postCallbackDelayed(Choreographer.CALLBACK_ANIMATION, mShowRunnable,
null, 48);
}
}
//step2 确保锁屏视图已经创建
private void ensureView() {
//检查mRoot(锁屏界面的根视图)是否已经存在。
if (mRoot == null) {
//加载锁屏界面
inflateView();
}
}
//step3 加载锁屏界面
private void inflateView() {
// 如果之前已经添加过锁屏视图,先将其移除
removeView();
// 通过LayoutInflater从keyguard_bouncer布局文件中加载锁屏界面布局
mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
// 从加载的布局中获取KeyguardViewBase实例
mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
// 为锁屏视图设置锁图案工具,用于处理锁屏图案相关逻辑
mKeyguardView.setLockPatternUtils(mLockPatternUtils);
// 为锁屏视图设置ViewMediatorCallback,用于处理锁屏界面的回调事件
mKeyguardView.setViewMediatorCallback(mCallback);
// 将锁屏视图添加到容器视图中,确保它在容器的最后面
mContainer.addView(mRoot, mContainer.getChildCount());
// 初始时将锁屏视图的可见性设置为不可见
mRoot.setVisibility(View.INVISIBLE);
// 设置系统UI可见性,禁用HOME按钮,这样用户在锁屏界面上不会看到HOME按钮
mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
}
//...
//隐藏锁屏界面关键流程
//step1 隐藏锁屏界面
public void hide(boolean destroyView) {
// 取消任何即将执行的显示锁屏的操作
cancelShowRunnable();
// 如果锁屏视图不为空,则进行清理
if (mKeyguardView != null) {
// 移除锁屏视图上的解散动作,即用户不再能通过这个视图解散锁屏
mKeyguardView.setOnDismissAction(null);
// 清理锁屏视图,这可能包括重置状态、停止动画等
mKeyguardView.cleanUp();
}
// 如果传入的参数destroyView为true,则完全移除锁屏视图
if (destroyView) {
removeView();
} else if (mRoot != null) {
// 如果不销毁视图,只是将其设置为不可见
mRoot.setVisibility(View.INVISIBLE);
}
}
//step2 锁屏界面不显示,取消线程
private void cancelShowRunnable() {
// 从Choreographer中移除之前安排的动画帧更新回调
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mShowRunnable, null);
// 将mShowingSoon标志设置为false,表示锁屏界面不再即将显示
mShowingSoon = false;
}
}
其中,StatusBarKeyguardViewManager类中的show方法负责实际显示锁屏界面。它首先将锁屏的显示状态设置为true,然后调用reset方法来重置锁屏状态。reset方法会根据锁屏是否被遮挡来决定是显示解锁界面(Bouncer)还是锁屏界面。
KeyguardBouncer类中的show方法用于显示解锁界面(Bouncer)。如果需要全屏解锁界面,它会隐藏锁屏并显示解锁界面。否则,它会显示锁屏并隐藏解锁界面,并准备解锁界面以供用户输入。
KeyguardBouncer类中的hide方法用于隐藏解锁界面。它会取消任何即将执行的显示操作,并根据传入的参数决定是销毁视图还是仅仅将其设置为不可见。
这些方法共同工作,确保了锁屏界面能够在适当的时机显示或隐藏,同时提供了用户反馈和设备安全性。