日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

IMS:InputChannel通过socket发送Input给App

發(fā)布時間:2023/12/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IMS:InputChannel通过socket发送Input给App 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

IMS:InputChannel通過socket發(fā)送Input給App

android11-release
IMS:InputManagerService啟動簡要
IMS:InputReader線程獲取輸入事件
IMS:InputDispatcher線程分發(fā)事件


InputChannel監(jiān)聽

??IMS與WMS強(qiáng)相關(guān),這個InputChannel就是在addView時是聲明。APP就是在Activity.java中setContentView(),經(jīng)過AMS與WMS之間交互,這里不過多介紹,最終 WindowManagerImpl.addView() 內(nèi)部再調(diào)用 WindowManagerGlobal.addView()。


添加App的View

frameworks/base/core/java/android/view/WindowManagerGlobal.java frameworks/base/core/java/android/view/ViewRootImpl.java

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {synchronized (this) {if (mView == null) {// ... ... ... ...InputChannel inputChannel = null;if ((mWindowAttributes.inputFeatures& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {inputChannel = new InputChannel();}// ... ... ... ...try {mOrigWindowType = mWindowAttributes.type;mAttachInfo.mRecomputeGlobalAttributes = true;collectViewAttributes();adjustLayoutParamsForCompatibility(mWindowAttributes);res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mDisplayCutout, inputChannel,mTempInsets, mTempControls);setFrame(mTmpFrame);} catch (RemoteException e) {// ... ... ... ...if (DEBUG_LAYOUT) Log.v(mTag, "Added window " + mWindow);// ... ... ... ...if (inputChannel != null) {if (mInputQueueCallback != null) {mInputQueue = new InputQueue();mInputQueueCallback.onInputQueueCreated(mInputQueue);}mInputEventReceiver = new WindowInputEventReceiver(inputChannel,Looper.myLooper());}// ... ... ... ...// Set up the input pipeline.CharSequence counterSuffix = attrs.getTitle();mSyntheticInputStage = new SyntheticInputStage();InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,"aq:native-post-ime:" + counterSuffix);InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);InputStage imeStage = new ImeInputStage(earlyPostImeStage,"aq:ime:" + counterSuffix);InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,"aq:native-pre-ime:" + counterSuffix);mFirstInputStage = nativePreImeStage;mFirstPostImeInputStage = earlyPostImeStage;mPendingInputEventQueueLengthCounterName = "aq:pending:" + counterSuffix;// ... ... ... ...}}}
  • 1、InputChannel 初始化工作
  • 2、mWindowSession.addToDisplayAsUser 通過Binder調(diào)用,進(jìn)入system進(jìn)程的Session。這里最終構(gòu)建(server)、(client)的InputChannel。
  • 3、WindowInputEventReceiver 接收器初始化
  • 4、InputStage 責(zé)任鏈調(diào)用

構(gòu)建(server)、(client)的InputChannel

frameworks/base/services/core/java/com/android/server/wm/Session.java frameworks/services/core/java/com/android/server/wm/WindowManagerService.java frameworks/services/core/java/com/android/server/wm/WindowState.java frameworks/base/core/java/android/view/InputChannel.java frameworks/base/core/jni/android_view_InputChannel.cpp frameworks/native/libs/input/InputTransport.cpp public int addWindow(Session session, IWindow client, int seq,LayoutParams attrs, int viewVisibility, int displayId, Rect outFrame,Rect outContentInsets, Rect outStableInsets,DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,InsetsState outInsetsState, InsetsSourceControl[] outActiveControls,int requestUserId) {// ... ... ... ...final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], seq, attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);// ... ... ... ...final boolean openInputChannels = (outInputChannel != null&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);if (openInputChannels) {win.openInputChannel(outInputChannel);}// ... ... ... ...}

  • inputChannels[0] 所對應(yīng) (server) 的 InputChannel ,保存到 mInputChannel;并添加 Connection ,“InputDispatcher” 線程的 Looper 添加對 socket 服務(wù)端的監(jiān)聽
  • inputChannels[1] 所對應(yīng) (client) 的 InputChannel ,傳遞給 outInputChannel,最終傳遞給 ViewRootImpl 的 mInputChannel

WindowInputEventReceiver接收器初始化

frameworks/base/core/java/android/view/ViewRootImpl.java frameworks/base/core/java/android/view/InputEventReceiver.java frameworks/base/core/jni/android_view_InputEventReceiver.cpp



receiver->initialize()初始化設(shè)置setFdEvents,這里 handler/Looper 輪詢回調(diào) LooperCallback,POLL_CALLBACK某個被監(jiān)聽 fd 被觸發(fā)回調(diào)response.request.callback->handleEvent(fd, events, data);

class NativeInputEventReceiver : public LooperCallback { // ... ... ... ... status_t NativeInputEventReceiver::initialize() {setFdEvents(ALOOPER_EVENT_INPUT);return OK; } // ... ... ... ... void NativeInputEventReceiver::setFdEvents(int events) {if (mFdEvents != events) {mFdEvents = events;int fd = mInputConsumer.getChannel()->getFd();if (events) {mMessageQueue->getLooper()->addFd(fd, 0, events, this, nullptr);} else {mMessageQueue->getLooper()->removeFd(fd);}} }int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {// ... ... ... ... }

InputStage 責(zé)任鏈調(diào)用

frameworks/base/core/java/android/view/ViewRootImpl.java

InputStage初始化,Input 事件傳遞過來會調(diào)用 InputStage.deliver,通過責(zé)任鏈模式執(zhí)行

InputChannel通過socket發(fā)送Input給App

?? 通過上邊了解相關(guān)的前期工作,接著 IMS:InputDispatcher線程分發(fā)事件 經(jīng)過 InputChannel 通過 socket 向遠(yuǎn)端的socket發(fā)送消息給Window。


監(jiān)聽 fd 回調(diào) LooperCallback

::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); LooperCallback 回調(diào)到 handleEvent

frameworks/base/core/jni/android_view_InputEventReceiver.cpp frameworks/base/core/java/android/view/InputChannel.java frameworks/base/core/java/android/view/ViewRootImpl.java


最終走到WindowInputEventReceiver的onInputEvent,通過enqueueInputEvent -> doProcessInputEvents -> deliverInputEvent -> stage.deliver(q)調(diào)用執(zhí)行InputStage 責(zé)任鏈

InputStage的各子類Input事件onProcess處理


查看父類InputStage主要result = onProcess(q)處理Input事件,apply->forward->onDeliverToNext->mNext.deliver處理責(zé)任鏈傳遞或finish。

abstract class InputStage {private final InputStage mNext;// ... ... ... ...public InputStage(InputStage next) {mNext = next;}// ... ... ... ...public final void deliver(QueuedInputEvent q) {if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {forward(q);} else if (shouldDropInputEvent(q)) {finish(q, false);} else {traceEvent(q, Trace.TRACE_TAG_VIEW);final int result;try {result = onProcess(q);} finally {Trace.traceEnd(Trace.TRACE_TAG_VIEW);}apply(q, result);}}// ... ... ... ...protected void forward(QueuedInputEvent q) {onDeliverToNext(q);}// ... ... ... ...protected void apply(QueuedInputEvent q, int result) {if (result == FORWARD) {forward(q);} else if (result == FINISH_HANDLED) {finish(q, true);} else if (result == FINISH_NOT_HANDLED) {finish(q, false);} else {throw new IllegalArgumentException("Invalid result: " + result);}}// ... ... ... ...protected void onDeliverToNext(QueuedInputEvent q) {if (DEBUG_INPUT_STAGES) {Log.v(mTag, "Done with " + getClass().getSimpleName() + ". " + q);}if (mNext != null) {mNext.deliver(q);} else {finishInputEvent(q);}}// ... ... ... ...}

例如ViewPostImeInputStage中processKeyEvent


mView.dispatchKeyEvent(event)事件發(fā)送到App界面,這里mView就是DecorView,涉及PhoneWindow.java、DecorView.java

frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java frameworks/base/core/java/com/android/internal/policy/DecorView.java


這里handled可以判斷應(yīng)用是否攔截KeyEvent事件,但是需要明白的是不管應(yīng)用攔不攔截,Input事件都已經(jīng)發(fā)送給應(yīng)用了。

Activity回調(diào)Callback

frameworks/base/core/java/android/app/Activity.java frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java frameworks/base/core/java/com/android/internal/policy/DecorView.java


cb.dispatchKeyEvent(event) 這個Window.Callback是Activity回調(diào)注冊

總結(jié)

以上是生活随笔為你收集整理的IMS:InputChannel通过socket发送Input给App的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。