1、使用方法
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(keyCode);//其中keyCode是要发送的键值比如,确认按键,在KeyEvent.java定义为23,keyCode 就是23
2、/frameworks/base/core/java/android/app/Instrumentation.java
public void sendKeyDownUpSync(int keyCode) {
sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));//根据keyCode new了一个KeyEvent
sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
}
之后会调用sendKeySync接口发送按键
public void sendKeySync(KeyEvent event) {
validateNotAppThread();
long downTime = event.getDownTime();
long eventTime = event.getEventTime();
int source = event.getSource();
if (source == InputDevice.SOURCE_UNKNOWN) {
source = InputDevice.SOURCE_KEYBOARD;
}
if (eventTime == 0) {
eventTime = SystemClock.uptimeMillis();
}
if (downTime == 0) {
downTime = eventTime;
}
KeyEvent newEvent = new KeyEvent(event);
newEvent.setTime(downTime, eventTime);
newEvent.setSource(source);
newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
setDisplayIfNeeded(newEvent);
InputManagerGlobal.getInstance().injectInputEvent(newEvent,
InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
}
前面在都会event进行设置,最后调用injectInputEvent进行下一步转发
调用到/frameworks/base/core/java/android/hardware/input/InputManagerGlobal.java 里的
public boolean injectInputEvent(InputEvent event, int mode, int targetUid) {
Objects.requireNonNull(event , "event must not be null");
if (mode != InputEventInjectionSync.NONE
&& mode != InputEventInjectionSync.WAIT_FOR_FINISHED
&& mode != InputEventInjectionSync.WAIT_FOR_RESULT) {
throw new IllegalArgumentException("mode is invalid");
}
try {
return mIm.injectInputEventToTarget(event, mode, targetUid);
//其中,mIm是IInputManager的对象,InputManagerService实现了IInputManager接口,所以这里调用到InputManagerService.java的injectInputEventToTarget接口
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
之后到 /frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
会用到
result = mNative.injectInputEvent(event, injectIntoUid,
targetUid, mode, INJECTION_TIMEOUT_MILLIS,
WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
//其中mNative是NativeInputManagerService的对象,injectInputEvent的实现在/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
com_android_server_input_InputManagerService.cpp
{"injectInputEvent", "(Landroid/view/InputEvent;ZIIII)I", (void*)nativeInjectInputEvent},
static jint nativeInjectInputEvent(JNIEnv* env, jobject nativeImplObj, jobject inputEventObj,
jboolean injectIntoUid, jint uid, jint syncMode,
jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
const std::optional<int32_t> targetUid = injectIntoUid ? std::make_optional(uid):
std::nullopt;
// static_cast is safe because the value was already checked at the Java layer
//if判断该event是Motion的还是keyEvent,我们发送的是keyevent
InputEventInjectionSync mode = static_cast<InputEventInjectionSync>(syncMode);
if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
const KeyEvent keyEvent = android_view_KeyEvent_toNative(env, inputEventObj);
const InputEventInjectionResult result =
im->getInputManager()->getDispatcher().injectInputEvent(&keyEvent,
targetUid,
mode,std::chrono::milliseconds(timeoutMillis),uint32_t(policyFlags));
return static_cast<jint>(result);
} int>(InputEventInjectionResult::FAILED);
}
.....................................
}
下一步到/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp里的injectInputEvent,代码很多,主要最后会调用到
mPolicy.interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
其中,InputDispatcherPolicyInterface& mPolicy
而NativeInputManager继承InputDispatcherPolicyInterface,所以我们查看/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp 里的
NativeInputManager的接口实现
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent& keyEvent,
uint32_t& policyFlags) {
.........
jint wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
eyEventObj.get(), policyFlags);
//这里调用到了mServiceObj对象中的interceptKeyBeforeQueueing方法,即InputManagerService.java
//里的interceptKeyBeforeQueueing方法
}
@SuppressWarnings("unused")
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
synchronized (mFocusEventDebugViewLock) {
if (mFocusEventDebugView != null) {
mFocusEventDebugView.reportEvent(event);
}
}
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}
之后到/frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
又到/frameworks/base/services/core/java/com/android/server/policy/WindowManagerPolicy.java
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
而/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 中的class PhoneWindowManager implements WindowManagerPolicy,所以到这里就到了我们一般修改的按键拦截类PhoneWindowManager
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
final int keyCode = event.getKeyCode();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 ||
event.isWakeKey();
..............................
//在这个类中可以做自定义的按键拦截
}