1【Android 12】Input相关服务的创建和启动

在这里插入图片描述

Input相关服务启动的起点在SystemServer.startOtherServices:

    /**
     * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startOtherServices");

        final Context context = mSystemContext;
        ......
        InputManagerService inputManager = null;
        ......

        try {
            ......

            t.traceBegin("StartInputManagerService");
            inputManager = new InputManagerService(context);
            t.traceEnd();

            ......

            t.traceBegin("StartInputManager");
            inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
            inputManager.start();
            t.traceEnd();
            
            ....
        }    
    }

1)、创建了一个InputManagerService对象inputManager。

2)、调用了InputManagerService.start方法。

先分析InputManagerService的创建流程,然后再分析start流程。

在这里插入图片描述

1 创建

在这里插入图片描述

1.1 InputManagerService.init

    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        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());

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

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

初始化了一些成员变量,唯一需要注意的是mPtr保存了一个指向Native层的input相关服务对象的指针:

    // Pointer to native input manager service object.
    private final long mPtr;

我们重点关注nativeInit的部分。

1.2 com_android_server_input_InputManagerService.nativeInit

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

    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

这里调用了JNI层InputManagerService的nativeInit函数。

这一步创建了一个NativeInputManager实例。

1.3 NativeInputManager.init

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.pointerCapture = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;

    InputManager* im = new InputManager(this, this);
    mInputManager = im;
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

这里创建了一个Native层的InputManager对象,它对应的就是之前在Java层创建的InputManagerService。

1.4 InputManager.init

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    mReader = createInputReader(readerPolicy, mClassifier);
}

1.4.1 创建InputDispatcher对象

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

创建了一个InputDispatcher对象。

1.4.2 创建InputClassifier对象

基于上一步创建的InputDispatcher对象,创建了一个InputClassifier对象:

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

将其内部的mListener指向了上一步创建的InputDispatcher实例,mListener是:

    // The next stage to pass input events to
    sp<InputListenerInterface> mListener;

如注释所说,InputClassifier会将输入事件传给mListener,后续我们会看到事件是怎么从InputClassifier传到InputDispatcher的。

1.4.3 创建InputReader对象

基于上一步创建的InputClassifier对象,创建一个InputReader对象:

sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

这里创建了一个EventHub对象,然后基于这个EventHub和之前传入的InputClassifier来创建InputReader。

InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
                         const sp<InputReaderPolicyInterface>& policy,
                         const sp<InputListenerInterface>& listener)
      : mContext(this),
        mEventHub(eventHub),
        mPolicy(policy),
        mGlobalMetaState(0),
        mLedMetaState(AMETA_NUM_LOCK_ON),
        mGeneration(1),
        mNextInputDeviceId(END_RESERVED_ID),
        mDisableVirtualKeysTimeout(LLONG_MIN),
        mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);

    { // acquire lock
        std::scoped_lock _l(mLock);

        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    } // release lock
}

看到这里基于传入的InputClassifier生成了一个QueuedInputListener对象,QueuedInputListener定义在InputListener.h中:

/*
 * An implementation of the listener interface that queues up and defers dispatch
 * of decoded events until flushed.
 */
class QueuedInputListener : public InputListenerInterface {
protected:
    virtual ~QueuedInputListener();

public:
    explicit QueuedInputListener(const sp<InputListenerInterface>& innerListener);

    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
    virtual void notifyKey(const NotifyKeyArgs* args) override;
    virtual void notifyMotion(const NotifyMotionArgs* args) override;
    ......

    void flush();

private:
    sp<InputListenerInterface> mInnerListener;
    std::vector<NotifyArgs*> mArgsQueue;
};

QueuedInputListener用来在刷新前将解码后的事件进行排队和延迟分发。

这里的mArgsQueue存储的是NotifyArgs类型的对象,NotifyArgs是描述输入事件的超类,其子类有键盘事件NotifyKeyArgs和触摸事件NotifyMotionArgs等,那么mArgsQueue就是用来存储这些排队等待分发的事件的。

这里的mInnerListener赋值在QueuedInputListener的构造方法中:

QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
        mInnerListener(innerListener) {
}

那么这里的mInnerListener指向的是一个InputClassifier,QueuedInputListener调用flush函数后,mArgsQueue就会发送到mInnerListener也就是InputClassifier处。

扯远了,后面再分析具体事件是怎么从InputReader到InputClassifier再到InputDispatcher的。

1.5 小结

1)、创建了Java上层的InputManagerService,JNI层的NativeInputManager以及Native层的InputManager。

2)、Native层的InputManager在创建的时候,创建了InputReader和InputDispatcher,并且创建了一个InputClassifier对象。

3)、InputReader内部有一个成员变量mQeueuInputListener,mQeueuInputListener维护了一个当前正在排队等待分发的输入事件队列mArgsQueue,并且有一个mInnerListener成员指向InputClassifier,QueuedInputListener调用flush函数后,mArgsQueue就会发送到mInnerListener也就是InputClassifier处。

4)、InputClassifier有一个成员变量mListener,指向InputDispatcher,InputClassifer收到的事件会发送给mListener,最终,InputReader获取到的事件会通过InputClassifier发送给InputDispatcher。

2 启动

在这里插入图片描述

2.1 InputManagerService.start

    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);
        ......
    }

上面分析了InputManagerService初始化过程,现在来看InputManagerService的启动流程,这里也是调用了JNI层InputManagerService.nativeStart。

2.2 com_android_server_input_InputManagerService.nativeStart

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

这里传入的指针是之前1.2节中com_android_server_input_InputManagerService.nativeInit处得到的NativeInputManager的指针,那么这里就可以获取之前已经创建过的NativeInputManager,最后调用了Native层的InputManager.start。

2.3 InputManager.start

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

InputManager.start调用了InputReader.start和InputDispatcher.start,分别分析一下具体内容。

2.3.1 InputReader.start

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

这里看到,InputReader.start函数会创建一个唯一的名为“InputReader”的InputThread对象,并且赋值给InputThread类型的mThread成员变量。

InputThread的构造方法定义是:

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

可以看到,首先InputThread内部也会先创建一个InputThreadImpl类型的对象赋值给mThread成员变量,接着调用mThread.run。

InputThreadImpl继承自Thread,那么调用mThread.run会调用到InputThreadImpl的threadLoop函数,再看下InputThreadImpl的定义:

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

    bool threadLoop() override {
        mThreadLoop();
        return true;
    }
};

只要threadLoop函数返回true,以下语句就会一直循环调用:

mThreadLoop();

这里传入的循环函数是InputReader的loopOnce。

那么这里也就是说,调用InputReader的start函数后,会创建一个名为“InputReader”的InputThread对象,并且其内部线程mThread会一直循环调用InputReader.loopOnce函数。

2.3.2 InputDispatcher.start

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

InputDispatcher.start也是同理,会创建一个名为“InputDispatcher”的InputThread对象,其内部线程mThread会一直循环调用InputDispatcher.dispatchOnce函数。

2.4 小结

1)、InputReader内部维护一个唯一的,名为“InputReader”的InputThread对象,该InputThread对象内部有一个线程会一直循环调用InputReader的loopOnce函数,这个线程可以认为是InputReader的读取线程。

2)、InputDispatcher内部维护一个唯一的,名为“InputDispatcher”的InputThread对象,该InputThread对象内部有一个线程会一直循环调用InputDispatcher的dispatchOnce函数,这个线程可以认为是InputDispatcher的分发线程。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 中调用 Lua 创建服务,可以使用 LuaSocket 库和 Android Service 机制。 首先,你需要在 Android Studio 中创建一个 Service,并且在 Service 的 onCreate() 方法中启动 Lua 虚拟机。然后,你需要使用 LuaSocket 库创建一个服务器,并且在服务器的监听回调函数中处理客户端的请求。 下面是一个简单的例子,展示了如何在 Android 中调用 Lua 创建服务: 1. 在 Android Studio 中创建一个 Service,例如 MyService。 2. 在 MyService 的 onCreate() 方法中启动 Lua 虚拟机,并且加载 LuaSocket 库: ```java public class MyService extends Service { private LuaState L; private ServerSocket serverSocket; @Override public void onCreate() { super.onCreate(); // 启动 Lua 虚拟机 L = LuaStateFactory.newLuaState(); L.openLibs(); // 加载 LuaSocket 库 L.getGlobal("require"); L.pushString("socket"); L.call(1, 1); L.setGlobal("socket"); // 创建服务器 try { serverSocket = new ServerSocket(8080); } catch (IOException e) { e.printStackTrace(); } } } ``` 3. 在 MyService 的 onStartCommand() 方法中启动服务器,并且在服务器的监听回调函数中处理客户端的请求: ```java public class MyService extends Service { private LuaState L; private ServerSocket serverSocket; @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); // 启动服务器 new Thread(new Runnable() { @Override public void run() { while (true) { try { Socket clientSocket = serverSocket.accept(); // 处理客户端请求 InputStream input = clientSocket.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(input)); String request = reader.readLine(); String response = handleRequest(request); OutputStream output = clientSocket.getOutputStream(); output.write(response.getBytes()); clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); return START_STICKY; } private String handleRequest(String request) { // 在 Lua 中处理请求,并返回响应 L.getGlobal("handle_request"); L.pushString(request); L.call(1, 1); String response = L.toString(-1); L.pop(1); return response; } } ``` 4. 在 Lua 中编写处理请求的代码,并且将其保存为一个 Lua 文件(例如 handle_request.lua): ```lua function handle_request(request) -- 在 Lua 中处理请求,并返回响应 return "Hello, world!" end ``` 5. 在 MyService 的 onCreate() 方法中加载 handle_request.lua 文件: ```java public class MyService extends Service { private LuaState L; private ServerSocket serverSocket; @Override public void onCreate() { super.onCreate(); // 启动 Lua 虚拟机 L = LuaStateFactory.newLuaState(); L.openLibs(); // 加载 LuaSocket 库 L.getGlobal("require"); L.pushString("socket"); L.call(1, 1); L.setGlobal("socket"); // 加载 handle_request.lua 文件 L.getGlobal("dofile"); L.pushString("/path/to/handle_request.lua"); L.call(1, 0); // 创建服务器 try { serverSocket = new ServerSocket(8080); } catch (IOException e) { e.printStackTrace(); } } } ``` 这样,你就可以在 Android 中调用 Lua 创建服务了。当客户端发送请求时,服务将会在 Lua 中处理请求,并返回响应。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值