PhoneWindowManager处理事件分析(十一)

1, 基本概念

PhoneWindowManager也是运行于systemserver线程中,在Event事件分发之前处理,比如电源键。Event事件分发后,仅有包含Activity的apk线程才可以处理,如果apk中没有activity但是想处理Event事件怎么办呢?可以在PhoneWindowManager做做文章了。

在SystemServer中,

inputManager = new InputManagerService(context);
  wm = WindowManagerService.main(context, inputManager,
        mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
        !mFirstBoot, mOnlyCore);
 ServiceManager.addService(Context.WINDOW_SERVICE, wm);
 ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

 mActivityManagerService.setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); // 消息分发之前的回调
inputManager.start();

InputManagerService的创建以及启动已经论述了,在此就不多说了。在

WindowManagerService中新建了PhoneWindowManager和InputMonitor,并且将设置为InputManagerService对象的回调对象。其实这2个类都和Event的处理有关,在Event分发之前进行处理,相当于截取,具体的细节就一层一层抽丝剥茧了。

PhoneWindowManager是没有对应的C/C++层代码了。

看下InputManagerService的setWindowManagerCallbacks方法,

public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
        mWindowManagerCallbacks = callbacks;
    }

因此, InputManagerService的变量mWindowManagerCallbacks指向InputMonitor对象。

2处理流程


InputDispatcher的notifyKey方法中,Event进队列之前,会调用interceptKeyBeforeQueueing方法,

mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

mPolicy变量是什么呢?通过查找,是NativeInputManager对象,

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
        uint32_t& policyFlags) {
    bool interactive = mInteractive.load();
    if (interactive) {
        policyFlags |= POLICY_FLAG_INTERACTIVE;
    }
    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime();
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        jint wmActions;
        if (keyEventObj) {
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,
                    keyEventObj, policyFlags);
            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                wmActions = 0;
            }
            android_view_KeyEvent_recycle(env, keyEventObj);
            env->DeleteLocalRef(keyEventObj);
        }
•••
}

在register_android_server_InputManager方法中,

int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
            gInputManagerMethods, NELEM(gInputManagerMethods));
•••
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");

很明显了,调用Java层InputManagerService的interceptKeyBeforeQueueing方法,后面就没有什么困难了,最后调用PhoneWindowManager的interceptKeyBeforeQueueing方法。

看下InputMonitor的方法,有一些也是同样的方法调用,关键是C/C++层的代码什么时候调用,觉得InputMonitor的主要目的还是解耦,防止PhoneWindowManager和InputManagerService太紧,

public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
        mService.mPolicy.notifyLidSwitchChanged(whenNanos, lidOpen);
    }
public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
        mService.mPolicy.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
    }
 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
    }
    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
        return mService.mPolicy.interceptMotionBeforeQueueingNonInteractive(
                whenNanos, policyFlags);
    }
    public long interceptKeyBeforeDispatching(
            InputWindowHandle focus, KeyEvent event, int policyFlags) {
        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
        return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
    }
    public KeyEvent dispatchUnhandledKey(
            InputWindowHandle focus, KeyEvent event, int policyFlags) {
        WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
        return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
    }
    public int getPointerLayer() {
        return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_POINTER)
                * WindowManagerService.TYPE_LAYER_MULTIPLIER
                + WindowManagerService.TYPE_LAYER_OFFSET;
    }

在InputDispatcher.cpp的中的Event入队列之后,dispatchKeyLocked方法中会调用doInterceptKeyBeforeDispatchingLockedInterruptible方法,然后调用NativeInputManager的interceptKeyBeforeDispatching方法,

nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
            &event, entry->policyFlags);

最后会调用PhoneWindowManager的interceptKeyBeforeDispatching方法。


所以,如果apk中没有acitivity但是想监听Event事件怎么办呢?

在PhoneWindowManager的interceptKeyBeforeQueueing或者interceptKeyBeforeDispatching方法中稍加处理就可以了。

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值