问题
1.PhoneWindowManager.interceptKeyBeforeQueueing/interceptKeyBeforeDispatching怎么跟系统服务input关联?
2.Activity.dispatchTouchEvent/dispatchKeyEvent怎么跟系统服务input的触摸/按键事件关联?
3.PowerManagerService.userActivityFromNative怎么被系统服务input触发?
adb查询
adb shell cmd input
adb shell dumpsys input
代码
frameworks/base/services/java/com/android/server
SystemServer.java
frameworks/base/services/core/java/com/android/server/wm
WindowManagerService.java
frameworks/base/services/core/java/com/android/server/policy
PhoneWindowManager.java
frameworks/base/services/core/java/com/android/server/input
InputManagerService.java
frameworks/base/services/core/jni/
com_android_server_input_InputManagerService.cpp(NativeInputManager)
frameworks/native/services/inputflinger
InputManager.cpp
InputDispatcher.cpp(InputDispatcherThread)
InputReader.cpp(InputReaderThread)
注:
7.1
分析
1.input启动
com.android.server.SystemServer
private void startOtherServices() {
···
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);
traceEnd();
···
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
traceEnd();
···
traceBeginAndSlog("StartInputManager");
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
traceEnd();
···
final InputManagerService inputManagerF = inputManager;
mActivityManagerService.systemReady(new Runnable() {
public void run() {
···
try {
// TODO(BT) Pass parameter to input manager
if (inputManagerF != null) inputManagerF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
···
}
}
···
}
1)WindowManagerService和InputManagerService是强耦合。WindowManagerService的main方法注入inputmanager
2)input服务设置window服务的回调方法。也就是当input有变动,可通过回调方法通知window。
2.input的初始化
com.android.server.input.InputManagerService
/* InputManagerService的构造方法*/
public InputManagerService(Context context) {
······
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
······
}
public void start() {
nativeStart(mPtr);
······
}
以上两个方法都关联native层
3.input的nativie层
1)关键对象的初始化及调用
com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
···
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());//注意,serviceObj就是InputManagerService
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
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.");
}
}
a)将InputManagerService对象传到native层,并传给创建的NativeInputManager对象
b)启动NativeInputManager的InputManager
2)NativeInputManager初始化
com_android_server_input_InputManagerService.cpp
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
·······
mContextObj = env->NewGlobalRef(contextObj);
mServiceObj = env->NewGlobalRef(serviceObj);
······
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
a)NativeInputManager继承InputReaderPolicyInterface,关联InputReader事件,例如:notifyInputDevicesChanged
NativeInputManager继承InputDispatcherPolicyInterface,关联InputDispatcher事件,例如:interceptKeyBeforeQueueing/interceptKeyBeforeDispatching
b)InputManagerService对象在Native存在的名称是mServiceObj
c)初始化InputManager,并将InputManager和EventHub关联
3)InputManager初始化及启动
InputManager.cpp
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);
}
status_t InputManager::start() {
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
···
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
···
return OK;
}
a)InputManager中创建了InputReader和InputDispatcher。InputReader负责从底层(通过EventHub)读取数据,InputDispatcher负责分发来自InputReader数据
b)InputReader关联上EventHub、InputDispatcher的回调类(InputListenerInterface)、InputReader本身的回调类(InputReaderPolicyInterface)
c)InputManager创建两个线程mReaderThread、mDispatcherThread,
4-1)线程简介,以InputReaderThread为例
InputReader.h
class InputReaderThread : public Thread {
public:
InputReaderThread(const sp<InputReaderInterface>& reader);
virtual ~InputReaderThread();
private:
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
};
InputReader.cpp
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputReaderThread::~InputReaderThread() {
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
当线程run起来,则调用threadLoop,因为threadLoop返回true,则会一直循环threadLoop
4-2)分析InputReader
InputReader.cpp
a)InputReader构造函数
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy),
mGlobalMetaState(0), mGeneration(1),
mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);
···
}
简单的说,policy为NativeInputManager对象,listener为InputDispatcher对象
,此时mQueuedListener关联了InputDispatcher对象
b)执行loopOnce
void InputReader::loopOnce() {
···
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
···
if (count) {
//增加InputDevice设备或者处理业务
processEventsLocked(mEventBuffer, count);
}
···
} // release lock
···
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
···
mQueuedListener->flush();
}
c)关注processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
···
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
···
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
···
}
···
}
}
(1)addDeviceLocked会初始化InputDevice,并且addMapper很多对象进行,例如KeyboardInputMapper、MultiTouchInputMapper、SingleTouchInputMapper
(2)processEventsForDeviceLocked是处理业务
d)关注processEventsForDeviceLocked
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
···
InputDevice* device = mDevices.valueAt(deviceIndex);
···
device->process(rawEvents, count);
}
4-2-1)如果是按键事件,则调用KeyboardInputMapper
11)关注KeyboardInputMapper.process
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
···
if (isKeyboardOrGamepadKey(scanCode)) {
processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
}
break;
}
···
}
}
12)关注KeyboardInputMapper.processKey
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
int32_t usageCode) {
···
NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener()->notifyKey(&args);
}
(1)getListener()是InputDispather
(2)调用Dispatcher.notifyKey
4-2-2)如果是触摸事件,则调用MultiTouchInputMapper
11)MultiTouchInputMapper.process
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
TouchInputMapper::process(rawEvent);
mMultiTouchMotionAccumulator.process(rawEvent);
}
(1)切换成执行TouchInputMapper.process
(2)过程很复杂,只挑过程
12)省略复杂分析过程
TouchInputMapper.process ---> TouchInputMapper.sync ---> TouchInputMapper.processRawTouches --->TouchInputMapper.cookAndDispatch ---> TouchInputMapper.dispatchTouches ---> TouchInputMapper.dispatchMotion
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
int32_t action, int32_t actionButton, int32_t flags,
int32_t metaState, int32_t buttonState, int32_t edgeFlags,
const PointerProperties* properties, const PointerCoords* coords,
const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
float xPrecision, float yPrecision, nsecs_t downTime) {
···
NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
action, actionButton, flags, metaState, buttonState, edgeFlags,
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
getListener()->notifyMotion(&args);
}
(1)getListener()是InputDispather
(2)调用Dispatcher.notifyMotion
5)分析InputDispatcher
a)InputDispatcherThread调用
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
循环执行threadLoop
b)InputDispatcher构造函数
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy),
mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(NULL),
mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
···
}
mPolicy其实就是NativeInputManager
c)InputDispatcher.dispatchOnce
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
···
if (!haveCommandsLocked()) {//队列mCommandQueue,如果没有命令则走进去
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {//执行命令
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
···
mLooper->pollOnce(timeoutMillis);//wait。等待mLooper.wake
}
(1)关注dispatchOnceInnerLocked的执行
(2)当线程wait时,只有超时或者wake才能触发线程重新执行threadLoop,即重新执行dispatchOnce
d)InputDispatcher.dispatchOnceInnerLocked
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
···
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) {//如果队列为null,则最后直接return
···
if (!mPendingEvent) {
return;
}
} else {
//从队列mInboundQueue取出对象
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
//pokeUserActivityLocked最后回到PowerManagerService.userActivityFromNative
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
resetANRTimeoutsLocked();
}
···
switch (mPendingEvent->type) {
···
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
···
//分发按键事件
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
···
//分发触摸事件
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime);
break;
}
default:
ALOG_ASSERT(false);
break;
}
if (done) {
···
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
(1)关注队列mInboundQueue。这里的数据来源由InputReader传递而来
(2)根据TYPE类型,执行触摸或按键事件
e-1)以按键事件为例,分析来自InputReader的数据
11)InputDispatcher.notifyKey
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
···
//mPolicy即NativeInputManager,回调到InputManagerService.interceptKeyBeforeQueueing
//即由PhoneWindowManager.interceptKeyBeforeQueueing实现
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {//过滤器
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
int32_t repeatCount = 0;
//创建KeyEntry对象
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
//将newEntry插入队列
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {//是否唤醒InputDispatcherThread线程
mLooper->wake();
}
}
12)InputDispatcher.enqueueInboundEventLocked
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty();
//将entry放入mInboundQueue队列
mInboundQueue.enqueueAtTail(entry);
···
switch (entry->type) {
case EventEntry::TYPE_KEY: {
···
break;
}
case EventEntry::TYPE_MOTION: {
···
break;
}
}
return needWake;
}
13)调用mLooper->wake(),则回到InputDispatcher.dispatchOnce
14)执行InputDispatcher.dispatchKeyLocked
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
···
// Give the policy a chance to intercept the key.
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
//拦截事件分析
CommandEntry* commandEntry = postCommandLocked(
& InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
if (mFocusedWindowHandle != NULL) {
commandEntry->inputWindowHandle = mFocusedWindowHandle;
}
commandEntry->keyEntry = entry;
entry->refCount += 1;
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
if (*dropReason == DROP_REASON_NOT_DROPPED) {
*dropReason = DROP_REASON_POLICY;
}
}
···
//按键分发
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
(1)如果满足拦截条件,则将对象插入mCommandQueue队列中,从而回到dispatchOnce调用函数runCommandsLockedInterruptible,从而达到PhoneWindowManager.interceptKeyBeforeDispatching的业务实现
(2)如果PhoneWindowManager拦截成功了,则按键不再继续分发;如果没有拦截,则通过dispatchOnce的循环执行,再进行dispatchEventLocked分发,此时entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP
15)InputDispatcher.dispatchEventLocked进行数据分发
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
···
//pokeUserActivityLocked最后回到PowerManagerService.userActivityFromNative
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
//socket通信
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
···
}
}
}
e-2)以触摸事件为例,分析来自InputReader的数据
此过程与按键流程相差无几,我们重点分析差一点
12)InputDispatcher.notifyMotion
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
···
//mPolicy即NativeInputManager,回调到InputManagerService.interceptMotionBeforeQueueingNonInteractive
//即由PhoneWindowManager.interceptMotionBeforeQueueingNonInteractive实现
mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
bool needWake;
{ // acquire lock
mLock.lock();
···
// Just enqueue a new motion event.
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, args->actionButton, args->flags,
args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
//加入队列
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {//唤醒线程
mLooper->wake();
}
}
(1)触摸事件在PhoneWindowManager中也有对应的方法:interceptMotionBeforeQueueingNonInteractive
12)InputDispatcher.dispatchMotionLocked
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
···
if (isPointerEvent) {//找窗口
// Pointer event. (eg. touchscreen)
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// Non touch event. (eg. trackball)
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
···
//分发触摸事件
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
(1)findTouchedWindowTargetsLocked找关键窗口。此过程很复杂,不做解析
(2)dispatchEventLocked分发触摸事件
总结
1.针对按键事件,反馈到PhoneWindowManager的方法执行顺序如下
(1)interceptKeyBeforeQueueing --> (2)interceptKeyBeforeDispatching --> (3)app:Activity.dispatchKeyEvent
如果(1)拦截了,就不会再执行(2)、(3),如果(2)拦截了,就不会再执行(3),整个过程时串行存在
2.针对触摸事件,反馈到PhoneWindowManager的方法执行顺序如下
(1)interceptMotionBeforeQueueingNonInteractive --> (2)app:Activity.dispatchTouchEvent
这里一般在屏幕黑的情况下做处理
3.不管任何一种事件,都会触发PowerManagerService.userActivityFromNative
主要由Dispatcher.pokeUserActivityLocked执行
参考学习
https://www.jianshu.com/p/debbc56ab2d3
https://www.jianshu.com/p/d4988d632e82
https://blog.csdn.net/aeolia_zhang/article/details/19914467
https://blog.csdn.net/lwz622/article/details/80769351
https://blog.csdn.net/learnrose/article/details/6236890
https://segmentfault.com/a/1190000019032508?utm_source=tag-newest
https://www.jianshu.com/p/f05d6b05ba17
https://blog.csdn.net/lilian0118/article/details/28617185
https://blog.csdn.net/woshihongliu/article/details/82867619
网友评论