Android 8.1 系统锁屏显示流程整理

简介: Android 8.1 系统锁屏显示流程整理

平台:


RK3399 + Android 8.1


源码跟踪:


系统启动时显示锁屏:


|-- frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java


KeyguardServiceDelegate mKeyguardDelegate;
    /** {@inheritDoc} */
    @Override
    public void init(Context context, IWindowManager windowManager,
            WindowManagerFuncs windowManagerFuncs) {
  ...
        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
                new StateCallback() {
                    @Override
                    public void onTrustedChanged() {
                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
                    }
                });
    }
  /** {@inheritDoc} */
    @Override
    public void systemBooted() {
        bindKeyguard();
        ...
    }
    private void bindKeyguard() {
        synchronized (mLock) {
            if (mKeyguardBound) {
                return;
            }
            mKeyguardBound = true;
        }
        mKeyguardDelegate.bindService(mContext);
    }
    /** {@inheritDoc} */
    @Override
    public void systemReady() {//系统服务启动完成.
        // In normal flow, systemReady is called before other system services are ready.
        // So it is better not to bind keyguard here.
        mKeyguardDelegate.onSystemReady();
  }


所有的锁屏相关操作由mKeyguardDelegate 代理完成:


|-- frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java


public void bindService(Context context) {
       Intent intent = new Intent();
       final Resources resources = context.getApplicationContext().getResources();
       final ComponentName keyguardComponent = ComponentName.unflattenFromString(
               resources.getString(com.android.internal.R.string.config_keyguardComponent));
       intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
       intent.setComponent(keyguardComponent);
       if (!context.bindServiceAsUser(intent, mKeyguardConnection,
               Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
    ...
    }
   }
    private final ServiceConnection mKeyguardConnection = new ServiceConnection() {
       @Override
       public void onServiceConnected(ComponentName name, IBinder service) {
           if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
           mKeyguardService = new KeyguardServiceWrapper(mContext,
                   IKeyguardService.Stub.asInterface(service), mCallback);
    }
   }
   public void onSystemReady() {
       if (mKeyguardService != null) {
           mKeyguardService.onSystemReady();
       } else {
           mKeyguardState.systemIsReady = true;
       }
   }


BINDER对应的服务组件定义:


|-- frameworks/base/core/res/res/values/config.xml


<string name="config_keyguardComponent" translatable="false">com.android.systemui/com.android.systemui.keyguard.KeyguardService</string>


直指SystemUI:


|–frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java


private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
        @Override // Binder interface
        public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
            checkPermission();
            mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered);
            mKeyguardLifecyclesDispatcher.dispatch(
                    KeyguardLifecyclesDispatcher.FINISHED_GOING_TO_SLEEP);
        }
  }
        @Override // Binder interface
        public void onSystemReady() {
            Trace.beginSection("KeyguardService.mBinder#onSystemReady");
            checkPermission();
            mKeyguardViewMediator.onSystemReady();
            Trace.endSection();
        }


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java


/**
     * Let us know that the system is ready after startup.
     */
    public void onSystemReady() {
        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();
    }


进休眠或关屏幕:


|-- frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java



@Override
    public void finishedGoingToSleep(int why) {
        ..
        if (mKeyguardDelegate != null) {
            mKeyguardDelegate.onFinishedGoingToSleep(why,
                    mCameraGestureTriggeredDuringGoingToSleep);
        }
        mCameraGestureTriggeredDuringGoingToSleep = false;
    }


|-- frameworks/base/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java


public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
       if (mKeyguardService != null) {
           mKeyguardService.onFinishedGoingToSleep(why, cameraGestureTriggered);
       }
       mKeyguardState.interactiveState = INTERACTIVE_STATE_SLEEP;
   }


中间跳转代码与上面相似, 此处省略


|–frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java


public void onFinishedGoingToSleep(int why, boolean cameraGestureTriggered) {
    ...
           if (mPendingLock) {
               doKeyguardLocked(null);
    ...
   }
   /** 最终显示锁屏的关键函数
    * Enable the keyguard if the settings are appropriate.
    */
   private void doKeyguardLocked(Bundle options) {
    ...
      //在8.1, 采用PIN等密码锁时, 设备中的存储(data)会被加密, 在关机重启后, 进入一个一级启动状态
      //这时候, DATA中的数据是原始的, 只有核心应用在这个阶段才是可用的, 同样, 一些系统设置项, 属性系统项, DATA中的文件,
      //如: 在正常开机时, 保存一个文件到/data/file.txt, 在这阶段, 是找不到file.txt这个文件的.
      //这是一个解密界面(Settings中的CryptKeeper), 同样需要输入当前设备解锁密码, 用于解密data.
      //当成功解密后(checkVoldPassword 返回true), 启动时是不需要显示锁屏的. 
               if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
               if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
               // Without this, settings is not enabled until the lock screen first appears
               setShowingLocked(false);
               hideLocked();
               return;
           }
    ...
       if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
       showLocked(options);
   }
   /**
    * Send message to keyguard telling it to show itself
    * @see #handleShow
    */
   private void showLocked(Bundle options) {
       Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock");
       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);
       Trace.endSection();
   }
   /**
    * Handle message sent by {@link #showLocked}.
    * @see #SHOW
    */
   private void handleShow(Bundle options) {
       Trace.beginSection("KeyguardViewMediator#handleShow");
       final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
       if (mLockPatternUtils.isSecure(currentUser)) {
           mLockPatternUtils.getDevicePolicyManager().reportKeyguardSecured(currentUser);
       }
       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;
           adjustStatusBarLocked();
//更新最后一次操作时间, 以便系统计算进入休眠.
           userActivity();
           mShowKeyguardWakeLock.release();
       }
       mKeyguardDisplayManager.show();
       Trace.endSection();
   }


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java


protected KeyguardBouncer mBouncer;
    public void registerStatusBar(StatusBar statusBar,
            ViewGroup container,
            ScrimController scrimController,
            FingerprintUnlockController fingerprintUnlockController,
            DismissCallbackRegistry dismissCallbackRegistry) {
        ...
        mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
                mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry);
    }


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java


public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
            LockPatternUtils lockPatternUtils,
            ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry) {
        return new KeyguardBouncer(context, callback, lockPatternUtils, container,
                dismissCallbackRegistry);
    }


|-- frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java


public void show(boolean resetSecuritySelection) {
       final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser();
       if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) {
           // In split system user mode, we never unlock system user.
           return;
       }
       mFalsingManager.onBouncerShown();
       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;
       }
       final int activeUserId = ActivityManager.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) {
           Slog.w(TAG, "User can't dismiss keyguard: " + activeUserId + " != " + keyguardUserId);
       }
       mShowingSoon = true;
       // Split up the work over multiple frames.
       DejankUtils.postAfterTraversal(mShowRunnable);
   }
   private final Runnable mShowRunnable = new Runnable() {
       @Override
       public void run() {
           mRoot.setVisibility(View.VISIBLE);
           mKeyguardView.onResume();
           showPromptReason(mBouncerPromptReason);
           // We might still be collapsed and the view didn't have time to layout yet or still
           // be small, let's wait on the predraw to do the animation in that case.
           if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
               mKeyguardView.startAppearAnimation();
           } else {
               mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
                       new ViewTreeObserver.OnPreDrawListener() {
                           @Override
                           public boolean onPreDraw() {
                               mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);
                               mKeyguardView.startAppearAnimation();
                               return true;
                           }
                       });
               mKeyguardView.requestLayout();
           }
           mShowingSoon = false;
           mKeyguardView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
       }
   };


相关文章
|
11月前
|
Linux 测试技术 语音技术
【车载Android】模拟Android系统的高负载环境
本文介绍如何将Linux压力测试工具Stress移植到Android系统,用于模拟高负载环境下的CPU、内存、IO和磁盘压力,帮助开发者优化车载Android应用在多任务并发时的性能问题,提升系统稳定性与用户体验。
910 6
|
11月前
|
Java 数据库 Android开发
基于Android的电子记账本系统
本项目研究开发一款基于Java与Android平台的开源电子记账系统,采用SQLite数据库和Gradle工具,实现高效、安全、便捷的个人财务管理,顺应数字化转型趋势。
|
安全 算法 小程序
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
1125 28
【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
|
安全 搜索推荐 Android开发
Android系统SELinux安全机制详解
如此看来,SELinux对于大家来说,就像那位不眠不休,严阵以待的港口管理员,守护我们安卓系统的平安,维护这片海港的和谐生态。SELinux就这样,默默无闻,却卫士如山,给予Android系统一份厚重的安全保障。
557 18
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
1063 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
794 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
591 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
10830 2
|
Android开发
Android 仿音乐播放器自定义锁屏歌词功能
在平常使用音乐播放器时经常会遇到锁屏会显示歌词功能,做的时候也是各种手机不适配,翻阅了网上的文章,发现都是好几年前的,适配的安卓版本比较低,所以我就整合了一下分享给大家.
Android 仿音乐播放器自定义锁屏歌词功能

热门文章

最新文章