Android Input (6) -- PhoneWindowManager中Power,BACK等按键处理流程

Link:

Android Input (1) -- InputManagerService启动

Android Input (2) -- inputReader

Android Input (3) -- inputDispatcher

Android Input (4) -- inputDispatcher到ViewRootImpl

Android Input (5) -- ViewRootImpl 的事件分发(Activity ViewGroup View )

Android Input (6) -- PhoneWindowManager中Power,BACK等按键处理流程

Android Input (7) -- 模块的锁检测

Android Input (8) -- ANR input event原理


详情见 Android Input --InputReader

 

2.3.2.1 interceptKeyBeforeQueueing

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

 

sp<InputDispatcherPolicyInterface> mPolicy;
class InputDispatcherPolicyInterface : public virtual RefBase {
public:

    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;

     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
     * should be dispatched to applications.
     */
    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;

//NativeInputManager 初始化InputManager传入的this,就是InputManager中的dispatcherPolicy

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);
...
    sp<EventHub> eventHub = new EventHub();   //create EventHub
    mInputManager = new InputManager(eventHub, this, this);
}

@frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);   //初始化InputDispatcher
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);   //初始化InputReader
    initialize();
}

//InputDispatcher初始化就赋值 policy 为mPolicy

 

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),  //赋值
    ...
    policy->getDispatcherConfiguration(&mConfig);
}

@frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

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);
        } else {

        }

        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    } else {
        if (interactive) {
            policyFlags |= POLICY_FLAG_PASS_TO_USER;
        }
    }
}

//calss InputManagerService method:interceptKeyBeforeQueueing

int register_android_server_InputManager(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
            gInputManagerMethods, NELEM(gInputManagerMethods));
    jclass clazz;
    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");

    GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
            "filterInputEvent", "(Landroid/view/InputEvent;I)Z");

    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");

InputManagerService中的WindowManagerCallbacks是接口 implements InputManagerService.WindowManagerCallbacks

@frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

 

// Native callback.
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
    return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}

public interface WindowManagerCallbacks {
    ...
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
    public long interceptKeyBeforeDispatching(InputWindowHandle focus,
}

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

startOtherServices初始化传入的InputMonitor

 

private void startOtherServices() {
    inputManager = new InputManagerService(context);   //初始化InputManagerService

    wm = WindowManagerService.main(context, inputManager,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
            !mFirstBoot, mOnlyCore, new PhoneWindowManager());
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);  //可以通过IInputManager来binder调用InputManagerService方法
    inputManager.setWindowManagerCallbacks(wm.getInputMonitor());   //setWindowManagerCallbacks
    inputManager.start();  //start inputmanager
}

得到的就是wms的mInputMonitor

@frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public InputMonitor getInputMonitor() {
    return mInputMonitor;
}

//使用WindowManagerPolicy的interceptKeyBeforeQueueing

@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
//使用WindowManagerPolicy的interceptKeyBeforeQueueing
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {   //implements WindowManagerCallbacks
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
    }
}

看谁使用的WindowManagerPolicy接口

 

private final WindowManagerService mService;
final WindowManagerPolicy mPolicy;

@frameworks/base/core/java/android/view/WindowManagerPolicy.java
public interface WindowManagerPolicy {
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
}

PhoneWindowManager是接口WindowManagerPolicy

事件处理和拦截主要在这里,包括POWER灭屏,声音,语言助手,camera,BACK键之类的处理

 

public class PhoneWindowManager implements WindowManagerPolicy {

//可以看下policyFlags这个参数 
   @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean canceled = event.isCanceled();
        final int keyCode = event.getKeyCode();

        boolean useHapticFeedback = down
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && event.getRepeatCount() == 0;

        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK: {   //返回键
                if (down) {
                    interceptBackKeyDown();
                } else {
                    boolean handled = interceptBackKeyUp(event);

                    // Don't pass back press to app if we've already handled it via long press
                    if (handled) {
                        result &= ~ACTION_PASS_TO_USER;
                    }
                }
                break;
            }

            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                break;
            }
            case KeyEvent.KEYCODE_POWER: {  //POWER键行为控制
                // Any activity on the power button stops the accessibility shortcut
                cancelPendingAccessibilityShortcutAction();
                result &= ~ACTION_PASS_TO_USER;   //看起来~ACTION_PASS_TO_USER是表示拦截事件
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactive);
                } else {
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }

            //看起来像是导航栏上的事件
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
                result &= ~ACTION_PASS_TO_USER;
                interceptSystemNavigationKey(event);
                break;
            }

            case KeyEvent.KEYCODE_SLEEP: {
                break;
            }
            case KeyEvent.KEYCODE_MEDIA_PLAY:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MUTE:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
                ...
            case KeyEvent.KEYCODE_CALL: {
                break;
            }
            case KeyEvent.KEYCODE_VOICE_ASSIST: {   //看起来是唤醒语音助手
                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
                            keyguardActive ? 1 : 0, 0);
                break;
            }

        if (useHapticFeedback) {   //震动反馈
            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
        }
        if (isWakeKey) {
            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
        }
        return result;
    }
    
    //经过一系列判断后,调用vibrate实现振动
    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
        return true;
    }

}

 

 

 

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值