android4.3 按键消息处理分析

Android4.3按键消息处理与之前的版本有稍微的区别,基本原理还是一样的,这里主要从两个阶段来分析:

1.前期的准备工作,即开机时启动相应的的线程,静候按键事件的来临

2.当有按键消息时,进行消息的分发等处理

先看一张类图:

从类图中看出,主要涉及到的类有PhoneWindowManager、WindowManagerService、inputManagerService、 InputManager

先看第一个问题,前期的准备工作:

1.开机时先启动inputManagerService,由ServerThread负责启动;

  inputManager = new InputManagerService(context, wmHandler);

            Slog.i(TAG, "Window Manager");
            wm = WindowManagerService.main(context, power, display, inputManager,
                    uiHandler, wmHandler,
                    factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                    !firstBoot, onlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

            ActivityManagerService.self().setWindowManager(wm);

            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();

看inputManagerService的构造函数:

 public InputManagerService(Context context, Handler handler) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(handler.getLooper());

        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
    }

先new一个InputManagerHandler,然后调用一个native方法,把service和handler的消息队列作为参数传入,

nativeInit对应是com_android_server_input_InputManagerService.cpp中的nativeInit,,这个通过JNI的机制进行关联。

这里不多说,看nativeInit:

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

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

这里主要是创建一个NativeInputManager对象,看起构造函数:

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

    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
    }

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}

这里主要是创建一个InputManager,看起构造函数:

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

这里看到了创建对象InputDispatcher 、InputReader以及两个时刻在跑的线程对象:mReaderThread、mDispatcherThread

至此初始化的第一步是完成了,但创建的线程还没start,还开始正真的干活,看开启过程

至此前期的准备工作都做完,两线程开始干活,静候按键事件来临

2.当有按键事件时两个线程处理流程见下图:

两条主线:

a.  InputReader从EventHub中获取到按键事件,并通知InputDispatcher;InputDispatcher接到通知后调用

interceptKeyBeforeQueueing方法进行相关的操作,并把按键事件加入到队列中,等待后面处理。

加入队列源码:

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry);
    traceInboundQueueLengthLocked();

b.  InputDispatcher从消息队列中获取按键消息,调用interceptKeyBeforeDispatching方法判断是否对此消息进行拦截,

根据其结果进行判断:

    nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
            &event, entry->policyFlags);

    mLock.lock();

    if (delay < 0) {
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
    } else if (!delay) {
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
    } else {
        entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
        entry->interceptKeyWakeupTime = now() + delay;
    }

其中在InputDispatcher中调用的interceptKeyBeforeQueueing和interceptKeyBeforeDispatching方法都是对应着

PhoneWindowManager中的同名方法。

android4.3 按键消息处理分析

时间: 2024-10-06 20:18:29

android4.3 按键消息处理分析的相关文章

android4.3 Bluetooth(le)分析之startLeScan分析

BluetoothAdapter.java中有low enery(le)的一些方法,android提供了这些方法,但源码中并未找到这些方法的调用之处.本文档主要分析这类方法的执行流程,来了解下le到底做了些什么. 本文主要就是分析下startLeScan方法(两个重载方法). public boolean startLeScan(LeScanCallback callback) { return startLeScan(null, callback); } public boolean star

Android4.42-Setting源码分析之蓝牙模块Bluetooth(下)

接着上一篇Android4.42-Settings源码分析之蓝牙模块Bluetooth(上) 继续蓝牙模块源码的研究 THREE,蓝牙模块功能实现 switch的分析以及本机蓝牙重命名和可见性的分析见上一篇,接下来进行第三章第三部分的介绍:关于蓝牙远程设备列表的加载.如果没有看过,建议看看上一篇关第一章蓝牙的布局,有助于理解 3>,设备列表的加载 因为这部分代码很多,所以在介绍时先说一下思路,程序首先通过底层的BluetoothAdapter的getBondedDevices()方法获取到已配对

Android4.4 耳机检测分析

在ALSA架构中,ASOC是由3个部分组成:Platform.CODEC & Machine.而耳机检测一般是在Machine driver里实现,当然也可以在CODEC driver里实现.耳机插拔接口Jack的结构图如图1所示(iPhone和Nokia耳机MIC & GROUND正好相反). 图1.Jack结构图 耳机检测信号HP_DET#可以通过以下有两种方式传递到SOC端: 1.直接将HP_DET#信号接到SOC端: 2.将HP_DET#信号先接到CODEC端,再有CODEC端GP

Android4.0 Surface机制分析

1. java层面的Surface 对于Surface我们的认识主要是android的类Surface, android的文档描述Surface是"Handle onto a raw buffer that is being managed by the screen compositor",这个描述透漏出两个信息:首先,Surface是一个raw buffer的句柄,通过它去管理一个raw buffer,其次,Surface本身是由screen compositor来管理的.但是ra

Android4.4 Telephony流程分析——SIM卡开机时的数据加载

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 本文主要介绍sim卡数据的读取过程,当射频状态处于准备状态时,此时UiccCardApplication应处于AppState.APPSTATE_READY状态,我们沿着这个信号跟踪下去.阅读本文时可先阅读Android4.4 Telephony流程分析--SIM卡开机时的初始化一文,了解Radio和sim卡状态更新过程. 先来看一下数据加载的序列图: step1~step3,走的是更新过程

Android4.4 Telephony流程分析——拨号应用(Dialer)的通话记录加载过程

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. Android系统通话记录存储在联系人数据库contacts2.db中的calls表中,通话记录(calllog)存储到数据库的时机可查看我之前的一篇博客Android4.4 Telephony流程分析--电话挂断step39,系统提供了CallLogProvider这个ContentProvider来供外界访问.我们来看本文将会使用到的CallLogProvider的代码片段: /** *

Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 本文主要介绍GsmServiceStateTracker是怎么管理网络的?手机开机后,怎么去注册网络?网络状态是怎么变换传递的. Android在ServiceState.java中定义了四种ServiceState状态和16中无线通信网络类型: public class ServiceState implements Parcelable { /** * Normal operation

Android4.4 fence机制分析

Android4.4 fence机制分析 在任何一个系统中,无可避免的都会跟各种buffers打交道,最经典的模式就是消费-生产者模式,一个独立的buffer在它们之间的交换等操作都需要一个机制来控制每个buffer的"生命周期",即ALLOCATION 和 RELEASE ,此外还要考虑到同步性问题,什么时候可以read buffer和write buffer都需要听从调遣. 在android中的fence就是这样一个为了解决同步性而出现的机制.首先从fence的语义角度来分析一下它

Android4.4 Telephony流程分析——彩信(MMS)发送过程

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 彩信收发依靠WAP网络,在Android4.4中的实现基于Http协议的应用.下图为几个彩信传输过程中的关键类: SendTransaction:发送彩信 NotificationTransaction:彩信接收 ReadRecTransaction:彩信阅读报告 RetrieveTransaction:彩信下载 TransactionService是个service,负责调度处理各种彩信事