input子系统:InputManagerService
由于客户新提了一个屏蔽设备的功能需求(屏蔽鼠标、键盘、触摸等输入子系统事件),刚开始一头雾水,不知道从哪改起。
看了一些网上的文章,这就要涉及到InputManagerService这个庞大的东西,就需要大概了解这个服务的基本流程。
先贴几张框架图:
一.输入事件传递流程的组成部分:
输入系统是外界与Android设备交互的基础,仅凭输入系统是无法完成输入事件传递的,因此需要输入系统和Android系统的其他成员来共同完成事件传递。输入系统事件传递需要经过以下几个部分。
输入事件传递流程可以大致的分为三个部分,分别是输入系统部分、WMS处理部分和View处理部分。
输入系统部分
输入系统部分主要又分为输入子系统和InputManagerService组成(以下简称IMS),在Android中还有一个IMS(IP Multimedia Subsystem)意为为IP多媒体子系统,不要搞混了。
Android的输入设备有很多种,比如屏幕、键盘、鼠标、游戏手柄、操纵杆等等,其中应用开发接触最多的屏幕。当输入设备可用时,Linux内核会在/dev/input中创建对应的设备节点。
用户操作这些输入设备时会产生各种事件比如按键事件、触摸事件、鼠标事件等。
输入事件所产生的原始信息会被Linux内核中的输入子系统采集,原始信息由Kernel space的驱动层一直传递到User space的设备节点。
Android提供了getevent和sendevent两个工具帮助开发者从设备节点读取输入事件和写入输入事件。

IMS所做的工作就是监听/dev/input下的所有的设备节点,当设备节点有数据时会将数据进行加工处理并找到合适的Window,将输入事件派发给它。
WMS处理部分
WMS的职责之一就是输入系统的中转站,WMS作为Window的管理者,会配合IMS将输入事件交由合适的Window来处理。
View处理部分
View处理部分应该是大家最熟悉的了,一般情况下,输入事件最终会交由View来处理,应用开发者就可以通过一些回调方法轻松得到这个事件的封装类并对其进行处理,比如onTouchEvent(MotionEvent ev)方法。
二、IMS服务部分
启动内容:
0.startOtherServices启动InputManagerService
1.inputManagerService启动初始化
2.eventhub初始化
3.InputDispatcherThread初始化和启动
4.inputReaderThread启动
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/java/com/android/server/SystemServer.java startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService


在startOtherServices这个函数里面实现ims的创建和启动。
public InputManagerService(Context context) { this.mContext = context; this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper()); mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" + mUseDevInputEventForAudioJack); mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());////调用jni String doubleTouchGestureEnablePath = context.getResources().getString( R.string.config_doubleTouchGestureEnableFile); mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : new File(doubleTouchGestureEnablePath); LocalServices.addService(InputManagerInternal.class, new LocalService()); }

NativeInputManager如下:
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper), mInteractive(true) { JNIEnv* env = jniEnv(); mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); { AutoMutex _l(mLock); mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; mLocked.pointerSpeed = 0; mLocked.pointerGesturesEnabled = true; mLocked.showTouches = false; mLocked.hardwareRotation = 0; char property[PROPERTY_VALUE_MAX]; if (property_get("ro.sf.hwrotation", property, "0") > 0) { mLocked.hardwareRotation = atoi(property) / 90; } } mInteractive = true; sp<EventHub> eventHub = new EventHub(); ////创建EventHub
mInputManager = new InputManager(eventHub, this, this); } ///创建InputManager
public void start() { Slog.i(TAG, "Starting input manager"); nativeStart(mPtr); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); registerPointerSpeedSettingObserver(); registerShowTouchesSettingObserver(); registerAccessibilityLargePointerSettingObserver(); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updatePointerSpeedFromSettings(); updateShowTouchesFromSettings(); updateAccessibilityLargePointerFromSettings(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); updatePointerSpeedFromSettings(); updateShowTouchesFromSettings(); updateAccessibilityLargePointerFromSettings(); //wmc enable filterInputEvent nativeSetInputFilterEnabled(mPtr,true); //这个函数enable,才能启动filterInputEvent这个拦截的函数
}
nativeStart同样是调用的com_android_server_input_InputManagerService.cpp中的:

// Native callback. final boolean filterInputEvent(InputEvent event, int policyFlags) { //wmc add lock inputevent boolean disableInputManager = "open".equals(SystemProperties.get("persist.sys.lock_device")); if(disableInputManager){ return false; //根据读到的属性,直接返回false, } synchronized (mInputFilterLock) { if (mInputFilter != null) { try { mInputFilter.filterInputEvent(event, policyFlags); } catch (RemoteException e) { /* ignore */ } return false; } } event.recycle(); return true; }
可以设置广播来实现设置属性:
if(intent.getAction().equals(BOARDCAST_LOCK_DEVICE)) { boolean lockdevice= intent.getBooleanExtra("lockdevice",false); if(lockdevice){ SystemProperties.set("persist.sys.lock_device", "open"); }else{ SystemProperties.set("persist.sys.lock_device", "close"); } }
这样就可以实现这个功能了。
整个框架流程图如下:
此篇文章用了很多网上文章框架图,在此声明一下!
参考的主要文章如下:
https://www.jianshu.com/p/42d95cdca70b
https://blog.csdn.net/vv0_0vv/article/details/105217737
https://blog.csdn.net/wd229047557/article/details/100764889
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!