Android 16系统源码_自由窗口(一)触发自由窗口模式
前言
从 Android 7.0 开始,Google 推出了一个名为“多窗口模式”的新功能,允许在设备屏幕上同时显示多个应用,多窗口模式允许多个应用同时共享同一屏幕,多窗口模式(Multi Window Supports)目前支持以下三种配置:
分屏模式:让系统可以左右或上下并排显示应用。
画中画模式:在应用中用小窗口叠加显示其他应用
自由窗口模式:在可移动且可调整大小的单独窗口中显示各个应用。
本系列文章我们主要来分析一下自由窗口模式相关的知识点。
通过最近任务进入自由窗口模式
打开Activity,然后进入最近任务触发自由窗口,可以成功进入自由窗口模式,具体可以参考下图。
默认情况下在最近任务列表中点击应用图标,弹出的菜单列表中是没有自由窗口这个选项的,可以通过以下两种方式开启。
1、进入开发者模式页面进行开关开启
2、通过adb指令开启
adb shell settings put global force_resizable_activities 1 //强制应用支持自由缩放
adb shell settings put global enable_freeform_support 1 //开启自由窗口功能
adb shell am restart 或者 adb reboot
其实开发者模式页面的两个开关,本质也是修改force_resizable_activities和enable_freeform_support这两个数据库字段。
adb指令进入自由窗口模式
adb shell am start-activity --windowingMode 5 <package/activity>
全屏/自由窗口层级树信息对比
我使用的安卓模拟器屏幕尺寸为1080x2400,通过adb shell dumpsys activity containers指令可以将Activity的层级树信息导出来,这里我们分别导出全屏模式和自由窗口模式下页面层级树的信息,看看二者有什么不同。
全屏模式层级树信息
全屏模式下层级树的DefaultTaskDisplayArea节点信息如下所示。
#1 DefaultTaskDisplayArea type=undefined mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#3 Task=18 type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ActivityRecord{a200ce1 u0 com.example.myapplication/.MainActivity t18} type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ac18fc1 com.example.myapplication/com.example.myapplication.MainActivity type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#2 Task=1 type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 Task=10 type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ActivityRecord{918f596 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t10} type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 c296ee2 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#1 Task=8 type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ActivityRecord{6fa0b29 u0 com.android.dialer/.main.impl.MainActivity t8} type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 c7c5ed4 com.android.dialer/com.android.dialer.main.impl.MainActivity type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 Task=2 type=undefined mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#1 Task=4 type=undefined mode=multi-window override-mode=multi-window requested-bounds=[0,2400][1080,3600] bounds=[0,2400][1080,3600]#0 Task=3 type=undefined mode=multi-window override-mode=multi-window requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]
在全屏模式下MainActivity的相关信息如下:
- 根Task的mode=fullscreen(全屏模式),bounds=[0,0][1080,2400]
- 父节点ActivityRecord的mode=fullscreen(全屏模式),bounds=[0,0][1080,2400]
- MainActivity的mode=fullscreen(全屏模式),bounds=[0,0][1080,2400]
自由窗口模式层级树信息
自由窗口模式下层级树的DefaultTaskDisplayArea节点信息如下所示。
#1 DefaultTaskDisplayArea type=undefined mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#3 Task=18 type=standard mode=freeform override-mode=freeform requested-bounds=[50,113][590,1313] bounds=[50,113][627,1313]#0 ActivityRecord{a200ce1 u0 com.example.myapplication/.MainActivity t18} type=standard mode=freeform override-mode=undefined requested-bounds=[0,0][0,0] bounds=[50,113][627,1313]#0 62f1d77 com.example.myapplication/com.example.myapplication.MainActivity type=standard mode=freeform override-mode=undefined requested-bounds=[0,0][0,0] bounds=[50,113][627,1313]#2 Task=1 type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 Task=10 type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ActivityRecord{918f596 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t10} type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 c296ee2 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher type=home mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#1 Task=8 type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 ActivityRecord{6fa0b29 u0 com.android.dialer/.main.impl.MainActivity t8} type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 c7c5ed4 com.android.dialer/com.android.dialer.main.impl.MainActivity type=standard mode=fullscreen override-mode=undefined requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#0 Task=2 type=undefined mode=fullscreen override-mode=fullscreen requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]#1 Task=4 type=undefined mode=multi-window override-mode=multi-window requested-bounds=[0,2400][1080,3600] bounds=[0,2400][1080,3600]#0 Task=3 type=undefined mode=multi-window override-mode=multi-window requested-bounds=[0,0][0,0] bounds=[0,0][1080,2400]
在自由窗口模式下MainActivity的相关信息如下:
- 根Task的mode=freeform(自由模式),bounds=[50,113][627,1313]
- 父节点ActivityRecord的mode=freeform(自由模式),bounds=[50,113][627,1313]
- MainActivity的mode=freeform(全屏模式),bounds=[50,113][627,1313]
自由窗口模式SurfaceFlinger信息可见图层信息
Display 4619827259835644672 (active) HWC layers:
---------------------------------------------------------------------------------------------------------------------------------------------------------------Layer nameZ | Window Type | Comp Type | Transform | Disp Frame (LTRB) | Source Crop (LTRB) | Frame Rate (Explicit) (Seamlessness) [Focused]
---------------------------------------------------------------------------------------------------------------------------------------------------------------Wallpaper BBQ wrapper#63rel 0 | 0 | DEVICE | 0 | 0 0 1080 2400 | 21.0 47.0 440.0 977.0 | [ ]
---------------------------------------------------------------------------------------------------------------------------------------------------------------com.android.launcher3/com.android.la[...]3.uioverrides.QuickstepLauncher#1179rel 0 | 1 | DEVICE | 0 | 0 0 1080 2400 | 0.0 0.0 1080.0 2400.0 | [ ]
---------------------------------------------------------------------------------------------------------------------------------------------------------------com.example.myapplication/com.example.myapplication.MainActivity#1192rel 0 | 1 | DEVICE | 0 | 50 113 627 1313 | 0.0 0.0 577.0 1200.0 | [*]
---------------------------------------------------------------------------------------------------------------------------------------------------------------Caption of Task=42#1199rel 0 | 0 | DEVICE | 0 | 50 113 627 223 | 0.0 0.0 577.0 110.0 | [ ]
---------------------------------------------------------------------------------------------------------------------------------------------------------------StatusBar#80rel 0 | 2000 | DEVICE | 0 | 0 0 1080 63 | 0.0 0.0 1080.0 63.0 | [ ]
---------------------------------------------------------------------------------------------------------------------------------------------------------------NavigationBar0#76rel 0 | 2019 | DEVICE | 0 | 0 2274 1080 2400 | 0.0 0.0 1080.0 126.0 | [ ]
---------------------------------------------------------------------------------------------------------------------------------------------------------------
- Caption of Task=42#1199 自由窗口顶部的菜单栏
总结
经过对比可以发现
- 当应用Activity处于全屏模式的时候,Activity,父节点ActivityRecord,根Task全部为fullscreen(全屏模式),根Task直接挂载在DefaultTaskDisplayArea节点上。
- 而当应用Activity处于自由窗口模式的时候,Activity,父节点ActivityRecord,根Task全部为freeform(自由模式),该Task直接挂载在DefaultTaskDisplayArea叶子节点上。
- 当处于自由模式的时候,系统会为自由窗口添加一个名为Caption of Task的顶部菜单栏视图。
理解了这些,后面我们再结合Android系统任务栈的特性,才能够更好的理解分屏模式框架的实现思路。
相关文章:

Android 16系统源码_自由窗口(一)触发自由窗口模式
前言 从 Android 7.0 开始,Google 推出了一个名为“多窗口模式”的新功能,允许在设备屏幕上同时显示多个应用,多窗口模式允许多个应用同时共享同一屏幕,多窗口模式(Multi Window Supports)目前支持以下三种…...

sqli-labs第十八关——POST-UA注入
一:判断注入类型 先在用户名和密码框尝试判断,发现都得不到需要的回显 所以查看源码 可以发现username和password的输入后端都做了检查,没法直接注入 所以我们尝试uagent注入 UA注入: 没有url解码处理只识别原始空格ÿ…...
流式优先架构:彻底改变实时数据处理
近年来,随着现代组织的数据环境日趋复杂且高速流动,传统数据库系统已难以满足实时分析、物联网应用以及即时决策的需求。围绕批处理和静态数据模型设计的 RDBMS(关系型数据库管理系统)在架构层面缺乏实时处理能力,而流…...
WebSockets 在实时通信中的应用与优化
WebSockets 在实时通信中的应用与优化 1. 引言 在现代互联网应用中,实时通信 已成为许多场景的核心需求,如在线聊天、直播互动、在线游戏、实时数据推送等。而传统的 HTTP 轮询或长轮询方式往往伴随着 高延迟、资源浪费 等问题,使得开发者在…...
零基础教程:用 Docker + pgloader 将 MySQL 数据库迁移到 PostgreSQL
在日常开发中,可能会遇到从 MySQL 迁移到 PostgreSQL 的需求。你也许是: 正在准备从传统架构转向云原生;想使用 PostgreSQL 更强的事务与 JSON 支持;想统一团队数据库技术栈;纯粹为了尝试学习不同的数据库系统。别担心,无需手动写导出脚本,无需配置复杂工具,只需借助 D…...

mac上安装 Rust 开发环境
1.你可以按照提示在终端中执行以下命令(安全、官方支持): curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh然后按提示继续安装即可。 注意:安装过程中建议选择默认配置(按 1 即可)。 如果遇…...
解决RedisTemplate的json反序列泛型丢失问题
背景 在使用redisTemplate操作redis时我们针对对象的序列化通常将序列化成json存储到redis。一般如下配置 Bean ConditionalOnMissingBean public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory redisConnectionFactory, ObjectProvider<RedisT…...
【Elasticsearch】创建别名的几种方式
在 Elasticsearch 中,有以下几种创建索引别名的方式: 1. 在创建索引时指定别名 在创建索引时,可以直接在索引定义中指定别名。这种方式可以在索引创建的同时完成别名的绑定,避免后续的额外操作。 示例: json PUT /te…...
【JAVA】中文我该怎么排序?
📘 Java 中文排序教学文档(基于 Collator) 🧠 目录 概述Java 中字符串排序的默认行为为什么需要 Collator使用 Collator 进行中文排序升序 vs 降序排序自定义对象字段排序多字段排序示例总结对比表附录:完整代码示例 …...

《C 语言字符串操作从入门到实战(下篇):strncpy/strncat/strstr 等函数原理与实现》
目录 七. strncpy函数的使用与模拟实现 7.1 strncpy函数理解 7.2 strncpy函数使用示例 7.3 strncpy函数模拟实现 八. strncat函数的使用与模拟实现 8.1 strncat函数理解 8.2 strncat函数使用示例 8.3 strncat函数模拟实现 九. strncmp函数的使用 9.1 strncmp函数理…...

百度飞桨PaddleOCR 3.0开源发布 OCR精度跃升13%
百度飞桨 PaddleOCR 3.0 开源发布 2025 年 5 月 20 日,百度飞桨团队正式发布了 PaddleOCR 3.0 版本,并将其开源。这一新版本在文字识别精度、多语种支持、手写体识别以及高精度文档解析等方面取得了显著进展,进一步提升了 PaddleOCR 在 OCR …...

Xilinx 7Series\UltraScale 在线升级FLASH STARTUPE2和STARTUPE3使用
一、FPGA 在线升级 FPGA 在线升级FLASH时,一般是通过逻辑生成SPI接口操作FLASH,当然也可以通过其他SOC经FPGA操作FLASH,那么FPGA就要实现在启动后对FLASH的控制。 对于7Series FPGA,只有CCLK是专用引脚,SPI接口均为普…...

数字孪生驱动的离散制造智能升级:架构设计与工程实践
针对离散制造行业多品种、小批量的生产特性,本文提出一种基于数字孪生的智能制造解决方案。以某国家级智能制造试点示范项目为载体,构建"云-边-端"协同的数字孪生系统,实现设备综合效率(OEE)提升28.7%、订单…...

9.4在 VS Code 中配置 Maven
在 VS Code 中配置 Maven 需要完成 Maven 环境安装 一、安装 Maven(如果未安装) 下载 Maven 访问 Apache Maven 官网,下载最新版本的 Maven(如apache-maven-3.9.9-bin.zip)。 解压文件 将下载的 ZIP 文件解压到本地目…...
mmaction2——tools文件夹下
build_rawframes.py 用法示例 python tools/data/build_rawframes.py data/videos data/frames --task rgb --level 2 --ext mp4 --use-opencv --num-worker 8总结: 只需要 RGB 帧,推荐 --use-opencv,简单高效,无需额外依赖。 …...

新能源汽车充电桩资源如何利用资源高效配置?
新能源汽车充电桩资源的高效配置是实现绿色交通转型的关键环节。随着新能源汽车保有量的快速增长,充电基础设施的供需矛盾日益凸显。如何优化充电桩资源布局、提升使用效率、平衡不同场景需求,成为当前亟待解决的问题。以下是几点关于充电桩资源高效配置…...
python 程序实现了毫米波大规模MIMO系统中的信道估计对比实验
python 程序实现了毫米波大规模MIMO系统中的信道估计对比实验 import numpy as np import matplotlib.pyplot as plt import tensorflow as tf from tensorflow.keras.models import Sequential, Model from tensorflow.keras.layers...
NTFS0x90属性和0xa0属性和0xb0属性的一一对应关系是index_entry中的index_node中VCN和runlist和bitmap
第一部分: 0: kd> dt _FILE_RECORD_SEGMENT_HEADER 0xc1241400 Ntfs!_FILE_RECORD_SEGMENT_HEADER 0x000 MultiSectorHeader : _MULTI_SECTOR_HEADER 0x008 Lsn : _LARGE_INTEGER 0x80e74aa 0x010 SequenceNumber : 5 0x012 Referen…...
PDF 编辑批量拆分合并OCR 识别
各位办公小能手们!你们有没有过被PDF文件折磨得死去活来的经历?反正我是有,每次要编辑PDF,那叫一个费劲啊!不过呢,今天我要给大家介绍一款神器——WPS PDF to Word,有了它,PDF编辑那…...

LeetCode --- 450周赛
题目列表 3550. 数位和等于下标的最小下标 3551. 数位和排序需要的最小交换次数 3552. 网格传送门旅游 3553. 包含给定路径的最小带权子树 II 一、数位和等于下标的最小下标 直接模拟计算数位和即可,代码如下 // C class Solution { public:int smallestIndex(ve…...

SpringBoot中消息转换器的选择
SpringBoot返回xml-CSDN博客 是返回JSON 还是XML 是由内容协商机制确认的,SpringBoot为了开发便利性,如果我没有该消息转换器,默认就返回了JSON,如果需要XML那么,引入 <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>…...
(初级)前端初学者入门指南:HTML5与CSS3核心知识详解
对于前端初学者来说,掌握HTML5和CSS3的基础知识是构建现代化网页的第一步。本文将围绕语义化标签、多媒体嵌入、盒模型、Flexbox布局和Grid布局五大核心知识点展开,通过代码示例和详细解析帮助大家快速上手。 一、HTML5:从结构到交互的革新 …...

基于点标注的弱监督目标检测方法研究
摘要 在计算机视觉领域,目标检测需要大量精准标注数据,但人工标注成本高昂。弱监督目标检测通过低成本标注训练模型,成为近年研究热点。本文提出一种基于点标注的弱监督目标检测算法,仅需在图像中物体中心点标注,即可高…...
【RichTextEditor】 【分析2】RichTextEditor设置文字内容背景色
【RichTextEditor】 【分析2】RichTextEditor设置文字内容背景色 都说AI Coder的Cursor很牛,也付费用了, 但这个背景色,搞了一天也没改过来。 最后,让它分析该控件的层次结构及文本内容显示的位置。 然后,搞定&#…...

超越OpenAI CodeX的软件工程智能体:Jules
目前AI编码代理(coding agent)领域正迅速崛起,Google推出了一款名为Jules的非同步编码代理(asynchronous coding agent),主要针对专业开发者,与传统在开发环境中直接辅助编码的Cursor或Windsurf…...
Qt实战教程:设计并实现一个结构清晰、功能完整的桌面应用
概述 本文以文本编辑器项目作为示例,文本编辑器是一个非常适合新手入门的经典项目。它具备了桌面应用开发中的核心要素: 窗口管理菜单栏和工具栏文件操作(打开、保存)多文档支持(可选)国际化支持(多语言)插件系统(进阶扩展)通过这个项目,你将学习到如何使用Qt进行桌…...

轻量化MEC终端 特点
MEC(多接入边缘计算)解决方案通过将计算能力下沉至网络边缘,结合5G网络特性,已在多个行业实现低延迟、高可靠、高安全的应用部署。以下从技术架构、核心优势及典型场景三方面进行总结: 一、技术架构 分层设计 MEC架…...

NIST提出新型安全指标:识别潜在被利用漏洞
美国国家标准与技术研究院(NIST)近日公布了一项突破性的安全指标,旨在评估哪些软件漏洞可能已被利用——即使相关组织尚未察觉。 这项由前NIST专家Peter Mell和网络安全与基础设施安全局(CISA)Jonathan Spring共同完成…...

List介绍
什么是List 在集合框架中,List是一个接口,继承自Collection Collection也是一个接口,该接口中规范了后序容器中常用的一些方法 Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下࿱…...

正则表达式全解:一文学会正则表达式【附在线正则表达式练习网站】
1.正则表达式的作用 案例演示 先给大家看一个例子,在以下文本中存储了一些职位信息: Python3 高级开发工程师 上海互教教育科技有限公司上海-浦东新区2万/月02-18满员 测试开发工程师(C++/python) 上海墨鹍数码科技有限公司上海-浦东新区2.5万/每月02-18未满员 Python3 …...