当前位置: 首页 > news >正文

Android7 Input(一)Android Input服务初始化

本系列博客主要描述Android 7.1系统中输入管理服务InputManagerService的源码分析。

概述

本文主要描述了InputManagerService服务的初始化和启动,在Android7系统上InputManagerService服务的框架如下所示:

注:箭头的方向,并不能真实代表数据流向方向。

1、FrameWorks层:inputManagerService对外提供服务的模块;

2、JNI层:因为InputManagerService要去管理底层硬件输入设备,而在Android 7系统的所有与硬件相关的部分,都会涉及到JNI层。用C++代码去管理硬件设备;

3、Inputfliger: 是InputManager事件处理的核心事件,包括事件的获取和分发等;

4、kernel层,主要涉及的input输入驱动,并且将设备产生的事件通过inpu子系统上传给C++ inputflinger层;

5、硬件层,具体的输入设备,因为输入设备的类型很过,这里只是大概罗列出了嵌入式设备上常用的几个;

InputManagerService服务的初始化和启动比较简单,由SystemServer服务创建并拉起。

源码路径

本文描述中涉及的源码有:

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

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

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

framesworks/native/services/inputflinger/inputManager.cpp

InputManagerServie服务的初始化

java层的服务初始化

在系统核心服务SystemServer初始化中,在启动其他服务startOtherService方法中,会创建InputManagerService服务。代码片段如下所示:

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

 private void startOtherServices() {
                ......
            traceBeginAndSlog("StartInputManagerService");
            /* 创建InputManagerService服务 */
            inputManager = new InputManagerService(context);
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

            traceBeginAndSlog("StartWindowManagerService");
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            /* 注册InputManagerServie服务  */
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

            if (!disableVrManager) {
                traceBeginAndSlog("StartVrManagerService");
                mSystemServiceManager.startService(VrManagerService.class);
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }

            mActivityManagerService.setWindowManager(wm);

            /* 设置InputManagerService的窗口回调接口 */
            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            ......
            }

1、在systemServer的服务中创建InputManagerService;

2、设置InputManagerService的窗口回调接口,因此最终的事件要传递给上层App的Windows窗口去处理;

创建InputManagerService并进入它的构造方法继续初始化,代码片段如下所示:

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

 public InputManagerService(Context context) {
        this.mContext = context;
        /* 创建Handler, 并使用displayThead现成的Looper */
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        /* 调用InputManagerService服务的JNI方法nativeInit继续初始化 */
        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());
    }

在构造方法中:

1、创建InputManagerHander,并使用DisplayThread线程的Looper处理Handler消息;

2、调用InputManagerService服务的JNI方法nativeInit()方法继续初始化,并且将mHandler.getLooper().getQueue()队列传递给JNI层,在前面的初始化中InputManagerService自己的Handler使用了DisplayThread的Looper, 也就是说,在这个地方等同于将DisplayThread线程的消息队列传递给了InputManagerService的JNI层;

native层的初始化

根据前面的描述,InputManagerService服务的Java层调用nativeInit方法,继续初始化Native层,初始化代码片段,如下所示:

a、nativeInit()

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

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    /* 将java层的messageQueue对象转化到对应的native层的messageQueue对象 */
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    /* 创建NativeInputManager输入管理 */
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    /* 将native层的对象指针返回java层 */
    return reinterpret_cast<jlong>(im);
}

1、将java层的MessageQueue对象转化到它对应native层的C++对象,这个比较管理,涉及到后面的事件处理,暂时先不描述;

2、创建NativeInputManager对象;

3、返回JNI创建的C++对象的指针返回java层;

b、NativeInputManger的初始化

NativeInputManager的初始化,关键代码片段如下所示:

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
 
    ......
    /* 创建EventHub() 事件获取*/
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);

1、创建EventHub()对象,该对象,主要就是获取输入事件(各种输入设备产生的事件和软件模拟产生的事件);

2、创建InputManager对象;

c、InputManager对象的初始化

framesworks/native/services/inputflinger/inputManager.cpp

InputManager对象初始化中如下所示:

   const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    /* 创建事件分发对象 */
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    /* 创建事件获取对象 */
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();

1、创建事件分发对象;

2、创建事件获取对象;

3、创建事件分发和事件获取线程,如下所示:

void InputManager::initialize() {
    /* 创建事件获取线程 */
    mReaderThread = new InputReaderThread(mReader);
    /* 创建事件分发线程 */
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

至此,InputManagerService服务从java层的初始化过程到JNI层的初始化过程,描述完成.

InputManagerService服务启动

Java层的启动

InputManagerSerivice服务在Java层的启动,也是在SystemServer服务中完成。非常简单。执行代码片段如下所示:

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

/* 设置InputManagerService的窗口回调接口 */
            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            /* 启动InputManagerService服务 */
            inputManager.start();

然后调用InputManagerService中的start方法,关键执行代码片段如下:

public void start() {
        Slog.i(TAG, "Starting input manager");
        /* 调用JNI层nativeStart */
        nativeStart(mPtr);

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        

1、直接调用jni层的nativeStart的接口;

Native层的启动

jni层的启动,关键代码片段如下所示:

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.");
    }
}

最终调用InputManager的start方法

framesworks/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;
}

总结

1、InputManagerService服务的注册和启动都在SystemServer服务中完成;

2、InputManagerservice服务初始化过程中会在native层注册事件获取和分发的线程;

3、整个初始化过程中,从Java层到native层都传递了DisplayThread线程的Looper的MessageQueue;

相关文章:

  • anythingLLM结合searXNG实现联网搜索
  • LeetCode Hot 100 - 子串 | 560.和为K的子数组、239.滑动窗口最大值、76.最小覆盖子串
  • 【Vue3入门1】03-Vue3的基本操作(下)
  • Cocos Creator Shader入门实战(五):材质的了解、使用和动态构建
  • 推荐一个智能抠图与背景替换工具,支持docker部署、API调用
  • go复习目录
  • 基于Sentinel-1A GRD洪涝淹没范围提取(SDWI阈值法和OSTU自动阈值法)
  • .NET 10 新的 JsonIgnoreCondition
  • Python Lambda 函数详解
  • 智慧高速,安全护航:视频监控平台助力高速公路高效运营
  • 知识分享导航
  • Jmeter简介、学习目标及安装启动
  • Maven下载以及项目创建(笔记)
  • 开发一款自然语言转sql的网页版数据库管理工具,不需要使用网上那些付费版,自己搭建一套数据库管理工具,免费开源
  • Unix 域套接字(本地套接字)
  • YOLOv12环境配置,手把手教你使用YOLOv12训练自己的数据集和推理(附YOLOv12网络结构图),全文最详细教程
  • 基于Spring Boot的产业园区智慧公寓管理系统的设计与实现(LW+源码+讲解)
  • 一区思路!
  • Java-模块二-1
  • Java 对 PDF 文件添加水印
  • 对话郑永年:我们谈判也是为世界争公义
  • 男子退机票被收90%的手续费,律师:虽然合规,但显失公平
  • 茅台回应“茅台1935脱离千元价位带竞争”:愿与兄弟酒企共同培育理性消费生态
  • 礼来公布头对头研究详细结果:替尔泊肽在所有减重目标中均优于司美格鲁肽
  • 全国重点网络媒体和网络达人走进沧州,探寻“文武双全”的多重魅力
  • 巴称巴控克什米尔地区11人在印方夜间炮击中身亡