【android 9】【input】【9.发送按键事件3——Inputchannel的创建过程】

系列文章

本人系列文章-CSDN博客


目录

系列文章

目录

1.简介

1.1 主要步骤

1.2 时序图

2.源码分析

2.1 WindowManagerImpl的addView

2.2 WindowManagerGlobal的addView

2.3 ViewRootImpl

2.4 getWindowSession

 2.5 WMS中的openSession

 2.6 Session

2.7 class W

2.8 setView

2.9 addToDisplay

2.10 addWindow

2.11 openInputChannel

2.12 Java层openInputChannelPair

2.13 android_view_InputChannel_nativeOpenInputChannelPair

2.14 openInputChannelPair

2.15 transferTo

2.16 WMS向IMS注册并监听socket

2.17 nativeRegisterInputChannel

2.18 android_view_InputChannel_getInputChannel

2.19 android_server_InputWindowHandle_getHandle

2.20 registerInputChannel

2.21 InputDispatcher::registerInputChannel

2.22 Connection

2.23 android_view_InputChannel_setDisposeCallback

2.24 WindowInputEventReceiver

2.25 InputEventReceiver

2.26 nativeInit

2.27 NativeInputEventReceiver

2.28 initialize

2.29 setFdEvents

2.30 Looper::addFd


1.简介

上一篇中,主要介绍了按键事件中inputdispatcher线程的分发流程,最后会通过sokcet对发送按键消息到应用端,那么这个socket对是什么时候创建的呢?是什么时候和IMS建立连接的呢?本文便主要解答一下这部分内容。

1.1 主要步骤

1.首先当Activity启动后,应用程序端会创建一个空的InputChannel对象。

2.然后应用程序端会通过binder调用到WMS服务,WMS服务会通过openInputChannel 方法会创建一对 InputChannel,一个给到IMS,一个会通过binder调用返回给应用端。

3.然后WMS会将其中一个socket注册到IMS服务中,IMS服务通过epoll机制来监听,是否有来自应用端发送的消息,当应用程序端通过sokcet发送消息时,IMS中的handleReceiveCallback回调函数会执行。

4.然后此时应用端到WMS的binder调用函数返回,返回给应用程序端一个socket,应用程序端会创建一个NativeInputEventReceiver对象,同时应用程序端也会通过epoll机制来监听,是否有来自IMS发送的消息,当存在IMS发送事件到应用程序端时,会调用NativeInputEventReceiver的handleEvent函数。

1.2 时序图

 (图片可保存到本地放大观看)

2.源码分析

首先当Activity启动后,最终会调用到WindowManagerImpl.addView()函数,我们便从WindowManagerImpl.addView()函数进行分析。

2.1 WindowManagerImpl的addView

主要作用:

1.调用WindowManagerGlobal对象的addview对象。

public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) 
{
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);//mGlobal就是WindowManagerGlobal对象
}

2.2 WindowManagerGlobal的addView

主要作用:

1.创建ViewRootImpl对象。

2.调用ViewRootImpl的setView函数,此函数会创建空的InputChannel对象,然后传给WMS,WMS会返回一个和IMS连接好的socket给应用程序端。

此时我们仍然在应用程序进程中。

public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
			//view代表添加哪个窗口,此时view是DecorView
			//params窗口的参数
			//display显示到那块屏幕上
			//parentWindow父窗口是谁
       
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;


        ViewRootImpl root;
        View panelParentView = null;

        synchronized (mLock) {

            int index = findViewLocked(view, false);//从mViews中查找此view是否已经存在
			/*
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    // Don't wait for MSG_DIE to make it's way through root's queue.
                    mRoots.get(index).doDie();
                } else {
                    throw new IllegalStateException("View " + view
                            + " has already been added to the window manager.");
                }
                // The previous removeView() had not completed executing. Now it has.
            }*/


            root = new ViewRootImpl(view.getContext(), display);

            view.setLayoutParams(wparams);

            mViews.add(view);//将此DecorView保存到mViews容器中
            mRoots.add(root); //将此ViewRootImpl保存到容器中
            mParams.add(wparams);//保存参数

            // do this last because it fires off messages to start doing things
            try {
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
                // BadTokenException or InvalidDisplayException, clean up.
                if (index >= 0) {
                    removeViewLocked(index, true);
                }
                throw e;
            }
        }
    }

2.3 ViewRootImpl

主要作用:

1.获取IWindowSession代理类,此类用于应用端和wms进行通信。

2.new W(this);W 继承自 IWindow.Stub,用于wms服务端向应用端通信。在调用本类的setView时会将此W对象传递给WMS。

//ViewRootImpl.Java
public ViewRootImpl(Context context, Display display) {
        mContext = context;
        mWindowSession = WindowManagerGlobal.getWindowSession();//获取IWindowSession代理类,此类用于应用和wms进行通信
        mDisplay = display;//显示到那个display中
        mDirty = new Rect();
        mTempRect = new Rect();
        mVisRect = new Rect();
        mWinFrame = new Rect();
        mWindow = new W(this);//w继承自class W extends IWindow.Stub,用于wms服务端向应用端通信
        mFirst = true; // true代表此view第一次被添加
        mChoreographer = Choreographer.getInstance();
        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
}

2.4 getWindowSession

主要作用:

1.获取和WMS通信用的Session对象。

//WindowManagerGlobal.java
public static IWindowSession getWindowSession() {
        synchronized (WindowManagerGlobal.class) {
            if (sWindowSession == null) {
                try {
                    InputMethodManager imm = InputMethodManager.getInstance();//输入法
                    IWindowManager windowManager = getWindowManagerService();//获取wms的binder代理对象
                    sWindowSession = windowManager.openSession(
                            new IWindowSessionCallback.Stub() {//传入了客户端实现的WindowSessionCallback回调类,用于wms通信到应用程序
                                @Override
                                public void onAnimatorScaleChanged(float scale) {
                                    ValueAnimator.setDurationScale(scale);
                                }
                            },
                            imm.getClient(), imm.getInputContext());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            return sWindowSession;
        }
}
//aidl接口如下
IWindowSession openSession(in IWindowSessionCallback callback, in IInputMethodClient client,
            in IInputContext inputContext);

 2.5 WMS中的openSession

主要作用:

1.此时会走到WMS中,WMS中会创建一个session对象

//此时会调用到WMS中
public class WindowManagerService extends IWindowManager.Stub
        implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs 
{
			public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
            IInputContext inputContext) 
			{
				if (client == null) throw new IllegalArgumentException("null client");
				if (inputContext == null) throw new IllegalArgumentException("null inputContext");
				Session session = new Session(this, callback, client, inputContext);
				return session;//
		    }
}

 2.6 Session

主要作用为:
1.此类内部会保存WindowManagerService对象和客户端实现的IWindowSessionCallback类对象

class Session extends IWindowSession.Stub implements IBinder.DeathRecipient 
{
	public Session(WindowManagerService service, IWindowSessionCallback callback,
            IInputMethodClient client, IInputContext inputContext) {
        mService = service;//此时service是WindowManagerService对象
        mCallback = callback;//callback是客户端实现的IWindowSessionCallback类对象,是一个binder对象
        mClient = client;//此时是输入法的客户端
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();

        synchronized (mService.mWindowMap) {
            if (mService.mInputMethodManager == null && mService.mHaveInputMethods) {
                IBinder b = ServiceManager.getService(
                        Context.INPUT_METHOD_SERVICE);
                mService.mInputMethodManager = IInputMethodManager.Stub.asInterface(b);//获取输入法的binder代理对象
            }
        }
        long ident = Binder.clearCallingIdentity();
        try {
            // Note: it is safe to call in to the input method manager
            // here because we are not holding our lock.
            if (mService.mInputMethodManager != null) {
                mService.mInputMethodManager.addClient(client, inputContext,
                        mUid, mPid);//将此addClient添加到输入法中
            } else {
                client.setUsingInputMethod(false);
            }
            client.asBinder().linkToDeath(this, 0);
        } catch (RemoteException e) {
            // The caller has died, so we can just forget about this.
            try {
                if (mService.mInputMethodManager != null) {
                    mService.mInputMethodManager.removeClient(client);
                }
            } catch (RemoteException ee) {
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
	
}

2.7 class W

主要作用:

1.W 继承自 IWindow.Stub,用于wms服务端向应用端通信。在调用本类的setView时会将此W对象传递给WMS

static class W extends IWindow.Stub {
        private final WeakReference<ViewRootImpl> mViewAncestor;
        private final IWindowSession mWindowSession;

        W(ViewRootImpl viewAncestor) {
            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
            mWindowSession = viewAncestor.mWindowSession;//客户端保存IWindowSession session通信对象
        }
}

2.8 setView

主要作用为:

1.应用端创建空的InputChannel对象。

2.应用端通过binder调用addToDisplay函数,此时会走到到wms服务中,在wms中会对mInputChannel赋值,并返回。返回的是一个已经和IMS连接的socket。

3.当应用端拿到socket后,会new WindowInputEventReceiver对象,此对象内部最终后调用应用端ui主线程的Looper::addFd函数,通过epoll机制监听此socket,当存在IMS发送事件到应用程序端时,会调用NativeInputEventReceiver的handleEvent函数。

//frmaework/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
	    //view是view代表添加哪个窗口,此时view是DecorView
		//params窗口的参数
		//panelParentView,如果是子窗口,则子窗口存在父窗口,此时是普通窗口,则为null
        synchronized (this) {
            if (mView == null) {
                mView = view;
                mWindowAttri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值