从input tap来看事件注入的调用流程
来源:互联网 发布:手机上怎么看淘宝分销 编辑:程序博客网 时间:2024/05/28 23:12
搜索Input event injection from得到InputManagerService.java
private boolean injectInputEventInternal(InputEvent event, int displayId, 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, displayId, 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:
return 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;
}
}
搜索nativeInjectInputEvent
$ find . -name *.c*|xargs grep 'nativeInjectInputEvent'
Binary file ./out/target/common/obj/JAVA_LIBRARIES/services.core_intermediates/classes/com/android/server/input/InputManagerService.class matches
./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp:static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp: { "nativeInjectInputEvent", "(JLandroid/view/InputEvent;IIIIII)I",
./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp: (void*) nativeInjectInputEvent },
vi ./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,
jint syncMode, jint timeoutMillis, jint policyFlags) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
KeyEvent keyEvent;
status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);
if (status) {
jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");
return INPUT_EVENT_INJECTION_FAILED;
}
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
& keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
uint32_t(policyFlags));
} else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);
if (!motionEvent) {
jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");
return INPUT_EVENT_INJECTION_FAILED;
}
return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(
motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,
uint32_t(policyFlags));
} else {
jniThrowRuntimeException(env, "Invalid input event type.");
return INPUT_EVENT_INJECTION_FAILED;
}
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
一个比较暴力的方法是,屏蔽掉权限检查的code,
int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags) {
ALOGD("=====<<<<<>>>>>5-4 policyFlags |= POLICY_FLAG_TRUSTED");
if (hasInjectionPermission(injectorPid, injectorUid)) {
policyFlags |= POLICY_FLAG_TRUSTED;
}
bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
ALOGD("hasInjectionPermission called");
return injectorUid == 0
|| mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);
}
这样就可以进行跨进程,跨页面进行点击了
调到了frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp中的
bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid) {
ALOGD("-====== JNI, checkInjectEventsPermissionNonReentrant called");
JNIEnv* env = jniEnv();
jboolean result = env->CallBooleanMethod(mServiceObj,
gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
result = false;
}
return result;
}
里面又回调到InputManagerService.java中的
// Native callback.
private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
}
检查INJECT_EVENTS权限
只有系统级ap才可以有INJECT_EVENTS permission,这样设计的目的是为了系统安全
- 从input tap来看事件注入的调用流程
- 从`Sample`来看`Tinker`的启动流程
- mui的单击事件 tap
- Android 上从外部应用注入按键事件流程分析
- Android 上从外部应用注入按键事件流程分析
- 从华为面试来看C/C++的调用约定
- 后台服务,注入input事件
- 从发布者和订阅者来看事件
- input子系统 事件流程浅析
- zepto tap事件的一个bug
- zepto tap事件的一个bug
- zepto tap事件的一个bug
- Input调用流程(好文)
- java GUI事件模型的调用流程
- 从浏览者访问网页的流程来看如何提高系统反应速度(1)--客户端交互
- 学习摘录---[从系统架构师的观点来看软件开发流程]
- C++从虚函数表的底层来看虚函数调用问题
- tap,touch,touchstart事件与click事件的区别
- Failed to Match * of * Components using Unique Identifiers
- 线性结构——队列
- Prim算法
- Ubuntu17.04搭建Shadowsocks
- QListWidget使用整理
- 从input tap来看事件注入的调用流程
- 关于xml的规范
- lintcode-- 四数之和
- 湖南省第九届大学生计算机程序设计竞赛 好老师
- linux下离线安装mysql
- OpenJudge-49:计算对数
- 解决record is locked by another user
- Kruskal算法(不能运行)
- Android-auto-android-car崛起-黑莓的QNX在汽车领域的未来将如何