基于Android 7.0源码分析
核心服务的类图
- InputManagerService
- 负责管理Android输入子系统
- 封装C++层的InputManager并提供回调
- NativeInputManager
- InputManagerService的JNI实现
- InputManagerService与C++层的InputManager之间的桥梁
- InputManager
- Android系统输入事件处理的核心
- InputReader
- 包含一些列InputMapper
- InputReaderThread
- "InputReader"线程负责读取、预处理原始输入事件以及发送事件到由"InputDispatcherThread"线程管理队列中
- InputDispatcher
- InputDispatcherThread
- "InputDispatcher"线程负责将新的事件异步的发送给应用
- EventHub
- 从系统的输入设备获取事件,管理输入设备
核心服务的创建
下面从InputManagerService
的创建开始分析
......
// 添加Systrace以及system log
traceBeginAndSlog("StartInputManagerService");
// context为systemserver的上下文
inputManager = new InputManagerService(context);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
......
下面看InputManagerService
的构造函数
public InputManagerService(Context context) {
this.mContext = context;
// 创建InputManagerHandler用于与"android.display"线程通信
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
+ mUseDevInputEventForAudioJack);
// 创建NativeInputManager
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
// 添加LocalService到LocalServices,用于SystemServer内部通信
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
下面看nativeInit
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// 这里messageQueue为"android.display"线程的消息队列
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 创建NativeInputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
下面看NativeInputManager
的创建
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
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;
}
mInteractive = true;
// 创建EventHub
sp<EventHub> eventHub = new EventHub();
// 创建InputManager
mInputManager = new InputManager(eventHub, this, this);
}
首先看EventHub
的构造函数,然后看InputManager
的创建
EventHub::EventHub(void) :
mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
mOpeningDevices(0), mClosingDevices(0),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false), mNeedToScanDevices(true),
mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
// 创建epoll监听文件描述符
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno);
// 创建通知事件队列
mINotifyFd = inotify_init();
// 创建观察者监视DEVICE_PATH(/dev/input)下的设备文件的创建与删除
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d",
DEVICE_PATH, errno);
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
eventItem.data.u32 = EPOLL_ID_INOTIFY;
// 监听mINotifyFd
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
int wakeFds[2];
// 创建pipe用于主动唤醒EventHub
result = pipe(wakeFds);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d",
errno);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
errno);
eventItem.data.u32 = EPOLL_ID_WAKE;
// 监听mWakeReadPipeFd
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
errno);
int major, minor;
getLinuxRelease(&major, &minor);
// EPOLLWAKEUP was introduced in kernel 3.5
mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);
}
至此,EventHub
还没有监听特定的输入设备文件描述符。下面看InputManager
的创建
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 创建InputDispatcher,dispatcherPolicy引用NativeInputManager
mDispatcher = new InputDispatcher(dispatcherPolicy);
// 创建InputReader, readerPolicy引用NativeInputManager
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
// 创建InputDispatcherThread以及InputReaderThread
initialize();
}
小结
- 策略模式
- 代理模式
核心服务的启动
下面从InputManagerService
的start()
开始分析
......
// wm.getInputMonitor()返回InputMonitor对象
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
// 调用InputManagerService的start方法
inputManager.start();
......
public void start() {
Slog.i(TAG, "Starting input manager");
// 调用nativeStart,mPtr为NativeInputManager对象的地址
nativeStart(mPtr);
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
// 监听Setting数据库的改变
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
// 注册广播接收机,接收用户切换广播
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
// 获取Setting数据库信息
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
下面看NativeStart()
的实现
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// 调用InputManager的start方法
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
下面看InputManager
的start()
实现
status_t InputManager::start() {
// 启动InputDispatcher线程
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
// 启动InputReader线程
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputReader thread due to error %d.", result);
mDispatcherThread->requestExit();
return result;
}
return OK;
}
至此,EventHub还不能接收输入事件,当InputReader线程启动后会请求EventHub扫描、添加输入设备,下面分析InputReader启动后,EventHub扫描、添加输入设备的过程。
我们从InputReaderThread
的threadLoop()
开始分析。
bool InputReaderThread::threadLoop() {
// 调用InputReader的loopOnce()
mReader->loopOnce();
// 返回值为true,循环调用
return true;
}
下面看InputReader
的loopOnce()
实现
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
......
// 读取输入事件,返回读取的事件数
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {
// 处理输入事件
processEventsLocked(mEventBuffer, count);
}
......
}
......
// 通知InputDispatcherThread分发事件
mQueuedListener->flush();
}
下面首先分析EventHub
的getEvents()
方法,然后看InputReader
的processEventsLocked
方法。
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
AutoMutex _l(mLock);
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
......
// 首次进入mNeedToScanDevices为true,扫描设备
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
// 构造设备添加事件,mOpeningDevices指向设备链表头
while (mOpeningDevices != NULL) {
Device* device = mOpeningDevices;
ALOGV("Reporting device opened: id=%d, name=%s\n",
device->id, device->path.string());
mOpeningDevices = device->next;
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED;
event += 1;
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
// 添加设备扫描完成事件
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
event->when = now;
event->type = FINISHED_DEVICE_SCAN;
event += 1;
if (--capacity == 0) {
break;
}
}
......
// 有事件立即返回
if (event != buffer || awoken) {
break;
}
......
}
// All done, return the number of events we read.
return event - buffer;
}
下面看scanDevicesLocked()
的实现
void EventHub::scanDevicesLocked() {
// 扫描/dev/input下的输入设备
status_t res = scanDirLocked(DEVICE_PATH);
if(res < 0) {
ALOGE("scan dir failed for %s\n", DEVICE_PATH);
}
// 创建虚拟按键设备
if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
createVirtualKeyboardLocked();
}
}
下面看scanDirLocked()
的实现
status_t EventHub::scanDirLocked(const char *dirname)
{
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
openDeviceLocked(devname);
}
closedir(dir);
return 0;
}
scanDirLocked()
的实现相对简单,扫描/dev/input目录下的设备文件,并打开合法的文件。下面看openDeviceLocked()
的实现。
status_t EventHub::openDeviceLocked(const char *devicePath) {
char buffer[80];
ALOGV("Opening device: %s", devicePath);
// 打开设备
int fd = open(devicePath, O_RDWR | O_CLOEXEC);
......
// Get device name.
// 获取设备名
if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
//fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name.setTo(buffer);
}
......
// Check to see if the device is on our excluded list
// 检查设备是否在排除列表中
for (size_t i = 0; i < mExcludedDevices.size(); i++) {
const String8& item = mExcludedDevices.itemAt(i);
if (identifier.name == item) {
ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
close(fd);
return -1;
}
}
......
// 创建设备对象分配设备id
// Allocate device. (The device object takes ownership of the fd at this point.)
int32_t deviceId = mNextDeviceId++;
Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
......
// Load the configuration file for the device.
// 加载设备配置文件(*.idc)
loadConfigurationLocked(device);
// Figure out the kinds of events the device reports.
// 设置输入设备驱动上报的事件类型
// EV_KEY 按键事件,EV_ABS 绝对坐标,如Touch事件
ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
ioctl(fd, EVIOCGBIT(EV_FF, sizeof(device->ffBitmask)), device->ffBitmask);
ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);
......
// Register with epoll.
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
if (mUsingEpollWakeup) {
eventItem.events |= EPOLLWAKEUP;
}
eventItem.data.u32 = deviceId;
// 设备文件描述符添加到EventHub的epoll
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
delete device;
return -1;
}
......
// 设备添加到EventHub的mDevices中
addDeviceLocked(device);
return 0;
}
EventHub扫描完输入设备后,产生一系列设备添加事件,下面看InputReader
处理设备添加事件。回到InputReader
的loopOnce()
中看processEventsLocked
的实现。
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
// 普通的输入事件,同一设备的事件作为一个batch
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
ALOGD("BatchSize: %d Count: %d", batchSize, count);
#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
// 处理设备添加
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
// 处理设备扫描完成
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
下面重点看设备添加事件处理函数addDeviceLocked()
的实现
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex >= 0) {
ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
return;
}
// 从EventHub获取设备信息
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
// 创建输入设备并添加相应的InputMapper
InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
if (device->isIgnored()) {
ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
identifier.name.string());
} else {
ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
identifier.name.string(), device->getSources());
}
// 添加到mDevices中
mDevices.add(deviceId, device);
bumpGenerationLocked();
......
}
下面看createDeviceLocked()
的实现
InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, uint32_t classes) {
// 创建InputDevice
InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
controllerNumber, identifier, classes);
......
// Keyboard-like devices.
// 类键盘设备添加InputMapper
uint32_t keyboardSource = 0;
// 普通的按键类型
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
// 普通的按键keyboardSource
keyboardSource |= AINPUT_SOURCE_KEYBOARD;
}
if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
}
if (classes & INPUT_DEVICE_CLASS_DPAD) {
keyboardSource |= AINPUT_SOURCE_DPAD;
}
if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
keyboardSource |= AINPUT_SOURCE_GAMEPAD;
}
if (keyboardSource != 0) {
device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
}
// Cursor-like devices.
// 类Cursor(鼠标或者traceball)设备添加InputMapper
if (classes & INPUT_DEVICE_CLASS_CURSOR) {
device->addMapper(new CursorInputMapper(device));
}
// Touchscreens and touchpad devices.
// 触摸屏、触控板设备添加InputMapper
if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
// 通常为MultiTouch
device->addMapper(new MultiTouchInputMapper(device));
} else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
device->addMapper(new SingleTouchInputMapper(device));
}
......
}
InputMapper负责加工原始的输入事件,一个输入设备可以关联多个InputMapper,这样可以处理不同类型的事件。
至此,Input核心服务启动完成,接下来EventHub就可以监听驱动上报的输入事件了。
网友评论