FW SystemUI Keyguard解析(二)
文章目录
- CTS之Keyguard Menu事件处理
CTS之Keyguard Menu事件处理
事件触发点:
NotificationShadeWindowViewController.dispatchKeyEvent
设置setInteractionEventHandler回调之后通过NotificationShadeWindowView 触发
调用到return mService.onMenuPressed();
public class NotificationShadeWindowViewController {public void setupExpandedStatusBar() {mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() {//省略代码@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {boolean down = event.getAction() == KeyEvent.ACTION_DOWN;switch (event.getKeyCode()) {case KeyEvent.KEYCODE_BACK:if (!down) {mService.onBackPressed();}return true;case KeyEvent.KEYCODE_MENU:if (!down) {return mService.onMenuPressed();//☆☆☆☆}break;case KeyEvent.KEYCODE_SPACE:if (!down) {return mService.onSpacePressed();}break;case KeyEvent.KEYCODE_VOLUME_DOWN:case KeyEvent.KEYCODE_VOLUME_UP:if (mStatusBarStateController.isDozing()) {MediaSessionLegacyHelper.getHelper(mView.getContext()).sendVolumeKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE, true);return true;}break;}return false;}});}
}public class NotificationShadeWindowView extends FrameLayout {@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (mInteractionEventHandler.interceptMediaKey(event)) {return true;}if (super.dispatchKeyEvent(event)) {return true;}return mInteractionEventHandler.dispatchKeyEvent(event);//☆☆☆☆}
}
以上通过接口会调用到
StatusBar类中去
public class StatusBar{public boolean onMenuPressed() {if (shouldUnlockOnMenuPressed()) {mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);//☆☆☆☆return true;}return false;}}public class ShadeControllerImpl implements ShadeController {@Overridepublic void animateCollapsePanels(int flags, boolean force) {animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);//☆☆☆☆}@Overridepublic void animateCollapsePanels(int flags, boolean force, boolean delayed,float speedUpFactor) {if (!force && mStatusBarStateController.getState() != StatusBarState.SHADE) {runPostCollapseRunnables();return;}if (SPEW) {Log.d(TAG, "animateCollapse():"+ " mExpandedVisible=" + getStatusBar().isExpandedVisible()+ " flags=" + flags);}if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {getStatusBar().postHideRecentApps();}// TODO(b/62444020): remove when this bug is fixedLog.v(TAG, "NotificationShadeWindow: " + getNotificationShadeWindowView()+ " canPanelBeCollapsed(): "+ getNotificationPanelViewController().canPanelBeCollapsed());if (getNotificationShadeWindowView() != null&& getNotificationPanelViewController().canPanelBeCollapsed()) {// release focus immediately to kick off focus change transitionmNotificationShadeWindowController.setNotificationShadeFocusable(false);getStatusBar().getNotificationShadeWindowViewController().cancelExpandHelper();getStatusBarView().collapsePanel(true /* animate */, delayed, speedUpFactor);//☆☆☆☆} else {mBubbleControllerLazy.get().collapseStack();}}}public abstract class PanelBar extends FrameLayout {public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) {boolean waiting = false;PanelViewController pv = mPanel;if (animate && !pv.isFullyCollapsed()) {pv.collapse(delayed, speedUpFactor);waiting = true;} else {pv.resetViews(false /* animate */);pv.setExpandedFraction(0); // just in casepv.cancelPeek();}if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting);if (!waiting && mState != STATE_CLOSED) {// it's possible that nothing animated, so we replicate the termination// conditions of panelExpansionChanged herego(STATE_CLOSED);onPanelCollapsed();//☆☆☆☆}}
}public class PhoneStatusBarView extends PanelBar {private Runnable mHideExpandedRunnable = new Runnable() {@Overridepublic void run() {if (mPanelFraction == 0.0f) {mBar.makeExpandedInvisible();//☆☆☆☆}}};@Overridepublic void onPanelCollapsed() {super.onPanelCollapsed();// Close the status bar in the next frame so we can show the end of the animation.post(mHideExpandedRunnable);//☆☆☆☆mIsFullyOpenedPanel = false;}
}public class StatusBar extends SystemUI {void makeExpandedInvisible() {if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible+ " mExpandedVisible=" + mExpandedVisible);if (!mExpandedVisible || mNotificationShadeWindowView == null) {return;}// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)mStatusBarView.collapsePanel(/*animate=*/ false, false /* delayed*/,1.0f /* speedUpFactor */);mNotificationPanelViewController.closeQs();mExpandedVisible = false;visibilityChanged(false);// Update the visibility of notification shade and status bar window.mNotificationShadeWindowController.setPanelVisible(false);mStatusBarWindowController.setForceStatusBarVisible(false);// Close any guts that might be visiblemGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);mShadeController.runPostCollapseRunnables();setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {showBouncerIfKeyguard();//☆☆☆☆} else if (DEBUG) {Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");}mCommandQueue.recomputeDisableFlags(mDisplayId,mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */);// Trimming will happen later if Keyguard is showing - doing it here might cause a jank in// the bouncer appear animation.if (!mStatusBarKeyguardViewManager.isShowing()) {WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);}}private void showBouncerIfKeyguard() {if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)&& !mKeyguardViewMediator.isHiding()) {mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */); //☆☆☆☆}}}public class StatusBarKeyguardViewManager {public void showBouncer(boolean scrimmed) {if (mShowing && !mBouncer.isShowing()) {mBouncer.show(false /* resetSecuritySelection */, scrimmed);//☆☆☆☆}updateStates();}
}public class KeyguardBouncer {private final Runnable mShowRunnable = new Runnable() {@Overridepublic void run() {mRoot.setVisibility(View.VISIBLE);showPromptReason(mBouncerPromptReason);final CharSequence customMessage = mCallback.consumeCustomMessage();if (customMessage != null) {mKeyguardView.showErrorMessage(customMessage);}// 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() {@Overridepublic boolean onPreDraw() {mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this);mKeyguardView.startAppearAnimation();//☆☆☆☆return true;}});mKeyguardView.requestLayout();}mShowingSoon = false;if (mExpansion == EXPANSION_VISIBLE) {mKeyguardView.onResume();mKeyguardView.resetSecurityContainer();showPromptReason(mBouncerPromptReason);}SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN);}};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();}
}public class KeyguardHostView extends FrameLayout implements SecurityCallback {public void startAppearAnimation() {mSecurityContainer.startAppearAnimation();//☆☆☆☆}
}public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {public void startAppearAnimation() {if (mCurrentSecuritySelection != SecurityMode.None) {getSecurityView(mCurrentSecuritySelection).startAppearAnimation();//☆☆☆☆}}
}public class KeyguardPINView extends KeyguardPinBasedInputView {@Overridepublic void startAppearAnimation() {enableClipping(false);setAlpha(1f);//☆☆☆☆setTranslationY(mAppearAnimationUtils.getStartTranslation());AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 500 /* duration */,0, mAppearAnimationUtils.getInterpolator());mAppearAnimationUtils.startAnimation2d(mViews,new Runnable() {@Overridepublic void run() {enableClipping(true);}});}}相关文章:
FW SystemUI Keyguard解析(二)
文章目录 CTS之Keyguard Menu事件处理 CTS之Keyguard Menu事件处理 事件触发点: NotificationShadeWindowViewController.dispatchKeyEvent 设置setInteractionEventHandler回调之后通过NotificationShadeWindowView 触发 调用到return mService.onMenuPressed(); public cla…...
MySQL之备份与恢复(二)
备份与恢复 定义恢复需求 如果一切正常,那么永远也不需要考虑恢复。但是,一旦需要恢复,只有世界上最好的备份系统是没用的,还需要一个强大的恢复系统。 不幸的是,让备份系统平滑工作比构造良好的恢复过程和工具更容易…...
MySQL:保护数据库
保护数据库 1. 用户1.1 创建用户1.2 查看用户1.3 删除用户1.4 修改密码 2. 权限2.1 授予权限2.2 查看权限2.3 撤销权限 之前都是介绍本地数据库而你自己就是数据库的唯一用户,所以不必考虑安全问题。但实际业务中数据库大多放在服务器里,你必须妥善处理好…...
不是大厂云用不起,而是五洛云更有性价比
明月代维的一个客户的大厂云境外云服务器再有几天就到期了,续费提醒那是提前一周准时到来,但是看到客户发来的续费价格截图,我是真的没忍住。这不就是在杀熟吗?就这配置续费竟然如此昂贵?说实话这个客户的服务器代维是…...
C++初学者指南-3.自定义类型(第一部分)-异常
C初学者指南-3.自定义类型(第一部分)-异常 文章目录 C初学者指南-3.自定义类型(第一部分)-异常简介什么是异常?第一个示例用途:报告违反规则的行为异常的替代方案标准库异常处理 问题和保证资源泄露使用 RAII 避免内存泄漏!析构函数:不要让异…...
学会python——用python编写一个电子时钟(python实例十七)
目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.电子时钟程序 3.1 代码构思 3.2代码实例 3.3运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性…...
elementui中@click短时间内多次触发,@click重复点击,做不允许重复点击处理
click快速点击,发生多次触发 2.代码示例: //html<el-button :loading"submitLoading" type"primary" click"submitForm">确 定</el-button>data() {return {submitLoading:false,}}//方法/** 提交按钮 */sub…...
助力游戏实现应用内运营闭环,融云游戏社交方案升级!
通信能力在所有应用场景都是必备组件,这源于社交属性带给应用的增长神话。 在游戏场景,玩家从少数核心向大众用户泛化扩展的过程,就是游戏深度融合社交能力的过程。 从单机到联机,游戏乐趣的升级 1996 年,游戏界顶流…...
守护创新之魂:源代码防泄漏的终极策略
在信息化快速发展的今天,企业的核心机密数据,尤其是源代码,成为了企业竞争力的关键所在。然而,源代码的泄露风险也随之增加,给企业的安全和发展带来了巨大威胁。在这样的背景下,SDC沙盒作为一种创新的源代码…...
Halcon 基于分水岭的目标分割
一 分水岭 1 分水岭介绍 传统的分水岭分割方法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是地质学上的拓扑地貌,图像中每一像素的灰度值表示该点的海拔高度,每一个局部极小值及其周边区域称为集水盆地&…...
PHP 面向对象编程(OOP)入门指南
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,通过使用对象来设计和组织代码。PHP作为一种广泛使用的服务器端脚本语言,支持面向对象编程。本文将介绍PHP面向对象编程的基本概念和用法࿰…...
Django学习第三天
python manage.py runserver 使用以上的命令启动项目 实现新建用户数据功能 views.py文件代码 from django.shortcuts import render, redirect from app01 import models# Create your views here. def depart_list(request):""" 部门列表 ""&qu…...
Vue3实现点击按钮实现文字变色
1.动态样式实现 1.1核心代码解释: class"power-station-perspective-item-text": 为这个 span 元素添加了一个 CSS 类,以便对其样式进行定义。 click"clickItem(item.id)": 这是一个 Vue 事件绑定。当用户点…...
深入理解Vue生命周期钩子函数
深入理解Vue生命周期钩子函数 Vue.js 是一款流行的前端框架,通过其强大的响应式数据绑定和组件化的开发方式,使得前端开发变得更加简单和高效。在Vue应用中,每个组件都有其生命周期,这些生命周期钩子函数允许开发者在不同阶段执行…...
Linux-gdb
目录 1.-g 生成含有debug信息的可执行文件 2.gdb开始以及gdb中的常用执行指令 3.断点的本质用法 4.快速跳出函数体 5.其他 1.-g 生成含有debug信息的可执行文件 2.gdb开始以及gdb中的常用执行指令 3.断点的本质用法 断点的本质是帮助我们缩小出问题的范围 比如,…...
Oracle分析表和索引(analyze)
分析表 analyze table tablename compute statistics; 分析索引 analyze index indexname compute statistics; 该语句生成的统计信息会更新user_tables这个视图的统计信息,分析的结果被Oracle用于基于成本的优化生成更好的查询计划 对于使用CBO(Cost-Base Optimization)很有好…...
MyBatis踩坑记录-多表关联字段相同,字段数据覆盖问题
MyBatis踩坑记录-多表关联字段相同,字段数据覆盖问题 1. 背景描述2. 实体记录3. 错误映射3.1 造成的影响 4. 解决办法4.1 修改映射文件 5. 修复后的效果5.1 返回的数据5.2 正确展示 7. end ~ 1. 背景描述 现有一下业务,单个任务下可能会有多个子任务&am…...
昇思25天学习打卡营第6天|数据变换 Transforms
学习目标:熟练掌握数据变换操作 熟悉mindspore.dataset.transforms接口 实践掌握常用变换 昇思大模型平台学习心得记录: 一、关于mindspore.dataset.transforms 1.1 变换 mindspore.dataset.transforms.Compose将多个数据增强操作组合使用。 mindspo…...
在线JSON可视化工具--改进
先前发布了JSON格式化可视化在线工具,提供图形化界面显示结构关系功能,并提供JSON快速格式化、JSON压缩、快捷复制、下载导出、对存在语法错误的地方能明确显示,而且还支持全屏,极大扩大视野区域。 在线JSON格式化可视化工具 但…...
探讨命令模式及其应用
目录 命令模式命令模式结构命令模式适用场景命令模式优缺点练手题目题目描述输入描述输出描述题解 命令模式 命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
