Android input之IMS初始化

2024-05-15 06:58
文章标签 android input 初始化 ims

本文主要是介绍Android input之IMS初始化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在input子系统中,有两个主要角色,reader和dispatcher。前者通过EventHub读取input事件,然后将读取到的事件封装成rawevent放到queue中,而后者则是从该queue中拿rawevent并进行消费,对该事件进行分发,决定是否将该事件传递给应用。

InputReader和InputDispatcher是两个线程,先看看这两个家伙怎么启动的。然后再分别看是如何分工协作的。

IMS初始化

Android中用来处理输入相关的服务是InputManagerService,该服务在Android系统启动的过程中被SysetemService启动,具体启动位置在startOtherServices中:

//frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {...InputManagerService inputManager = null;...traceBeginAndSlog("StartInputManagerService");inputManager = new InputManagerService(context);traceEnd();...traceBeginAndSlog("StartInputManager");inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());inputManager.start();traceEnd();...
}

这里只列出了InputManagerService相关的,在startOtherServices方法中,先new一个InputManagerService对象,然后调用它的start方法启动。我们直接看下InputManagerService的构造函数:

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
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方法,有可能就是用来创建InputReader和InputDispatcher线程的String doubleTouchGestureEnablePath = context.getResources().getString(R.string.config_doubleTouchGestureEnableFile);mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :new File(doubleTouchGestureEnablePath);LocalServices.addService(InputManagerInternal.class, new LocalService());
}

构造函数很简单,这里有个jni方法的调用,很可能就是用来创建InputReader和InputDispatcher线程的。它的实现如下:

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);if (messageQueue == nullptr) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);return reinterpret_cast<jlong>(im);
}

这里创建了一个本地的InputManager,继续跟踪:

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {JNIEnv* env = jniEnv();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.pointerCapture = false;mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;}mInteractive = true;mInputManager = new InputManager(this, this);
}

可以看到,NativeInputManager本身只是一层壳,真正有料的是InputManger,InputManager的实现如下:

//frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {mDispatcher = new InputDispatcher(dispatcherPolicy);mClassifier = new InputClassifier(mDispatcher);mReader = createInputReader(readerPolicy, mClassifier);initialize();
}void InputManager::initialize() {mReaderThread = new InputReaderThread(mReader);mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

终于看到,InputDispatcher和InputReader以及相应的mReaderThread和mDispatcherThread线程的创建。线程是载体,主要的做事人还是mDispatcher和mReader。
一张图总结:
在这里插入图片描述

IMS服务start

如上只是创建了InputReader和InputDispatcher对象和相应的线程,那在哪里启动的线程呢?InputManager中有一个start方法:

//frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputReader thread due to error %d.", result);mDispatcherThread->requestExit();return result;}return OK;
}

这里会调用两个线程的run方法,从而启动线程。而各自的threadLoop方法中,实际做了如下事情:

//frameworks/native/services/inputflinger/InputReaderBase.cpp
bool InputReaderThread::threadLoop() {mReader->loopOnce();return true;
}
//frameworks/native/services/inputflinger/InputDispatcher.cpp
bool InputDispatcherThread::threadLoop() {mDispatcher->dispatchOnce();return true;
}

各自跑到了InputReader和InputDispatcher的方法中。所以说线程只是个载体,真正的精华在InputReader和InputDispatcher类中。
如上的start方法,实际上也是java层的调用。SystemService在构造了InputManageService服务后,调用了它的start方法启动服务,方法实现如下:

//frameworks/base/services/core/java/com/android/server/input/InputManagerService.javapublic void start() {Slog.i(TAG, "Starting input manager");nativeStart(mPtr);...
}

nativeStart是一个jni方法,在JNI层中的接口则直接调用了动态库libinputflinger中InputManager的start方法:

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}
}

结语

如上就是IMS的初始化以及启动相关,在这个过程中,创建了InputReader对象和InputDispatcher对象以及对应的线程对象,线程只是载体,真正做事的是mReader和mDispatcher。接下来会单独对InputReader和InputDispatcher进行分析。

微信公众号

我在微信公众号也有写文章,更新比较及时。欢迎关注。关注有惊喜哦!
公众号名称为【Android系统实战开发】。

这篇关于Android input之IMS初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991127

相关文章

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目