重学WMS层级结构单手OneHanded Feature作用-源码分析

RK3572-Android16-记录一次OTA升级失败解决方案 这里记录一次解决RK3576 Android16 OTA 用Recovery 升级失败的一次解决案例,将部分经验作为总结。本次OTA升级耗时了几天,最终是RK给出的解决方案,再加上经验来解决了其它部分问题新平台,高一点的Android版本,可能本身有bug,多请教平台来,不要蒙着干,干不出来的。 阅读详情

背景:

aosp自带的单手模式一般如下:
在这里插入图片描述单手模式本身在层级结构树中是有单独的一个Feature:
在这里插入图片描述结构树构建时候代码配置如下:
在这里插入图片描述
详细的原理及结合Winscope分析之前已经有分享过
重学WMS核心层级结构树之Feature作用-实战案例讲解

不过没有拿出具体源码分析,本文就来补充这块单手模式的源码分析,看看源码中这个Feature到底是如何影响单手模式的偏移的。

OneHanded位置偏移设置

位置Y方向偏移堆栈情况如下:

  setPosition (tx=3358664428444  sc=OneHanded:32:32) x=0.0 y=1183.4318
  java.lang.Throwable
  	at android.view.SurfaceControlRegistry.checkCallStackDebugging(SurfaceControlRegistry.java:330)
  	at android.view.SurfaceControl$Transaction.setPosition(SurfaceControl.java:3041)
  	at com.android.wm.shell.onehanded.OneHandedSurfaceTransactionHelper.translate(OneHandedSurfaceTransactionHelper.java:56)
  	at com.android.wm.shell.onehanded.OneHandedAnimationController$OneHandedTransitionAnimator$1.applySurfaceControlTransaction(OneHandedAnimationController.java:284)
  	at com.android.wm.shell.onehanded.OneHandedAnimationController$OneHandedTransitionAnimator.onAnimationUpdate(OneHandedAnimationController.java:188)
  	at android.animation.Animator$AnimatorCaller.lambda$static$4(Animator.java:855)
  	at android.animation.Animator$AnimatorCaller$$ExternalSyntheticLambda6.call(D8$$SyntheticClass:0)
  	at android.animation.Animator.callOnList(Animator.java:666)
  	at android.animation.ValueAnimator.animateValue(ValueAnimator.java:1645)
  	at android.animation.ValueAnimator.animateBasedOnTime(ValueAnimator.java:1405)
  	at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1563)
  	at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:344)
  	at android.animation.AnimationHandler.-$$Nest$mdoAnimationFrame(Unknown Source:0)
  	at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:87)
  	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1404)
  	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1415)
  	at android.view.Choreographer.doCallbacks(Choreographer.java:1015)
  	at android.view.Choreographer.doFrame(Choreographer.java:941)
  	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1389)
  	at android.os.Handler.handleCallback(Handler.java:959)
  	at android.os.Handler.dispatchMessage(Handler.java:100)
  	at android.os.Looper.loopOnce(Looper.java:232)
  	at android.os.Looper.loop(Looper.java:317)
  	at android.os.HandlerThread.run(HandlerThread.java:85)

代码剖析

frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java
在这里插入图片描述
那么看看这里的leash是哪里传递过来的
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
            mOneHandedAnimationCallbacks.forEach(
                    (callback) -> callback.onAnimationUpdate(tx, 0f, mCurrentValue)
            );
            applySurfaceControlTransaction(mLeash, tx, animation.getAnimatedFraction());
        }

那么这里的mLeash又是哪来的呢?
在这里插入图片描述
这里OneHandedTransitionAnimator又是由ofYOffset方法导致的构造
在这里插入图片描述
而ofYOffset又是通过getAnimator方法获取的
在这里插入图片描述
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java

private void animateWindows(WindowContainerToken token, SurfaceControl leash, float fromPos,
            float toPos, @OneHandedAnimationController.TransitionDirection int direction,
            int durationMs) {
        final OneHandedAnimationController.OneHandedTransitionAnimator animator =
                mAnimationController.getAnimator(token, leash, fromPos, toPos,
                        mLastVisualDisplayBounds);
//省略
    }

再看看animateWindows方法
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java

    /**
     * Offset the windows by a given offset on Y-axis, triggered also from screen rotation.
     * Directly perform manipulation/offset on the leash.
     */
    public void scheduleOffset(int xOffset, int yOffset) {
        final float fromPos = mLastVisualOffset;
 //省略
 //这里会调用的mDisplayAreaTokenMap这个集合来遍历获取leash
        mDisplayAreaTokenMap.forEach(
                (token, leash) -> {
                    animateWindows(token, leash, fromPos, yOffset, direction,
                            mEnterExitAnimationDurationMs);
                });
        mLastVisualOffset = yOffset;
    }

那么这里的mDisplayAreaTokenMap又是哪里设置的呢?

frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java

  @Override
    public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
            @NonNull SurfaceControl leash) {
        leash.setUnreleasedWarningCallSite(
                "OneHandedSiaplyAreaOrganizer.onDisplayAreaAppeared");
        mDisplayAreaTokenMap.put(displayAreaInfo.token, leash);
    }

onDisplayAreaAppeared调用地方呢?可以看看如下registerOrganizer

    @Override
    public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) {
        final List<DisplayAreaAppearedInfo> displayAreaInfos =
                super.registerOrganizer(displayAreaFeature);
        for (int i = 0; i < displayAreaInfos.size(); i++) {
            final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
            onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
        }
        mIsReady = true;
        updateDisplayBounds();
        return displayAreaInfos;
    }

这里的调用是
frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java

    private void updateOneHandedEnabled() {
     //省略

        if (mDisplayAreaOrganizer.getDisplayAreaTokenMap().isEmpty()) {
            mDisplayAreaOrganizer.registerOrganizer(
                    OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
        }
    }

注意在这里时候registerOrganizer时候有传递FEATURE_ONE_HANDED这个参数

获取OneHanded对应的WindowContainer

frameworks/base/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java

 @Override
    public ParceledListSlice<DisplayAreaAppearedInfo> registerOrganizer(
            IDisplayAreaOrganizer organizer, int feature) {
        enforceTaskPermission("registerOrganizer()");
        try {
            synchronized (mGlobalLock) {
                if (mOrganizersByFeatureIds.get(feature) != null) {
                    mOrganizersByFeatureIds.remove(feature).destroy();
                }

                final DisplayAreaOrganizerState state = new DisplayAreaOrganizerState(organizer,
                        feature);
                final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>();
                mService.mRootWindowContainer.forAllDisplays(dc -> {
                    dc.forAllDisplayAreas((da) -> {
                    	//遍历出所有为FEATURE_ONE_HANDED的da
                        if (da.mFeatureId != feature) return;
                        displayAreaInfos.add(organizeDisplayArea(organizer, da,
                                "DisplayAreaOrganizerController.registerOrganizer"));
                    });
                });

                mOrganizersByFeatureIds.put(feature, state);
                return new ParceledListSlice<>(displayAreaInfos);
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

到此就OneHanded相关Feature剖析讲解完成。

主要流程分为如下两个:

1、收集所有的Feature为FEATURE_ONE_HANDED的WindowContainer,进行保存到集合

2、单手设置本质就是对上面所有FEATURE_ONE_HANDED的WindowContainer进行位置Y方向的偏移

华为Atlas 300I推理卡驱动安装全攻略:从环境检查到常见问题解决 本文提供了华为Atlas 300I推理卡驱动安装的完整实战指南。从安装前的系统环境检查、内核版本匹配,到详细的二进制.run文件安装步骤、源码编译及高级定制化部署,涵盖了驱动安装的全流程。文章重点解析了安装过程中的关键决策、常见问题排查与解决方案,并针对生产环境的多卡配置、性能调优及安全加固给出了专业建议,旨在帮助用户高效、稳定地完成AI推理加速卡的部署。 阅读详情

相关推荐

在 Ubuntu 22.04 上配置 SonarQube 与 CI/CD 流水线实现自动化代码审查

本文详细介绍了在Ubuntu 22.04系统上配置SonarQube并与CI/CD流水线集成的完整流程,实现自动化代码审查。从环境准备、数据库配置到核心参数调优,再到与Jenkins和GitHub Actions的深度集成,提供了实战技巧和性能优化建议,帮助团队提升代码质量监控效率。

weixin_28829325的博客 260

Android 开发入门实践(二):Kotlin 空安全,从可空类型到安全访问

延续 NewsApp 项目中的新闻标题练习,记录 Kotlin 安全调用。

Easyhood的博客 290

【凌智视觉模块】rv1106 部署 pp-humseg 模型

人像分割技术实现摘要 人像分割是利用计算机视觉技术将图像/视频中的人物与背景分离的像素级处理技术。凌智视觉模块基于RV1106芯片开发,支持高效视觉模型部署。当前主流方法包括PP-HumanSeg、BiSeNet等深度学习模型,其中PP-HumanSegV2以96.63% mIoU精度和63FPS手机端速度成为SOTA方案。 实现流程包含: 初始化RKNN模型后端 图像预处理(尺寸调整、颜色空间转换) 执行模型推理 后处理(概率解码、动态阈值分割、形态学优化) 代码实现要点: 使用RKNPU2Backend

m0_50786932的博客 986

Android 模块化收口:能力组合框架、手写 LifecycleOwner 与热修复共存

二十多个模块业务高度相似却各有差异,核心矛盾在于“统一与灵活”的平衡。通过角色接口组合(如IProjectAware、IVoiceAware)实现能力按需注入,新增功能零侵入;用模板方法锁定生命周期流程,确保顺序一致;结合@CallSuper与工厂方法,既约束关键逻辑,又保留子类自由。最终实现:骨架统一、填空自由,管得住业务,又不侵入业务。

mmsx990的博客 397

MATLAB 2022b 用户专属:保姆级IPOPT求解器安装配置全流程(含OPTI工具箱)

本文为MATLAB 2022b用户提供IPOPT求解器的详细安装与配置指南,涵盖OPTI工具箱的适配安装、环境变量设置及常见问题解决方案。通过实战案例演示非线性优化问题的求解过程,帮助用户高效部署这一强大的优化工具,提升工程计算效率。

weixin_29092031的博客 405

SSD性能测试进阶:用fio的io_uring引擎榨干你的NVMe硬盘

本文深入探讨了如何利用fio的io_uring引擎对NVMe SSD进行深度性能测试。通过对比传统libaio引擎,详解了io_uring低开销、高并发的优势。文章提供了从测试矩阵设计、队列深度分析到写入放大观察和尾延迟可视化的完整进阶方法,并附有实战案例与脚本,旨在帮助用户科学压榨NVMe硬盘的极限性能,获取更真实的评估数据。

weixin_29247219的博客 326

Android 开发入门实践(十三):用 Intent、UiState 和 Reducer 理解 MVI 的状态更新

本文记录第141—145课对MVI架构的入门实践,通过“返回列表”功能逐步构建意图(NewsIntent)、状态(NewsUiState)与状态转换(reduce)机制。基于单向数据流,用户操作生成意图,ViewModel通过Reducer根据旧状态计算新状态,并通过StateFlow更新Compose界面。代码实现清晰分离关注点,强化了对状态管理、事件驱动与数据流的理解。

Easyhood的博客 325

ENVI5.6 Seamless Mosaic多景影像镶嵌色差问题

多景影像无缝镶嵌色差问题拟解决方法

Matchaya的博客 7704

Android Message源码阅读

本文梳理了Android Handler机制中Message的核心设计:链表结构、消息复用池(sPool)及回收机制,重点解析了异步消息与同步屏障(SyncBarrier)的协同机制。当主线程需优先处理UI绘制等高优先级任务时,系统通过postSyncBarrier插入屏障,使Looper跳过普通同步消息,优先执行标记为异步的UI渲染任务,确保帧率流畅。该机制是保障Android界面响应性的关键技术之一。

u012116089的博客 201

静态时序分析(STA)_深入解析Data to Data Checks的零周期挑战

本文深入解析了静态时序分析(STA)中Data to Data Checks的核心概念与零周期挑战。重点探讨了当Setup要求值超过时钟周期时,工具如何调整发射沿,并导致Hold检查的发射与捕获沿“分裂”这一反直觉现象。文章通过案例详细解读了时序报告,并提供了通过调整约束或接受多周期保持两种策略来应对这一挑战,帮助工程师正确理解和处理此类复杂时序检查。

weixin_29204205的博客 351

CAN:CANape使用Function处理数据

CANape中的function and script习惯称之为脚本(实际为函数和脚本)。这里介绍function,可以实现简单信号a和信号b乘法,比如计算功率(转速与扭矩乘)。该功能前期有专业人员做支援,当时问其编制方法,其回答是看帮助文件。现在没有支援自己动手。 功能描述:电压信号阶梯增加,每次保持1.5s,测量后0.5s位移平均值(假设信号步长10ms,需要取样50个点,但该脚本中点的数目为10个)。图示如下: 刚开始看了软件Function definition→Library function,

Morven 1万+

安卓部署Linux性能实测:一颗移动处理器,能否胜任日常 Linux 开发?

本文通过在一加Ace5上部署NimoteCode的ARM64 Linux环境,测试了其在CoreMark、SQLite编译及并行构建中的表现。结果显示,尽管单核性能约2.34GHz,多核扩展比达6.15×,但优化编译耗时仍高达35秒,反映移动处理器虽具备一定开发能力,却受限于文件系统开销与运行环境(如PRoot)。实际开发中,非优化构建效率较高,而并行编译可显著提速。结论:安卓手机可作为轻量级开发辅助工具,但无法替代桌面环境,真正价值在于便携性与即时响应,而非全功能替代。

一个不知名码农的专栏 324

FPGA原理与结构(3)——存储单元(Storage Elements)

触发器,锁存器,寄存器,为什么xilinx推荐高电平复位,为什么latch依然存在,FPGA中的触发器与锁存器

apple_53311083的博客 2962

Android 17 全栈性能分析关键字与源码手册

FrameTimeline 找异常帧,ATrace 找阶段,thread_state 找等待类型,ftrace 找内核原因,Simpleperf 找 CPU 热点,驱动源码找最终触发条件;任何根因结论都必须回到同一对象、同一时间窗口和同一条依赖链。

weixin_43228946的博客 373

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

CTF 命令执行题学习笔记:终端特殊字符 $IFS 与 %09 的用法(HelloCTF RCE-labs)

空格被过滤时:用%09(TAB)或$IFS代替空格关键词被过滤时:用通配符?或字符类[f]拼出被禁的词,让 WAF 在原始字符串里看不到它,shell 在执行时再展开这类技巧在后续的命令执行题里会反复用到,建议亲手在靶机上敲一遍感受一下。

YY888888_的博客 542

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Android 开发入门实践(九):把新闻数据与页面状态交给 ViewModel

本文记录第110—117课学习成果:将页面标题、新闻列表及选中编号逐步迁移至NewsViewModel,通过ViewModelProvider获取实例并读取数据。页面调用ViewModel方法处理选择与返回,实现状态管理解耦。过程中纠正了对Activity重建机制的误解,并厘清mutableStateOf的可观察性与ViewModel对象生命周期的区别,深化了对Compose状态更新机制的理解。

Easyhood的博客 221

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

云手机私有化部署完整方案:基于ARM服务器搭建私有安卓云集群

ARM 服务器是私有化安卓云集群最优硬件底座,原生架构匹配 Android,高密度、低损耗,非常适合企业内网场景。整套私有化方案的核心,从来不是 “跑起来安卓”,而是隔离可控、可审计、可运维、可扩容。两条路线各有取舍:开源自建灵活、门槛高;商用私有化交付开箱即用、安全能力完备,是当前企业生产环境主流方案。六边云手机私有化方案,补齐了自建方案在驱动适配、管控平台、审计合规、信创适配上的短板,适合对数据主权、内网隔离有强需求的政企、自研 App、垂直行业客户。

a598652的博客 334

Android 顶点上传:Heap 到 Direct 的零拷贝,省的是 JNI 次数

一帧数十万次putFloat的性能瓶颈源于频繁跨JNI边界,每次开销远超传输字节数。通过将写入与上传解耦:用堆内ByteBuffer高速写入,最后一次性put(writeBuf)批量传至堆外DirectByteBuffer,将数百万次边界调用压缩为一次,实现近10倍性能提升。关键在于复用堆外缓冲区、统一端序,并结合“更新-绘制”分离,仅在数据变更时上传顶点,平移缩放时零开销重绘,彻底释放CPU瓶颈。

mmsx990的博客 478

谷歌相机9.2下载(GCam 安卓通用版 安装与使用说明)

谷歌相机9.2版移植自Pixel原生相机,支持Camera2 API的Android 10+设备安装,凭借多帧合成技术在夜景、HDR+与人像模式表现优异。可提升暗光画质、优化动态范围与背景虚化效果,支持视频防抖及配置文件自定义。安装需确认机型兼容性,建议备份原相机,避免冲突。资源可通过kuake链接获取,仅限学习测试使用。

2611_96675819的博客 160

Android 系统启动与调试中的日志抓取方式全解析

│ 用户操作/系统事件 ││ │▼ ▼│ (驱动/硬件/内存管理) │ │ (App/SystemServer) ││ │ │ ││ │▼ ▼│ dmesg 命令 │ │ logd daemon ││ cat /proc/kmsg │ │ (分类存储到分区) ││ │▼ ▼│ 串口 UART │ │ logcat 命令 ││ (硬件直连,最早输出) │ │ adb logcat ││ │▼│ (汇总所有日志+系统状态) │工具最佳用途关键优势主要局限dmesg。

zhaoshuzhaoshu的专栏 266

【Android】听写播放器改版:中英文书写速度拆项与「正在读」高亮

现象:把播放页主体抽成后,里面给LazyColumn加想让它占满剩余高度,编译报错(weight 不可用)。原因weight不是通用修饰符,是RowScope的扩展函数。是个普通函数,函数体里没有接收者,自然调不到。解决private fun ColumnScope.PlaybackBody(...) { /* 这里就能用 Modifier.weight(1f) */ }调用处仍在原来的Column { }里,无需改动。预防:Compose 的布局修饰符都是作用域绑定。

木头大左的博客 241

Android 开发入门实践(十):用 Kotlin 协程完成模拟加载、取消与异常处理

本文记录第118—125课对NewsApp的协程改造:从viewModelScope.launch启动协程,逐步加入delay模拟等待、suspend函数封装、withContext(Dispatchers.IO)切换线程并观察上下文恢复机制。通过日志验证withContext完成后恢复原执行上下文(非自动回主线程),纠正了初始理解偏差。引入Job管理任务,实现加载取消与重复点击防护,结合异常处理与状态管理,完成可观察、可中断的异步流程。

Easyhood的博客 390

go消息推送之极光推送 (JPush REST API + SDK,覆盖安卓与iOS)

使用 gorush有个绕不开的问题:国内安卓设备上 FCM 基本不可达,华为、小米、OPPO、vivo 各自为政——此时可用极光推送(JPush)作解决方案。它的思路和前面几家都不一样:App 集成极光 SDK 后拿到统一的 RegistrationID,服务端发一条 REST 请求,极光云端自动把消息路由到 APNs、各家厂商通道或极光自有长连接。这里给出了:一个用纯标准库直接调用极光的;另一个用社区维护的,类型化参数,接口注释与官方文档逐条对应。两个功能相同,可放在一起对比学习。

qq_40467670的博客 181

工业智能体:从Codex/Claude到项目实战~系列文章11:Codex 批量重构老系统:激活历史 DCS/PLC 存量代码

本期提出规模化重构工业老系统(如DCS/PLC代码)的可执行方法论:通过AST静态分析量化风险,按“盘点评估→样板重构→批量迁移→回归灰度”四阶段推进;利用Codex实现模块级批量重构,并以“金标准样本”确保数值一致性;接入CI流水线实现自动化守护。强调“小步改、保语义、可回滚”,结合绞杀者模式渐进替代,实现存量代码的安全激活。来自华北理工大学段一凡的博客文章

段一凡的博客 369

android 动画掉帧

动画

yeshen.org 242

MySQL 数据库账户及授权

MySQL 8.0默认使用caching_sha2_password认证插件,可通过show variables like '%password%'查看密码策略。通过validate_password插件可设置密码强度,策略等级包括LOW、MEDIUM、STRONG,支持长度、大小写、数字、特殊字符及字典检查。密码策略可临时或永久配置。用户需先创建账户再授权,遵循最小权限原则,避免root账户远程访问。常用权限如CREATE、DROP、SELECT、INSERT、UPDATE等按级别分配,确保安全与管理规范

Y_P_W的博客 186
上一篇: 重学wms的Feature之FEATURE_WINDOWED_MAGNIFICATION剖析
下一篇: 自由窗口圆角无效/ubuntu无法用wifi/输入窗口层次/user版本pull出data下文件-vip学员近期答疑问题汇总
千里马学框架
博客等级 码龄6年 1万+粉丝 650原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千里马学框架

帮助你了,就请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值