本文主要是介绍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初始化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!