android WindowManagerService addFakeWindow 研究

首先,该方法起源于:

FakeWindow com.android.server.wm.WindowManagerService.addFakeWindow(Looper looper, Factory inputEventReceiverFactory, String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen)
定义位置:

<span style="font-family: Arial, Helvetica, sans-serif;">FakeWindow android.view.WindowManagerPolicy.WindowManagerFuncs.addFakeWindow(Looper looper, Factory inputEventReceiverFactory, String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags, boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen)</span>

实现:

        synchronized (mWindowMap) {
            FakeWindowImpl fw = new FakeWindowImpl(this, looper, inputEventReceiverFactory,
                    name, windowType,
                    layoutParamsFlags, layoutParamsPrivateFlags, canReceiveKeys,
                    hasFocus, touchFullscreen);
            int i=0;
            while (i<mFakeWindows.size()) {
                if (mFakeWindows.get(i).mWindowLayer <= fw.mWindowLayer) {
                    break;
                }
            }
            mFakeWindows.add(i, fw);
            mInputMonitor.updateInputWindowsLw(true);

好,接下来该看 FakeWindowImpl ,位置:

com.android.server.wm.FakeWindowImpl
到这里我先讲讲我为什么要研究这个方法,因为我发现这个方法有一个功能是可以添加一个虚拟窗口,监听全屏触摸事件,我想实现的就是监听全局触摸事件,所以可以以此方法为切入点!


我们来看看他的构造函数:

public FakeWindowImpl(WindowManagerService service,
            Looper looper, InputEventReceiver.Factory inputEventReceiverFactory,
            String name, int windowType, int layoutParamsFlags, int layoutParamsPrivateFlags,
            boolean canReceiveKeys, boolean hasFocus, boolean touchFullscreen) 

InputEventReceiver.Factory inputEventReceiverFactory, 这个参数才是我的重点,因为他才是接收 InputEvent 的实体,那好我们看看构造函数如何使用此参数咯,

重点来啦,

        InputChannel[] channels = InputChannel.openInputChannelPair(name);
        mServerChannel = channels[0];
        mClientChannel = channels[1];
        mService.mInputManager.registerInputChannel(mServerChannel, null);

        mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(
                mClientChannel, looper);
重点在于 InputChannel ,看来我得先搞懂他是什么咯,

关于 InputChannel 可以移步到这里: Android入门之在客户进程中注册InputChannel  Android入门之创建InputChannel


再看 InputEventReceiver 的创建,

 mInputEventReceiver = inputEventReceiverFactory.createInputEventReceiver(mClientChannel, looper);

这个对象在这里:

com.android.internal.policy.impl.PhoneWindowManager.mHideNavInputEventReceiverFactory
    final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
            new InputEventReceiver.Factory() {
        @Override
        public InputEventReceiver createInputEventReceiver(
                InputChannel inputChannel, Looper looper) {
            return new HideNavInputEventReceiver(inputChannel, looper);
        }
    };
InputEventReceiver 的实现是:
    /**
     * Input handler used while nav bar is hidden.  Captures any touch on the screen,
     * to determine when the nav bar should be shown and prevent applications from
     * receiving those touches.
     */
    final class HideNavInputEventReceiver extends InputEventReceiver {
        public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
            super(inputChannel, looper);
        }
他这个对象是干嘛用的呢,我们知道从 Android 4.2 开始,开发者可以将导航栏 和 状态栏隐藏来使屏幕显示更多内容,这个对象就是用来监听导航栏隐藏掉的时候,如何呼唤出来,要不然就得重启手机了 偷笑,不过就此吐槽几点,Android 框架过于复杂, 以至于一个导航栏处理起来都是很麻烦,废话不多说,


来看 InputEventReceiver 如何使用 InputChannel:

    /**
     * Creates an input event receiver bound to the specified input channel.
     *
     * @param inputChannel The input channel.
     * @param looper The looper to use when invoking callbacks.
     */
    public InputEventReceiver(InputChannel inputChannel, Looper looper) {
        if (inputChannel == null) {
            throw new IllegalArgumentException("inputChannel must not be null");
        }
        if (looper == null) {
            throw new IllegalArgumentException("looper must not be null");
        }

        mInputChannel = inputChannel;
        mMessageQueue = looper.getQueue();
        mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                inputChannel, mMessageQueue);

        mCloseGuard.open("dispose");
    }
我们看到他的工作赚到了 native 层,nativeInit,这我就不深究了,我已经知道我该怎么做了!


重点就是先使用:

InputChannel[] channels = InputChannel.openInputChannelPair(name); 

创建一对输入接收器,然后向 InputManagerService 注册 channel :

void com.android.server.input.InputManagerService.registerInputChannel(InputChannel inputChannel, InputWindowHandle inputWindowHandle)


Android输入输出机制之来龙去脉之前生后世


然后我开始测试代码。。。























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值