Step 1、SystemServer.main
启动InputManagerService服务是在SystemServer.java文件中的ServerThread.initAndLoop函数中启动。代码位于frameworks\base\services\java\com\android\server文件中。
public static void main(String[] args) {
......
// This used to be its own separate thread, but now it is
// just the loop we run on the main thread.
ServerThread thr = new ServerThread();
thr.initAndLoop();
}
Step 2、
class ServerThread {
……
public void initAndLoop() {
……
Context context = null;
……
// Create a handler thread just for the window manager to enjoy.
HandlerThread wmHandlerThread = new HandlerThread("WindowManager");//为WindowManager创建Handler线程
wmHandlerThread.start();//启动该Handler线程
Handler wmHandler = new Handler(wmHandlerThread.getLooper());//使用WindowManager的Handler线程Looper为WindowManager创建Handler
wmHandler.post(new Runnable() {
@Override
public void run() {
//Looper.myLooper().setMessageLogging(new LogPrinter(
// android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_DISPLAY);
android.os.Process.setCanSelfBackground(false);
// For debug builds, log event loop stalls to dropbox for analysis.
if (StrictMode.conditionallyEnableDebugLogging()) {
Slog.i(TAG, "Enabled StrictMode logging for WM Looper");
}
}
});
……
context = ActivityManagerService.main(factoryTest);//使用ActivityManagerService.main函数初始化Context类型变量context
……
try {
……
Slog.i(TAG, "Input Manager");
inputManager = new InputManagerService(context, wmHandler);//使用之前初始化的context和WindowManager的Handler创建InputManagerService实例
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power, display, inputManager,
wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);//使用PowManagerService、DisplayManagerService和InputManagerService实例以及WM的Handler创建WindowManagerService实例
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
ActivityManagerService.self().setWindowManager(wm);// ActivityManagerService与WindowManagerService间需要交互
//InputManagerService可通过WindowManagerService中的InputMonitor实例的多个成员函数与WindowManagerService交互
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();//启动InputManagerService服务
display.setWindowManager(wm);//DisplayManagerService与WindowManagerService间需要交互
display.setInputManager(inputManager);// DisplayManagerService与InputManagerService间需要交互
……
}
Looper.loop();//
}
……
}
这里首先为WindowManager创建Handler线程wmHandlerThread并获取其Handler(wmHandler),再根据WMS的Handler(wmHandler)创建InputManagerService实例后,使用该实例创建WMS实例,并将IMS实例与WMS实例加入ServiceManager队列进行管理。
其中InputMonitor实现了InputManagerService类中定义的WindowManagerCallbacks接口,这样InputManagerService可以通过该接口类中的多个接口通知WindowManagerService。
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
…
}
下面先分析InputManagerService的构造函数。
public class InputManagerService extends IInputManager.Stub
implements Watchdog.Monitor, DisplayManagerService.InputManagerFuncs {
static final String TAG = "InputManager";
......
public InputManagerService(Context context, Handler handler) {
this.mContext = context;//context由SystemServer.initAndLoop函数中ActivityManagerService.main函数获得
this.mHandler = new InputManagerHandler(handler.getLooper());//handler为SystemServer.initAndLoop函数中创建的WindowManager的Handler
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
......
}
这里将InputManagerService构造函数的参数context、handler保存起来,随后继续调用native层函数nativeInit,通过JNI机制就会使用刚保存的context和handler来调用framework\bases\services\jni\com_android_server_input_InputManagerService.cpp文件中的nativeInit函数。
Step 4、com_android_server_input_InputManagerService.nativeInit
static jint nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);//获取Java层的消息队列MessageQueue对应native层的地址指针,随后得到一个NativeMessageQueue指针对象。
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());//使用Java层的InputManagerService实例、上下文和Handler创建native层的InputManager。这个Java层可调用到C层代码,进行输入相关的处理。
im->incStrong(0);
return reinterpret_cast(im);//返回NativeInputManager指针实例的地址,保存在InputManagerService.mPtr中
}
Step 5、NativeInputManager. NativeInputManager
先来看一下NativeInputManager的相关代码,位于frameworks\base\services\jni\ com_android_server_input_InputManagerService.cpp文件中。
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {
……
public:
NativeInputManager(jobject contextObj, jobject serviceObj, const sp& looper);
……
}
由上可以知道,NativeInputManager类继承自多个类,包括InputReaderPolicyInterface、InputDispatcherPolicyInterface和PointerControllerPolicyInterface。由此可以推断,NativeInputManager会实现InputReader、InputDispatcher和PointerController这三个接口类,这些与触摸事件的输入和分发过程相关。
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper) {
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;
}
sp eventHub = new EventHub();//创建EventHub实例,该实例用于收集Android系统的触摸或者按键消息
mInputManager = new InputManager(eventHub, this, this);//根据 EventHub实例、NativeInputManager本身内部的InputReaderPolicy和InputDispatcherPolicy接口创 //建一个InputManager对象来实现Input的管理,包括接收和分发。
}
Step 6、InputManager.InputManager
InputManager的构造函数代码位于frameworks\base\services\input\InputManager.cpp文件中
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);//创建InputDispatcher对象
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);//创建InputReader对象
initialize();
}
直接分析initialize函数。
Step 7、InputManager.initialize
代码位于frameworks\base\services\input\InputManager.cpp文件中
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);//创建InputReader线程,用于接收Input事件
mDispatcherThread = new InputDispatcherThread(mDispatcher);//创建InputDispatcher线程,用于分发Input事件
}
这里创建了InputReader线程和InputDispatcher线程,那么要让这两个线程启动的启动工作的话需要调用线程的run函数。之前在分析SystemServer.java中的initAndLoop函数中有这样一句话:
inputManager.start();//启动InputManagerService服务
我们知道这里的inputManager对象是InputManagerService类型,故调用的是InputManagerService.start函数(framework\base\service\input\InputManager.cpp),来看看该函数的代码:
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);//注册ACTION_USER_SWITCHED广播接收器
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
由Step 4可知,本段代码中mPtr保存的是NativeInputManager类型对象指针地址,与该NativeInputManager对象对应的是Java层的InputManager对象。Java层通过mPtr变量和JNI机制即可在C层完成Input相关操作和处理。和InputManagerService.init函数一样,start函数依旧是通过JNI实现了Java层调用C层函数nativeStart(位于framework\bases\services\jni\com_android_server_input_InputManagerService.cpp文件)的功能。
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {
NativeInputManager* im = reinterpret_cast(ptr);
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
易知ptr存放单位是NativeInputManager指针的地址值,获取到该地址存放的NativeInputManager指针后,便可通过该指针完成上层Java函数调用下层C函数。下一步则调用的是C层的InputManager.start函数。
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;
}
在InputManager.start函数执行完成后,就开启了InputReaderThread和InputDispatcherThread两个线程的执行。
至此,InputManagerService服务的启动基本上分析完毕了。从上面的分析过程,对于InputManagerService服务个人的理解是:
InputManagerService服务主要由三部分构成——EventHub、InputReader、InputDispatcher。
EventHub,它管理系统中所有可以识别的输入设备的输入事件;
InputReader,从EventHub中获取输入事件;
InputDispatcher,负责把事件分发给输入目标,其中的一些功能(如识别输入目标)由独立的policy对象控制。
接下来的几篇文章会分别分析上面的三个部分,待续。