Android系统源码分析Input - 启动流程

Input是Android 平台中负责处理用户输入事件核心组件,他的主要作用有:从各种硬件设备(触摸屏、物理键盘、鼠标等)接收原始输入事件、将输入事件传递给正确的应用程序和视图、识别多点触控手势。Input是Android实现流畅人机交互的基础设施,直接影响用户体验的质量。因此我们有必要进行深入理解。

  1. 在SystemServer启动过程中会启动很多系统服务,其中就包括InputManagerServic。可以看到在创建WindowManagerService的时候把inputManager传了进去,并且在InputManagerService中设置了WindowManagerCallbacks,这样他们就可以互相通信了。
ini 复制代码
// frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ...
    WindowManagerService wm = null;
    InputManagerService inputManager = null;
    ...
    
    inputManager = new InputManagerService(context);
    ...
    
    wm = WindowManagerService.main(context, inputManager, !mFirstBoot,
        new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
    ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_HIGH
                | DUMP_FLAG_PROTO);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
    ...
    
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());    
}
  1. 在InputManagerService的构造过程中,创建了NativeInputManagerService.NativeImpl。NativeImpl的构造器调用了init(),这是个jni接口。
scss 复制代码
// frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

static class Injector {
    Injector(Context context, Looper looper, UEventManager uEventManager) {
        mContext = context;
        mLooper = looper;
        mUEventManager = uEventManager;
    }
    ...
    
    NativeInputManagerService getNativeService(InputManagerService service) {
        return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
    }
}

public InputManagerService(Context context) {
    this(new Injector(context, DisplayThread.get().getLooper(), new UEventManager() {}));
}

InputManagerService(Injector injector) {
    ...
    mNative = injector.getNativeService(this);
    ...
}
java 复制代码
// frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java

class NativeImpl implements NativeInputManagerService {
@SuppressWarnings({"unused", "FieldCanBeLocal"})
    private final long mPtr;

    NativeImpl(InputManagerService service, MessageQueue messageQueue) {
        mPtr = init(service, messageQueue);
    }
    
    private native long init(InputManagerService service, MessageQueue messageQueue);
}    
  1. init方法中创建了NativeInputManager,这里和java层使用了同一个looper。
ini 复制代码
// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj,
                        jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }

    static std::once_flag nativeInitialize;
    NativeInputManager* im = nullptr;
    std::call_once(nativeInitialize, [&]() {
        // Create the NativeInputManager, which should not be destroyed or deallocated for the
        // lifetime of the process.
        im = new NativeInputManager(serviceObj, messageQueue->getLooper());
    });
    LOG_ALWAYS_FATAL_IF(im == nullptr, "NativeInputManager was already initialized.");
    return reinterpret_cast<jlong>(im);
}
  1. NativeInputManager构造器中创建了InputManager,并注册了inputflinger服务
scss 复制代码
// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp


NativeInputManager::NativeInputManager(jobject serviceObj, const sp<Looper>& looper)
      : mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    mServiceObj = env->NewGlobalRef(serviceObj);

    InputManager* im = new InputManager(this, *this, *this, *this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}
  1. 创建InputManager时传入的四个参数用于回调java层。这里创建了InputDispacher和InputReader。SystemServer调用InputManagerService的start(),最终会调用到InputManager的start()。这里又分别调用了InputDispacher和InputReader的start()
ini 复制代码
// frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy,
                           InputDispatcherPolicyInterface& dispatcherPolicy,
                           PointerChoreographerPolicyInterface& choreographerPolicy,
                           InputFilterPolicyInterface& inputFilterPolicy) {

    // 创建Dispacher
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    // 将InputDispacher封装为TracedInputListener,并添加到mTracingStages中
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputDispatcher", *mDispatcher));

    if (ENABLE_INPUT_FILTER_RUST) {
        mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust,
                                                     inputFilterPolicy);
        mTracingStages.emplace_back(
                std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));
    }

    if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
        mCollector = std::make_unique<InputDeviceMetricsCollector>(*mTracingStages.back());
        mTracingStages.emplace_back(
                std::make_unique<TracedInputListener>("MetricsCollector", *mCollector));
    }

    mProcessor = std::make_unique<InputProcessor>(*mTracingStages.back());
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("InputProcessor", *mProcessor));

    mChoreographer =
            std::make_unique<PointerChoreographer>(*mTracingStages.back(), choreographerPolicy);
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("PointerChoreographer", *mChoreographer));

    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mTracingStages.back());
    mTracingStages.emplace_back(
            std::make_unique<TracedInputListener>("UnwantedInteractionBlocker", *mBlocker));

    mReader = createInputReader(readerPolicy, *mTracingStages.back());
    }back(
            std::make_unique<TracedInputListener>("UnwantedInteractionBlocker", *mBlocker));
    // 创建InputReader时将mTracingStages传给InputReader
    mReader = createInputReader(readerPolicy, *mTracingStages.back());
}

status_t InputManager::start() {
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReader->start();
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);

        mDispatcher->stop();
        return result;
    }

    return OK;
}
  1. 在创建InputReader时,创建了EventHub。
ruby 复制代码
// frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp

std::unique_ptr<InputDispatcherInterface> createInputDispatcher(
        InputDispatcherPolicyInterface& policy) {
    return std::make_unique<android::inputdispatcher::InputDispatcher>(policy);
}
  1. InputDispatcher和InputReader分别在start()中创建了自己的线程
ruby 复制代码
// frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                 std::unique_ptr<trace::InputTracingBackendInterface> traceBackend) {
    mLooper = sp<Looper>::make(false);
    ...
}

status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }

    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}
kotlin 复制代码
// frameworks/native/services/inputflinger/reader/InputReader.cpp

status_t InputReader::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }

    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}
相关推荐
selt7915 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao6 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost7 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城7 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下7 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho1239 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此9 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao10 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji341610 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot10 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar