wms
文章平均质量分 79
千里马学框架
安卓架构师,安卓技术专家,android framework
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Winscope如何让你的系统app在可以展示ViewCapture相关数据?
此方法通过避免为每个窗口使用单独的环形缓冲区来避免过度消耗内存,但无法解决针对每个帧在 Perfetto 中存储每个状态的整个视图层次结构的问题。屏幕录制可以直观呈现视图在特定时间的状态,并显示其变化情况,但它们需要大量的 CPU 资源,并且可能会影响性能。此外,ViewCapture 会在视图级别逐帧显示可视化图表,与屏幕录制相比,可更轻松地检查特定时刻的视图状态。ViewCapture 会捕获窗口内各种视图及其属性的相关信息,以便您了解特定时刻的用户体验状态,并跟踪随时间的变化。:(冒号):分隔符。原创 2026-08-15 22:31:47 · 208 阅读 · 0 评论 -
安卓16王炸更新!四角圆角终于能“各玩各的”
那么请问在SurfaceFlinger中是如何实现对这四个圆角进行单独的弧度设置的?你这边如果自己去实现这个接口你是否有思路呢?然后再结合源码去对比看看哈。简单说我们原来设置的圆角,其实都是整个Task四个角都进行设置圆角,这里明显看到Task的左边没有任何圆角,但是右边都是圆角。如果让你去实现你会去如何设计呢?这样有了这个接口后,就可以轻易实现对四个圆角轻易控制。但是经过调查发现新版本aosp16上发现一个新的。测试结果坐标都是弧度为50,右边弧度为150。老版本aosp14上设置圆角接口只有一个。原创 2026-08-11 14:39:26 · 205 阅读 · 0 评论 -
小鹏车机竞品调研:车机分屏功能的竞品调研和实现方案
可以看到上面的其实也是处于分屏模式,而且分割线在最右侧,左边分屏的区域也是相当于全屏展示着,这个其实和我们三分屏讲解的相关实现,可以把分割线拖动到最右侧,但是这个时候还不退出分屏。1、分屏模式下可以某个分屏task全屏显示,但是这个时候还是分屏模式,分割线显示在边界,可以拖动分割线,重新进入正常比例的分屏。整体难度不大,这里给大家布置小鹏车机分屏给你为学员作业,作业的目标就是实现类似小鹏车机的2个亮点功能既可以。整体调研小鹏车机的分屏功能后,其实整体难度不大,修改难度远比小米su7的三分屏难度要小一些。原创 2026-07-10 12:11:52 · 222 阅读 · 0 评论 -
性能优化比拼:app启动流程之冷热启动Activity的SnapshotWindow
││ ││ └─ taskSwitch + snapshot → SNAPSHOT ← 温启动命中││││═══════ Snapshot 显示中,App 首帧正在绘制 ═══════││添加路径→→→ Binder →移除路径→→ Binder →更多fw实战干货请关注下面“千里马学框架”原创 2026-07-09 15:33:25 · 298 阅读 · 0 评论 -
重重学app冷启动流程桌面点击到SplashWindow显示与移除流程剖析-aosp16
Splash 创建:startSpecificActivity() → showStartingWindow() → getStartingWindowType() 返回 SPLASH_SCREEN→ SplashScreenStartingData → scheduleAddStartingWindow() → IPC → Shell 双线程并行渲染→ Splash 首帧显示 ✓。原创 2026-07-06 14:45:40 · 422 阅读 · 0 评论 -
wms你会吗?一起来分析aosp原生窗口显示bug-vip学员作业
后,正常课程中的10几个实战项目案例学会后,一般都具备了较强的实战能力,有的学员们希望马哥搞一些非课程的案例问题进行实战,想检测自己的实战解决问题能力如何。其实重叠还不是问题本质哈,主要是重叠显示的停留时间有点长,具体看这个窗口显示问题的bug情况。录屏看的话大家可能会觉得看不出啥问题,只看到一闪,因为本身问题可能就持续100ms左右,但是确实是会给出很不好的重影体验。5、给出相关的问题修复方案,这里有的学员可能一开始就说直接关闭动画暴力解决,但是如果不能关闭动画呢如何解决?1、开启设置中的开发者选项。原创 2026-07-01 15:33:21 · 269 阅读 · 0 评论 -
新版负一屏变天了!分享pixel新桌面负一屏技术调研报告
Pixel Launcher 的负一屏不是在 Launcher 进程内嵌入一个 View 或 Fragment,而是利用 Android 12+ 的,在 Launcher 的 Task 内创建一个独立的,将 Google App (Velvet) 的以模式嵌入其中。两个 Activity 拥有各自独立的 Window 和 Surface偏移目标机制层级View 层负一屏 (MinusOneActivity)Surface 层。原创 2026-06-30 15:23:44 · 370 阅读 · 0 评论 -
fw面试折叠屏不会?一起来调研荣耀手机折叠屏原理
硬件层面:两块独立的物理面板(port=147 和 port=148)逻辑层面:Display ID 0/1 是固定编号,窗口和应用挂在逻辑 Display 上不动切换本质:物理面板在两个逻辑 Display 之间"交换",每次只有一个被设为 enabled活跃的标志不活跃的标志控制源头中的enabled属性 →→ 设置 layerStack + 开关设备App 感知:通过收到新的屏幕尺寸/density/挖孔信息,触发重绘。原创 2026-06-24 14:59:09 · 3732 阅读 · 0 评论 -
安卓车载手机原生多屏闪黑问题分析及修复成果展示
注意这里可能会有视频黑屏后图层没有黑屏情况,这个原因前面wms课程blog等中应该讲解过,因为视频的帧率和图层的帧率本事是不一样的,所以二者不能代表每一帧都同步。在多屏启动过程中,主屏幕的task会直接reparent到新的display,但是主屏幕的底部task显示是需要一段时间的,这段时间就会一直黑屏。比如手机刷新率是90帧每秒,但是视频录制的帧率是30帧每秒,所以这块肯定是会有比较大的差异哈。因为底部Task的显示是需要时间的,所以自然在Task还没有显示的这段时间就是黑屏的状态。原创 2026-06-03 12:23:28 · 492 阅读 · 0 评论 -
aosp新增窗口层级 Type 完整实现方案(有源码)-wms需求和面试题
/ --- 插入到 TYPE_STATUS_BAR_ADDITIONAL 之后 ---/*** @hide*/// 2042/*** @hide*/// 2043注册到})注册到。原创 2026-05-30 16:47:16 · 296 阅读 · 0 评论 -
Windows上如何使用Winscope抓取查看数据?解决Windows无法使用Winscope问题
文章中也说明在aosp15如果直接使用编译好的离线html是有问题的,无法正常显示抓取的Winscope文件。那么这个python文件本身和java文件一样,本身就是跨平台的,可以在ubuntu系统系统上正常运行,那也可以windows上运行。这里会显示无法抓取到相关的数据,所以在windows上直接使用ubuntu上的winscope_proxy.py是行不通的。py文件中可能存在ubuntu上面的一些linux特有的方法,和一些特有的特性,这些方法无法在windows进行运行。原创 2026-05-18 12:00:52 · 586 阅读 · 0 评论 -
WMS/AMS深入WindowState如何正确找到自己在层级结构树中位置进行挂载
以下是一个│▼││ └─ mTokenMap.get(binder) → null (首次添加)││ .build()│ ││ └─[3] WindowToken 构造函数│ ││ ├─ mTokenMap.put(binder, token) // 注册到 DisplayContent│ ││ ├─[4] findAreaForToken(token) // 定位 DisplayArea.Tokens。原创 2026-05-11 15:23:59 · 507 阅读 · 0 评论 -
Winscope高级疑问“Invisible due to”是如何来的呢?
因为新版本aosp15的Winscope的html都是需要nodejs才可以拉起运行了,所以这里为了方便分析,拿一个aosp13的Winscope的html,因为这个版本的html是可以直接离线运行,所有的前端核心代码逻辑都在html中。老版本就是跨进程调用SurfaceFlinger的1025接口,把相关proto数据导出到文件中,新版本变成Perfetto了,其实也是差不多的,都是SurfaceFlinger本身提供数据源头。下面开始剖析这个Invisible due to来源问题。原创 2026-03-10 09:31:01 · 413 阅读 · 0 评论 -
分析WM Shell中线程相关的官方帮助文档
这几年WM Shell部分也在不断更新,而且基本上互联网,AI等对于WM Shell的知识几乎是空白的啥也搜不到,马哥这边对于WM Shell出了自己去代码调研以外,也会经常去寻找一些官方的文档资料进行学习,下面就是关于WM Shell相关的官方文档路径。今天分享一下我们比较陌生的的WM Shell的线程知识,针对这块我们一起看着官方文档学习哈,有啥要讨论分享的知识可以vip群中讨论发言哈。原创 2026-03-05 14:52:29 · 472 阅读 · 0 评论 -
wms开发常用调试开发技巧之WMShell的实用命令
这里有几个WMShell下面还有若干个子命令compatui,protolog,splitscreen等,可以使用这些子命令进行更加精确的控制WMShell相关的一些给你,当然如果没有输入任何子命令情况下,那就是默认输入所有WMShell的内部dump输出。在wms窗口开发工程师日常工作中,经常需要和WMShell打交道,比如分屏,自由窗口,startingwindow等都移入到了WMShell中。我们比较熟悉的SplitScreen相关,Pip相关,单手模式等都有相关的dump信息输出。原创 2025-11-30 21:21:01 · 875 阅读 · 0 评论 -
分屏SplitScreen干货技能:如何监听分屏Task进入退出及上下分屏位置
***//***//***/aidl接口主要有两个接口:onStagePositionChanged --代表分屏的stage位置有变化的时候回调,正常都是main side stage 值一般为0,1onTaskStageChanged --代表分屏task的有变化时候回调,比如退出分屏,进入分屏和2个参数stage,visible。stage代表当前taskId处于main还是side stage的位置,值一般为0,1上下分屏,如果-1就是退出分屏。原创 2025-11-13 11:48:06 · 1158 阅读 · 0 评论 -
AMS干货技能:如何监听Task前后台切换事件之TaskStackListener原理剖析
上面就是经典的监听系统task相关的情况的TaskStackListener,task变化的相关回调方法很多,它实际上是一个binder的实现端 ITaskStackListener.Stub,它的客户调用端,那当然是ATMS端。下面来展示一下上面的TaskStackListener监听的效果,这块我们就直接使用Launcher代码中TopTaskTracker类来进行实战测试,通过log打印既可以看出Task相关变化。什么时候Activity退出了?当前分屏的显示的是哪个Task,分屏是不是退出了?原创 2025-11-12 12:18:53 · 1117 阅读 · 0 评论 -
google官方文档教你使用 Winscope 捕获跟踪记录
您可在本地运行 Winscope 或通过 Web 服务器访问它。您可以使用 Winscope 捕获跟踪记录以进行本地开发和调试。Winscope 使用 adb,后者支持通过 USB 或 Wi-Fi 连接设备。启动 Winscope 后,系统会显示 Collect Traces 界面。原创 2025-11-03 09:42:04 · 1428 阅读 · 0 评论 -
windows系统上aosp15上winscope离线html如何使用?
文章中也说明在aosp15如果直接使用编译好的离线html是有问题的,无法正常显示抓取的Winscope文件。针对这样一个问题对于有些同学来说还是很不友好,因为很可能他们不想搭建node相关的环境,那么针对 aosp15上Winscope离线的html是否真的不可以使用呢?所以核心就是要安装http-server,它的安装有多种方式这里主要介绍npm安装方式。原创 2025-10-31 23:46:18 · 1198 阅读 · 0 评论 -
学员投稿:wms优化改进dumpsys层级结构树显示具体层级数字
因为这里的Leaf:3:12本身属于一个范围节点,而且本身这个节点下面就一个子节点,也就是说3-12层都是最后都是只装了一个窗口,没有再细分其他层级窗口节点,所以你可以认为这个3-12是一个整体上的一层既可以。原创 2025-10-26 10:46:28 · 962 阅读 · 0 评论 -
干货分享:aosp13锁屏壁纸部分原理剖析
这里主要就是到DataSystem目录获取对应的目录/data/system/users/0,加上锁屏壁纸对应的文件名字wallpaper_lock_orig,wallpaper_lock,构造出对应的File文件对象。到此服务端返回了fd后就业务完成,下面就是跨进程传递fd客户端,客户端拿到了fd后进行数据写入,这块回到最开头的WallpaperManager.java的setStream方法既可以。这里在设置的壁纸中就有壁纸设置的入口,选择正确壁纸图片,然后可以选着设置锁屏还是桌面壁纸。原创 2025-10-21 12:10:47 · 832 阅读 · 0 评论 -
手把手分析no focused window疑难ANR详细视频+笔记-千里马实战wms专题课程
验证确实发现ANR的Activity窗口的flag是fl=NOT_FOCUSABLE ,所以这个anr可以确诊为属于app自身设置了NOT_FOCUSABLE的flag。可以看到都为false,自然就不会有上面的Focus request,那么为啥这里的canReceive=false,日志也有打印reason。先有新窗口Focus request,再有上一个窗口的Focus leaving,最后有新窗口的Focus entering。所以am_anr日志看到的时间点正确是anr真实发生时间。原创 2025-09-28 11:00:04 · 1117 阅读 · 0 评论 -
安卓闪黑工具:aosp16版本Winscope之搜索功能剖析
在aosp16的Winscope体验时候发现多了数据的搜索功能,也体验了一下,这个新功能本身Winscope也自带了很多指导提示,主要是用来解决Winscope有时候寻找某个数据,某个layer时候的不便,本文来详细介绍一下这块搜索如何使用的内容。例如,在重复字段 visible_region.rect 的两个实例中,top 字段分别由 visible_region.rect[0].top 和 visible_region.rect[1].top 表示。使用左侧面板时,系统会开始搜索跟踪记录。原创 2025-08-27 12:00:29 · 1288 阅读 · 0 评论 -
aosp15/16版本Winscope新特性ViewCapture实战支持
此方法通过避免为每个窗口使用单独的环形缓冲区来避免过度消耗内存,但无法解决针对每个帧在 Perfetto 中存储每个状态的整个视图层次结构的问题。屏幕录制可以直观呈现视图在特定时间的状态,并显示其变化情况,但它们需要大量的 CPU 资源,并且可能会影响性能。此外,ViewCapture 会在视图级别逐帧显示可视化图表,与屏幕录制相比,可更轻松地检查特定时刻的视图状态。ViewCapture 会捕获窗口内各种视图及其属性的相关信息,以便您了解特定时刻的用户体验状态,并跟踪随时间的变化。原创 2025-08-25 01:03:08 · 1300 阅读 · 0 评论 -
必读干货:aosp/安卓16版本winscope编译踩坑过程及相关新特性介绍
Winscope这个开发工具其实每个安卓版本都在更新,而且每个版本的编译方法都有所不同,一般新版本Winscope和设备安卓版本还要进行匹配,不然可能会存在一定的兼容性问题。在以前14,15初期rc版本,其实不会有这个网络问题,那时候不会去Fetch,那么现在这个问题怎么办呢?那只能考虑楼梯啦,具体方法大家自己考虑哈,反正要解决你的terminal可以访问google既可以。今天受vip学员的求助,我们来探索aosp16版本Winscope编译全过程及相关的新特性体验。原创 2025-08-24 00:28:25 · 2132 阅读 · 0 评论 -
安卓闪黑黑屏分析工具:aosp14/15版本Winscope之时间轴部分使用剖析
点击展开图标后,Winscope 会显示一个更大的时间轴,其中包含所有跟踪记录。与迷你时间轴类似,展开式时间轴还提供缩放功能并支持快捷导航,从而增强用户与时间轴互动时的控制和精确度。如果你在某项特定跟踪记录的最后一个时间戳之后点击,Winscope 会加载该跟踪记录的最后一个时间戳。如果您放大过度,可以随时点击放大和缩小按钮旁边的刷新按钮 (时间轴重置按钮),将缩放级别重置为与第一个查看器标签页对应的轨迹长度。注意:箭头导航可在所选时间轴行(如果您点击了时间轴)或打开的跟踪记录标签页的状态之间跳转。原创 2025-08-20 11:04:28 · 963 阅读 · 0 评论 -
干货:aosp14/15版本Winscope各个功能使用详细说明(一)
Show diff 功能会以红色突出显示已移除的元素,以蓝色突出显示已修改的元素,并以绿色突出显示已创建的新元素。一个适用于 Winscope 视图(例如 WindowManager、SurfaceFlinger 和 ViewCapture)的 LAYERS 面板,包含来自跟踪记录的矩形元素,可直观地呈现其在 Z 轴上的位置和顺序。在 SurfaceFlinger 视图中,当在具有多个显示屏的设备上录制数据时,系统会显示一个菜单,其中包含可用的屏幕,以便您仅选择感兴趣的显示屏。原创 2025-08-19 09:02:10 · 1379 阅读 · 0 评论 -
重学WMS层级结构单手OneHanded Feature作用-源码分析
2、单手设置本质就是对上面所有FEATURE_ONE_HANDED的WindowContainer进行位置Y方向的偏移。1、收集所有的Feature为FEATURE_ONE_HANDED的WindowContainer,进行保存到集合。这里OneHandedTransitionAnimator又是由ofYOffset方法导致的构造。那么这里的mDisplayAreaTokenMap又是哪里设置的呢?那么看看这里的leash是哪里传递过来的。那么这里的mLeash又是哪来的呢?原创 2025-07-30 17:24:49 · 753 阅读 · 0 评论 -
重学wms的Feature之FEATURE_WINDOWED_MAGNIFICATION剖析
3、对系统的display的图层会进行Mirror,创建出一个新的MirroRoot图层,下面挂载了系统层级结构的Mirror图层,名字一般会在后面加上“(Mirror)”字样,内容和源图层一样。而且这些图层是有本质上是Mirror了现有的图层,比如桌面和壁纸都显示在放大镜的区域,而且只有放大镜的区域桌面和壁纸是放大的,其他非放大镜区域就是正常显示,那么是如何实现这样呢?但是大家是否有一个很大疑问?2、放大镜功能开启后,会创建对应的Windowless窗口,而且这个窗口有对应的SurfaceView。原创 2025-07-30 16:06:29 · 722 阅读 · 0 评论 -
深入再学wms:系统辅助放大镜功能原理剖析--学员作业
窗口放大功能Android 12 中引入的局部屏幕放大功能为弱视用户提供了经过改进的视图选项。弱视用户可能佩戴有一定度数的眼镜,或者由于环境条件或疾病而暂时难以看清屏幕。暂时性困难可能由过度照明或用户极度疲劳等原因导致。Android 12 中的局部屏幕放大功能让用户能够在整个屏幕放大和局部屏幕放大之间切换。使用局部屏幕放大功能,用户可以在屏幕上拖动放大的局部屏幕来查看不同区域。放大功能启用时,系统会显示一个可让用户切换到整个屏幕放大功能的切换按钮。原创 2025-07-29 12:54:42 · 506 阅读 · 0 评论 -
重学wms:你知道什么是AdjacentTask吗?分屏模式的判断方法
但是大家注意哈,正常情况下确实一般分屏模式的两个task是mode为multi-window,但是大家注意mutilwindow却不一定为分屏模式哈,比如以前的车载桌面那个Activity嵌入显示的模式,也是multiwindow但不是分屏模式。这里的AdjacentTask属于熟悉而又陌生的方法,熟悉在于你经常见到它在framework代码中,陌生在于你可能没有本质理解它什么意思,想不到它的实际场景。简单说就是Task1和Task2分别设置对方成为自己的AdjacentTask,形成如下图的依赖模式。原创 2025-05-20 08:30:00 · 1257 阅读 · 0 评论 -
安卓陌生知识点:IntentFirewall组件启动“防火墙”实战方式
源码位置:组件IntentFirewall的作用IntentFirewall是Android框架中的一个组件,它可以根据XML文件中定义的规则来控制Intent的发送和接收。Intent是Android中用于组件间通信和启动的一种消息对象,它可以携带动作、数据、类别等信息。IntentFirewall可以根据Intent的属性和调用者的信息,决定是否允许或拒绝Intent的传递,从而增强系统的安全性和灵活性。原创 2025-05-02 01:14:38 · 1094 阅读 · 0 评论 -
android如何不修改系统代码拦截Activity启动禁止打开某些应用在车机行车过程?-学员答疑总结
这个学员大概思路就是,可以在桌面applist图标点击进行屏蔽,这个明显不行哈,首先不说改了Launcher代码,最重要是只是applist点击进行屏蔽根本无法覆盖,你能保证你的app启动都是通过桌面点击么,完全有可能其他场景,比如后台service启动,或者其他Activity拉起。注释明显看出IActivityController实际上是监测AMS一些实际的发生接口,一般用于一些测试来监测系统的Activity的一些状态,这个不针对普通第三方app,属于一个隐藏api,不过对于系统app肯定是可见的。原创 2025-04-02 12:32:14 · 1106 阅读 · 0 评论 -
你知道桌面和壁纸Wallpaper都接收触摸事件原理吗?--第二篇
更多framework实战干货,请关注下面“千里马学框架”原创 2025-03-27 12:57:09 · 1008 阅读 · 0 评论 -
聊一聊安卓WallpaperService壁纸窗口触摸事件接收原理-第一篇
1、壁纸窗口本身在创建时候就已经有创建好对应的InputChannel,而且也会和正常窗口一样会有InputWindow在InputDispatcher,而且位置一般处于最底层2、要让壁纸可以接收事件,需要调用 setTouchEventsEnabled(true),主要是把Window不进行设置NOT_TOUCHABLE的flag。原创 2025-03-26 11:32:43 · 1674 阅读 · 0 评论 -
aosp15上winscope离线html如何使用?
文章中也说明在aosp15如果直接使用编译好的离线html是有问题的,无法正常显示抓取的Winscope文件。针对这样一个问题对于有些同学来说还是很不友好,因为很可能他们不想搭建node相关的环境,那么针对 aosp15上Winscope离线的html是否真的不可以使用呢?不过我们可能不关心原因,因为这块毕竟属于前端的知识,我们更关心应该怎么解决。原创 2024-12-10 23:14:23 · 2265 阅读 · 1 评论 -
Winscope中抓取window相关数据的原理剖析
因为Winscope是一个动态的过程,属于数据是不断变化的而上面只是开始抓取时候有往mBuffer中添加,那么是什么地方可以触发这个WindowTracing源源不断的打入log,即添加到mBuffer中?可以看出来这里会有一个很重要的 mRoot.dumpDebug,mRoot就是RootWindowContainer,它会迭代dump出来整个wms层级结构的所有数据的详细信息,这样也是浏览器上可以绘制层级结构详细信息的关键。然后主要看看WindowManagerShellCommand的相关的方法。原创 2024-11-30 12:02:34 · 1327 阅读 · 0 评论 -
Winscope重要干货知识点RelativeLayer相关的查看方式
实际查看明显发现SurfaceView位于Activity图层下面,和上面winscope的看着是有冲突的,那么这个到底是winscope不准确有问题,还是我们有啥知识点遗漏呢?这个部分就是相当于图层顺序的核心哈,其实winscope就已经有针对这个相对图层有明显的标识。这里winscope明显可以看到SurfaceView图层上相比其他图层还有一写标识上的差异,多了一些RelZ,和RelZParent这样的标识。Background for SurfaceView其实是位于Activity图层的下面。原创 2024-11-17 12:11:36 · 1005 阅读 · 0 评论 -
安卓aosp15手机上如何离线获取winscope文件
哈哈当然不是哈,只是aosp15新版本的手机上离线抓取已经一起整合到了perfectto部分了,不和原来一样抓取方式,所以自然原来按钮就去除了,接下来就重点给大家讲解aosp15上如何离线抓取winscope。这篇文章搭建的winscope的方式同样适用于aosp15版本,只需要使用最新的aosp15相关的源码环境的winscope依赖既可以完成编译。然后点击上面的Record trace按钮可以开始抓取了,点击结束抓取后可以看到如下路径data/local/traces已经有相关的文件。原创 2024-11-15 09:30:00 · 1021 阅读 · 0 评论 -
安卓手机/平板等设备添加左右两边侧边栏需求项目-学员作业布置
近期有学员朋友求助一个给安卓设备的左右两边要加入侧边栏的需求,这个需求其实还和平时的系统自带的Navigationbar,或者StatusBar等窗口不一样。因为无论是Navigationbar,或者StatusBar都是属于和手机屏幕画面是一起的,而这个左右侧边栏的需求是想把主屏幕画面和侧边栏画面是独立的,二者互不干扰的情况。3、侧边栏的画面不会因为正常手机画面的页面跳转而被覆盖,侧边栏点击相关按钮可以让正常手机画面有页面跳转等操作交互。1、input相关的触摸知识部分。2、wms相关的知识。原创 2024-11-11 09:25:49 · 621 阅读 · 0 评论
分享