【安卓12源码】Input子系统(1) - input启动流程

embedded/2024/10/18 12:32:17/

Android Input 体系中,大致有两种类型的事件:实体按键 key 事件,屏幕点击触摸事件。

如果根据事件类型的不同我们还能细分为基础实体按键的 key(power,volume up/down,recents,back,home),实体键盘按键,屏幕点击 (多点,单点),屏幕滑动等等的事件。

在 Android 整个 Input 体系中有三个格外重要的成员:Eventhub,InputReader,InputDispatcher。

它们分别担负着各自不同的职责,Eventhub 负责监听 / dev/input 产生 Input 事件,InputReader 负责从 Eventhub 读取事件,并将读取的事件发给 InputDispatcher,InputDispatcher 则根据实际的需要具体分发给当前手机获得焦点实际的 Window。

 inputmanagerservice启动原理

inpu子系统是运行在system 系统进程的

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

1325      private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
1326          t.traceBegin("startOtherServices");
。。。。。。
1471              t.traceBegin("StartInputManagerService");
// 1)创建 InputManagerService 对象
1472              inputManager = new InputManagerService(context);// 2)将其作为参数传入到wms 中
1488              wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
1489                      new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
// 增加这个input service,给客户端使用
1490              ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
1491                      DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
1492              ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
1493                      /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);// 3)启动 InputManagerService
1520              t.traceBegin("StartInputManager");
1521              inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
1522              inputManager.start();

1)创建 InputManagerService 对象

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

424      public InputManagerService(Context context) {
425          this.mContext = context;// 创建handler,在 DisplayThread 线程中处理
426          this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
427  
428          mStaticAssociations = loadStaticInputPortAssociations();
429          mUseDevInputEventForAudioJack =
430                  context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);// system 系统进程input,会打印下列的日志
431          Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
432                  + mUseDevInputEventForAudioJack);// 调用native 层的方法去初始化
433          mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
434  
435          String doubleTouchGestureEnablePath = context.getResources().getString(
436                  R.string.config_doubleTouchGestureEnableFile);
437          mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
438              new File(doubleTouchGestureEnablePath);
439  
440          LocalServices.addService(InputManagerInternal.class, new LocalService());
441      }

// 调用native 层的方法去初始化,looper 是 DisplayThread 线程

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

1488  static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
1489          jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
1490      sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
1491      if (messageQueue == nullptr) {
1492          jniThrowRuntimeException(env, "MessageQueue is not initialized.");
1493          return 0;
1494      }
1495  // 创建NativeInputManager 对象,looper 是DisplayThread 线程【再次说明】
1496      NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
1497              messageQueue->getLooper());
1498      im->incStrong(0);
1499      return reinterpret_cast<jlong>(im);
1500  }

创建NativeInputManager 对象

407  NativeInputManager::NativeInputManager(jobject contextObj,
408          jobject serviceObj, const sp<Looper>& looper) :// 缓存 mLooper
409          mLooper(looper), mInteractive(true) {
410      JNIEnv* env = jniEnv();
411  
412      mServiceObj = env->NewGlobalRef(serviceObj);
413  
414      {
415          AutoMutex _l(mLock);
416          mLocked.systemUiLightsOut = false;
417          mLocked.pointerSpeed = 0;
418          mLocked.pointerGesturesEnabled = true;
419          mLocked.showTouches = false;
420          mLocked.pointerCapture = false;
421          mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
422      }
423      mInteractive = true;
424  // 创建对象 InputManager,2个参数都是this
425      InputManager* im = new InputManager(this, this);
426      mInputManager = im;// 将其保存到 "inputflinger",给native 层调用
427      defaultServiceManager()->addService(String16("inputflinger"), im);
428  }

创建对象 InputManager,2个参数都是this
/frameworks/native/services/inputflinger/InputManager.cpp

53  InputManager::InputManager(
54          const sp<InputReaderPolicyInterface>& readerPolicy,
55          const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {// 1-1)创建 InputDispatcher对象
56      mDispatcher = createInputDispatcher(dispatcherPolicy);// 1-2)创建 InputClassifier 对象
57      mClassifier = new InputClassifier(mDispatcher);// 1-3)创建 InputReader 对象,传入了 InputClassifier对象
58      mReader = createInputReader(readerPolicy, mClassifier);
59  }
60  

// 1-1)创建 InputDispatcher对象
frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp

22  sp<InputDispatcherInterface> createInputDispatcher(
23          const sp<InputDispatcherPolicyInterface>& policy) {
24      return new android::inputdispatcher::InputDispatcher(policy);
25  }

 /frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

509  InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)//mPolicy 是 NativeInputManager,可以通过此从native层传消息给java 层,比如通知没有焦点窗口510        : mPolicy(policy),
511          mPendingEvent(nullptr),
512          mLastDropReason(DropReason::NOT_DROPPED),
513          mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
514          mAppSwitchSawKeyDown(false),
515          mAppSwitchDueTime(LONG_LONG_MAX),
516          mNextUnblockedEvent(nullptr),
517          mDispatchEnabled(false),
518          mDispatchFrozen(false),
519          mInputFilterEnabled(false),
520          // mInTouchMode will be initialized by the WindowManager to the default device config.
521          // To avoid leaking stack in case that call never comes, and for tests,
522          // initialize it here anyways.
523          mInTouchMode(true),
524          mMaximumObscuringOpacityForTouch(1.0f),
525          mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
526          mFocusedWindowRequestedPointerCapture(false),
527          mWindowTokenWithPointerCapture(nullptr),
528          mLatencyAggregator(),
529          mLatencyTracker(&mLatencyAggregator),
530          mCompatService(getCompatService()) {
531      mLooper = new Looper(false);
532      mReporter = createInputReporter();
533  
534      mKeyRepeatState.lastKeyEntry = nullptr;
535  
536      policy->getDispatcherConfiguration(&mConfig);
537  }

// 1-2)创建 InputClassifier 对象

/frameworks/native/services/inputflinger/InputClassifier.cpp

 构造函数中传入的参数 mListener 是inputdispatcher。而 InputClassifier也作为参数传入给 InputReader。相当于 InputClassifier 是 沟通 InputReader和 inputdispatcher 的桥梁

348  InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
349        : mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
350  

// 1-3)创建 InputReader 对象,传入了 InputClassifier对象

/frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp

23  sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
24                                             const sp<InputListenerInterface>& listener) {// 这里还创建了 EventHub,负责读取驱动的事件
25      return new InputReader(std::make_unique<EventHub>(), policy, listener);
26  }

InputReader 构造方法

/frameworks/native/services/inputflinger/reader/InputReader.cpp

43  InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
44                           const sp<InputReaderPolicyInterface>& policy,
45                           const sp<InputListenerInterface>& listener)
46        : mContext(this),
47          mEventHub(eventHub),
48          mPolicy(policy),
49          mGlobalMetaState(0),
50          mLedMetaState(AMETA_NUM_LOCK_ON),
51          mGeneration(1),
52          mNextInputDeviceId(END_RESERVED_ID),
53          mDisableVirtualKeysTimeout(LLONG_MIN),
54          mNextTimeout(LLONG_MAX),
55          mConfigurationChangesToRefresh(0) {// 创建 QueuedInputListener 对象,listener 是 InputClassifier.cpp
56      mQueuedListener = new QueuedInputListener(listener);
57  
58      { // acquire lock
59          std::scoped_lock _l(mLock);
60  
61          refreshConfigurationLocked(0);
62          updateGlobalMetaStateLocked();
63      } // release lock
64  }

/frameworks/native/services/inputflinger/InputListener.cpp

在调用 flush 后,可以将信息传递给 inputDispatcher 

315  QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
316          mInnerListener(innerListener) {
317  }367  void QueuedInputListener::flush() {
368      size_t count = mArgsQueue.size();
369      for (size_t i = 0; i < count; i++) {
370          NotifyArgs* args = mArgsQueue[i];
371          args->notify(mInnerListener);
372          delete args;
373      }
374      mArgsQueue.clear();
375  }

2)将其作为参数传入到wms 中

/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

1204      private WindowManagerService(Context context, InputManagerService inputManager,
1205              boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
1206              ActivityTaskManagerService atm, DisplayWindowSettingsProvider
1207              displayWindowSettingsProvider, Supplier<SurfaceControl.Transaction> transactionFactory,
1208              Supplier<Surface> surfaceFactory,
1209              Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
1210          installLock(this, INDEX_WINDOW);
1211          mGlobalLock = atm.getGlobalLock();
1212          mAtmService = atm;
1213          mContext = context;
1214          mIsPc = mContext.getPackageManager().hasSystemFeature(FEATURE_PC);
1215          mAllowBootMessages = showBootMsgs;
1216          mOnlyCore = onlyCore;
1217          mLimitedAlphaCompositing = context.getResources().getBoolean(
1218                  com.android.internal.R.bool.config_sf_limitedAlpha);
1219          mHasPermanentDpad = context.getResources().getBoolean(
1220                  com.android.internal.R.bool.config_hasPermanentDpad);
1221          mInTouchMode = context.getResources().getBoolean(
1222                  com.android.internal.R.bool.config_defaultInTouchMode);
1223          inputManager.setInTouchMode(mInTouchMode);
1224          mDrawLockTimeoutMillis = context.getResources().getInteger(
1225                  com.android.internal.R.integer.config_drawLockTimeoutMillis);
1226          mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(
1227                  com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);
1228          mMaxUiWidth = context.getResources().getInteger(
1229                  com.android.internal.R.integer.config_maxUiWidth);
1230          mDisableTransitionAnimation = context.getResources().getBoolean(
1231                  com.android.internal.R.bool.config_disableTransitionAnimation);
1232          mPerDisplayFocusEnabled = context.getResources().getBoolean(
1233                  com.android.internal.R.bool.config_perDisplayFocusEnabled);
1234          mAssistantOnTopOfDream = context.getResources().getBoolean(
1235                  com.android.internal.R.bool.config_assistantOnTopOfDream);
1236  
1237          mLetterboxConfiguration = new LetterboxConfiguration(context);
1238  // 缓存了 inputManager
1239          mInputManager = inputManager; // Must be before createDisplayContentLocked.

3)启动 InputManagerService

InputManager 类继承自 InputManagerInterface 接口,是系统处理输入事件的核心。 InputManager 包含两个线程:

  • InputReader  Thread(称为“ InputReader”)读取并预处理原始输入事件EventHub->getEvents,应用策略
  • InputDispatcher  Thread(称为“ InputDispatcher”)线程在队列上等待新事件,然 后异步将其分配给应用程序。

首先InputManagerService 设置callback: setWindowManagerCallbacks

该callback是:

4746      final InputManagerCallback mInputManagerCallback = new InputManagerCallback(this);

/frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java

    public InputManagerCallback(WindowManagerService service) {mService = service;}// 看起来是和回调通知消息给 wms相关public void notifyNoFocusedWindowAnr(@NonNull InputApplicationHandle applicationHandle) {mService.mAnrController.notifyAppUnresponsive(applicationHandle, "Application does not have a focused window");}

设置callback: setWindowManagerCallbacks

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

    public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {// 保证只有一个 callbackif (mWindowManagerCallbacks != null) {unregisterLidSwitchCallbackInternal(mWindowManagerCallbacks);}
// 缓存这个callbackmWindowManagerCallbacks = callbacks;registerLidSwitchCallbackInternal(mWindowManagerCallbacks);}

启动 InputManagerService

    public void start() {Slog.i(TAG, "Starting input manager");// native 去启动startnativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);registerPointerSpeedSettingObserver();registerShowTouchesSettingObserver();.........

nativeStart

/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);// 获取到 InputManager 对象,调用其start 的方法status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}
}

 /frameworks/native/services/inputflinger/InputManager.cpp

status_t InputManager::start() {// 调用InputDispatcher 的start 方法status_t result = mDispatcher->start();if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}// 调用InputReader 的start 方法result = mReader->start();if (result) {ALOGE("Could not start InputReader due to error %d.", result);mDispatcher->stop();return result;}return OK;
}

// 调用InputDispatcher 的start 方法

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

status_t InputDispatcher::start() {if (mThread) {return ALREADY_EXISTS;}// 再系统进程中创建线程,名字为 "InputDispatcher"
// 创建 InputThread 线程,传入lambda循环函数dispatchOncemThread = std::make_unique<InputThread>("InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });return OK;
}=============/frameworks/native/services/inputflinger/InputThread.cpp// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:explicit InputThreadImpl(std::function<void()> loop): Thread(/* canCallJava */ true), mThreadLoop(loop) {}~InputThreadImpl() {}private:std::function<void()> mThreadLoop;// 会调用 threadLoop,执行loop方法bool threadLoop() override {mThreadLoop();return true;}
};} // namespace// 创建 InputThread
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake): mName(name), mThreadWake(wake) {// 创建InputThreadImpl对象,传入 loop函数mThread = new InputThreadImpl(loop);
// 开启线程循环。mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

执行loop 方法 

void InputDispatcher::dispatchOnce() {nsecs_t nextWakeupTime = LONG_LONG_MAX;{ // acquire lockstd::scoped_lock _l(mLock);mDispatcherIsAlive.notify_all();// Run a dispatch loop if there are no pending commands.// The dispatch loop might enqueue commands to run afterwards.if (!haveCommandsLocked()) {dispatchOnceInnerLocked(&nextWakeupTime);}// Run all pending commands if there are any.// If any commands were run then force the next poll to wake up immediately.if (runCommandsLockedInterruptible()) {nextWakeupTime = LONG_LONG_MIN;}// If we are still waiting for ack on some events,// we might have to wake up earlier to check if an app is anr'ing.const nsecs_t nextAnrCheck = processAnrsLocked();nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);// We are about to enter an infinitely long sleep, because we have no commands or// pending or queued eventsif (nextWakeupTime == LONG_LONG_MAX) {mDispatcherEnteredIdle.notify_all();}} // release lock// Wait for callback or timeout or wake.  (make sure we round up, not down)nsecs_t currentTime = now();int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);mLooper->pollOnce(timeoutMillis);
}

// 调用InputReader 的start 方法

/frameworks/native/services/inputflinger/reader/InputReader.cpp

status_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}// 同理,也是在系统进程中创建一个线程,名字为 InputReader
// 执行方法 loopOnce()mThread = std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });return OK;
}============
void InputReader::loopOnce() {int32_t oldGeneration;int32_t timeoutMillis;bool inputDevicesChanged = false;std::vector<InputDeviceInfo> inputDevices;{ // acquire lockstd::scoped_lock _l(mLock);oldGeneration = mGeneration;timeoutMillis = -1;uint32_t changes = mConfigurationChangesToRefresh;if (changes) {mConfigurationChangesToRefresh = 0;timeoutMillis = 0;refreshConfigurationLocked(changes);} else if (mNextTimeout != LLONG_MAX) {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);}} // release lock// 去从驱动中读取input 事件size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lockstd::scoped_lock _l(mLock);mReaderIsAliveCondition.notify_all();if (count) {processEventsLocked(mEventBuffer, count);}


http://www.ppmy.cn/embedded/43727.html

相关文章

AI赋能数字人:打造与语音节奏完美匹配的高质量手势动画

在数字化时代,人机交互正以前所未有的速度进化,而AI数字人的发展正是这一进程中的重要里程碑。近期,一项旨在根据语音内容自动生成匹配手势的技术方案引起了广泛关注,该技术不仅增强了数字人的表现力,也为远程沟通、教育、娱乐等多个领域带来了革新性的应用潜力。本文将深…

蓝桥杯第1022题 玩具蛇 基础DFS C++ Java

题目 思路和解题方法 问题理解&#xff1a;此题要求找出将一条由16节正方形构成的玩具蛇放入4x4的方格中的不同方式数。每节蛇可以是直线或直角转弯&#xff0c;且蛇的形状需要完全覆盖盒子里的16个格子&#xff0c;每个格子仅被蛇的一个部分占据。 状态表示&#xff1a;使用一…

基于深度学习的 CT 重建核的图像转换改进了肺部结节或肿块的放射组学再现性 | 文献速递-深度学习结合影像组学

Title 题目 Deep Learning–based Image Conversion of CT Reconstruction Kernels Improves Radiomics Reproducibility for Pulmonary Nodules or Masses 基于深度学习的 CT 重建核的图像转换改进了肺部结节或肿块的放射组学再现性 Background 背景 Intratumor hetero…

synopsys EDA 2016 合集 下载

包含如下安装包&#xff0c;如需安装服务也可联系我 FineSim_vL_2016.03 Laker201612 Library Compiler M-2016.12 Update Training PrimeTime M-2016.12 Update Training StarRC M-2016.12 Update Training SynopsysInstaller_v3.3 TSMC-65nm(OA) fm_vL-2016.03-SP1 fpga_vL-…

【MySQL】SQL 基础

文章目录 【 1. SQL 的书写规则 】1.1 大小写规则1.2 常量的表示1.3 注释1.4 HELP 系统帮助 【 2. 常用数据库函数 】2.1 SHOW DATABASES 显示数据库2.2 CREATE DATABASE 创建数据库2.3 ALTER DATABASE 修改数据库2.4 DROP DATABASE 删除数据库2.5 USE 选择数据库 【 3. RDBMS …

Qt第八章绘图

第八章绘图 文章目录 第八章绘图基本绘制和填充绘制图形使用画笔QPen使用画刷QBrush样式&#xff0c;颜色&#xff0c;纹理填充渐变填充 坐标变换绘图函数QImage是为I/O和直接像素访问和操作而设计优化的QPixmap是为在屏幕上显示图像而设计优化的QBitmap只是一个继承了QPixmap的…

代码随想录算法训练营Day7|454.四数相加II、 383. 赎金信、15. 三数之和、 18. 四数之和

454.四数相加II 四个数组分成两组进行for循环&#xff0c;先用HashMap存储所有第一组for循环出现的和的次数。再进行第二组for循环&#xff0c;每一次得出的和判断其负数是否在map的key中&#xff0c;如果存在&#xff0c;就加上这个value。 class Solution {public int four…

滑动窗口-java

主要通过单调队列来解决滑动窗口问题&#xff0c;得到滑动窗口中元素的最大值和最小值。 目录 前言 一、滑动窗口 二、算法思路 1.滑动窗口 2.算法思路 3.代码详解 三、代码如下 1.代码如下 2.读入数据 3.代码运行结果 总结 前言 主要通过单调队列来解决滑动窗口问题&#xff…