1 前言

IMS 是 InputManagerService 的简称,主要负责输入事件管理。

1.1 基本概念

  • 输入设备:屏幕、电源/音量、键鼠、充电口、蓝牙、wifi 等
  • 设备节点:当输入设备可用时,Linux 内核会在 /dev/input 中创建对应的设备节点
  • 输入事件:触摸事件、按键事件、鼠标事件、插拔事件等
  • 输入子系统:负责采集 Linux 内核中输入事件原始信息,原始信息由 Kernel space 的驱动层一直传递到 User space 的设备节点

IMS 所做的工作就是监听 /dev/input 下的所有的设备节点,当设备节点有数据时,对数据进行加工处理并找到合适的 Window,将输入事件派发给它。

1.2 IMS 框架

        (1)EventHub

  • 监听、扫描、打开 /dev/input 目录下的输入设备
  • 根据配置文件和键值映射文件对设备进行配置和键值映射
  • 将所有设备添加到本地列表中
  • 抽取驱动程序上报的 inputEvent,主要包含设备可用性变化事件(设备事件)、设备节点中读取的原始输入事件。

        (2)InputReader

  • 根据设备类型添加不同 InputMapper
  • 通过 EventHub.getEvents() 获取 EventHub 中未处理的事件

        (3)InputDispatcher

  • 事件过滤,并发给上层。

2 Java 层 IMS 初始化流程

2.1 IMS 启动流程

        (1)main

/frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {new SystemServer().run();
}

        (2)run

/frameworks/base/services/java/com/android/server/SystemServer.java

private void run() {try {...// 创建LooperLooper.prepareMainLooper();// 加载libandroid_servers.soSystem.loadLibrary("android_servers");// 创建系统的 Context:ContextImpl.createSystemContext(new ActivityThread())createSystemContext();// 创建 SystemServiceManagermSystemServiceManager = new SystemServiceManager(mSystemContext);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);...}...try {//启动引导服务,ActivityManagerService、ActivityTaskManagerService、PackageManagerService、PowerManagerService、DisplayManagerService 等startBootstrapServices(); //启动核心服务,BatteryService、UsageStatusService 等startCoreServices(); //启动其他服务,InputManagerService、WindowManagerService、CameraService、AlarmManagerService 等startOtherServices(); ...}...// 开启消息循环Looper.loop();
}

        (3)startOtherServices

/frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {...WindowManagerService wm = null;...InputManagerService inputManager = null;...try {...inputManager = new InputManagerService(context);...//PhoneWindowManager 是 WMP 的实现类wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);ServiceManager.addService(Context.WINDOW_SERVICE, wm, false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);ServiceManager.addService(Context.INPUT_SERVICE, inputManager, false, DUMP_FLAG_PRIORITY_CRITICAL);...mActivityManagerService.setWindowManager(wm);...wm.onInitReady(); //initPolicy...//wm 的 mInputManagerCallback 属性在定义时就被初始化inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start();...}
}

通过 ServiceManager.addService() 将 Context.INPUT_SERVICE 与 IMS 绑定,因此在其他进程中可以通过如下方式获取 IMS。

IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
IInputManager im = IInputManager.Stub.asInterface(b);

2.2 IMS 初始化

        (1)构造方法

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public InputManagerService(Context context) {this.mContext = context;//在 android.display 线程中处理消息this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());...//mPtr 为 JNI 层 NativeInputManager 对象的地址mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());String doubleTouchGestureEnablePath = context.getResources().getString(R.string.config_doubleTouchGestureEnableFile);mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null : new File(doubleTouchGestureEnablePath);//添加本地服务LocalServices.addService(InputManagerInternal.class, new LocalService());
}

nativeInit() 方法在 JNI 层创建了 NativeInputManager 对象,并返回其地址(后文会介绍);LocalService 是 IMS 的内部类,也是 InputManagerInternal 的实现类。

        (2)setWindowManagerCallbacks

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {mWindowManagerCallbacks = callbacks;
}

callbacks 来自 WMS.mInputManagerCallback,属于 InputManagerCallback 类(IMS.WindowManagerCallbacks 的实现类),WMS.mInputManagerCallback 在定义时就被初始化。

        (3)start

/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

public void start() {//启动 Native 层的 InputReaderThread 和 InputDispatcherThread 线程nativeStart(mPtr);//注册监听器registerPointerSpeedSettingObserver();registerShowTouchesSettingObserver();registerAccessibilityLargePointerSettingObserver();mContext.registerReceiver(new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {updatePointerSpeedFromSettings();updateShowTouchesFromSettings();updateAccessibilityLargePointerFromSettings();}}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);updatePointerSpeedFromSettings();updateShowTouchesFromSettings();updateAccessibilityLargePointerFromSettings();
}

nativeStart() 方法启动 Native 层 InputReaderThread 和 InputDispatcherThread 线程(后面会介绍)。

3 Native 层 IMS 初始化流程

本节主要介绍 IMS 构造方法中调用 nativeInit() 方法、start() 方法中调用 nativeStart() 方法的后续流程。

如图,展示了 IMS 初始化流程,浅蓝色、绿色、紫色分别表示 Java 层、JNI 层、Native 层。

3.1 nativeInit 后续流程

        (1)gInputManagerMethods

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static const JNINativeMethod gInputManagerMethods[] = {//Java 层调用的 nativeInit 方法对应 JNI 层的 nativeInit 方法{ "nativeInit","(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",(void*) nativeInit },//Java 层调用的 nativeStart 方法对应 JNI 层的 nativeStart 方法{ "nativeStart", "(J)V",(void*) nativeStart },...
}

gInputManagerMethods 数组列出了 Java 层调用 nativeInit()、nativeStart() 方法到 JNI 层具体调用方法的映射关系。

        (2)nativeInit

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

//Java 层调用:mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
static jlong nativeInit(JNIEnv* env, jclass, jobject serviceObj, jobject contextObj, jobject messageQueueObj) {//获取 JNI 层消息队列sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);...//创建 NativeInputManagerNativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper());im->incStrong(0);//返回 NativeInputManager 对象指针给 Java 层(mPtr)return reinterpret_cast<jlong>(im);
}

NativeInputManager 是在该文件中定义的类。

        (3)NativeInputManager

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

#include <inputflinger/InputManager.h>NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper), mInteractive(true) {JNIEnv* env = jniEnv();mServiceObj = env->NewGlobalRef(serviceObj);...mInteractive = true;//创建 Native 层 InputManager,2 个 this 分别为:InputReaderPolicyInterface、InputDispatcherPolicyInterfacemInputManager = new InputManager(this, this);defaultServiceManager()->addService(String16("inputflinger"), mInputManager, false);
}

NativeInputManager 实现了 RefBase、InputReaderPolicyInterface、InputDispatcherPolicyInterface、PointerControllerPolicyInterface 4个接口。InputManager.h 中定义了抽象的 InputManager 类,InputManager.cpp 实现了 InputManager.h 中的抽象方法。

        (4)InputManager

/frameworks/native/services/inputflinger/InputManager.h

class InputManager : public InputManagerInterface, public BnInputFlinger {...
public:InputManager(const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);virtual status_t start();...virtual void setInputWindows(const std::vector<InputWindowInfo>& handles, const sp<ISetInputWindowsListener>& setInputWindowsListener);virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);...virtual void registerInputChannel(const sp<InputChannel>& channel);
private:sp<InputReaderInterface> mReader;sp<InputReaderThread> mReaderThread;sp<InputClassifierInterface> mClassifier;sp<InputDispatcherInterface> mDispatcher;sp<InputDispatcherThread> mDispatcherThread;void initialize();
};

注意:InputManager 继承了 BnInputFlinger 接口(Binder 跨进程通讯的服务端)。

        (5)InputManager

/frameworks/native/services/inputflinger/InputManager.cpp

#include "InputManager.h"
#include "InputReaderFactory.h"InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {//创建 InputDispatchermDispatcher = new InputDispatcher(dispatcherPolicy);mClassifier = new InputClassifier(mDispatcher);//创建 InputReader,createInputReader() 是 InputReaderFactory 类的方法mReader = createInputReader(readerPolicy, mClassifier);initialize();
}

        (6)InputDispatcher

/frameworks/native/services/inputflinger/InputDispatcher.cpp

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :mPolicy(policy), ... {//创建消息循环mLooper = new Looper(false);mReporter = createInputReporter();...policy->getDispatcherConfiguration(&mConfig);
}

        (7)createInputReader

/frameworks/native/services/inputflinger/InputReaderFactory.cpp

sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) {return new InputReader(new EventHub(), policy, listener);
}

注意:此处创建了 EventHub,并注入到 InputReader 中。

        (8)InputReader

/frameworks/native/services/inputflinger/InputReader.cpp

InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) :mContext(this), mEventHub(eventHub), mPolicy(policy), ... {mQueuedListener = new QueuedInputListener(listener);...
}

        (9)EventHub

/frameworks/native/services/inputflinger/EventHub.cpp

EventHub::EventHub(void) :mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),mOpeningDevices(nullptr), mClosingDevices(nullptr),mNeedToSendFinishedDeviceScan(false),mNeedToReopenDevices(false), mNeedToScanDevices(true),mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {...mEpollFd = epoll_create1(EPOLL_CLOEXEC);...mINotifyFd = inotify_init();mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);...int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);...int wakeFds[2];result = pipe(wakeFds);...mWakeReadPipeFd = wakeFds[0];mWakeWritePipeFd = wakeFds[1];result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);...result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);...eventItem.data.fd = mWakeReadPipeFd;result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);...
}

        (10)initialize

/frameworks/native/services/inputflinger/InputManager.cpp

void InputManager::initialize() {mReaderThread = new InputReaderThread(mReader);mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

InputReaderThread 和 InputDispatcherThread 都继承了 Thread 类。

在 InputManager.h 文件中,已申明 InputReaderThread 和 InputDispatcherThread 的源码不再开源,如下。

/** By design, the InputReaderThread class and InputDispatcherThread class do not share any*/

3.2 nativeStart 后续流程

        (1)nativeStart

/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static void nativeStart(JNIEnv* env, jclass, jlong ptr) {//通过对象地址获取 NativeInputManager 对象指针NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);//调用 Native 层 InputManager 的 start() 方法status_t result = im->getInputManager()->start();...
}inline sp<InputManager> getInputManager() const {return mInputManager;
}

        (2)start

/frameworks/native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {//开启 DispatcherThread 线程status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);...//开启 ReaderThread 线程result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);...return OK;
}

【framework】IMS启动流程相关推荐

  1. Android Framework内部启动流程

    App启动过程导图 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求 system_server进程接收到请求后,向z ...

  2. ZF2(Zend framework 2)启动流程和框架配置分析

    转自:http://helion.name/archives/423.html#more-423 下面的内容都以官网的"ZendSkeletonApplication"为架构基础, ...

  3. Android Framework启动流程

    Framework启动流程 在手机的Linux系统启动后,Framework层第一个启动的进程就是zygote.Zygote负责预加载framework层的共享资源,比如SDK中的类,同时它是fram ...

  4. framework之Activity启动流程(基于Android11源码)

    一步步看,你就会对activity的启动流程有深刻的认知. 引言 Android11上,Activity的启动流程与Android10的实现(可以参考Activity的启动过程详解(基于10.0源码) ...

  5. 源码分析-Activity的启动流程

    以android 6.0源码为参考,其他版本api会稍有不同 在Activity中,启动一个Activity的方法 @Override public void startActivity(Intent ...

  6. Android 蓝牙启动流程(以及设置蓝牙为作为sink模式 接收端模式)

    本文以Android 7.1为基础 最近在做蓝牙开发,研究了一下蓝牙的启动流程,总结一下 Google在Android源码中推出了它和博通公司一起开发的BlueDroid以替代BlueZ.BlueZ的 ...

  7. Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]

    摘要:PackageManagerService是Android系统核心服务之一,在Android中的非常重要,主要负责APK.jar包等的管理. 阅读本文大约需要花费50分钟. 文章的内容主要还是从 ...

  8. Android10.0系统启动之Launcher(桌面)启动流程-[Android取经之路]

    摘要:上一节我们讲完了Android10.0的ActivityManagerService的启动流程,在AMS的最后启动了Launcher进程,今天我们就来看看Launcher的真正启动流程. 阅读本 ...

  9. Android 10.0 系统服务之ActivityMnagerService-AMS启动流程-[Android取经之路]

    摘要:上一节我们讲完了SystemServer的启动过程,这一节接着上一节的步骤,来讲解ActivityManagerService的启动过程. ActivityManagerService简称AMS ...

最新文章

  1. teach-es6-2(class)
  2. java设计模式之简单工厂模式
  3. SAP 电商云 Spartacus UI CheckoutDeliveryService 的单元测试设计
  4. .Net字符暂存池(String Intern Pool)
  5. JAVA环境指定xms512_【JAVA学习】java虚拟机内存配置,-Xss256m -Xms512m -Xmx800m -XX:MaxPermSize=512m...
  6. Java怎么跑不起来_tarsJava example 跑不起来
  7. linux硬盘怎么分配合适,500G的硬盘,怎么分区比较合理?
  8. 机器学习系列-AdaBoost
  9. ASP.NET页面输出缓存知识
  10. UEBA能够检测的七大类安全风险
  11. win10开启无线网卡服务器,Win10笔记本电脑无线网卡 教你如何开启Win10笔记本内置无线网卡...
  12. 《 指数基金投资指南 》by 银行螺丝钉 - 笔记 - 3
  13. 在vue中使用marked解析MARKDOWN,生成目录,运行代码示例
  14. 【Apollo 6.0项目实战】Perception模块
  15. HIVE如何进行随机抽样
  16. 黄牛落泪!全球显卡价格纷纷跳水,高价囤货滞销
  17. 班章管家理财入门基础常识有什么?理财产品怎样买最合适
  18. C++之memcpy的用法
  19. 重学C++笔记之(十三)友元、异常和其他
  20. 求弹性模量和泊松比计算题_弹性模量E和泊松比

热门文章

  1. AOSP>设计>测试(第二节)测试开发工作流
  2. 在Win10上使用BC3.1
  3. NB-IoT卡eSIM卡(5*6毫米)贴片卡引脚定义及尺寸
  4. c语言sleep作用,c语言sleep用法是什么?
  5. Head First HTML 和 CSS
  6. 易验APP一键登录对接文档
  7. python 乘法运算定律_乘法运算定律专项练习题
  8. python随机抽样_掌握python中的随机抽样
  9. 微博数据库设计 _转
  10. android aar编程,Android Studio模块化编程实践之aar