Input子系统(一)启动篇

news2024/10/3 10:33:24

代码路径

基于AndroidS(12.0)代码

system/core/libutils/Threads.cpp

frameworks/base/services
	- java/com/android/server/SystemServer.java
	- core
		- java/com/android/server/input/InputManagerService.java
		- jni/com_android_server_input_InputManagerService.cpp

frameworks/native/services/inputflinger/
	- InputManager.cpp
	- InputThread.cpp
	- reader
		- InputReader.cpp
	- dispatcher
		- InputDispatcher.cpp

启动流程图

在这里插入图片描述

从流程图可以看出,启动过程的有两条主线:create、start,下面分别针对这两条主线进行源码分析

create主线

create主线主要是创建 Input 系统相关对象,从 Java 层一直到 Native 层。

SystemServer启动

//=====> SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
	inputManager = new InputManagerService(context);
	... ...
	//将InputManagerService注册到ServiceManager,其名字为 input
	ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
	... .. 
	inputManager.start();
}

创建InputManagerService

//=====> InputManagerService.java

public InputManagerService(Context context) {
    // 运行在线程"android.display"
    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
    
	//初始化 NativeInputManager,并返回其句柄
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}

Jni.nativeInit

//=====> com_android_server_input_InputManagerService.cpp

//JNI原型 -> long nativeInit(InputManagerService, Context, MessageQueue);
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
	
	//android_os_MessageQueue.h中的方法,获取 MessageQueue 中保存的 NativeMessageQueue 对象
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
	
	//初始化 NativeInputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

创建 NativeInputManager

//=====> com_android_server_input_InputManagerService.cpp

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    InputManager* im = new InputManager(this, this);
    mInputManager = im;
	
	//注册 InputManager 到 SystemServer,服务名为 inputflinger
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

创建 InputManager

//=====> InputManager.cpp

//这里传入的readerPolicy、dispatcherPolicy 都是 NativeInputManager
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
   	//创建 InputDispatcher
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    //对事件分类,事件分发前必须经过的阶段
    mClassifier = new InputClassifier(mDispatcher);
    //创建 InputReader
    mReader = createInputReader(readerPolicy, mClassifier);
}

创建 InputDispatcher

//=====> InputDispatcher.cpp

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
      : mPolicy(policy),
        ... ...
        mCompatService(getCompatService()) {
        
    mLooper = new Looper(false);
    mReporter = createInputReporter();
    mKeyRepeatState.lastKeyEntry = nullptr;
    policy->getDispatcherConfiguration(&mConfig);
}

创建 InputReader

//=====> InputReader.cpp

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
		... ...
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);
    .... ...
}

start主线

start主线会启动两条线程 InputReader(读取事件)、InputDispatcher(分发事件),并且这两条线程会一直循环执行,不会终止。

Jni.nativeStart

//=====> com_android_server_input_InputManagerService.cpp

//Jni原型 ->  void nativeStart(long ptr),其 ptr 参数为 NativeInputManager 的句柄
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

在创建 InputManager 的时候创建了 mDispatcher、mReader

//=====> InputManager.cpp

status_t InputManager::start() {
	//开启 InputDispatcher Looper
    status_t result = mDispatcher->start();
    if (result) {
        return result;
    }
	
	//开启 InputReader 的 Looper
    result = mReader->start();
    if (result) {
        mDispatcher->stop();
        return result;
    }

    return OK;
}

InputReader.start

创建一个InputThread线程,线程名为 InputReader

status_t InputReader::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}

InputThread 会创建 InputThreadImpl ,InputThreadImpl 继承自 libutils 中的 Thread,其会一直运行threadLoop 函数,直到该函数返回 false 则会停止循环。结合上面的代码可以知道 InputReader 线程一直运行的是 loopOnce 方法,mEventHub->wake是在InputThread析构时候调用。

//=====> InputThread.cpp

class InputThreadImpl : public Thread {
public:
    explicit InputThreadImpl(std::function<void()> loop)
          : Thread(/* canCallJava */ true), mThreadLoop(loop) {}
private:
    std::function<void()> mThreadLoop;
	
	//返回true则会一直运行
    bool threadLoop() override {
        mThreadLoop();
        return true;
    }
};

InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {
    mThread = new InputThreadImpl(loop);
    //开始运行Thread
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

InputDispatcher.start

同样 InputDispatcher 也会启动一个线程,线程名为 InputDispatcher,然后一直运行 dispatchOnce 方法。

//=====> InputDispatcher.cpp

status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

参考

  • Input系统 - 启动篇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/397300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三步 让你的 vscode 自动编译ts文件

三步让你的 vscode 自动编译ts文件 TypeScript环境安装与如何在vscode实现自动编译ts文件? 文章目录三步让你的 vscode 自动编译ts文件前提条件环境安装自动编译运行监视任务时报错&#xff1f;前提条件 安装 node 环境 环境安装 tsc 作用&#xff1a;负责将ts 代码 转为 浏…

感知器算法

感知器算法原理说明 感知器是一种二分类的线性分类算法&#xff0c;其原理基于神经元的工作原理。感知器将输入数据通过加权求和的方式映射到一个输出&#xff0c;然后根据输出的结果进行分类。 具体来说&#xff0c;给定一个训练集 D(x1,y1),(x2,y2),...,(xn,yn)D{(x_1,y_1)…

研报精选230308

目录 【行业230308东吴证券】电力设备行业深度报告&#xff1a;氢能深度&#xff1a;绿氢&#xff0c;第四次能源革命的载体【个股230308安信证券_沪光股份】优秀的民营汽车线束供应商&#xff0c;行业国产化替代空间广阔【行业230308中原证券】食品饮料行业2月月报&#xff1a…

银行数字化转型导师坚鹏:数字化转型为什么需要致良知与知行合一

在银行数字化转型过程中&#xff0c;特别需要致良知与知行合一哲学思想的指导。 知中有行&#xff0c;行中有知&#xff1b;行极而知&#xff0c;知极而行&#xff1b;知行无端&#xff0c;知行无始。知与行是一件事&#xff0c;做事与培养本体&#xff08;修心&#xff09;也是…

手动集成Tencent SDK遇到的坑!!!

手动集成的原因 由于腾讯未把Tencent SDK上传到Github中&#xff0c;所以我们不能通过Cocoapods的方式集成&#xff0c;只能通过官方下载其SDK手动集成。 Tencent SDK手动集成步骤 1.访问腾讯开放平台SDK下载界面&#xff0c;找到并下载iOS_SDK_V3.5.1。&#xff08;目前最新…

数组(四)-- LC[167] 两数之和-有序数组

1 两数之和 1.1 题目描述 题目链接&#xff1a;https://leetcode.cn/problems/two-sum/description/ 1.2 求解思路 1. 暴力枚举 最容易想到的方法是枚举数组中的每一个数 x&#xff0c;寻找数组中是否存在 target - x 参考代码 class Solution(object):def twoSum(self, n…

Nginx学习(3)—— 反向代理、负载均衡、动静分离、URLRewrite、防盗链

文章目录网关、代理与反向代理Nginx的反向代理配置基于反向代理的负载均衡的配置负载均衡策略负载均衡权重相关配置&#xff08;weight&#xff09;动静分离Nginx配置动静分离URL-rewrite伪静态配置负载均衡URL-rewrite防盗链网关、代理与反向代理 什么是反向代理&#xff1a;…

在linux上部署Java项目

在Linux部署Java环境 要是想要部署java web程序,首先要配置环境 jdk tomcat mysql 安装jdk 推荐的方法是使用yum直接安装openjdk(开源的,与官方的jdk功能差不多),目前使用的最多的就是jdk8系列 yum list | grep jdk 在源上搜索所有关于jdk的文件 devel表示development的意思…

3.8多线程

案例一-线程安全的单例模式(面试)是一种设计模式,设计模式针对写代码时的一些常见场景给出一些经典解决方案单例模式的两种典型实现饿汉模式懒汉模式饿汉的单例模式:比较着急去进行创建实例懒汉的单例模式,是不太着急创建实例,,只是在用的时候,才真正创建这个是类对象,也就是.c…

【C++修炼之路】26.C++11(语法糖)

每一个不曾起舞的日子都是对生命的辜负 C11C11(语法糖)本节目标一.C11简介二.统一的列表初始化2.1 {}初始化2.2 std::initializer_list三.声明3.1 auto3.2 decltype3.3 nullptr四.总结C11(语法糖) 本节目标 C11简介 列表初始化 变量类型推导 一.C11简介 在2003年C标准委员…

信息收集-

url&#xff1a; https://en.wikipedia.org:443/wiki/hypertext_Transfer_Protocol?id123#HTTP/1.1_response_messages https&#xff1a;协议 en.wikipedia.org&#xff1a;域名 443&#xff1a;端口 wiki/hypertext_Transfer_Protocol&#xff1a;文件路径 id123&…

Unity 混合操作(Blending)

渲染图形时&#xff0c;在执行所有着色器并应用所有纹理后&#xff0c;像素将写入到屏幕。这些像素与已有像素的组合方式由 Blend 命令控制。用于生成透明对象。《Unity Shader入门精要》大致解释&#xff1a;片元通过了模板测试和深度测试之后&#xff0c;会进行混合步骤。如果…

三、SpringMVC的拦截器

1. SpringMVC的拦截器 针对请求和响应进行的额外的处理.在请求和响应的过程中添加预处理,后处理和最终处理. 2. 拦截器的应用场景 1、日志记录&#xff1a;记录请求信息的日志 2、权限检查&#xff0c;如登录检查 3、性能检测&#xff1a;检测方法的执行时间 3. 拦截器执行的…

调用一个函数时发生了什么?

欢迎来到 Claffic 的博客 &#x1f49e;&#x1f49e;&#x1f49e; 前言&#xff1a; 用C语言写代码&#xff0c;如果一个工程相对复杂时&#xff0c;我们往往会采取封装函数的方式。在主函数中调用函数 这一看似简单的过程&#xff0c;实际上有很多不宜观察的细节&#xff0…

计算机组成原理|第三章(笔记)

目录第三章 系统总线3.1 总线的基本概念3.2 总线的分类3.2.1 片内总线3.2.2 系统总线3.2.3 通信总线3.3 总线特性及性能指标3.3.1 总线的特性3.3.2 总线性能指标3.4 总线结构3.4.1 单总线结构3.4.2 多总线结构3.4.3 总线结构举例3.5 总线控制3.5.1 总线判优控制3.5.2 总线通信控…

ALG和STUN

目录 ALG 应用层网关讲解 Client1使用FTP主动模式建立FTP Client1使用FTP被动模式建立FTP STUN讲解 ALG 应用层网关讲解 用来替换应用层信息 Client1使用FTP主动模式建立FTP 主动模式&#xff1a;服务器收到客户端发来的请求FTP的地址和端口 服务器使用20端口直接向客户端建…

webpack dll 提升构建速度

DLL&#xff0c;动态链接库&#xff08;Dynamic Link Library 或者 Dynamic-link Library&#xff09;&#xff0c;由微软公司提出。目的是为了节约应用程序所需的磁盘和内存空间。 在一个传统的非共享库中&#xff0c;如果两个程序调用同一个子程序&#xff0c;就会出现两份那…

Redis-6集群

文章目录前言Redis集群原理搭建Redis集群集群拓展后记前言 前两期介绍和搭建了Redis的主从复制架构和哨兵模式&#xff0c;虽然哨兵模式能够实现自动故障转移主备切换&#xff0c;一定程度上提高了系统的容错性 但这两种架构模式都不能解决单节点的并发压力和物理上线的问题&…

行测-判断推理-图形推理-样式规律-空间重构-立体拼合

有凸必有凹&#xff0c;排除A CD显然不对选BA和4能组成长方体B和3能组成长方体C和1能组成长方体选D这两个东西应该在同一侧&#xff0c;排除A C中间应该要由凸起&#xff0c;排除D选B图1向左旋转90图2逆时针旋转90选A

内网环境解决SSL证书问题

本来这个没什么好写的&#xff0c;但是坑实在有点多&#xff0c;不得不写个文章记录下来。 创建证书看这里&#xff01;&#xff01;&#xff01; 很多知识点要结合这个页面内容来看。 创建证书已经看过相关文章&#xff0c;然后用unity跑的时候发现连不上&#xff0c;完全没…