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
//mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); mpolicy是InputDispatcherPolicyInterface
sp 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) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
...
sp eventHub = new EventHub(); //create EventHub
mInputManager = new InputManager(eventHub, this, this);
}
@frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy); //初始化InputDispatcher
mReader = new InputReader(eventHub, readerPolicy, mDispatcher); //初始化InputReader
initialize();
}
//InputDispatcher初始化就赋值 policy 为mPolicy
InputDispatcher::InputDispatcher(const sp& 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;
}
}