Android 12系统源码_输入系统(二)InputManagerService服务

前言

上一篇我们简单介绍了Android系统输入事件的常见类型和事件的传递流程,输入事件的传递流程主要分三个部分,输入系统处理部分、WMS处理部分、View处理部分。
在这里插入图片描述
其中输入系统处理部分细分为输入子系统处理部分和InputManagerService处理部分,输入子系统主要是对事件源的原始信息进行采集,而InputManagerService则是监听dev/input下的所有设备节点,当设备节点有数据时会将数据进行加工处理并分发给合适的窗口,在讲解InputManagerService具体是如何处理输入事件的之前,我们需要先来认识一下InputManagerService这个服务。

一、IMS的启动

系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生,主要用来启动frameworks层中的服务。和其他服务一样,InputManagerService服务也是在这里被启动的,下面我们简单列出SystemServer中和IMS启动相关的源码。

1.1 SystemServer阶段

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

public final class SystemServer {

    private DisplayManagerService mDisplayManagerService;

    public static void main(String[] args) {
        new SystemServer().run();
    }
    
   private void run() {
    	...代码省略...
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);//引导服务
            startCoreServices(t);//核心服务
            startOtherServices(t);//其他服务
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
    	...代码省略...
    }
       
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
         ...代码省略...
         WindowManagerService wm = null;
         InputManagerService inputManager = null;
         ...代码省略...
         t.traceBegin("StartInputManagerService");
         inputManager = new InputManagerService(context);//注释1,创建InputManagerService对象
         t.traceEnd();
         ...代码省略...
         t.traceBegin("StartWindowManagerService");
          // WMS needs sensor service ready
          mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
          //注释2,WindowManagerService作为输入系统的中转站,其内部持有InputManagerService的引用
          wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                  new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
          //将WindowManagerService添加到ServiceManager
          ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
          //将InputManagerService添加到ServiceManager
          ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
          t.traceEnd();
          ...代码省略...
          t.traceBegin("StartInputManager");
          inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
          inputManager.start();//注释3,启动IMS服务
          t.traceEnd();
          ...代码省略...          
     }
}

SystemServer的startOtherServices方法先是在注释1处创建InputManagerService对象,接着在注释2处把IMS作为参数传给WMS以便其创建的实例对象包含有IMS的引用,然后将WMS和IMS都添加到了ServiceManager中进行统一管理,然后还会调用IMS的setWindowManagerCallbacks方法将输入事件回调和WMS进行关联,最后在注释3处调用IMS的start方法启动IMS。

1.2 InputManagerService的创建

1.2.1 InputManagerService构造方法

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

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    
    private final long mPtr;
        
    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);
            
    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());//注释1,创建InputManagerHandler对象

        mStaticAssociations = loadStaticInputPortAssociations();
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());//注释2,调用nativeInit方法

        String doubleTouchGestureEnablePath = context.getResources().getString(
                R.string.config_doubleTouchGestureEnableFile);
        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
            new File(doubleTouchGestureEnablePath);

        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }
    
 }

注释1处使用android.display线程的Looper创建了InputManagerHandler,这样InputManagerHandler便会运行在android.display线程中,android.display线程是系统共享的单例前台线程,这个线程内部执行了WMS的创建。
注释2处调用了nativeInit方法,此方法是一个Native方法,该方法会返回一个NativeInputManager对象指针地址,将该地址赋值给属性变量mPtr,这个属性变量后面后面我们还会提到。

1.2.2 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) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
	//注释1,创建NativeInputManager对象
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);//注释2,返回对象指针
}

// --- NativeInputManager ---
class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface {
protected:
    virtual ~NativeInputManager();
public:
    NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper);
    inline sp<InputManagerInterface> getInputManager() const { return mInputManager; //返回对象实例 }
private:
	sp<InputManagerInterface> mInputManager;//InputManager对象

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    mServiceObj = env->NewGlobalRef(serviceObj);
    {
        AutoMutex _l(mLock);
        mLocked.systemUiLightsOut = false;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;
	//注释3,创建InputManager对象
    InputManager* im = new InputManager(this, this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

在注释1处会创建NativeInputManager对象,然后在NativeInputManager的构造方法中,也就是注释3处,会创建InputManager对象,进一步通过inputManager来读取设备节点的增删事件和原始输入事件。最后nativeInit方法会调用reinterpret_cast方法,在C++中,reinterpret_cast 是一种类型转换操作符,用于在不同类型之间进行低级别的转换,它提供了一种不安全但非常强大的转换方式,通常用于将一个指针或引用类型转换为另一种类型,**这种转换只是将指针的表示重新解释为另一种类型,不改变指针所指向的内存内容。**这里将该对象指针返回给了java层, 这是为了打通java和native层,下次需要使用native层的NativeInputManager对象的时候,直接传递这个对象指针就可以访问了。

1.2.3 InputManager的构造方法

>frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    //注释1,创建inputDispatcher对象
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    //注释2,创建InputReader对象,其内部持有mDispatcher的引用
    mReader = createInputReader(readerPolicy, mClassifier);
}

>frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) {
    //创建InputDispatcher对象
    return new android::inputdispatcher::InputDispatcher(policy);
}

>frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    //创建InputReader对象
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

在注释1处创建InputDispatcher类对象mDispatcher,然后在注释2处创建InputReader类对象mReader,其内部持有mDispatcher的引用,InputReader会不断循环读取EventHub中的原始输入事件,在对这些原始输入事件进行加工后交给InputDispatcher,由于WMS会将所有的窗口信息实时更新到InputDispatcher中,这样InputDispatcher就可以将输入事件派发给合适的窗口。

1.3 InputManagerService的启动

SystemServer的startOtherServices方法中关于IMS的最后一步是调用IMS的start方法。

1.3.1 InputManagerService的start方法

public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
        
    private final long mPtr; 
    private static native void nativeStart(long ptr);
    
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);//注释1,调用nativeStart方法
        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);//注释2,将自身添加到看门狗中进行监控
    	...代码省略...
    }
 }

在注释1处调用nativeStart方法,此方法同样是一个Native方法,这里调用该方法的时候,还将前面在InputManagerService构造方法中创建的NativeInputManager对象指针传递了进来。在注释2处将自身添加到watchdog中进行监控,用户定时检测系统关键服务是否可能发生死锁。

1.3.2 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);//注释1,获取NativeInputManager对象指针
    status_t result = im->getInputManager()->start();//注释2,调用InputManager的start方法
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}
// --- NativeInputManager ---
class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface {
public:
    NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper);
    inline sp<InputManagerInterface> getInputManager() const { return mInputManager; //注释3,返回对象实例 }
private:
	sp<InputManagerInterface> mInputManager;

在注释1处,将存储在Java层的NativeInputManager对象指针重新转化成Native层需要的对象指针,然后调用NativeInputManager的getInputManager方法获取其内部持有的InputManager对象,并调用InputManager对象的start方法。

1.3.3 InputManager的start方法

>frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
    status_t result = mDispatcher->start();//注释1,调用inputdispatcher的start方法
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }
    result = mReader->start();//注释2,调用InputReader的start方法
    if (result) {
        ALOGE("Could not start InputReader due to error %d.", result);
        mDispatcher->stop();
        return result;
    }
    return OK;
}

在注释1处调用InputDispatcher的start方法,该方法内部会开启一个名为InputDispatcher的事件分发线程,在注释2处调用InputDispatcher的start方法,该方法内部会开启一个名为InputReader的事件读取线程。

1.3.3.1 Thread

在分析InputDispatcher和InputReader两个线程之前,我们需要先来看下Thread的run方法。

>system/core/libutils/Threads.cpp
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
	...代码省略...
	//调用createThreadEtc方法
    res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread);
	...代码省略...
}

int Thread::_threadLoop(void* user)
    Thread* const self = static_cast<Thread*>(user);
	...代码省略...
    do {
        bool result;
        result = self->threadLoop();
		...代码省略...
        if (result == false || self->mExitPending) {
			...代码省略...
            break;
        }
		...代码省略...
    } while(strong != 0);
}

threadLoop是一个方法指针,第二个参数是自己,最终会调用到_threadLoop方法并传入this指针,_threadLoop方法内部会调用self->threadLoop(),这个self就是当前Thread的this指针,除了result返回false或者调用了requestExit才会退出。 不然会一直循环调用self->threadLoop()函数,threadLoop在Thread中是一个纯虚函数,在其子类中实现,所以后面只要分析子线程的threadLoop方法即可。

1.3.3.2 InputDispatcher的start方法
>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
status_t InputDispatcher::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    //注释1,创建InputThread对象
    mThread = std::make_unique<InputThread>(
            "InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
    return OK;
}

>frameworks/base/libs/androidfw/include/androidfw/Util.h
template <typename T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
  return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
}

>frameworks/native/services/inputflinger/InputThread.cpp
class InputThreadImpl : public Thread {
public:
    explicit InputThreadImpl(std::function<void()> loop)
          : Thread(/* canCallJava */ true), mThreadLoop(loop) {}

    ~InputThreadImpl() {}
    
private:
    std::function<void()> mThreadLoop;    
};
/**
 *
 * @param name  线程的名称
 * @param loop  线程要执行的主循环函数或任务
 * @param wake 一个回调函数,用于唤醒或通知线程的动作
 */
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {
    mThread = new InputThreadImpl(loop);//注释2,创建InputThreadImpl对象,该对象用于处理线程的实际操作。
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

在注释1处创建InputThread对象,分别传入了线程名称InputDispatcher、线程主循环函数dispatchOnce,回调函数mLooper->wake();然后在注释2处,也就是InputThread的构造方法中,创建InputThreadImpl对象,该对象继承自Thread ,是真正处理线程实际操作的对象。

1.3.3.3 InputDispatcher的dispatchOnce方法

在InputDispatcher线程启动之后,该线程循环执行的是dispatchOnce方法。

>frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        std::scoped_lock _l(mLock);
        mDispatcherIsAlive.notify_all();

        //注释1,检测缓存队列中是否有等待处理的命令
        if (!haveCommandsLocked()) {
            //将输入事件派发给合适的窗口
            dispatchOnceInnerLocked(&nextWakeupTime);
        }
        if (runCommandsLockedInterruptible()) {
        	//记录线程下次被唤醒的时间
            nextWakeupTime = LONG_LONG_MIN;
        }
        //注释2,检查ANR
        const nsecs_t nextAnrCheck = processAnrsLocked();
        nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
        //注释3,处理空闲状态
        if (nextWakeupTime == LONG_LONG_MAX) {
            mDispatcherEnteredIdle.notify_all();
        }
    } // release lock

    //注释4,计算InputDisPatcherThread需要休眠的最长时间
    nsecs_t currentTime = now();
    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
    //让mLooper线程休眠,timeoutMillis是休眠的最长时间
    mLooper->pollOnce(timeoutMillis);
}

在注释1处判断,如果没有待处理的命令,调用 dispatchOnceInnerLocked 方法执行一次调度循环;nextWakeupTime用于记录下次唤醒的时间,如果有待处理的命令,则将 nextWakeupTime 设置为 LONG_LONG_MIN,这表示需要立即处理下一个任务,因为命令的执行可能影响了调度的时机。在注释2处检查是否需要处理 ANR 事件,nextAnrCheck 记录了下一次检查 ANR 的时间,将 nextWakeupTime 更新为当前唤醒时间和 ANR 检查时间中的最小值,以确保在 ANR 检查之前唤醒。在注释3处,如果判断nextWakeupTime为LONG_LONG_MAX,表示没有命令、事件或待处理的任务,调度器将进入一个几乎无限长的睡眠状态,此时会通知其他线程或组件事件派发器已进入空闲状态。
在注释4处获取当前时间 currentTime,并使用toMillisecondTimeoutDelay方法计算直到 nextWakeupTime 的超时时间, 调用 mLooper->pollOnce(timeoutMillis) 方法,进入等待状态,直到有事件到达、超时或者有其他需要唤醒的情况发生。

1.3.3.4 InputReader的start和loopOnce方法

和InputDispatcher的start方法类似,InputReader的start方法也是进一步创建InputThread对象,分别传入了线程名称InputReader、线程主循环函数loopOnce,回调函数mEventHub->wake();该线程启动之后会循环执行loopOnce方法。

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

void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    std::vector<InputDeviceInfo> inputDevices;
    { // acquire lock
        std::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
    //注释1,获取设备节点的原始输入事件信息
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

    { // acquire lock
        std::scoped_lock _l(mLock);
        //通知所有等待的线程,输入读取器仍然活跃。
        mReaderIsAliveCondition.notify_all();

        if (count) {
            //注释2,对mEventBuffer中的原始输入事件信息进行加工处理,加工后的输入事件会交给InputDispatcher来处理
            processEventsLocked(mEventBuffer, count);
        }

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            if (now >= mNextTimeout) {
                //注释3,处理超时事件
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now);
            }
        }

        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            inputDevices = getInputDevicesLocked();
        }
    } // release lock

    //注释4,如果输入设备状态发生了变化,调用mPolicy->notifyInputDevicesChanged方法进行事件通知
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    mQueuedListener->flush();//刷新或处理排队的监听器事件。
}

在注释1处从事件缓冲区中获取设备节点的原始输入事件信息并将其存放到mEventBuffer中,timeoutMillis 是等待事件的超时时间,mEventBuffer 是存放事件的缓冲区,EVENT_BUFFER_SIZE 是缓冲区的大小,事件信息主要有两种,设备节点的增删事件、原始输入事件;在注释2处 判断是否有事件,如果有则调用processEventsLocked方法,该方法会对mEventBuffer中的原始输入事件信息进行加工处理,并将加工后的输入事件会交给InputDispatcher处理;在注释3处判断输入事件是否已经超时,如果超时则调用timeoutExpiredLocked方法处理超时事件;在注释4处判断输入设备状态是否发生了变化,如果是则通知相关的策略或组件。

二、IMS架构图

这里我们结合InputManagerService的构造方法和start方法画了个简单的IMS架构图。
IMS架构图

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值