SystemUI导航栏
SystemUI导航栏
- 1、系统中参数项
- 1.1 相关开关属性
- 2.2 属性设置代码
- 2、设置中设置“三按钮”导航更新流程
- 2.1 属性资源覆盖叠加
- 2.2 SystemUI导航栏接收改变广播
- 2.3 SystemUI导航栏布局更新
- 2.4 时序图
android13-release
1、系统中参数项
1.1 相关开关属性
设置->系统->手势->系统导航->“三按钮”导航

- 设置中:
“三按钮”导航
packages/apps/Settings/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
packages/apps/Settings/res/values-zh-rCN/strings.xml
<string name="legacy_navigation_title" msgid="7877402855994423727">"“三按钮”导航"</string>
- 默认导航栏模式:
config_navBarInteractionMode
frameworks/base/core/res/res/values/config.xml<!-- Controls the navigation bar interaction mode:0: 3 button mode (back, home, overview buttons)1: 2 button mode (back, home buttons + swipe up for overview)2: gestures only for back, home and overview --><integer name="config_navBarInteractionMode">0</integer><!-- Whether a software navigation bar should be shown. NOTE: in the future this may beautodetected from the Configuration. --><bool name="config_showNavigationBar">false</bool>
- Settings数据库中:
adb shell settings get Secure navigation_mode
frameworks/base/core/java/android/provider/Settings.java/*** Navigation bar mode.* 0 = 3 button* 1 = 2 button* 2 = fully gestural* @hide*/ @Readable public static final String NAVIGATION_MODE ="navigation_mode";
- prop属性
"qemu.hw.mainkeys":允许系统属性覆盖此设置。由仿真器使用。使用方法hasNavigationBar()- 导航栏高度:
navigation_bar_height
frameworks/base/core/res/res/values/dimens.xml<!-- Height of the bottom navigation / system bar. --><dimen name="navigation_bar_height">48dp</dimen><!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height --><dimen name="navigation_bar_height_landscape">48dp</dimen>
2.2 属性设置代码
设置中显示判断:
String NAV_BAR_MODE_3BUTTON_OVERLAY = "com.android.internal.systemui.navbar.threebutton";:
/product/overlay/NavigationBarMode3Button/NavigationBarMode3ButtonOverlay.apkString NAV_BAR_MODE_2BUTTON_OVERLAY = "com.android.internal.systemui.navbar.twobutton";:
/product/overlay/NavigationBarMode2Button/NavigationBarMode2ButtonOverlay.apkString NAV_BAR_MODE_GESTURAL_OVERLAY = "com.android.internal.systemui.navbar.gestural";:
/product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
packages/apps/Settings/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
static boolean isOverlayPackageAvailable(Context context, String overlayPackage) {try {return context.getPackageManager().getPackageInfo(overlayPackage, 0) != null;} catch (PackageManager.NameNotFoundException e) {// Not found, just return unavailablereturn false;}
}
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;mNavBarMode = mNavigationModeController.addListener(mModeChangedListener);
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
private int getCurrentInteractionMode(Context context) {int mode = context.getResources().getInteger(com.android.internal.R.integer.config_navBarInteractionMode);if (DEBUG) {Log.d(TAG, "getCurrentInteractionMode: mode=" + mode+ " contextUser=" + context.getUserId());}return mode;
}public void updateCurrentInteractionMode(boolean notify) {mCurrentUserContext = getCurrentUserContext();int mode = getCurrentInteractionMode(mCurrentUserContext);mUiBgExecutor.execute(() ->Settings.Secure.putString(mCurrentUserContext.getContentResolver(),Secure.NAVIGATION_MODE, String.valueOf(mode)));if (DEBUG) {Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);dumpAssetPaths(mCurrentUserContext);}if (notify) {for (int i = 0; i < mListeners.size(); i++) {mListeners.get(i).onNavigationModeChanged(mode);}}
}
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
if (mDisplayContent.isDefaultDisplay) {mHasStatusBar = true;mHasNavigationBar = mContext.getResources().getBoolean(R.bool.config_showNavigationBar);// Allow a system property to override this. Used by the emulator.// See also hasNavigationBar().String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");if ("1".equals(navBarOverride)) {mHasNavigationBar = false;} else if ("0".equals(navBarOverride)) {mHasNavigationBar = true;}
} else {mHasStatusBar = false;mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
}
2、设置中设置“三按钮”导航更新流程
2.1 属性资源覆盖叠加
OverlayManagerService 运行时资源叠加层 (RRO)
点击设置后,导航栏模式通过OverlayManagerService服务对config_navBarInteractionMode资源进行叠加,而settings的Secure表中navigation_mode属性只是记录模式。
frameworks/base/services/core/java/com/android/server/om/OverlayManagerService.java
资源叠加主要文件:config.xml
frameworks/base/core/res/res/values/config.xml
/product/overlay/NavigationBarMode3Button/NavigationBarMode3ButtonOverlay.apk
/product/overlay/NavigationBarMode2Button/NavigationBarMode2ButtonOverlay.apk
/product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
updateActivityManager(affectedPackages, userId):发送受覆盖状态更改影响的所有目标包的配置更改事件。broadcastActionOverlayChanged(targets, userId):发送覆盖包已更改广播ACTION_OVERLAY_CHANGED。
private void updateTargetPackagesLocked(@Nullable Set<PackageAndUser> updatedTargets) {if (CollectionUtils.isEmpty(updatedTargets)) {return;}persistSettingsLocked();final SparseArray<ArraySet<String>> userTargets = groupTargetsByUserId(updatedTargets);for (int i = 0, n = userTargets.size(); i < n; i++) {final ArraySet<String> targets = userTargets.valueAt(i);final int userId = userTargets.keyAt(i);final List<String> affectedPackages = updatePackageManagerLocked(targets, userId);if (affectedPackages.isEmpty()) {// The package manager paths are already up-to-date.continue;}FgThread.getHandler().post(() -> {// Send configuration changed events for all target packages that have been affected// by overlay state changes.updateActivityManager(affectedPackages, userId);// Do not send broadcasts for all affected targets. Overlays targeting the framework// or shared libraries may cause too many broadcasts to be sent at once.broadcastActionOverlayChanged(targets, userId);});}
}
2.2 SystemUI导航栏接收改变广播
mReceiver :监听ACTION_OVERLAY_CHANGED广播
Secure.NAVIGATION_MODE:记录导航栏模式改变值
mListeners.get(i).onNavigationModeChanged(mode):通知导航栏模式改变的ModeChangedListener监听
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java
private BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (DEBUG) {Log.d(TAG, "ACTION_OVERLAY_CHANGED");}updateCurrentInteractionMode(true /* notify */);}
};public NavigationModeController(Context context,DeviceProvisionedController deviceProvisionedController,ConfigurationController configurationController,@UiBackground Executor uiBgExecutor,DumpManager dumpManager) {//... ...IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);overlayFilter.addDataScheme("package");overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);//... ...
}public void updateCurrentInteractionMode(boolean notify) {mCurrentUserContext = getCurrentUserContext();int mode = getCurrentInteractionMode(mCurrentUserContext);mUiBgExecutor.execute(() ->Settings.Secure.putString(mCurrentUserContext.getContentResolver(),Secure.NAVIGATION_MODE, String.valueOf(mode)));if (DEBUG) {Log.d(TAG, "updateCurrentInteractionMode: mode=" + mode);dumpAssetPaths(mCurrentUserContext);}if (notify) {for (int i = 0; i < mListeners.size(); i++) {mListeners.get(i).onNavigationModeChanged(mode);}}
}
2.3 SystemUI导航栏布局更新
NavigationModeController通知监听执行onNavigationModeChanged方法更新,最后navBar.getView().updateStates()执行更新界面NavigationBarView:
updateSlippery():更新WindowManager.LayoutParams.FLAG_SLIPERY状态,具体取决于是否启用了向上滑动,或者通知是否在未处于动画状态的情况下完全打开。如果启用了slide,触摸事件将离开导航栏窗口并进入全屏应用程序/主页窗口,如果没有,则手势离开导航栏后,导航栏将收到取消的触摸事件。reloadNavIcons():重新导入导航栏相关图片资源updateNavButtonIcons:更新界面导航栏图标、显示状态,及活动触摸区域
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@Override
public void onNavigationModeChanged(int mode) {if (mNavMode == mode) {return;}final int oldMode = mNavMode;mNavMode = mode;updateAccessibilityButtonModeIfNeeded();mHandler.post(() -> {// create/destroy nav bar based on nav mode only in unfolded stateif (oldMode != mNavMode) {updateNavbarForTaskbar();}for (int i = 0; i < mNavigationBars.size(); i++) {NavigationBar navBar = mNavigationBars.valueAt(i);if (navBar == null) {continue;}navBar.getView().updateStates();}});
}
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
public void updateStates() {if (mNavigationInflaterView != null) {// Reinflate the navbar if needed, no-op unless the swipe up state changesmNavigationInflaterView.onLikelyDefaultLayoutChange();}updateSlippery();reloadNavIcons();updateNavButtonIcons();WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!mShowSwipeUpUi);getHomeButton().setAccessibilityDelegate(mShowSwipeUpUi ? mQuickStepAccessibilityDelegate : null);
}
2.4 时序图

相关文章:
SystemUI导航栏
SystemUI导航栏 1、系统中参数项1.1 相关开关属性2.2 属性设置代码 2、设置中设置“三按钮”导航更新流程2.1 属性资源覆盖叠加2.2 SystemUI导航栏接收改变广播2.3 SystemUI导航栏布局更新2.4 时序图 android13-release 1、系统中参数项 1.1 相关开关属性 设置->系统->…...
3d 贴图下载quixel
Quixel Megascans https://polyhaven.com/a/studio_small_03 Quixel Bridge:3D艺术家的宝库 在3D建模和渲染的世界中,找到高质量、适合项目的贴图素材至关重要。Quixel Bridge就是这样一个为3D艺术家提供大量免费贴图素材的资源库。在本文中ÿ…...
Linux权限维持
SSH 后门 软链接sshd 目标主机建立软连接: ln -sf /usr/sbin/sshd /tmp/su;/tmp/su -oport1189 #端口可以任意指定,最好伪装一下 查看端口: netstat -anlp|grep 1189 攻击机ssh登录: ssh rootx.x.x.x -p 1189 #如果root用户…...
互联网通信的核心协议HTTP和HTTPS
HTTP:超文本传输协议 HTTP,全称为超文本传输协议(Hypertext Transfer Protocol),是一种用于在Web上传输超文本文档的协议。它是Web通信的基础,允许浏览器与Web服务器之间的数据交换。HTTP使用了经典的客户…...
javaWeb网上购物系统的设计与实现
摘 要 随着计算机网络技术的飞速发展和人们生活节奏的不断加快,电子商务技术已经逐渐融入了人们的日常生活当中,网上商城作为电子商务最普遍的一种形式,已被大众逐渐接受。因此开发一个网上商城系统,适合当今形势,更加…...
MySQL 主从复制、读写分离
MySQL 主从复制、读写分离 1、MySQL 主从复制1.1什么是主从复制?1.2为什么要读写分离呢?1.3 什么时候要读写分离?1.4主从复制与读写分离1.5mysql支持的复制类型1.6主从复制的工作过程1.7MySQL 读写分离原理1.8目前较为常见的 MySQL 读写分离分…...
基于虚拟阻抗的下垂控制——孤岛双机并联Simulink仿真
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
windows内核编程(2021年出版)笔记
1. Windows内部概览 1.1 进程 进程包含以下内容: 可执行程序,代码和数据私有的虚拟地址空间,分配内存时从这里分配主令牌,保存进程默认安全上下文,进程中的线程执行代码时会用到它私有句柄表,保存进程运…...
时序预测 | MATLAB实现EMD-iCHOA+GRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测
时序预测 | MATLAB实现EMD-iCHOAGRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测 目录 时序预测 | MATLAB实现EMD-iCHOAGRU基于经验模态分解-改进黑猩猩算法优化门控循环单元的时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 EMD-iCHOAGR…...
FFmpeg 命令:从入门到精通 | FFmpeg 解码流程
FFmpeg 命令:从入门到精通 | FFmpeg 解码流程 FFmpeg 命令:从入门到精通 | FFmpeg 解码流程流程图FFmpeg 解码的函数FFmpeg 解码的数据结构补充小知识 FFmpeg 命令:从入门到精通 | FFmpeg 解码流程 本内容参考雷霄骅博士的 FFmpeg 教程。 流…...
连接虚拟机工具推荐
连接虚拟机工具推荐 连接虚拟机的工具有很多种,以下是一些常用的推荐: PuTTY:这是一个非常常用的SSH和telnet客户端,适用于Windows系统。它允许你在本地机器上通过命令行接口远程登录到虚拟机。 SecureCRT:这是一个支…...
万字详解HTTP协议面试必备技能
目录 一、HTTP 是什么 二、理解 "应用层协议" 2.1理解 HTTP 协议的工作过程 2.2HTTP 协议格式 2.3抓包工具的使用 2.4抓包工具的原理 2.5抓包结果 2.5.1HTTP请求 2.5.2HTTP响应 2.6协议格式总结 三、HTTP 请求 (Request) 3.1认识 URL 3.1.1URL 基本格式 …...
Debian跳过grub页面
nano /etc/default/grub将GRUB_TIMEOUT的值改为0 将GRUB_CMDLINE_LINUX_DEFAULT的值改为"quiet splash" 如果要禁用开局日志的话,将GRUB_CMDLINE_LINUX_DEFAULT的值改为"quiet splash loglevel0" update-grub...
【已解决】RuntimeError Java gateway process exited before sending its port number
RuntimeError: Java gateway process exited before sending its port number 问题 思路 🎯方法一 在代码前加入如下代码(如图): import os os.environ[‘JAVA_HOME’] “/usr/local/jdk1.8.0_221” # 记得把地址改成自己的 …...
数据结构与算法-循环链表、双向链表
我们这里接着上一篇单链表继续往下深入学习循环链表、双向链表。 链表 🎈3.循环链表🔭3.1循环链表的概念🔭3.2循环链表的基本操作🔎3.2.1创建空表🔎3.2.2插入操作🔎3.2.3删除操作 🎈4.双向链表&…...
javascript中依次输出元素并不断循环实现echarts柱图动画效果
循环来遍历数组并输出其中的元素 在JavaScript中,你可以使用循环来遍历数组并输出其中的元素。如果你想要依次输出6个元素并不断循环,可以使用如下的代码: let arr [/* 你的数组 */];for (let i 0; i < arr.length; i) {console.log(a…...
互联网Java工程师面试题·Memcached篇·第一弹
目录 1、Memcached 是什么,有什么作用? 1.1 memcached 服务在企业集群架构中有哪些应用场景? 1.1.1 作为数据库的前端缓存应用 1.1.2 作业集群的 session 会话共享存储 2、Memcached 服务分布式集群如何实现? 3、Memcach…...
git 详解-提升篇
git 冷门使用 承接上一篇 《git 进阶篇》,简单讲解 git 冷门使用方法。 码农常规使用工具 git 偶尔也有非常规操作。例如:提交代码时同事已经更新,但又不想回退本地补丁;或者已经提交补丁需要变更提交日志信息。 作者࿱…...
RPA的安全风险及应对策略
RPA已经深度革新了工作流程,大大提升效率并减少了人为错误,使企业运营更加高效。据预测,至2030年,全球RPA市场将以39.9%的复合年增长率持续发展,这显示了RPA对企业生产力的巨大推动力。 RPA能够承担人类的繁琐工作&am…...
数据结构与算法--贪心算法
数据结构与算法-贪心算法 1 贪心算法的概念 2 贪心算法的套路 3 贪心算法常用技巧 4 会议问题 5 字典序问题 1 贪心算法的概念 在某一标准下,优先考虑最满足标准的样本,最后考虑不满足标准的样本,最终得到一个答案的算法,叫做贪心算法 也就是说 不是从整体上加以考虑,所…...
Pro Workflow:基于SQLite持久化记忆的AI编程助手智能协作系统
1. 项目概述:从重复纠正到智能协作的进化如果你和我一样,每天都在用Claude Code、Cursor这类AI编程助手,那你肯定经历过这个场景:周一你告诉它“测试里别用Mock数据库”,它点头答应;周五你写新功能…...
别再乱用`define了!SV宏定义实战避坑指南(从`ifdef到字符串拼接)
别再乱用define了!SV宏定义实战避坑指南(从ifdef到字符串拼接) 在SystemVerilog开发中,宏定义(define)是提高代码复用性和灵活性的利器,但同时也是隐藏最深的"代码地雷"之一。许多开发…...
工业 DC-DC 设计|钡特电源 DF2-05S05LS 与 F0505S-2WR3 封装互通硬件适配分析
在工业控制、智能传感及嵌入式设备研发中,小功率隔离直流电源模块是板级供电的核心单元,直接影响系统稳定性与长期运行成本。硬件工程师选型时,需重点关注参数匹配、封装适配、环境耐受性及性价比,而钡特电源 DF2-05S05LS 与 F050…...
回流平台深耕闲置翡翠流通,以数字化服务激活珠宝产业新动能
据中国珠宝玉石首饰行业协会数据,我国珠宝玉石首饰产业市场规模持续扩大,翡翠玉石作为第二大珠宝消费品类,市场存量可观。与此同时,发达国家二手高端消费品交易占整个高端消费品市场的20%至30%,我国目前占比约5%&#…...
如何在FF14中实现三倍效率的钓鱼体验?智能计时助手完全解析
如何在FF14中实现三倍效率的钓鱼体验?智能计时助手完全解析 【免费下载链接】Fishers-Intuition 渔人的直感,最终幻想14钓鱼计时器 项目地址: https://gitcode.com/gh_mirrors/fi/Fishers-Intuition 在《最终幻想14》的广阔世界中,钓鱼…...
3个简单步骤掌握gInk:Windows上最轻量的免费屏幕画笔工具
3个简单步骤掌握gInk:Windows上最轻量的免费屏幕画笔工具 【免费下载链接】gInk An easy to use on-screen annotation software inspired by Epic Pen. 项目地址: https://gitcode.com/gh_mirrors/gi/gInk gInk屏幕画笔工具是一款专为Windows用户设计的实时…...
Git Hooks与代码质量左移:self-review工具实战指南
1. 项目概述:从“自我审查”到“代码质量守护者”最近在GitHub上看到一个挺有意思的项目,叫motiful/self-review。光看名字,你可能会觉得这又是一个关于代码审查流程或者团队协作规范的工具。但点进去仔细研究后,我发现它的定位非…...
R语言clusterProfiler包KEGG富集分析报错?别慌,这份2024最新避坑指南帮你搞定
R语言clusterProfiler包KEGG富集分析2024避坑实战指南 当你在深夜的实验室里盯着RStudio不断弹出的红色报错信息,第十次尝试调整enrichKEGG参数却依然看到"replacement has length zero"这个令人绝望的提示时,可能已经忍不住要摔键盘了。这份…...
Linux 2.6内核源码深度解读:kernel/time.c文件分析
一、引言:内核的时间维度与心跳引擎kernel/time.c是Linux内核中掌控时间流动与计时基准的核心文件,它负责将底层硬件时钟的离散脉冲转化为系统可用的连续时间概念,并为内核所有需要计时的功能提供基础设施。在操作系统语境中,&quo…...
ARM Cortex-M位带操作:从原理到实战,实现GPIO原子级高效控制
1. 项目概述:从“点灯”到“位带”,一次底层效率的跃迁如果你是从51单片机或者Arduino这类平台转战到ARM Cortex-M系列微控制器(比如STM32)的开发者,在点亮第一个LED时,可能会感到一丝“别扭”。在51单片机…...
