Merge "Fix drag and drop (1/3)"
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index a19fe17..6ea1270 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -268,7 +268,11 @@
AHardwareBuffer_Desc trialDesc = *desc;
trialDesc.width = 4;
trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4;
- trialDesc.layers = desc->layers == 1 ? 1 : 2;
+ if (desc->usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) {
+ trialDesc.layers = desc->layers == 6 ? 6 : 12;
+ } else {
+ trialDesc.layers = desc->layers == 1 ? 1 : 2;
+ }
AHardwareBuffer* trialBuffer = nullptr;
int result = AHardwareBuffer_allocate(&trialDesc, &trialBuffer);
if (result == NO_ERROR) {
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 0d8d34f..843eb37 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -22,6 +22,7 @@
shared_libs: [
"libinputflinger_base",
+ "libinputreporter",
"libinputreader",
"libbase",
"libbinder",
@@ -125,6 +126,35 @@
],
}
+cc_library_shared {
+ name: "libinputreporter",
+
+ srcs: [
+ "InputReporter.cpp",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "liblog",
+ "libutils",
+ ],
+
+ header_libs: [
+ "libinputflinger_headers",
+ ],
+
+ export_header_lib_headers: [
+ "libinputflinger_headers",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+}
+
subdirs = [
"host",
"tests",
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index b2d2f14..18c3ded 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -220,7 +220,6 @@
// --- EventHub ---
-const int EventHub::EPOLL_SIZE_HINT;
const int EventHub::EPOLL_MAX_EVENTS;
EventHub::EventHub(void) :
@@ -762,13 +761,27 @@
return nullptr;
}
+/**
+ * The file descriptor could be either input device, or a video device (associated with a
+ * specific input device). Check both cases here, and return the device that this event
+ * belongs to. Caller can compare the fd's once more to determine event type.
+ * Looks through all input devices, and only attached video devices. Unattached video
+ * devices are ignored.
+ */
EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->fd == fd) {
+ // This is an input device event
+ return device;
+ }
+ if (device->videoDevice && device->videoDevice->getFd() == fd) {
+ // This is a video device event
return device;
}
}
+ // We do not check mUnattachedVideoDevices here because they should not participate in epoll,
+ // and therefore should never be looked up by fd.
return nullptr;
}
@@ -874,12 +887,33 @@
}
Device* device = getDeviceByFdLocked(eventItem.data.fd);
- if (device == nullptr) {
- ALOGW("Received unexpected epoll event 0x%08x for unknown device fd %d.",
+ if (!device) {
+ ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.",
eventItem.events, eventItem.data.fd);
+ ALOG_ASSERT(!DEBUG);
continue;
}
-
+ if (device->videoDevice && eventItem.data.fd == device->videoDevice->getFd()) {
+ if (eventItem.events & EPOLLIN) {
+ size_t numFrames = device->videoDevice->readAndQueueFrames();
+ if (numFrames == 0) {
+ ALOGE("Received epoll event for video device %s, but could not read frame",
+ device->videoDevice->getName().c_str());
+ }
+ } else if (eventItem.events & EPOLLHUP) {
+ // TODO(b/121395353) - consider adding EPOLLRDHUP
+ ALOGI("Removing video device %s due to epoll hang-up event.",
+ device->videoDevice->getName().c_str());
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+ device->videoDevice = nullptr;
+ } else {
+ ALOGW("Received unexpected epoll event 0x%08x for device %s.",
+ eventItem.events, device->videoDevice->getName().c_str());
+ ALOG_ASSERT(!DEBUG);
+ }
+ continue;
+ }
+ // This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
@@ -994,6 +1028,16 @@
return event - buffer;
}
+std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
+ AutoMutex _l(mLock);
+
+ Device* device = getDeviceLocked(deviceId);
+ if (!device || !device->videoDevice) {
+ return {};
+ }
+ return device->videoDevice->consumeFrames();
+}
+
void EventHub::wake() {
ALOGV("wake() called");
@@ -1044,6 +1088,7 @@
};
status_t EventHub::registerFdForEpoll(int fd) {
+ // TODO(b/121395353) - consider adding EPOLLRDHUP
struct epoll_event eventItem = {};
eventItem.events = EPOLLIN | EPOLLWAKEUP;
eventItem.data.fd = fd;
@@ -1072,10 +1117,21 @@
status_t result = registerFdForEpoll(device->fd);
if (result != OK) {
ALOGE("Could not add input device fd to epoll for device %" PRId32, device->id);
+ return result;
+ }
+ if (device->videoDevice) {
+ registerVideoDeviceForEpollLocked(*device->videoDevice);
}
return result;
}
+void EventHub::registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice) {
+ status_t result = registerFdForEpoll(videoDevice.getFd());
+ if (result != OK) {
+ ALOGE("Could not add video device %s to epoll", videoDevice.getName().c_str());
+ }
+}
+
status_t EventHub::unregisterDeviceFromEpollLocked(Device* device) {
if (device->hasValidFd()) {
status_t result = unregisterFdFromEpoll(device->fd);
@@ -1084,10 +1140,23 @@
return result;
}
}
+ if (device->videoDevice) {
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
+ }
return OK;
}
-status_t EventHub::openDeviceLocked(const char *devicePath) {
+void EventHub::unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice) {
+ if (videoDevice.hasValidFd()) {
+ status_t result = unregisterFdFromEpoll(videoDevice.getFd());
+ if (result != OK) {
+ ALOGW("Could not remove video device fd from epoll for device: %s",
+ videoDevice.getName().c_str());
+ }
+ }
+}
+
+status_t EventHub::openDeviceLocked(const char* devicePath) {
char buffer[80];
ALOGV("Opening device: %s", devicePath);
@@ -1345,6 +1414,7 @@
}
// Find a matching video device by comparing device names
+ // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
if (device->identifier.name == videoDevice->getName()) {
device->videoDevice = std::move(videoDevice);
@@ -1422,6 +1492,9 @@
Device* device = mDevices.valueAt(i);
if (videoDevice->getName() == device->identifier.name) {
device->videoDevice = std::move(videoDevice);
+ if (device->enabled) {
+ registerVideoDeviceForEpollLocked(*device->videoDevice);
+ }
return;
}
}
@@ -1632,6 +1705,7 @@
for (size_t i = 0; i < mDevices.size(); i++) {
Device* device = mDevices.valueAt(i);
if (device->videoDevice && device->videoDevice->getPath() == devicePath) {
+ unregisterVideoDeviceFromEpollLocked(*device->videoDevice);
device->videoDevice = nullptr;
return;
}
@@ -1662,6 +1736,7 @@
unregisterDeviceFromEpollLocked(device);
if (device->videoDevice) {
+ // This must be done after the video device is removed from epoll
mUnattachedVideoDevices.push_back(std::move(device->videoDevice));
}
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 7fa9cb6..6173452 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -257,6 +257,7 @@
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
mLooper = new Looper(false);
+ mReporter = createInputReporter();
mKeyRepeatState.lastKeyEntry = nullptr;
@@ -841,6 +842,7 @@
if (*dropReason != DROP_REASON_NOT_DROPPED) {
setInjectionResultLocked(entry, *dropReason == DROP_REASON_POLICY
? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
+ mReporter->reportDroppedKey(entry->sequenceNum);
return true;
}
@@ -4025,6 +4027,10 @@
bool InputDispatcher::afterKeyEventLockedInterruptible(const sp<Connection>& connection,
DispatchEntry* dispatchEntry, KeyEntry* keyEntry, bool handled) {
if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
+ if (!handled) {
+ // Report the key as unhandled, since the fallback was not handled.
+ mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+ }
return false;
}
@@ -4192,6 +4198,9 @@
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Unhandled key event: No fallback key.");
#endif
+
+ // Report the key as unhandled, since there is no fallback key.
+ mReporter->reportUnhandledKey(keyEntry->sequenceNum);
}
}
return false;
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 05b5dad..7e6de6a 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -37,6 +37,7 @@
#include <unordered_map>
#include "InputListener.h"
+#include "InputReporter.h"
namespace android {
@@ -1186,6 +1187,8 @@
void traceInboundQueueLengthLocked();
void traceOutboundQueueLengthLocked(const sp<Connection>& connection);
void traceWaitQueueLengthLocked(const sp<Connection>& connection);
+
+ sp<InputReporter> mReporter;
};
/* Enqueues and dispatches input events, endlessly. */
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 73fcb11..3d5f1d9 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -6483,11 +6483,13 @@
}
}
- NotifyMotionArgs args(mContext->getNextSequenceNum(), when, getDeviceId(),
+ const int32_t deviceId = getDeviceId();
+ std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
+ NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId,
source, mViewport.displayId, policyFlags,
action, actionButton, flags, metaState, buttonState, edgeFlags,
deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
- xPrecision, yPrecision, downTime, /* videoFrames */ {});
+ xPrecision, yPrecision, downTime, std::move(frames));
getListener()->notifyMotion(&args);
}
diff --git a/services/inputflinger/InputReporter.cpp b/services/inputflinger/InputReporter.cpp
new file mode 100644
index 0000000..cf4220f
--- /dev/null
+++ b/services/inputflinger/InputReporter.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "InputReporter.h"
+
+namespace android {
+
+// --- InputReporter ---
+
+void InputReporter::reportUnhandledKey(uint32_t sequenceNum) {
+ // do nothing
+}
+
+void InputReporter::reportDroppedKey(uint32_t sequenceNum) {
+ // do nothing
+}
+
+sp<InputReporter> createInputReporter() {
+ return new InputReporter();
+}
+
+} // namespace android
diff --git a/services/inputflinger/include/EventHub.h b/services/inputflinger/include/EventHub.h
index ae70169..295aca8 100644
--- a/services/inputflinger/include/EventHub.h
+++ b/services/inputflinger/include/EventHub.h
@@ -211,6 +211,7 @@
* Returns the number of events obtained, or 0 if the timeout expired.
*/
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
/*
* Query current input state.
@@ -303,6 +304,7 @@
const int32_t* keyCodes, uint8_t* outFlags) const;
virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize);
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId);
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const;
virtual bool hasLed(int32_t deviceId, int32_t led) const;
@@ -381,7 +383,7 @@
}
};
- status_t openDeviceLocked(const char *devicePath);
+ status_t openDeviceLocked(const char* devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
void createVirtualKeyboardLocked();
void addDeviceLocked(Device* device);
@@ -400,7 +402,9 @@
status_t registerFdForEpoll(int fd);
status_t unregisterFdFromEpoll(int fd);
status_t registerDeviceForEpollLocked(Device* device);
+ void registerVideoDeviceForEpollLocked(const TouchVideoDevice& videoDevice);
status_t unregisterDeviceFromEpollLocked(Device* device);
+ void unregisterVideoDeviceFromEpollLocked(const TouchVideoDevice& videoDevice);
status_t scanDirLocked(const char *dirname);
status_t scanVideoDirLocked(const std::string& dirname);
@@ -410,6 +414,10 @@
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
Device* getDeviceByPathLocked(const char* devicePath) const;
+ /**
+ * Look through all available fd's (both for input devices and for video devices),
+ * and return the device pointer.
+ */
Device* getDeviceByFdLocked(int fd) const;
bool hasKeycodeLocked(Device* device, int keycode) const;
@@ -470,9 +478,6 @@
int mInputWd;
int mVideoWd;
- // Epoll FD list size hint.
- static const int EPOLL_SIZE_HINT = 8;
-
// Maximum number of signalled FDs to handle at a time.
static const int EPOLL_MAX_EVENTS = 16;
diff --git a/services/inputflinger/include/InputReporter.h b/services/inputflinger/include/InputReporter.h
new file mode 100644
index 0000000..c86dcda
--- /dev/null
+++ b/services/inputflinger/include/InputReporter.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUT_REPORTER_H
+#define _UI_INPUT_REPORTER_H
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+/*
+ * The interface used by the InputDispatcher to report information about input events after
+ * it is sent to the application, such as if a key is unhandled or dropped.
+ */
+class InputReporter: public virtual RefBase {
+protected:
+ virtual ~InputReporter() { }
+
+public:
+ // Report a key that was not handled by the system or apps.
+ // A key event is unhandled if:
+ // - The event was not handled and there is no fallback key; or
+ // - The event was not handled and it has a fallback key,
+ // but the fallback key was not handled.
+ virtual void reportUnhandledKey(uint32_t sequenceNum);
+
+ // Report a key that was dropped by InputDispatcher.
+ // A key can be dropped for several reasons. See the enum
+ // InputDispatcher::DropReason for details.
+ virtual void reportDroppedKey(uint32_t sequenceNum);
+};
+
+/*
+ * Factory method for InputReporter.
+ */
+sp<InputReporter> createInputReporter();
+
+} // namespace android
+
+#endif // _UI_INPUT_REPORTER_H
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index b5d2090..d39d8dc 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -692,6 +692,10 @@
return 1;
}
+ virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) {
+ return {};
+ }
+
virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
Device* device = getDevice(deviceId);
if (device) {