Input 输入事件防止屏幕睡眠流程

adb shell getevent  -ltr 收到了输入事件
/dev/input/event3: 0003 0039 00000646
/dev/input/event3: 0003 0035 00000177
/dev/input/event3: 0003 0036 00000098
/dev/input/event3: 0001 014a 00000001
/dev/input/event3: 0000 0000 00000000
/dev/input/event3: 0003 0039 ffffffff
/dev/input/event3: 0001 014a 00000000
/dev/input/event3: 0000 0000 00000000

adb shell  dumpsys power  有keyguard有锁状态下
Screen off timeout: 10000 ms
Screen dim duration: 2000 ms
即8秒亮屏2秒暗屏后进入睡眠

//Input 输入事件读取分发流程大致如下:

InputReader::loopOnce-->
{
读取底层事件
mEventHub->getEvents
通知InputDispatcher处理事件
mQueuedListener->flush();
}
InputListener. QueuedInputListener::flush()-->

InputDispatcher::notifyKey-->
循环读取事件进行分发
InputDispatcherThread::threadLoop-->
InputDispatcher::dispatchOnce--->
InputDispatcher::dispatchOnceInnerLocked-->
/从事件队列中取出事件,调用pokeUserActivityLocked最终连接PowerMangerService保持屏幕唤醒
在systemui有添加了INPUT_FEATURE_DISABLE_USER_ACTIVITY这个flag导致在有keyguard的状态下不会触发走InputDispatcher的pokeUserActivityLocked
....
{
        // Poke user activity for this event.
         if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
             pokeUserActivityLocked(mPendingEvent);
         }
...
}
InputDispatcher.pokeUserActivityLocked{
         if (info->inputFeatures & InputWindowInfo::INPUT_FEATURE_DISABLE_USER_ACTIVITY) {
 #if DEBUG_DISPATCH_CYCLE
             ALOGD("Not poking user activity: disabled by window '%s'.", info->name.c_str());
 #endif
             return;
         }
     }
}

传递流程
InputDispatcher.doPokeUserActivityLockedInterruptible--->
com_android_server_input_InputManagerService.pokeUserActivity--->
com_android_server_power_PowerManagerService.android_server_PowerManagerService_userActivity-->
PowerManagerService.userActivityFromNative--->
PowerManagerService.userActivityInternal-->
PowerManagerService.userActivityNoUpdateLocked{
    updatePowerStateLocked();
}
如上在systemui 有keyguard界面上需要使用userActivity来保持屏幕唤醒

private PowerManager mPM;
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mPM.userActivity(SystemClock.uptimeMillis(), false);

///Input部分堆栈

	Line 230583: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #00 pc 00000000000245f4  /system/lib64/libinputflinger.so (android::InputDispatcher::pokeUserActivityLocked(android::InputDispatcher::EventEntry const*)+356)
	Line 230583: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #00 pc 00000000000245f4  /system/lib64/libinputflinger.so (android::InputDispatcher::pokeUserActivityLocked(android::InputDispatcher::EventEntry const*)+356)
	Line 230583: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #00 pc 00000000000245f4  /system/lib64/libinputflinger.so (android::InputDispatcher::pokeUserActivityLocked(android::InputDispatcher::EventEntry const*)+356)
	Line 230584: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #01 pc 00000000000276a0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchEventLocked(long, android::InputDispatcher::EventEntry*, std::__1::vector<android::InputTarget, std::__1::allocator<android::InputTarget>> const&)+152)
	Line 230584: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #01 pc 00000000000276a0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchEventLocked(long, android::InputDispatcher::EventEntry*, std::__1::vector<android::InputTarget, std::__1::allocator<android::InputTarget>> const&)+152)
	Line 230584: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #01 pc 00000000000276a0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchEventLocked(long, android::InputDispatcher::EventEntry*, std::__1::vector<android::InputTarget, std::__1::allocator<android::InputTarget>> const&)+152)
	Line 230585: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #02 pc 00000000000250b0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchKeyLocked(long, android::InputDispatcher::KeyEntry*, android::InputDispatcher::DropReason*, long*)+1568)
	Line 230585: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #02 pc 00000000000250b0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchKeyLocked(long, android::InputDispatcher::KeyEntry*, android::InputDispatcher::DropReason*, long*)+1568)
	Line 230585: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #02 pc 00000000000250b0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchKeyLocked(long, android::InputDispatcher::KeyEntry*, android::InputDispatcher::DropReason*, long*)+1568)
	Line 230585: 01-02 06:48:25.795 D/InputDispatcher( 1004):   #02 pc 00000000000250b0  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchKeyLocked(long, android::InputDispatcher::KeyEntry*, android::InputDispatcher::DropReason*, long*)+1568)
	Line 230586: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #03 pc 0000000000024040  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchOnceInnerLocked(long*)+1200)
	Line 230586: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #03 pc 0000000000024040  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchOnceInnerLocked(long*)+1200)
	Line 230587: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #04 pc 0000000000023aa8  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchOnce()+120)
	Line 230587: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #04 pc 0000000000023aa8  /system/lib64/libinputflinger.so (android::InputDispatcher::dispatchOnce()+120)
	Line 230588: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #05 pc 0000000000037d8c  /system/lib64/libinputflinger.so (android::InputDispatcherThread::threadLoop()+20)
	Line 230588: 01-02 06:48:25.796 D/InputDispatcher( 1004):   #05 pc 0000000000037d8c  /system/lib64/libinputflinger.so (android::InputDispatcherThread::threadLoop()+20)
InputReader Loop 流程如下
getEvents:通过 EventHub (监听目录 /dev/input )读取事件放入 mEventBuffer ,而mEventBuffer 是一个大小为256的数组, 再将事件 input_event 转换为 RawEvent
processEventsLocked: 对事件进行加工, 转换 RawEvent -> NotifyKeyArgs(NotifyArgs)
QueuedListener->flush:将事件发送到 InputDispatcher 线程, 转换 NotifyKeyArgs -> KeyEntry(EventEntry)
-->InputDispatcher.notifyKey
{
  mPolicy->interceptKeyBeforeQueueing
  KeyEntry* newEntry = new KeyEntry
  enqueueInboundEventLocked(newEntry)
}
///
InputDispatcher 的核心逻辑如下:
dispatchOnce()
dispatchOnceInnerLocked(): 从 InputDispatcher 的 mInboundQueue 队列,取出事件 EventEntry。另外该方法开始执行的时间点 (currentTime) 便是后续事件 dispatchEntry 的分发时间 (deliveryTime)
->1.dispatchKeyLocked()
{
doInterceptKeyBeforeDispatchingLockedInterruptible
findFocusedWindowTargetsLocked
dispatchEventLocked
}
->2.dispatchMotionLocked
{
findTouchedWindowTargetsLocked
dispatchEventLocked
}
doInterceptKeyBeforeDispatchingLockedInterruptible ->mPolicy->interceptKeyBeforeDispatching 向上传递拦截
//
enqueueDispatchEntryLocked():生成事件 DispatchEntry 并加入 connection 的 outbound 队列
startDispatchCycleLocked():从 outboundQueue 中取出事件 DispatchEntry, 重新放入 connection 的 waitQueue 队列;
InputChannel.sendMessage 通过 socket 方式将消息发送给远程进程;
runCommandsLockedInterruptible():通过循环遍历地方式,依次处理 mCommandQueue 队列中的所有命令。而 mCommandQueue 队列中的命令是通过 postCommandLocked() 方式向该队列添加的。
///


InputReader将Key的信息封装成一个NotifyKeyArgs对象,调用InputDispatcher的notifyKey来处理
frameworks/native/services/inputflinger/InputDispatcher.cpp
dispatchOnce--->
dispatchOnceInnerLocked{
 switch (mPendingEvent->type) {
 ....
 ....
    case EventEntry::TYPE_KEY:
            dispatchKeyLocked
    case EventEntry::TYPE_MOTION:
            dispatchMotionLocked
}
---->
会遍历inputTargets中所有InputTarget,每个InputTarget都对应着一个InputChannel,
每个InputChannel对应着一个Connection,代表着InputDispatcher和Window的联系纽带。
这个方法的核心是findFocusedWindowTargetsLocked寻找焦点窗口inputTargets
dispatchEventLocked--->

pokeUserActivityLocked -->
doPokeUserActivityLockedInterruptible


/ALOGD_CALLSTACK("pokeUserActivityLocked");
注册
registerInputChannel
registerInputMonitor-->

handleReceiveCallback-->
/frameworks/native/libs/input/InputTransport.cpp
receiveFinishedSignal根据返回的状态退出 handleReceiveCallback 的死循环
handleReceiveCallback{
  for (;;) {
   //接收窗口处理完成的消息
   connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
  }
  // 这里post一个command
  d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
} -->
finishDispatchCycleLocked -->
onDispatchCycleFinishedLocked--->
doDispatchCycleFinishedLockedInterruptible  --->
afterKeyEventLockedInterruptible  -->
....
mPolicy->dispatchUnhandledKey


receiveFinishedSignal-->


///
第一处
finishDispatchCycleLocked-->
onDispatchCycleFinishedLocked-->
doDispatchCycleFinishedLockedInterruptible{
DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
 if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
 // 主要是对unhandle key的policy
    afterKeyEventLockedInterruptible(connection,dispatchEntry, keyEntry, handled);
 } else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
    afterMotionEventLockedInterruptible(connection,dispatchEntry, motionEntry, handled);
 }
1.  startDispatchCycleLocked
}

第二处
dispatchKeyLocked--->
///分发Event事件
dispatchEventLocked{
 ///向上传递保持系统唤醒
 pokeUserActivityLocked(eventEntry);
 for (const InputTarget& inputTarget : inputTargets) {
     //找到目标连,将eventEntry发送到inputTarget
     prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
 }

}
prepareDispatchCycleLocked-->
enqueueDispatchEntriesLocked{
...
     // If the outbound queue was previously empty, start the dispatch cycle going.
     if (wasEmpty && !connection->outboundQueue.isEmpty()) {
         startDispatchCycleLocked(currentTime, connection);
     }
...     

// 如果当前connection的outBoundQueque里还有Event则继续下一轮的Dispatch周期
startDispatchCycleLocked


startDispatchCycleLocked{-->

 case EventEntry::TYPE_KEY: 
             connection->inputPublisher.publishKeyEvent
 case EventEntry::TYPE_MOTION:
             connection->inputPublisher.publishMotionEvent

}

frameworks/native/libs/input/InputTransport.cpp
调用InputChanel的SendMessage(),SendMessage()再动用socket的send()函数,将打包好的Message发送给窗口。
publishKeyEvent{
....
准备发送消息,与连接的上层
return mChannel->sendMessage(&msg)
....
}

后看看handleReceiveCallback回调

InputDispatcher与App交互过程

  1. InputDispatcher线程调用InputPublisher的publishKeyEvent向UI主线程发送input事件;
  2. UI主线程接收到该事件后,调用InputConsumer的consumeEvents来处理该事件, 一路执行到ViewRootImpl.deliverInputEvent()方法;
  3. UI主线程经过一系列的InputStage来处理, 当事件分发完成,则会执行finishInputEvent()方法.再进一步调用InputConsumer::sendFinishedSignal 告知InputDispatcher线程该时事件已处理完成.
  4. InputDispatcher线程收到该事件后, 执行InputDispatcher::handleReceiveCallback();最终会调用doDispatchCycleFinishedLockedInterruptible()方法 ,将dispatchEntry事件从等待队列(waitQueue)中移除.

「InputReader」 负责从 EventHub 里面把 Input 事件读取出来,然后交给 InputDispatcher 进行事件分发
「InputDispatcher」 在拿到 InputReader 获取的事件之后,对事件进行包装和分发 (也就是发给对应的)
「OutboundQueue」 里面放的是即将要被派发给对应 AppConnection 的事件
「WaitQueue」 里面记录的是已经派发给 AppConnection 但是 App 还在处理没有返回处理成功的事件
「PendingInputEventQueue」 里面记录的是 App 需要处理的 Input 事件,这里可以看到已经到了应用进程
「deliverInputEvent」 标识 App UI Thread 被 Input 事件唤醒
「InputResponse」 标识 Input 事件区域,这里可以看到一个 Input_Down 事件 + 若干个 Input_Move 事件 + 一个 Input_Up 事件的处理阶段都被算到了这里

模拟事件全部是通过input命令来实现的,首先看一下input命令的使用: 
usage: input ...

       input text <string>
       input keyevent <key code number or name>
       input tap <x> <y>
       input swipe <x1> <y1> <x2> <y2>

1. keyevent指的是android对应的keycode,比如home键的keycode=3,back键的keycode=4.

然后使用的话比较简单,比如想模拟home按键:

adb shell input keyevent 3

请查阅上述文章,根据具体keycode编辑即可。

2. 关于tap的话,他模拟的是touch屏幕的事件,只需给出x、y坐标即可。

此x、y坐标对应的是真实的屏幕分辨率,所以要根据具体手机具体看,比如你想点击屏幕(x, y) = (250, 250)位置:

adb shell input tap 250 250

3. 关于swipe同tap是一样的,只是他是模拟滑动的事件,给出起点和终点的坐标即可。例如从屏幕(250, 250), 到屏幕(300, 300)即

adb shell input swipe 250 250 300 300
adb shell input swipe 50 0 30 30

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值