Instrumentation中的sendKeyDownUpSync的调用过程

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();
    ..............................
    //在这个类中可以做自定义的按键拦截
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值