Android4.4——InputManagerService启动

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的构造函数。

Step 3、InputManagerService.InputManagerService
创建InputManagerService实例这里直接使用InputManagerService的构造函数创建。InputManagerService的构造函数位于frameworks\base\services\java\com\android\server\input\InputManagerService.java文件中。
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> 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<jint>(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>& looper);

    ……
}
由上可以知道,NativeInputManager类继承自多个类,包括InputReaderPolicyInterface、InputDispatcherPolicyInterface和PointerControllerPolicyInterface。由此可以推断,NativeInputManager会实现InputReader、InputDispatcher和PointerController这三个接口类,这些与触摸事件的输入和分发过程相关。
现在来看看NativeInputManager的构造函数部分的代码:
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& 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> 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<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& 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<NativeInputManager*>(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对象控制。


接下来的几篇文章会分别分析上面的三个部分,待续。









  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值