Android 12.0源码系列之IMSInputManagerService
Posted bubbleben
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 12.0源码系列之IMSInputManagerService相关的知识,希望对你有一定的参考价值。
android 12.0源码系列之IMS(一)InputManagerService
本篇涉及到的主要代码:
frameworks\\base\\services\\core\\java\\com\\android\\server\\SystemServer.java
frameworks\\base\\services\\core\\java\\com\\android\\server\\wm\\WindowManagerService.java
frameworks\\base\\services\\core\\java\\com\\android\\server\\input\\InputManagerService.java
Android
系统框架提供了众多的系统服务,比如管理四大组件的AMS(ActivityManagerService)
,管理窗口的WMS(WindowManagerService)
,管理应用安装, 卸载和更新的PMS(PackageManagerService)
,管理输入事件和输入设备的IMS(InputManagerService
)等,本系列将基于Android 12.0.0_r3
源码对系统框架服务的重点流程进行解读,旨在加深对Android
体系结构的理解,了解框架层运行原理,进而深入研究系统性能分析/系统优化/架构设计。
从功能上看,InputManagerService
的责任相对来讲比较单一,根据注释Wraps the C++ InputManager and provides its callbacks
可以看出其主要作用在于对native
层InputManager
的封装以及为java
层提供回调;从代码行数来讲,ActivityManagerService
-17212行(Android P
为27245行,从Android Q
开始解耦出ActivityTaskManagerService
后减少了代码量),PackageManagerService
-28946行,WindowManagerService
-8613行,InputManagerService
-3479行,其中InputManagerService
的代码量最少,相对来讲入手比较容易,所以本系列将从InputManagerService
入手一步步分析Java
层InputManagerService
和Native
层InputManager
的创建,Input
事件(Motion
/Key
等)的读取和分发流程,Input
超时触发ANR
的原理等,希望通过本系列的总结能够加深对框架的理解,遇到更多疑难杂症时可以站在更高的视野,从更多的角度来分析和解决问题。
1. SystemServer.startOtherServices
同其他系统服务一样,InputManagerService
也是在开机时由SystemServer
创建并以input
为别名添加到ServiceManager
中进行管理,鉴于篇幅限制仅列出与主要业务相关的代码(后面的系列和章节亦如此);
[-> SystemServer.java]
private void startOtherServices(@NonNull TimingsTraceAndSlog t)
WindowManagerService wm = null;
InputManagerService inputManager = null;
// 初始化InputManagerService对象[见第2小节]
inputManager = new InputManagerService(context);
// WindowManagerService依赖InputManagerService的创建
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 将名为"window"的系统服务添加到ServiceManager进行管理
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
// 将名为"input"的系统服务添加到ServiceManager进行管理
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
// 为InputManagerService注册WindowManagerCallbacks[见第3小节]
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
// 执行InputManagerService的start()方法[见第4小节]
inputManager.start();
try
// 为InputManagerService设置无线耳机设备变化的监听
inputManager.setWiredAccessoryCallbacks(
new WiredAccessoryManager(context, inputManager));
catch (Throwable e)
reportWtf("starting WiredAccessoryManager", e);
final InputManagerService inputManagerF = inputManager;
mActivityManagerService.systemReady(() ->
Slog.i(TAG, "Making services ready");
t.traceBegin("StartActivityManagerReadyPhase");
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
t.traceEnd();
// ActivityManagerService执行完systemReady之后,调用InputManagerService.systemRunning()
try
if (inputManagerF != null)
// InputManagerService的准备工作已经基本完成,可以开始运行[见第5小节]
inputManagerF.systemRunning();
catch (Throwable e)
reportWtf("Notifying InputManagerService running", e);
2. InputManagerService.constructor
[-> InputManagerService.java]
/*
* Wraps the C++ InputManager and provides its callbacks.
*/
public class InputManagerService extends IInputManager.Stub
implements Watchdog.Monitor
static final String TAG = "InputManager";
// Pointer to native input manager service object.
private final long mPtr;
private final Context mContext;
private final InputManagerHandler mHandler;
// native方法
private static native long nativeInit(InputManagerService service,
Context context, MessageQueue messageQueue);
public InputManagerService(Context context)
// system context
this.mContext = context;
// InputManagerHandler绑定android.display线程, 主要用于处理输入设备变化,键盘布局变化等事件
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
// 调用native方法初始化NativeInputManager, 并保存返回的指针, 我们在下一章会进行详细介绍
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
// 将LocalService添加到LocalServices,方便SystemServer中的其他服务调用
LocalServices.addService(InputManagerInternal.class, new LocalService());
private final class LocalService extends InputManagerInternal
@Override
public boolean injectInputEvent(InputEvent event, int mode)
return injectInputEventInternal(event, mode);
DisplayThread
是一个主要处理显示任务的单例线程,对时延的要求很高,所以优先级高于后台线程(THREAD_PRIORITY_BACKGROUND
)和前台线程(THREAD_PRIORITY_FOREGROUND
),基本只用于DisplayManagerService
,WindowManagerService
和InputManagerService
;
InputManagerInternal
是一个抽象类并声明了一些接口,InputManagerService
的内部类LocalService
继承并实现了这些接口,用于system_server
进程内部其他服务调用InputManagerService
;
3. InputManagerService.setWindowManagerCallbacks
[-> WindowMangerService.java]
final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);
public InputManagerCallback getInputManagerCallback()
return mInputManagerCallback;
WindowManagerCallbacks
是InputManagerService
内部定义的一个接口类,用于WindowManagerService
和InputManagerService
之间的交互,由InputManagerCallback
实现包括通知ANR
,通知系统配置变更,通知焦点改变,拦截按键/触屏消息的分发等在内的接口功能,可以通过WindowManagerService.getInputManagerCallback()
获取;
[-> InputManagerService.java]
// WindowManagerService策略类,由PhoneWindowManager实现
WindowManagerPolicy mPolicy;
private WindowManagerCallbacks mWindowManagerCallbacks;
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks)
mWindowManagerCallbacks = callbacks;
// Native callback.
private long interceptKeyBeforeDispatching(IBinder focus, KeyEvent event, int policyFlags)
return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
[-> InputManagerCallback.java]
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
这里以interceptKeyBeforeDispatching
为例说明:native
层在分发按键消息时会调用Java
层此方法,而InputManagerService
并不直接处理而是交由之前设置的InputManagerCallback
来处理,它又会将此事件交由WindowManagerService
的策略类PhoneWindowManager
进行专门处理。
4. InputManagerService.start
[-> InputManagerService.java]
public void start()
// 通过nativeInit拿到的指针mPtr继续调用jni方法nativeStart,启动native层的InputReader和InputDispatcher两条线程
nativeStart(mPtr);
// InputManagerService实现了Watchdog.Monitor接口并重写了monitor()方法
// WatchDog会定期调用monitor方法检查系统服务是否发生死锁
Watchdog.getInstance().addMonitor(this);
// 通过ContentObserver监听SettingsProvider中input相关设置项的值
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
registerLongPressTimeoutObserver();
registerMaximumObscuringOpacityForTouchSettingObserver();
registerBlockUntrustedTouchesModeSettingObserver();
// 由于每个用户可以有自己的设置, 所以需要监听用户切换的广播,并更新SettingsProvider中input相关设置项的值
mContext.registerReceiver(new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("user switched");
, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
// InputManagerService创建时会主动触发一次input相关设置项的刷新
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
updateDeepPressStatusFromSettings("just booted");
updateMaximumObscuringOpacityForTouchFromSettings();
// 获取屏蔽不受任务的触摸事件的设置项,并将其设置到InputDispatcher用于拦截触摸事件的上报
updateBlockUntrustedTouchesModeFromSettings();
这里继续通过nativeStart
创建InputDispatcher
和InputReader
,增加Watchdog
的监听和SettingsProvider
的更新和监听,相比较Android 11.0
增加了屏蔽不受信任的触摸事件
这一新特性(https://developer.android.google.cn/about/versions/12/behavior-changes-all#untrusted-touch-events);
// State for the currently installed input filter.
final Object mInputFilterLock = new Object();
private final Object mAssociationsLock = new Object();
private final Object mLidSwitchLock = new Object();
@Override
public void monitor()
synchronized (mInputFilterLock)
synchronized (mAssociationsLock) /* Test if blocked by associations lock. */
synchronized (mLidSwitchLock) /* Test if blocked by lid switch lock. */
nativeMonitor(mPtr);
Watchdog
会定时监听mInputFilterLock
,mAssociationsLock
和mLidSwitchLock
这三个对象是否发生死锁,同时通过nativeMonitor
监听native
层InputDispatcher
和InputReader
是否发生死锁;
5. InputManagerService.systemRunning
[-> InputManagerService.java]
public void systemRunning()
// 监听安装包移除/更新/替换的广播更新键盘布局
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
filter.addDataScheme("package");
mContext.registerReceiver(new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
updateKeyboardLayouts();
, filter, null, mHandler);
// 监听远程蓝牙设备别名改变的广播, 加载远程设备的别名
filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
mContext.registerReceiver(new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
reloadDeviceAliases();
, filter, null, mHandler);
// 往android.display线程发送消息重新加载设备别名和更新键盘布局
mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
// 通知WiredAccessoryManager.systemReady
if (mWiredAccessoryCallbacks != null)
mWiredAccessoryCallbacks.systemReady();
以上是关于Android 12.0源码系列之IMSInputManagerService的主要内容,如果未能解决你的问题,请参考以下文章
Android 12.0源码系列之IMSInputManagerService
Android 12.0源码系列之IMSInputManagerService
Android 11.0源码系列之IMSInputChannel
原Android热更新开源项目Tinker源码解析系列之三:so热更新