本文主要是介绍Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
需求:用户点击屏幕后取消原有定时任务,无操作后顺延原来定时任务
简单分析
要想全局监听,那必须是在 framework 中了,应该从哪里切入呢?先看看 log,每点击一次屏幕后发现打印
InputDispatcher: Asynchronous input event injection succeeded.
全局搜索找到 frameworks\native\services\inputflinger\InputDispatcher.cpp 中
这就有点难顶了,cpp 中想要通知 java 层还是有点困难的,一开始尝试了在此处发送广播
#include <unistd.h>
switch (injectionResult) {
case INPUT_EVENT_INJECTION_SUCCEEDED:
ALOGV(“Asynchronous input event injection succeeded.”);
execlp(“am”, “am”, “broadcast”,
“-n”, “com.android.systemui/com.pdd.sutie.CustomerReceiver”,
“-a”, “com.pdd.action.inputevent.inject”,
NULL);
exit(errno);
通过函数 execlp() 调用 am 指令发送广播,尝试后发现会把 system 进程搞挂,看来 execlp() 不能在此使用,那就只能搂底浆了,
从 cpp 往上找,最终找到 frameworks\base\services\core\java\com\android\server\input\InputManagerService.java 中
调用顺序如下
InputManagerService.java
injectInputEventInternal(event, mode)
com_android_server_input_InputManagerService.cpp
im->getInputManager()->getDispatcher()->injectInputEvent(
InputDispatcher.cpp
int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags)
解决办法
frameworks\base\services\core\java\com\android\server\input\InputManagerService.java
@Override // Binder callpublic boolean injectInputEvent(InputEvent event, int mode) {return injectInputEventInternal(event, mode);}private boolean injectInputEventInternal(InputEvent event, int mode) {if (event == null) {throw new IllegalArgumentException("event must not be null");}if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {throw new IllegalArgumentException("mode is invalid");}final int pid = Binder.getCallingPid();final int uid = Binder.getCallingUid();final long ident = Binder.clearCallingIdentity();final int result;try {result = nativeInjectInputEvent(mPtr, event, pid, uid, mode,INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);} finally {Binder.restoreCallingIdentity(ident);}switch (result) {case INPUT_EVENT_INJECTION_PERMISSION_DENIED:Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");throw new SecurityException("Injecting to another application requires INJECT_EVENTS permission");case INPUT_EVENT_INJECTION_SUCCEEDED://cczheng add for listen lcd input startandroid.util.Log.e("InputDispatcher", "Input event injection from pid " + pid + " succeeded.");Intent pIntent = new Intent("com.pdd.action.inputevent.inject");pIntent.setComponent(new android.content.ComponentName("com.android.systemui","com.pdd.sutie.CustomerReceiver"));mContext.sendBroadcast(pIntent);//cczheng add for listen lcd input endreturn true;case INPUT_EVENT_INJECTION_TIMED_OUT:Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");return false;case INPUT_EVENT_INJECTION_FAILED:default:Slog.w(TAG, "Input event injection from pid " + pid + " failed.");return false;}}
Android Input(四) -InputDispatcher分发事件
Android10 InputManagerService事件输入输出
这篇关于Framework 全局监听屏幕点击事件 INPUT_EVENT_INJECTION的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!