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设置为true
            mUpdateInputWindowsNeeded = true;
        if (updateInputWindows) { updateInputWindowsLw(false /*force*/); }  // 更新所有inputwindow
            if (!force && !mUpdateInputWindowsNeeded) { return; }
            scheduleUpdateInputWindows();
                //mUpdateInputWindowsPending只是用来保证post执行不被重复执行,配合锁实现
                if (!mUpdateInputWindowsPending)  mUpdateInputWindowsPending = true;  mHandler.post(mUpdateInputWindows); }
                    UpdateInputWindows::run()
                        if (mDisplayRemoved) { return; }  //没有display的话return
                        final 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 */);  // 遍历窗口更新inputInfo
                                 final int count = mChildren.size();
                                 for (int i = 0; i < count; i++) {
@frameworks/base/services/core/java/com/android/server/wm/WindowState.java
                                     if (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.java
                                                             inputWindowHandle.applyChangesToSurface(t, sc);
@frameworks/base/core/java/android/view/SurfaceControl.java
                                                                 t.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操作一起同步到底层SurfaceFlinger
                                                                                mComposerStates[handle] = s
                                                                            s->windowInfoHandle = new WindowInfoHandle(info); // 把对应的WindowInfo数据设置相应的参数给layer_state_t,就是surface里面的layer
                                                                            s->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或者当前窗口无法聚焦则return
                                    if (!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.cpp
                                            nativeSetFocusedWindow(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 request
                                        ProtoLog.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.cpp
                                        transaction->merge(std::move(*otherTransaction));
                                            mComposerStates[handle].state.merge(composerState.state);
                                            mInputWindowCommands.merge(other.mInputWindowCommands);
                                mDisplayContent.scheduleAnimation(); }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

薛文旺

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值