Android焦点之InputWindows的更新(二)

再次回到InputMonitor#updateInputWindows(),调用SurfaceControl.Transaction#merge,之后,当WindowAnimator.java的animate()时发起apply();可以是线程"android.anim"或"binder"线程;

@frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
updateFocusedWindowLocked // 向InputMonitor中设置焦点窗口
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java    if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) { getInputMonitor().setInputFocusLw(newFocus, updateInputWindows); }ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s display=%d", newWindow, mDisplayId); //这里log打印要切到那个窗口        final IBinder focus = newWindow != null ? newWindow.mInputChannelToken : null;  // 更新当前焦点窗口setUpdateInputWindowsNeededLw()  // 更新当前焦点窗口 使mUpdateInputWindowsNeeded设置为truemUpdateInputWindowsNeeded = true;if (updateInputWindows) { updateInputWindowsLw(false /*force*/); }  // 更新所有inputwindowif (!force && !mUpdateInputWindowsNeeded) { return; }scheduleUpdateInputWindows();//mUpdateInputWindowsPending只是用来保证post执行不被重复执行,配合锁实现if (!mUpdateInputWindowsPending)  mUpdateInputWindowsPending = true;  mHandler.post(mUpdateInputWindows); }UpdateInputWindows::run()if (mDisplayRemoved) { return; }  //没有display的话returnfinal boolean inDrag = mService.mDragDropController.dragDropActiveLocked();  // 是否正在拖拽mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag);   // 在默认显示上添加所有窗口。//显式创建的特殊InputConsumer对象mPipInputConsumer = getInputConsumer(INPUT_CONSUMER_PIP);  // 用于处理Nav相关input事件mWallpaperInputConsumer = getInputConsumer(INPUT_CONSUMER_WALLPAPER); // 用于处理壁纸相关input事件mRecentsAnimationInputConsumer = getInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION) // 用于处理最近的动画输入相关input事件resetInputConsumers(mInputTransaction);   // 重置mInputTransaction// 如果处于活动状态,则更新最近的输入消费者层final ActivityRecord activeRecents = getWeak(mActiveRecentsActivity);if (mAddRecentsAnimationInputConsumerHandle  && getWeak(mActiveRecentsActivity) != null) {final WindowContainer layer = getWeak(mActiveRecentsLayerRef);mRecentsAnimationInputConsumer.show(mInputTransaction, layer != null ? layer : getWeak(mActiveRecentsActivity));mAddRecentsAnimationInputConsumerHandle = false;}
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java                             mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);  // 遍历窗口更新inputInfofinal int count = mChildren.size();for (int i = 0; i < count; i++) {
@frameworks/base/services/core/java/com/android/server/wm/WindowState.javaif (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {forAllWindowTopToBottom(callback);if (applyInOrderWithImeWindows(callback, true /* traverseTopToBottom */)) {
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java                                                 if (callback.apply(this) 
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java                                                 mConsumer.accept(w);// 获取WindowState的InputWindowHandle对象,WindowState里保存着InputWindowHandle,每次复用,判断changes,减少同步final InputWindowHandleWrapper inputWindowHandle = w.mInputWindowHandle;//判断窗口mInputChannelToken是否为空;窗口是否销毁;窗口是否可以接受input事件if (w.mInputChannelToken == null || w.mRemoved || !w.canReceiveTouchInput()) {if (w.mWinAnimator.hasSurface()) {// 确保输入信息无法接收输入事件。可以省略。遮挡检测取决于类型或是否是可信覆盖。 populateOverlayInputInfo(inputWindowHandle, w);setInputWindowInfoIfNeeded(mInputTransaction, w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);}return;  // 跳过此窗口,因为它不可能接收输入。         final RecentsAnimationController recentsAnimationController = mService.getRecentsAnimationController();  // 最近任务是否存在             if (w.inPinnedWindowingMode()) { if (mAddPipInputConsumerHandle) { mPipInputConsumer.mWindowHandle.replaceTouchableRegionWithCrop( rootTask.getSurfaceControl()); } } // 处理处于PIP模式时的input事件if (mAddWallpaperInputConsumerHandle) {  mWallpaperInputConsumer.show(mInputTransaction, w); } // mWallpaperInputConsumer处理壁纸input事件if (mInDrag && w.isVisible() && w.getDisplayContent().isDefaultDisplay) { mService.mDragDropController.sendDragStartedIfNeededLocked(w); } // 是否处于拖拽过程中mService.mKeyInterceptionInfoForToken.put(w.mInputChannelToken, w.getKeyInterceptionInfo()); // 注册密钥拦截信息if (w.mWinAnimator.hasSurface()) { 
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java                                                     populateInputWindowHandle(inputWindowHandle, w);  // 填充InputWindowHandle
@frameworks/base/services/core/java/com/android/server/wm/InputWindowHandleWrapper.java                                                         inputWindowHandle.setFocusable(focusable);inputWindowHandle.setSurfaceInset(w.mAttrs.surfaceInsets.left);inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop);setInputWindowInfoIfNeeded(mInputTransaction,  w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);  //提交inputWindowHandle
@frameworks/base/services/core/java/com/android/server/wm/InputWindowHandleWrapper.javainputWindowHandle.applyChangesToSurface(t, sc);
@frameworks/base/core/java/android/view/SurfaceControl.javat.setInputWindowInfo(sc, mHandle);
@frameworks/base/core/jni/android_view_SurfaceControl.cpp                                                                 nativeSetInputWindowInfo(mNativeObject, sc.mNativeObject, handle);
@frameworks/native/libs/gui/SurfaceComposerClient.cpp// native层也有对应的surfacecontrol,刚刚封装的WindowInfo也被传递进来 transaction->setInputWindowInfo(ctrl, *handle->getInfo());                                                                                layer_state_t* s = getLayerState(sc);    //获取surfaceControl对应的layer_state_t(surfaceflinger的一个图层)   s.state.layerId = sc->getLayerId();//用于执行apply时,把所有的layer操作一起同步到底层SurfaceFlingermComposerStates[handle] = ss->windowInfoHandle = new WindowInfoHandle(info); // 把对应的WindowInfo数据设置相应的参数给layer_state_t,就是surface里面的layers->what |= layer_state_t::eInputInfoChanged; //在SurfaceFlinger会按照flag来解析改变数据                                                                                                      || applyImeWindowsIfNeeded(callback, traverseTopToBottom)) {updateInputFocusRequest(mRecentsAnimationInputConsumer);  //调用到Focus Request// 当应用程序获得焦点但其窗口尚未显示时,请从当前窗口中删除输入焦点,这强制输入焦点匹配 mDisplayContent.mCurrentFocus。//但是,如果发现更多特殊情况,即输入焦点和 mDisplayContent.mCurrentFocus 预计不匹配,则需要检查如何以及何时撤销焦点的整个逻辑。if (mDisplayContent.mFocusedApp != null && mInputFocus != null) {ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "App %s is focused,"  + " but the window is not ready. Start a transaction to remove focus from" + " the window of non-focused apps.", mDisplayContent.mFocusedApp.getName());mInputTransaction.removeCurrentInputFocus(mDisplayId) //从具有输入焦点的当前窗口中移除输入焦点。仅当当前聚焦的应用程序没有响应并且当前聚焦的窗口不属于当前聚焦的应用程序时才应调用。final IBinder focusToken = focus != null ? focus.mInputChannelToken : null;   //mInputChannelToken在openInputChannel的时候创建mInputChannelToken = mInputChannel.getToken();//如果当前焦点窗口没有surface或者当前窗口无法聚焦则returnif (!focus.mWinAnimator.hasSurface() || !focus.mInputWindowHandle.isFocusable()) {mInputFocus = null;return;requestFocus(focusToken, focus.getName());  //将包装出来的InputChannelToken(focusToken)信息向native层进行同步mInputFocus = focusToken;mInputFocusRequestTimeMillis = SystemClock.uptimeMillis(); //输入焦点请求时间  用于anr的计算
@frameworks/base/core/java/android/view/SurfaceControl.java //如果窗口可聚焦,则将焦点设置在由输入 {@code token} 标识的窗口上,否则请求将被丢弃。如果窗口不可见,则请求将排队,直到窗口变得可见或该请求被另一个请求覆盖//当前聚焦的窗口将立即失去焦点。这是为了向新获得焦点的窗口发送在完成其第一次绘制时发生的任何焦点调度事件mInputTransaction.setFocusedWindow(mInputFocus, windowName, mDisplayId);
@frameworks/base/core/jni/android_view_SurfaceControl.cppnativeSetFocusedWindow(mNativeObject, token,  windowName, null /* focusedToken */, null /* focusedWindowName */, displayId);sp<IBinder> toToken(ibinderForJavaObject(env, toTokenObj));request.displayId = displayId;
@frameworks/native/libs/gui/SurfaceComposerClient.cpp                                                transaction->setFocusedWindow(request);  //上面就是一些focusToken的异常检测,没问题,会调用这个方法mInputWindowCommands.focusRequests.push_back(request);//在这里打印要请求进入的窗口Focus requestProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Focus requested for window=%s", windowName); // 将mInputTransaction合并到mPendingTransaction上进行提交if (!mUpdateInputWindowsImmediately) {
@frameworks/base/core/java/android/view/SurfaceControl.java                                mDisplayContent.getPendingTransaction().merge(mInputTransaction);
@frameworks/base/core/jni/android_view_SurfaceControl.cpp                                nativeMergeTransaction(mNativeObject, other.mNativeObject);
@frameworks/native/libs/gui/SurfaceComposerClient.cpptransaction->merge(std::move(*otherTransaction));mComposerStates[handle].state.merge(composerState.state);mInputWindowCommands.merge(other.mInputWindowCommands);mDisplayContent.scheduleAnimation(); }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870146.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常用知识碎片 Vue3 ref和reactive (内含其他常用知识)

目录 ref和reactive ref reactive 总结&#xff1a; setup语法糖 语法糖是啥&#xff1f; Vue3 setup语法糖 Vue3 不使用setup语法糖示例&#xff1a; Vue3 使用setup语法糖示例&#xff1a; ref和eative主要区别 ref和reactive 在 Vue 3 中&#xff0c;ref 和 reac…

品牌渠道管控力度的平衡艺术

渠道管控力度要如何把握呢&#xff1f;是不是管控越严格就一定越好&#xff1f;例如&#xff0c;发现一次低价就处以高额罚款&#xff0c;发现一次窜货也重罚&#xff0c;其实处罚是对低价管控较为直接的一种方式&#xff0c;但并非处罚越重就一定能取得良好的管控效果。 比如品…

Java 中的 switch 语句:类型支持与限制

Java 中的 switch 语句&#xff1a;类型支持与限制 1、switch 语句支持的数据类型2、switch 语句不支持的数据类型3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在 Java 中&#xff0c;switch 语句是一种用于多分支选择的控制结构…

@SpringBootTest注解的用途是什么?

SpringBootTest注解是Spring Boot提供的一个用于测试的注解&#xff0c;主要用途是在测试过程中方便地创建一个应用上下文&#xff08;ApplicationContext&#xff09;。这个注解告诉Spring Boot去寻找一个主配置类&#xff08;比如带有SpringBootApplication的类&#xff09;&…

常见的负载均衡算法和实现方式

负载均衡的原理&#xff0c;并给出常见的负载均衡算法和实现方式 负载均衡是一种分布式系统设计策略&#xff0c;其目的是为了将用户请求分摊到多个服务器上&#xff0c;提高系统的可用性和响应速度。它通过动态地将工作负载分配给各个节点&#xff0c;避免单点过载并提升整体…

【编程范式】理解响应式编程(reactive programming)

文章目录 一、定义与特点二、核心概念三、应用场景四、优势与挑战五、总结 响应式编程&#xff08;Reactive Programming&#xff09;是一种面向数据流和变化传播的编程范式&#xff0c;其核心在于以非阻塞和异步的方式处理数据流&#xff0c;从而提高应用的响应性、可维护性和…

如何使用FreeFileSync:一款免费且专业的数据备份与文件同步软件

数据的重要性不言而喻&#xff0c;因此&#xff0c;定期做数据备份已经是每一个人的基本工作习惯了。 FreeFileSync 是一款强大专业且免费开源的 文件夹对比/同步/备份 软件工具。FreeFileSync通过比较其内容&#xff0c;日期或文件大小上的一个或多个文件夹&#xff0c;然后根…

android 图片轮播

在Android中&#xff0c;实现图片轮播&#xff08;也称为图片滑动或图片轮转&#xff09;通常涉及到使用ViewPager、RecyclerView配合PagerAdapter、RecyclerView.Adapter或者第三方库如Glide、Picasso来处理图片加载&#xff0c;以及一个定时器&#xff08;如Handler、Timer、…

统信UOS桌面操作系统上删除系统升级后GRUB中的回滚条目与备份

原文链接&#xff1a;统信UOS删除升级后GRUB中的回滚条目与备份 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于在统信UOS桌面操作系统上删除系统升级后GRUB中的回滚条目与备份的文章。在进行系统升级后&#xff0c;GRUB引导菜单中可能会出现多个回滚条目和备份…

深入解析C++中的特殊成员函数:构造函数、析构函数、拷贝构造函数与赋值操作符

深入解析C中的特殊成员函数&#xff1a;构造函数、析构函数、拷贝构造函数与赋值操作符 在C编程的浩瀚宇宙中&#xff0c;构造函数、析构函数、拷贝构造函数和赋值操作符是构成对象生命周期和行为的四大基石。它们各自扮演着不可或缺的角色&#xff0c;确保了对象从创建到销毁…

2024年华为OD机试真题-找座位-C++-OD统一考试(C卷D卷)

2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述: 在一个大型体育场内举办了一场大型活动,由于疫情防控的需要,要求每位观众的必须间隔至少一个空位才允许落座。现在给出一排观众座位分布图,座位中存在已落座的观众,请计…

nginx正向代理、反向代理、负载均衡

nginx.conf nginx首要处理静态页面 反向代理 动态请求 全局模块 work processes 1; 设置成服务器内核数的两倍&#xff08;一般不不超过8个超过8个反而会降低性能一般4个 1-2个也可以&#xff09; netstat -antp | grep 80 查端口号 *1、events块&#xff1a;* 配置影响ngi…

qt list 控件

Qt中的列表控件主要包括QListView和QListWidget。以下是对这两个控件的详细介绍&#xff1a; 一、QListView控件 创建&#xff1a;在Qt Designer中&#xff0c;可以通过拖拽的方式创建一个ListView控件。在代码中&#xff0c;可以使用QListView *listView new QListView(thi…

aws sap认证考试如何轻松通过

如何高效备考AWS SAP (Solutions Architect Professional) 认证? AWS SAP认证是AWS认证体系中难度最高的认证之一,要通过这个考试确实需要下一番功夫。但通过合理规划和有效准备,你可以提高通过的几率。以下是一些建议: 评估起点 首先诚实地评估自己的AWS知识水平和实践经验。…

气膜滑冰馆:滑冰爱好者的最佳选择—轻空间

滑冰运动在全球范围内越来越受欢迎&#xff0c;然而&#xff0c;传统滑冰馆在建设和运营过程中往往面临高能耗和环境控制难题。幸运的是&#xff0c;采用气膜结构作为建筑外壳的气膜滑冰馆&#xff0c;正在为滑冰爱好者提供一种全新的、节能的解决方案。 1. 气膜结构&#xff1…

Spring MVC -01

Spring 的 MVC 框架 Spring的MVC框架是Spring框架的一部分&#xff0c;它提供了用于开发Web应用程序的一组组件和设计模式。MVC是Model-View-Controller的缩写&#xff0c;是一种设计模式&#xff0c;用于将应用程序的逻辑与用户界面分离。 在Spring的MVC框架中&#xff0c;Mo…

独立站点:自主经营,不受平台限制的网站类型

独立站点&#xff0c;因自主运作且无需依附其他平台而得名&#xff0c;其内涵即为具备自有域名、自属服务器及内容的个体。相较于依赖第三方平台&#xff0c;独立站点能按自身需求进行经营&#xff0c;无任何限制。 然而&#xff0c;独立站并非涵盖所有网站类型。日常网络浏览…

MES 功能模块

MES系统&#xff08;Manufacturing Execution System&#xff0c;生产执行系统&#xff09;是制造业企业的关键管理系统之一&#xff0c;它通过集成生产计划、工艺流程、物料管理和生产过程数据等&#xff0c;实现了对生产和制造过程的全面管理和监控。MES系统的功能模块主要包…

小额贷记业务全解析与功能测试策略

一、小额贷记业务概述 小额贷记业务是小额支付系统的重要组成部分&#xff0c;它主要处理金额在规定起点以下的小额贷记支付业务。这种业务通常面向个人或小微企业&#xff0c;提供便捷、快速的资金划转服务。小额贷记业务的特点在于其金额较小、操作简便、处理速度快&#xff…

【线性表,线性表中的顺序表和链表】

目录 1、线性表的定义和基本操作1.1、线性表的定义1.2、线性表的基本操作 2、顺序表和链表的比较2.1、顺序表2.1.1、顺序表的定义和特点2.1.2、顺序表的实现&#xff08;1&#xff09;顺序表的静态分配&#xff1a;&#xff08;2&#xff09;顺序表的动态分配 2.1.3、顺序表的基…