Merge "Use ro.board.api_level instead of ro.vndk.version" into main
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a351811..922b0dd 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -3122,12 +3122,12 @@
return statusTFromBinderStatus(status);
}
-status_t ScreenshotClient::captureDisplay(DisplayId displayId,
+status_t ScreenshotClient::captureDisplay(DisplayId displayId, const gui::CaptureArgs& captureArgs,
const sp<IScreenCaptureListener>& captureListener) {
sp<gui::ISurfaceComposer> s(ComposerServiceAIDL::getComposerService());
if (s == nullptr) return NO_INIT;
- binder::Status status = s->captureDisplayById(displayId.value, captureListener);
+ binder::Status status = s->captureDisplayById(displayId.value, captureArgs, captureListener);
return statusTFromBinderStatus(status);
}
diff --git a/libs/gui/aidl/android/gui/CaptureArgs.aidl b/libs/gui/aidl/android/gui/CaptureArgs.aidl
new file mode 100644
index 0000000..920d949
--- /dev/null
+++ b/libs/gui/aidl/android/gui/CaptureArgs.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package android.gui;
+
+parcelable CaptureArgs cpp_header "gui/DisplayCaptureArgs.h";
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 4a2e0b9..d24f8ee 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -16,6 +16,7 @@
package android.gui;
+import android.gui.CaptureArgs;
import android.gui.Color;
import android.gui.CompositionPreference;
import android.gui.ContentSamplingAttributes;
@@ -238,7 +239,8 @@
* Capture the specified screen. This requires the READ_FRAME_BUFFER
* permission.
*/
- oneway void captureDisplayById(long displayId, IScreenCaptureListener listener);
+ oneway void captureDisplayById(long displayId, in CaptureArgs args,
+ IScreenCaptureListener listener);
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index b0253cc..ffe7e41 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -100,8 +100,8 @@
MOCK_METHOD(binder::Status, setGameContentType, (const sp<IBinder>&, bool), (override));
MOCK_METHOD(binder::Status, captureDisplay,
(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
- MOCK_METHOD(binder::Status, captureDisplayById, (int64_t, const sp<IScreenCaptureListener>&),
- (override));
+ MOCK_METHOD(binder::Status, captureDisplayById,
+ (int64_t, const gui::CaptureArgs&, const sp<IScreenCaptureListener>&), (override));
MOCK_METHOD(binder::Status, captureLayers,
(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
MOCK_METHOD(binder::Status, clearAnimationFrameStats, (), (override));
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 54c3aa7..5bf6c47 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -841,8 +841,14 @@
class ScreenshotClient {
public:
static status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
- static status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
+ static status_t captureDisplay(DisplayId, const gui::CaptureArgs&,
+ const sp<IScreenCaptureListener>&);
static status_t captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
+
+ [[deprecated]] static status_t captureDisplay(DisplayId id,
+ const sp<IScreenCaptureListener>& listener) {
+ return captureDisplay(id, gui::CaptureArgs(), listener);
+ }
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ec01189..60221aa 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -786,7 +786,8 @@
return binder::Status::ok();
}
- binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override {
+ binder::Status captureDisplayById(int64_t, const gui::CaptureArgs&,
+ const sp<IScreenCaptureListener>&) override {
return binder::Status::ok();
}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 3672387..a807d82 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -62,3 +62,10 @@
description: "Disable touch rejection when the stylus hovers the screen"
bug: "301216095"
}
+
+flag {
+ name: "enable_input_filter_rust_impl"
+ namespace: "input"
+ description: "Enable input filter rust implementation"
+ bug: "294546335"
+}
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 55a2682..1ada33e 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -64,11 +64,6 @@
return false;
}
-bool needsAndroidPEglMitigation() {
- static const int32_t vndk_version = base::GetIntProperty("ro.vndk.version", -1);
- return vndk_version <= 28;
-}
-
int egl_get_init_count(EGLDisplay dpy) {
egl_display_t* eglDisplay = egl_display_t::get(dpy);
return eglDisplay ? eglDisplay->getRefsCount() : 0;
@@ -365,14 +360,6 @@
if (len) {
// NOTE: we could avoid the copy if we had strnstr.
const std::string ext(start, len);
- // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
- // some Android P vendor partitions this extension under the draft KHR name,
- // but during Khronos review it was decided to demote it to EXT.
- if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
- findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
- mExtensionString.append("EGL_EXT_image_gl_colorspace ");
- }
-
if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
mExtensionString.append(ext + " ");
}
diff --git a/opengl/libs/EGL/egl_display.h b/opengl/libs/EGL/egl_display.h
index 87c2176..867a117 100644
--- a/opengl/libs/EGL/egl_display.h
+++ b/opengl/libs/EGL/egl_display.h
@@ -39,7 +39,6 @@
struct egl_connection_t;
bool findExtension(const char* exts, const char* name, size_t nameLen = 0);
-bool needsAndroidPEglMitigation();
class EGLAPI egl_display_t { // marked as EGLAPI for testing purposes
static std::map<EGLDisplay, std::unique_ptr<egl_display_t>> displayMap;
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 440eb17..a6af713 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -1644,26 +1644,6 @@
const egl_display_t* dp = validate_display(dpy);
if (!dp) return EGL_NO_IMAGE_KHR;
- std::vector<AttrType> strippedAttribs;
- if (needsAndroidPEglMitigation()) {
- // Mitigation for Android P vendor partitions: eglImageCreateKHR should accept
- // EGL_GL_COLORSPACE_LINEAR_KHR, EGL_GL_COLORSPACE_SRGB_KHR and
- // EGL_GL_COLORSPACE_DEFAULT_EXT if EGL_EXT_image_gl_colorspace is supported,
- // but some drivers don't like the DEFAULT value and generate an error.
- for (const AttrType* attr = attrib_list; attr && attr[0] != EGL_NONE; attr += 2) {
- if (attr[0] == EGL_GL_COLORSPACE_KHR &&
- dp->haveExtension("EGL_EXT_image_gl_colorspace")) {
- if (attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR &&
- attr[1] != EGL_GL_COLORSPACE_SRGB_KHR) {
- continue;
- }
- }
- strippedAttribs.push_back(attr[0]);
- strippedAttribs.push_back(attr[1]);
- }
- strippedAttribs.push_back(EGL_NONE);
- }
-
ContextRef _c(dp, ctx);
egl_context_t* const c = _c.get();
@@ -1671,8 +1651,7 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && eglCreateImageFunc) {
result = eglCreateImageFunc(dp->disp.dpy, c ? c->context : EGL_NO_CONTEXT, target, buffer,
- needsAndroidPEglMitigation() ? strippedAttribs.data()
- : attrib_list);
+ attrib_list);
}
return result;
}
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index b5f5df9..45c9b5c 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -76,6 +76,7 @@
srcs: [
"InputCommonConverter.cpp",
"InputDeviceMetricsCollector.cpp",
+ "InputFilter.cpp",
"InputProcessor.cpp",
"PointerChoreographer.cpp",
"PreferStylusOverTouchBlocker.cpp",
diff --git a/services/inputflinger/InputFilter.cpp b/services/inputflinger/InputFilter.cpp
new file mode 100644
index 0000000..1b8fad3
--- /dev/null
+++ b/services/inputflinger/InputFilter.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#define LOG_TAG "InputFilter"
+
+#include "InputFilter.h"
+
+namespace android {
+
+using aidl::com::android::server::inputflinger::IInputFilter;
+using AidlKeyEvent = aidl::com::android::server::inputflinger::KeyEvent;
+
+AidlKeyEvent notifyKeyArgsToKeyEvent(const NotifyKeyArgs& args) {
+ AidlKeyEvent event;
+ event.id = args.id;
+ event.eventTime = args.eventTime;
+ event.deviceId = args.deviceId;
+ event.source = args.source;
+ event.displayId = args.displayId;
+ event.policyFlags = args.policyFlags;
+ event.action = args.action;
+ event.flags = args.flags;
+ event.keyCode = args.keyCode;
+ event.scanCode = args.scanCode;
+ event.metaState = args.metaState;
+ event.downTime = args.downTime;
+ event.readTime = args.readTime;
+ return event;
+}
+
+NotifyKeyArgs keyEventToNotifyKeyArgs(const AidlKeyEvent& event) {
+ return NotifyKeyArgs(event.id, event.eventTime, event.readTime, event.deviceId, event.source,
+ event.displayId, event.policyFlags, event.action, event.flags,
+ event.keyCode, event.scanCode, event.metaState, event.downTime);
+}
+
+namespace {
+
+class RustCallbacks : public IInputFilter::BnInputFilterCallbacks {
+public:
+ RustCallbacks(InputListenerInterface& nextListener) : mNextListener(nextListener) {}
+ ndk::ScopedAStatus sendKeyEvent(const AidlKeyEvent& event) override {
+ mNextListener.notifyKey(keyEventToNotifyKeyArgs(event));
+ return ndk::ScopedAStatus::ok();
+ }
+
+private:
+ InputListenerInterface& mNextListener;
+};
+
+} // namespace
+
+InputFilter::InputFilter(InputListenerInterface& listener, IInputFlingerRust& rust)
+ : mNextListener(listener), mCallbacks(ndk::SharedRefBase::make<RustCallbacks>(listener)) {
+ LOG_ALWAYS_FATAL_IF(!rust.createInputFilter(mCallbacks, &mInputFilterRust).isOk());
+ LOG_ALWAYS_FATAL_IF(!mInputFilterRust);
+}
+
+void InputFilter::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
+ if (isFilterEnabled()) {
+ std::vector<int32_t> deviceIds;
+ for (auto info : args.inputDeviceInfos) {
+ deviceIds.push_back(info.getId());
+ }
+ LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyInputDevicesChanged(deviceIds).isOk());
+ }
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifyKey(const NotifyKeyArgs& args) {
+ if (!isFilterEnabled()) {
+ mNextListener.notifyKey(args);
+ return;
+ }
+ LOG_ALWAYS_FATAL_IF(!mInputFilterRust->notifyKey(notifyKeyArgsToKeyEvent(args)).isOk());
+}
+
+void InputFilter::notifyMotion(const NotifyMotionArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifySwitch(const NotifySwitchArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifySensor(const NotifySensorArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifyVibratorState(const NotifyVibratorStateArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
+ mNextListener.notify(args);
+}
+
+void InputFilter::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) {
+ mNextListener.notify(args);
+}
+
+bool InputFilter::isFilterEnabled() {
+ bool result;
+ LOG_ALWAYS_FATAL_IF(!mInputFilterRust->isEnabled(&result).isOk());
+ return result;
+}
+
+void InputFilter::dump(std::string& dump) {
+ dump += "InputFilter:\n";
+}
+
+} // namespace android
diff --git a/services/inputflinger/InputFilter.h b/services/inputflinger/InputFilter.h
new file mode 100644
index 0000000..699f3a0
--- /dev/null
+++ b/services/inputflinger/InputFilter.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 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.
+ */
+
+#pragma once
+
+#include <aidl/com/android/server/inputflinger/IInputFlingerRust.h>
+#include "InputListener.h"
+#include "NotifyArgs.h"
+
+namespace android {
+
+/**
+ * The C++ component of InputFilter designed as a wrapper around the rust implementation.
+ */
+class InputFilterInterface : public InputListenerInterface {
+public:
+ /**
+ * This method may be called on any thread (usually by the input manager on a binder thread).
+ */
+ virtual void dump(std::string& dump) = 0;
+};
+
+class InputFilter : public InputFilterInterface {
+public:
+ using IInputFlingerRust = aidl::com::android::server::inputflinger::IInputFlingerRust;
+ using IInputFilter = aidl::com::android::server::inputflinger::IInputFilter;
+ using IInputFilterCallbacks =
+ aidl::com::android::server::inputflinger::IInputFilter::IInputFilterCallbacks;
+
+ explicit InputFilter(InputListenerInterface& listener, IInputFlingerRust&);
+ ~InputFilter() override = default;
+ void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
+ void notifyKey(const NotifyKeyArgs& args) override;
+ void notifyMotion(const NotifyMotionArgs& args) override;
+ void notifySwitch(const NotifySwitchArgs& args) override;
+ void notifySensor(const NotifySensorArgs& args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs& args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs& args) override;
+ void dump(std::string& dump) override;
+
+private:
+ InputListenerInterface& mNextListener;
+ std::shared_ptr<IInputFilterCallbacks> mCallbacks;
+ std::shared_ptr<IInputFilter> mInputFilterRust;
+
+ bool isFilterEnabled();
+};
+
+} // namespace android
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 92c65e1..8cf61f9 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -42,6 +42,7 @@
sysprop::InputProperties::enable_input_device_usage_metrics().value_or(true);
const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
+const bool ENABLE_INPUT_FILTER_RUST = input_flags::enable_input_filter_rust_impl();
int32_t exceptionCodeFromStatusT(status_t status) {
switch (status) {
@@ -118,6 +119,7 @@
* The event flow is via the "InputListener" interface, as follows:
* InputReader
* -> UnwantedInteractionBlocker
+ * -> InputFilter
* -> PointerChoreographer
* -> InputProcessor
* -> InputDeviceMetricsCollector
@@ -132,6 +134,12 @@
mTracingStages.emplace_back(
std::make_unique<TracedInputListener>("InputDispatcher", *mDispatcher));
+ if (ENABLE_INPUT_FILTER_RUST) {
+ mInputFilter = std::make_unique<InputFilter>(*mTracingStages.back(), *mInputFlingerRust);
+ mTracingStages.emplace_back(
+ std::make_unique<TracedInputListener>("InputFilter", *mInputFilter));
+ }
+
if (ENABLE_INPUT_DEVICE_USAGE_METRICS) {
mCollector = std::make_unique<InputDeviceMetricsCollector>(*mTracingStages.back());
mTracingStages.emplace_back(
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 20b9fd5..aea7bd5 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -21,6 +21,7 @@
*/
#include "InputDeviceMetricsCollector.h"
+#include "InputFilter.h"
#include "InputProcessor.h"
#include "InputReaderBase.h"
#include "PointerChoreographer.h"
@@ -40,6 +41,7 @@
using android::os::BnInputFlinger;
+using aidl::com::android::server::inputflinger::IInputFilter;
using aidl::com::android::server::inputflinger::IInputFlingerRust;
namespace android {
@@ -137,6 +139,8 @@
std::unique_ptr<UnwantedInteractionBlockerInterface> mBlocker;
+ std::unique_ptr<InputFilterInterface> mInputFilter;
+
std::unique_ptr<PointerChoreographerInterface> mChoreographer;
std::unique_ptr<InputProcessorInterface> mProcessor;
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl
new file mode 100644
index 0000000..44f959e
--- /dev/null
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFilter.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package com.android.server.inputflinger;
+
+import com.android.server.inputflinger.KeyEvent;
+
+/**
+ * A local AIDL interface used as a foreign function interface (ffi) to
+ * filter input events.
+ *
+ * NOTE: Since we use this as a local interface, all processing happens on the
+ * calling thread.
+ */
+interface IInputFilter {
+
+ /** Callbacks for the rust InputFilter to call into C++. */
+ interface IInputFilterCallbacks {
+ /** Sends back a filtered key event */
+ void sendKeyEvent(in KeyEvent event);
+ }
+
+ /** Returns if InputFilter is enabled */
+ boolean isEnabled();
+
+ /** Notifies if a key event occurred */
+ void notifyKey(in KeyEvent event);
+
+ /** Notifies if any InputDevice list changed and provides the list of connected peripherals */
+ void notifyInputDevicesChanged(in int[] deviceIds);
+}
+
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
index 8e826fd..de852c0 100644
--- a/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/IInputFlingerRust.aidl
@@ -16,6 +16,9 @@
package com.android.server.inputflinger;
+import com.android.server.inputflinger.IInputFilter;
+import com.android.server.inputflinger.IInputFilter.IInputFilterCallbacks;
+
/**
* A local AIDL interface used as a foreign function interface (ffi) to
* communicate with the Rust component of inputflinger.
@@ -31,4 +34,7 @@
interface IInputFlingerRustBootstrapCallback {
void onProvideInputFlingerRust(in IInputFlingerRust inputFlingerRust);
}
+
+ /** Create the rust implementation of InputFilter. */
+ IInputFilter createInputFilter(IInputFilterCallbacks callbacks);
}
diff --git a/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl b/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl
new file mode 100644
index 0000000..e213221
--- /dev/null
+++ b/services/inputflinger/aidl/com/android/server/inputflinger/KeyEvent.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package com.android.server.inputflinger;
+
+/**
+ * Analogous to Android's native KeyEvent / NotifyKeyArgs.
+ * Stores the basic information about Key events.
+ */
+parcelable KeyEvent {
+ int id;
+ int deviceId;
+ long downTime;
+ long readTime;
+ long eventTime;
+ int source;
+ int displayId;
+ int policyFlags;
+ int action;
+ int flags;
+ int keyCode;
+ int scanCode;
+ int metaState;
+}
\ No newline at end of file
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 2d1a22b..cc0d49c 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -139,15 +139,15 @@
source(source),
displayId(displayId),
action(action),
- flags(flags),
keyCode(keyCode),
scanCode(scanCode),
metaState(metaState),
- repeatCount(repeatCount),
downTime(downTime),
syntheticRepeat(false),
interceptKeyResult(KeyEntry::InterceptKeyResult::UNKNOWN),
- interceptKeyWakeupTime(0) {
+ interceptKeyWakeupTime(0),
+ flags(flags),
+ repeatCount(repeatCount) {
EventEntry::injectionState = std::move(injectionState);
}
@@ -276,7 +276,7 @@
volatile int32_t DispatchEntry::sNextSeqAtomic;
-DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry,
+DispatchEntry::DispatchEntry(std::shared_ptr<const EventEntry> eventEntry,
ftl::Flags<InputTarget::Flags> targetFlags,
const ui::Transform& transform, const ui::Transform& rawTransform,
float globalScaleFactor)
@@ -287,21 +287,15 @@
rawTransform(rawTransform),
globalScaleFactor(globalScaleFactor),
deliveryTime(0),
- resolvedAction(0),
resolvedFlags(0) {
switch (this->eventEntry->type) {
case EventEntry::Type::KEY: {
- const KeyEntry& keyEntry = static_cast<KeyEntry&>(*this->eventEntry);
- resolvedEventId = keyEntry.id;
- resolvedAction = keyEntry.action;
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*this->eventEntry);
resolvedFlags = keyEntry.flags;
-
break;
}
case EventEntry::Type::MOTION: {
- const MotionEntry& motionEntry = static_cast<MotionEntry&>(*this->eventEntry);
- resolvedEventId = motionEntry.id;
- resolvedAction = motionEntry.action;
+ const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*this->eventEntry);
resolvedFlags = motionEntry.flags;
break;
}
@@ -321,24 +315,9 @@
}
std::ostream& operator<<(std::ostream& out, const DispatchEntry& entry) {
- out << "DispatchEntry{resolvedAction=";
- switch (entry.eventEntry->type) {
- case EventEntry::Type::KEY: {
- out << KeyEvent::actionToString(entry.resolvedAction);
- break;
- }
- case EventEntry::Type::MOTION: {
- out << MotionEvent::actionToString(entry.resolvedAction);
- break;
- }
- default: {
- out << "<invalid, not a key or a motion>";
- break;
- }
- }
std::string transform;
entry.transform.dump(transform, "transform");
- out << ", resolvedFlags=" << entry.resolvedFlags
+ out << "DispatchEntry{resolvedFlags=" << entry.resolvedFlags
<< ", targetFlags=" << entry.targetFlags.string() << ", transform=" << transform
<< "} original: " << entry.eventEntry->getDescription();
return out;
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index d44a211..e2e13c3 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -50,7 +50,7 @@
uint32_t policyFlags;
std::shared_ptr<InjectionState> injectionState;
- bool dispatchInProgress; // initially false, set to true while dispatching
+ mutable bool dispatchInProgress; // initially false, set to true while dispatching
/**
* Injected keys are events from an external (probably untrusted) application
@@ -72,6 +72,8 @@
virtual std::string getDescription() const = 0;
EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags);
+ EventEntry(const EventEntry&) = delete;
+ EventEntry& operator=(const EventEntry&) = delete;
virtual ~EventEntry() = default;
};
@@ -119,11 +121,9 @@
uint32_t source;
int32_t displayId;
int32_t action;
- int32_t flags;
int32_t keyCode;
int32_t scanCode;
int32_t metaState;
- int32_t repeatCount;
nsecs_t downTime;
bool syntheticRepeat; // set to true for synthetic key repeats
@@ -134,8 +134,11 @@
CONTINUE,
TRY_AGAIN_LATER,
};
- InterceptKeyResult interceptKeyResult; // set based on the interception result
- nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
+ // These are special fields that may need to be modified while the event is being dispatched.
+ mutable InterceptKeyResult interceptKeyResult; // set based on the interception result
+ mutable nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
+ mutable int32_t flags;
+ mutable int32_t repeatCount;
KeyEntry(int32_t id, std::shared_ptr<InjectionState> injectionState, nsecs_t eventTime,
int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
@@ -206,7 +209,7 @@
struct DispatchEntry {
const uint32_t seq; // unique sequence number, never 0
- std::shared_ptr<EventEntry> eventEntry; // the event to dispatch
+ std::shared_ptr<const EventEntry> eventEntry; // the event to dispatch
const ftl::Flags<InputTarget::Flags> targetFlags;
ui::Transform transform;
ui::Transform rawTransform;
@@ -217,12 +220,9 @@
// An ANR will be triggered if a response for this entry is not received by timeoutTime
nsecs_t timeoutTime;
- // Set to the resolved ID, action and flags when the event is enqueued.
- int32_t resolvedEventId;
- int32_t resolvedAction;
int32_t resolvedFlags;
- DispatchEntry(std::shared_ptr<EventEntry> eventEntry,
+ DispatchEntry(std::shared_ptr<const EventEntry> eventEntry,
ftl::Flags<InputTarget::Flags> targetFlags, const ui::Transform& transform,
const ui::Transform& rawTransform, float globalScaleFactor);
DispatchEntry(const DispatchEntry&) = delete;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 23ac088..7f4de7a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -295,9 +295,8 @@
}
dump.append(INDENT4);
dump += entry.eventEntry->getDescription();
- dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, resolvedAction=%d, age=%" PRId64
- "ms",
- entry.seq, entry.targetFlags.string().c_str(), entry.resolvedAction,
+ dump += StringPrintf(", seq=%" PRIu32 ", targetFlags=%s, age=%" PRId64 "ms", entry.seq,
+ entry.targetFlags.string().c_str(),
ns2ms(currentTime - entry.eventEntry->eventTime));
if (entry.deliveryTime != 0) {
// This entry was delivered, so add information on how long we've been waiting
@@ -354,7 +353,7 @@
}
std::unique_ptr<DispatchEntry> createDispatchEntry(
- const InputTarget& inputTarget, std::shared_ptr<EventEntry> eventEntry,
+ const InputTarget& inputTarget, std::shared_ptr<const EventEntry> eventEntry,
ftl::Flags<InputTarget::Flags> inputTargetFlags) {
if (inputTarget.useDefaultPointerTransform()) {
const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
@@ -455,10 +454,6 @@
bool shouldReportFinishedEvent(const DispatchEntry& dispatchEntry, const Connection& connection) {
const EventEntry& eventEntry = *dispatchEntry.eventEntry;
const int32_t& inputEventId = eventEntry.id;
- if (inputEventId != dispatchEntry.resolvedEventId) {
- // Event was transmuted
- return false;
- }
if (inputEventId == android::os::IInputConstants::INVALID_INPUT_EVENT_ID) {
return false;
}
@@ -1031,8 +1026,8 @@
}
case EventEntry::Type::FOCUS: {
- std::shared_ptr<FocusEntry> typedEntry =
- std::static_pointer_cast<FocusEntry>(mPendingEvent);
+ std::shared_ptr<const FocusEntry> typedEntry =
+ std::static_pointer_cast<const FocusEntry>(mPendingEvent);
dispatchFocusLocked(currentTime, typedEntry);
done = true;
dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
@@ -1040,7 +1035,7 @@
}
case EventEntry::Type::TOUCH_MODE_CHANGED: {
- const auto typedEntry = std::static_pointer_cast<TouchModeEntry>(mPendingEvent);
+ const auto typedEntry = std::static_pointer_cast<const TouchModeEntry>(mPendingEvent);
dispatchTouchModeChangeLocked(currentTime, typedEntry);
done = true;
dropReason = DropReason::NOT_DROPPED; // touch mode events are never dropped
@@ -1049,22 +1044,23 @@
case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
const auto typedEntry =
- std::static_pointer_cast<PointerCaptureChangedEntry>(mPendingEvent);
+ std::static_pointer_cast<const PointerCaptureChangedEntry>(mPendingEvent);
dispatchPointerCaptureChangedLocked(currentTime, typedEntry, dropReason);
done = true;
break;
}
case EventEntry::Type::DRAG: {
- std::shared_ptr<DragEntry> typedEntry =
- std::static_pointer_cast<DragEntry>(mPendingEvent);
+ std::shared_ptr<const DragEntry> typedEntry =
+ std::static_pointer_cast<const DragEntry>(mPendingEvent);
dispatchDragLocked(currentTime, typedEntry);
done = true;
break;
}
case EventEntry::Type::KEY: {
- std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
+ std::shared_ptr<const KeyEntry> keyEntry =
+ std::static_pointer_cast<const KeyEntry>(mPendingEvent);
if (!REMOVE_APP_SWITCH_DROPS) {
if (isAppSwitchDue) {
if (isAppSwitchKeyEvent(*keyEntry)) {
@@ -1086,8 +1082,8 @@
}
case EventEntry::Type::MOTION: {
- std::shared_ptr<MotionEntry> motionEntry =
- std::static_pointer_cast<MotionEntry>(mPendingEvent);
+ std::shared_ptr<const MotionEntry> motionEntry =
+ std::static_pointer_cast<const MotionEntry>(mPendingEvent);
if (!REMOVE_APP_SWITCH_DROPS) {
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
@@ -1104,8 +1100,8 @@
}
case EventEntry::Type::SENSOR: {
- std::shared_ptr<SensorEntry> sensorEntry =
- std::static_pointer_cast<SensorEntry>(mPendingEvent);
+ std::shared_ptr<const SensorEntry> sensorEntry =
+ std::static_pointer_cast<const SensorEntry>(mPendingEvent);
if (!REMOVE_APP_SWITCH_DROPS) {
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
@@ -1200,7 +1196,7 @@
bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newEntry) {
bool needWake = mInboundQueue.empty();
mInboundQueue.push_back(std::move(newEntry));
- EventEntry& entry = *(mInboundQueue.back());
+ const EventEntry& entry = *(mInboundQueue.back());
traceInboundQueueLengthLocked();
switch (entry.type) {
@@ -1233,7 +1229,7 @@
// time for it may have been handled in the policy and could be dropped.
if (keyEntry.action == AKEY_EVENT_ACTION_UP && mPendingEvent &&
mPendingEvent->type == EventEntry::Type::KEY) {
- KeyEntry& pendingKey = static_cast<KeyEntry&>(*mPendingEvent);
+ const KeyEntry& pendingKey = static_cast<const KeyEntry&>(*mPendingEvent);
if (pendingKey.keyCode == keyEntry.keyCode &&
pendingKey.interceptKeyResult ==
KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER) {
@@ -1248,7 +1244,7 @@
case EventEntry::Type::MOTION: {
LOG_ALWAYS_FATAL_IF((entry.policyFlags & POLICY_FLAG_TRUSTED) == 0,
"Unexpected untrusted event.");
- if (shouldPruneInboundQueueLocked(static_cast<MotionEntry&>(entry))) {
+ if (shouldPruneInboundQueueLocked(static_cast<const MotionEntry&>(entry))) {
mNextUnblockedEvent = mInboundQueue.back();
needWake = true;
}
@@ -1272,7 +1268,7 @@
return needWake;
}
-void InputDispatcher::addRecentEventLocked(std::shared_ptr<EventEntry> entry) {
+void InputDispatcher::addRecentEventLocked(std::shared_ptr<const EventEntry> entry) {
// Do not store sensor event in recent queue to avoid flooding the queue.
if (entry->type != EventEntry::Type::SENSOR) {
mRecentQueue.push_back(entry);
@@ -1473,7 +1469,7 @@
void InputDispatcher::drainInboundQueueLocked() {
while (!mInboundQueue.empty()) {
- std::shared_ptr<EventEntry> entry = mInboundQueue.front();
+ std::shared_ptr<const EventEntry> entry = mInboundQueue.front();
mInboundQueue.pop_front();
releaseInboundEventLocked(entry);
}
@@ -1487,7 +1483,7 @@
}
}
-void InputDispatcher::releaseInboundEventLocked(std::shared_ptr<EventEntry> entry) {
+void InputDispatcher::releaseInboundEventLocked(std::shared_ptr<const EventEntry> entry) {
const std::shared_ptr<InjectionState>& injectionState = entry->injectionState;
if (injectionState && injectionState->injectionResult == InputEventInjectionResult::PENDING) {
if (DEBUG_DISPATCH_CYCLE) {
@@ -1508,7 +1504,7 @@
}
std::shared_ptr<KeyEntry> InputDispatcher::synthesizeKeyRepeatLocked(nsecs_t currentTime) {
- std::shared_ptr<KeyEntry> entry = mKeyRepeatState.lastKeyEntry;
+ std::shared_ptr<const KeyEntry> entry = mKeyRepeatState.lastKeyEntry;
uint32_t policyFlags = entry->policyFlags &
(POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED);
@@ -1582,17 +1578,17 @@
// This event should go to the front of the queue, but behind all other focus events
// Find the last focus event, and insert right after it
- std::deque<std::shared_ptr<EventEntry>>::reverse_iterator it =
- std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(),
- [](const std::shared_ptr<EventEntry>& event) {
- return event->type == EventEntry::Type::FOCUS;
- });
+ auto it = std::find_if(mInboundQueue.rbegin(), mInboundQueue.rend(),
+ [](const std::shared_ptr<const EventEntry>& event) {
+ return event->type == EventEntry::Type::FOCUS;
+ });
// Maintain the order of focus events. Insert the entry after all other focus events.
mInboundQueue.insert(it.base(), std::move(focusEntry));
}
-void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, std::shared_ptr<FocusEntry> entry) {
+void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime,
+ std::shared_ptr<const FocusEntry> entry) {
std::shared_ptr<InputChannel> channel = getInputChannelLocked(entry->connectionToken);
if (channel == nullptr) {
return; // Window has gone away
@@ -1609,7 +1605,7 @@
}
void InputDispatcher::dispatchPointerCaptureChangedLocked(
- nsecs_t currentTime, const std::shared_ptr<PointerCaptureChangedEntry>& entry,
+ nsecs_t currentTime, const std::shared_ptr<const PointerCaptureChangedEntry>& entry,
DropReason& dropReason) {
dropReason = DropReason::NOT_DROPPED;
@@ -1680,8 +1676,8 @@
dropReason = DropReason::NOT_DROPPED;
}
-void InputDispatcher::dispatchTouchModeChangeLocked(nsecs_t currentTime,
- const std::shared_ptr<TouchModeEntry>& entry) {
+void InputDispatcher::dispatchTouchModeChangeLocked(
+ nsecs_t currentTime, const std::shared_ptr<const TouchModeEntry>& entry) {
const std::vector<sp<WindowInfoHandle>>& windowHandles =
getWindowHandlesLocked(entry->displayId);
if (windowHandles.empty()) {
@@ -1716,7 +1712,7 @@
return inputTargets;
}
-bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
+bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
if (!entry->dispatchInProgress) {
@@ -1850,7 +1846,7 @@
}
void InputDispatcher::dispatchSensorLocked(nsecs_t currentTime,
- const std::shared_ptr<SensorEntry>& entry,
+ const std::shared_ptr<const SensorEntry>& entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
if (DEBUG_OUTBOUND_EVENT_DETAILS) {
ALOGD("notifySensorEvent eventTime=%" PRId64 ", hwTimestamp=%" PRId64 ", deviceId=%d, "
@@ -1879,7 +1875,7 @@
std::scoped_lock _l(mLock);
for (auto it = mInboundQueue.begin(); it != mInboundQueue.end(); it++) {
- std::shared_ptr<EventEntry> entry = *it;
+ std::shared_ptr<const EventEntry> entry = *it;
if (entry->type == EventEntry::Type::SENSOR) {
it = mInboundQueue.erase(it);
releaseInboundEventLocked(entry);
@@ -1889,7 +1885,8 @@
return true;
}
-bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
+bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime,
+ std::shared_ptr<const MotionEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
ATRACE_CALL();
// Preprocessing.
@@ -1974,7 +1971,8 @@
enqueueInboundEventLocked(std::move(dragEntry));
}
-void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) {
+void InputDispatcher::dispatchDragLocked(nsecs_t currentTime,
+ std::shared_ptr<const DragEntry> entry) {
std::shared_ptr<InputChannel> channel = getInputChannelLocked(entry->connectionToken);
if (channel == nullptr) {
return; // Window has gone away
@@ -2020,7 +2018,7 @@
}
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
- std::shared_ptr<EventEntry> eventEntry,
+ std::shared_ptr<const EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
if (DEBUG_DISPATCH_CYCLE) {
@@ -3214,7 +3212,7 @@
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry> eventEntry,
+ std::shared_ptr<const EventEntry> eventEntry,
const InputTarget& inputTarget) {
ATRACE_NAME_IF(ATRACE_ENABLED(),
StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
@@ -3281,7 +3279,7 @@
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry> eventEntry,
+ std::shared_ptr<const EventEntry> eventEntry,
const InputTarget& inputTarget) {
ATRACE_NAME_IF(ATRACE_ENABLED(),
StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
@@ -3312,7 +3310,7 @@
}
void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry> eventEntry,
+ std::shared_ptr<const EventEntry> eventEntry,
const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) {
ftl::Flags<InputTarget::Flags> inputTargetFlags = inputTarget.flags;
@@ -3330,13 +3328,12 @@
// Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
// different EventEntry than what was passed in.
- EventEntry& newEntry = *(dispatchEntry->eventEntry);
+ eventEntry = dispatchEntry->eventEntry;
// Apply target flags and update the connection's input state.
- switch (newEntry.type) {
+ switch (eventEntry->type) {
case EventEntry::Type::KEY: {
- const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
- if (!connection->inputState.trackKey(keyEntry, dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags)) {
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*eventEntry);
+ if (!connection->inputState.trackKey(keyEntry, keyEntry.flags)) {
LOG(WARNING) << "channel " << connection->getInputChannelName()
<< "~ dropping inconsistent event: " << *dispatchEntry;
return; // skip the inconsistent event
@@ -3345,58 +3342,90 @@
}
case EventEntry::Type::MOTION: {
- const MotionEntry& motionEntry = static_cast<const MotionEntry&>(newEntry);
- // Assign a default value to dispatchEntry that will never be generated by InputReader,
- // and assign a InputDispatcher value if it doesn't change in the if-else chain below.
- constexpr int32_t DEFAULT_RESOLVED_EVENT_ID =
- static_cast<int32_t>(IdGenerator::Source::OTHER);
- dispatchEntry->resolvedEventId = DEFAULT_RESOLVED_EVENT_ID;
- if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
- } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
- } else {
- dispatchEntry->resolvedEventId = motionEntry.id;
- }
- if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
- !connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
- motionEntry.displayId)) {
- if (DEBUG_DISPATCH_CYCLE) {
- ALOGD("channel '%s' ~ enqueueDispatchEntryLocked: filling in missing hover "
- "enter event",
- connection->getInputChannelName().c_str());
- }
- // We keep the 'resolvedEventId' here equal to the original 'motionEntry.id' because
- // this is a one-to-one event conversion.
- dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
- }
+ std::shared_ptr<const MotionEntry> resolvedMotion =
+ std::static_pointer_cast<const MotionEntry>(eventEntry);
+ {
+ // Determine the resolved motion entry.
+ const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*eventEntry);
+ int32_t resolvedAction = motionEntry.action;
+ int32_t resolvedFlags = motionEntry.flags;
- if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
- }
- if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- }
- if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) {
- dispatchEntry->resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_OUTSIDE)) {
+ resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
+ } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_EXIT)) {
+ resolvedAction = AMOTION_EVENT_ACTION_HOVER_EXIT;
+ } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_HOVER_ENTER)) {
+ resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_EXIT)) {
+ resolvedAction = AMOTION_EVENT_ACTION_CANCEL;
+ } else if (dispatchMode.test(InputTarget::Flags::DISPATCH_AS_SLIPPERY_ENTER)) {
+ resolvedAction = AMOTION_EVENT_ACTION_DOWN;
+ }
+ if (resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
+ !connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
+ motionEntry.displayId)) {
+ if (DEBUG_DISPATCH_CYCLE) {
+ LOG(DEBUG) << "channel '" << connection->getInputChannelName().c_str()
+ << "' ~ enqueueDispatchEntryLocked: filling in missing hover "
+ "enter event";
+ }
+ resolvedAction = AMOTION_EVENT_ACTION_HOVER_ENTER;
+ }
+
+ if (resolvedAction == AMOTION_EVENT_ACTION_CANCEL) {
+ resolvedFlags |= AMOTION_EVENT_FLAG_CANCELED;
+ }
+ if (dispatchEntry->targetFlags.test(InputTarget::Flags::WINDOW_IS_OBSCURED)) {
+ resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ }
+ if (dispatchEntry->targetFlags.test(
+ InputTarget::Flags::WINDOW_IS_PARTIALLY_OBSCURED)) {
+ resolvedFlags |= AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED;
+ }
+
+ dispatchEntry->resolvedFlags = resolvedFlags;
+ if (resolvedAction != motionEntry.action) {
+ // Generate a new MotionEntry with a new eventId using the resolved action and
+ // flags.
+ resolvedMotion =
+ std::make_shared<MotionEntry>(mIdGenerator.nextId(),
+ motionEntry.injectionState,
+ motionEntry.eventTime,
+ motionEntry.deviceId, motionEntry.source,
+ motionEntry.displayId,
+ motionEntry.policyFlags, resolvedAction,
+ motionEntry.actionButton, resolvedFlags,
+ motionEntry.metaState,
+ motionEntry.buttonState,
+ motionEntry.classification,
+ motionEntry.edgeFlags,
+ motionEntry.xPrecision,
+ motionEntry.yPrecision,
+ motionEntry.xCursorPosition,
+ motionEntry.yCursorPosition,
+ motionEntry.downTime,
+ motionEntry.pointerProperties,
+ motionEntry.pointerCoords);
+ if (ATRACE_ENABLED()) {
+ std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
+ ") to MotionEvent(id=0x%" PRIx32 ").",
+ motionEntry.id, resolvedMotion->id);
+ ATRACE_NAME(message.c_str());
+ }
+
+ // Set the resolved motion entry in the DispatchEntry.
+ dispatchEntry->eventEntry = resolvedMotion;
+ eventEntry = resolvedMotion;
+ }
}
// Check if we need to cancel any of the ongoing gestures. We don't support multiple
// devices being active at the same time in the same window, so if a new device is
// active, cancel the gesture from the old device.
-
std::unique_ptr<EventEntry> cancelEvent =
- connection->inputState
- .cancelConflictingInputStream(motionEntry,
- dispatchEntry->resolvedAction);
+ connection->inputState.cancelConflictingInputStream(*resolvedMotion);
if (cancelEvent != nullptr) {
- LOG(INFO) << "Canceling pointers for device " << motionEntry.deviceId << " in "
+ LOG(INFO) << "Canceling pointers for device " << resolvedMotion->deviceId << " in "
<< connection->getInputChannelName() << " with event "
<< cancelEvent->getDescription();
std::unique_ptr<DispatchEntry> cancelDispatchEntry =
@@ -3408,31 +3437,20 @@
connection->outboundQueue.emplace_back(std::move(cancelDispatchEntry));
}
- if (!connection->inputState.trackMotion(motionEntry, dispatchEntry->resolvedAction,
+ if (!connection->inputState.trackMotion(*resolvedMotion,
dispatchEntry->resolvedFlags)) {
LOG(WARNING) << "channel " << connection->getInputChannelName()
<< "~ dropping inconsistent event: " << *dispatchEntry;
return; // skip the inconsistent event
}
- dispatchEntry->resolvedEventId =
- dispatchEntry->resolvedEventId == DEFAULT_RESOLVED_EVENT_ID
- ? mIdGenerator.nextId()
- : motionEntry.id;
- if (ATRACE_ENABLED() && dispatchEntry->resolvedEventId != motionEntry.id) {
- std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
- ") to MotionEvent(id=0x%" PRIx32 ").",
- motionEntry.id, dispatchEntry->resolvedEventId);
- ATRACE_NAME(message.c_str());
- }
-
- if ((motionEntry.flags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
- (motionEntry.policyFlags & POLICY_FLAG_TRUSTED)) {
+ if ((resolvedMotion->flags & AMOTION_EVENT_FLAG_NO_FOCUS_CHANGE) &&
+ (resolvedMotion->policyFlags & POLICY_FLAG_TRUSTED)) {
// Skip reporting pointer down outside focus to the policy.
break;
}
- dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction,
+ dispatchPointerDownOutsideFocus(resolvedMotion->source, resolvedMotion->action,
inputTarget.inputChannel->getConnectionToken());
break;
@@ -3450,14 +3468,14 @@
case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET: {
LOG_ALWAYS_FATAL("%s events should not go to apps",
- ftl::enum_string(newEntry.type).c_str());
+ ftl::enum_string(eventEntry->type).c_str());
break;
}
}
// Remember that we are waiting for this dispatch to complete.
if (dispatchEntry->hasForegroundTarget()) {
- incrementPendingForegroundDispatches(newEntry);
+ incrementPendingForegroundDispatches(*eventEntry);
}
// Enqueue the dispatch entry.
@@ -3606,18 +3624,17 @@
// Publish the motion event.
return connection.inputPublisher
- .publishMotionEvent(dispatchEntry.seq, dispatchEntry.resolvedEventId,
- motionEntry.deviceId, motionEntry.source, motionEntry.displayId,
- std::move(hmac), dispatchEntry.resolvedAction,
- motionEntry.actionButton, dispatchEntry.resolvedFlags,
- motionEntry.edgeFlags, motionEntry.metaState,
- motionEntry.buttonState, motionEntry.classification,
- dispatchEntry.transform, motionEntry.xPrecision,
- motionEntry.yPrecision, motionEntry.xCursorPosition,
- motionEntry.yCursorPosition, dispatchEntry.rawTransform,
- motionEntry.downTime, motionEntry.eventTime,
- motionEntry.getPointerCount(), motionEntry.pointerProperties.data(),
- usingCoords);
+ .publishMotionEvent(dispatchEntry.seq, motionEntry.id, motionEntry.deviceId,
+ motionEntry.source, motionEntry.displayId, std::move(hmac),
+ motionEntry.action, motionEntry.actionButton,
+ dispatchEntry.resolvedFlags, motionEntry.edgeFlags,
+ motionEntry.metaState, motionEntry.buttonState,
+ motionEntry.classification, dispatchEntry.transform,
+ motionEntry.xPrecision, motionEntry.yPrecision,
+ motionEntry.xCursorPosition, motionEntry.yCursorPosition,
+ dispatchEntry.rawTransform, motionEntry.downTime,
+ motionEntry.eventTime, motionEntry.getPointerCount(),
+ motionEntry.pointerProperties.data(), usingCoords);
}
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
@@ -3649,14 +3666,13 @@
// Publish the key event.
status = connection->inputPublisher
- .publishKeyEvent(dispatchEntry->seq,
- dispatchEntry->resolvedEventId, keyEntry.deviceId,
- keyEntry.source, keyEntry.displayId,
- std::move(hmac), dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags, keyEntry.keyCode,
- keyEntry.scanCode, keyEntry.metaState,
- keyEntry.repeatCount, keyEntry.downTime,
- keyEntry.eventTime);
+ .publishKeyEvent(dispatchEntry->seq, keyEntry.id,
+ keyEntry.deviceId, keyEntry.source,
+ keyEntry.displayId, std::move(hmac),
+ keyEntry.action, dispatchEntry->resolvedFlags,
+ keyEntry.keyCode, keyEntry.scanCode,
+ keyEntry.metaState, keyEntry.repeatCount,
+ keyEntry.downTime, keyEntry.eventTime);
break;
}
@@ -3774,7 +3790,7 @@
const std::array<uint8_t, 32> InputDispatcher::getSignature(
const MotionEntry& motionEntry, const DispatchEntry& dispatchEntry) const {
- const int32_t actionMasked = MotionEvent::getActionMasked(dispatchEntry.resolvedAction);
+ const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
if (actionMasked != AMOTION_EVENT_ACTION_UP && actionMasked != AMOTION_EVENT_ACTION_DOWN) {
// Only sign events up and down events as the purely move events
// are tied to their up/down counterparts so signing would be redundant.
@@ -3792,7 +3808,6 @@
const KeyEntry& keyEntry, const DispatchEntry& dispatchEntry) const {
VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(keyEntry);
verifiedEvent.flags = dispatchEntry.resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
- verifiedEvent.action = dispatchEntry.resolvedAction;
return sign(verifiedEvent);
}
@@ -4853,7 +4868,7 @@
return result;
}
-void InputDispatcher::setInjectionResult(EventEntry& entry,
+void InputDispatcher::setInjectionResult(const EventEntry& entry,
InputEventInjectionResult injectionResult) {
if (!entry.injectionState) {
// Not an injected event.
@@ -4914,13 +4929,13 @@
}
}
-void InputDispatcher::incrementPendingForegroundDispatches(EventEntry& entry) {
+void InputDispatcher::incrementPendingForegroundDispatches(const EventEntry& entry) {
if (entry.injectionState) {
entry.injectionState->pendingForegroundDispatches += 1;
}
}
-void InputDispatcher::decrementPendingForegroundDispatches(EventEntry& entry) {
+void InputDispatcher::decrementPendingForegroundDispatches(const EventEntry& entry) {
if (entry.injectionState) {
entry.injectionState->pendingForegroundDispatches -= 1;
@@ -5734,7 +5749,7 @@
// Dump recently dispatched or dropped events from oldest to newest.
if (!mRecentQueue.empty()) {
dump += StringPrintf(INDENT "RecentQueue: length=%zu\n", mRecentQueue.size());
- for (const std::shared_ptr<EventEntry>& entry : mRecentQueue) {
+ for (const std::shared_ptr<const EventEntry>& entry : mRecentQueue) {
dump += INDENT2;
dump += entry->getDescription();
dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
@@ -5757,7 +5772,7 @@
// Dump inbound events from oldest to newest.
if (!mInboundQueue.empty()) {
dump += StringPrintf(INDENT "InboundQueue: length=%zu\n", mInboundQueue.size());
- for (const std::shared_ptr<EventEntry>& entry : mInboundQueue) {
+ for (const std::shared_ptr<const EventEntry>& entry : mInboundQueue) {
dump += INDENT2;
dump += entry->getDescription();
dump += StringPrintf(", age=%" PRId64 "ms\n", ns2ms(currentTime - entry->eventTime));
@@ -6144,7 +6159,7 @@
uint32_t seq, bool handled,
nsecs_t consumeTime) {
// Handle post-event policy actions.
- std::unique_ptr<KeyEntry> fallbackKeyEntry;
+ std::unique_ptr<const KeyEntry> fallbackKeyEntry;
{ // Start critical section
auto dispatchEntryIt =
@@ -6300,7 +6315,7 @@
}
void InputDispatcher::doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
- KeyEntry& entry) {
+ const KeyEntry& entry) {
const KeyEvent event = createKeyEvent(entry);
nsecs_t delay = 0;
{ // release lock
@@ -6385,7 +6400,7 @@
sendWindowResponsiveCommandLocked(connectionToken, pid);
}
-std::unique_ptr<KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable(
+std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptable(
const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
const KeyEntry& keyEntry, bool handled) {
if (keyEntry.flags & AKEY_EVENT_FLAG_FALLBACK) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 574cf8b..8aa4a87 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -171,9 +171,9 @@
sp<Looper> mLooper;
- std::shared_ptr<EventEntry> mPendingEvent GUARDED_BY(mLock);
- std::deque<std::shared_ptr<EventEntry>> mInboundQueue GUARDED_BY(mLock);
- std::deque<std::shared_ptr<EventEntry>> mRecentQueue GUARDED_BY(mLock);
+ std::shared_ptr<const EventEntry> mPendingEvent GUARDED_BY(mLock);
+ std::deque<std::shared_ptr<const EventEntry>> mInboundQueue GUARDED_BY(mLock);
+ std::deque<std::shared_ptr<const EventEntry>> mRecentQueue GUARDED_BY(mLock);
// A command entry captures state and behavior for an action to be performed in the
// dispatch loop after the initial processing has taken place. It is essentially
@@ -223,7 +223,7 @@
REQUIRES(mLock);
// Adds an event to a queue of recent events for debugging purposes.
- void addRecentEventLocked(std::shared_ptr<EventEntry> entry) REQUIRES(mLock);
+ void addRecentEventLocked(std::shared_ptr<const EventEntry> entry) REQUIRES(mLock);
// App switch latency optimization.
bool mAppSwitchSawKeyDown GUARDED_BY(mLock);
@@ -235,7 +235,7 @@
// Blocked event latency optimization. Drops old events when the user intends
// to transfer focus to a new application.
- std::shared_ptr<EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
+ std::shared_ptr<const EventEntry> mNextUnblockedEvent GUARDED_BY(mLock);
sp<android::gui::WindowInfoHandle> findTouchedWindowAtLocked(
int32_t displayId, float x, float y, bool isStylus = false,
@@ -282,19 +282,19 @@
// Event injection and synchronization.
std::condition_variable mInjectionResultAvailable;
- void setInjectionResult(EventEntry& entry,
+ void setInjectionResult(const EventEntry& entry,
android::os::InputEventInjectionResult injectionResult);
void transformMotionEntryForInjectionLocked(MotionEntry&,
const ui::Transform& injectedTransform) const
REQUIRES(mLock);
std::condition_variable mInjectionSyncFinished;
- void incrementPendingForegroundDispatches(EventEntry& entry);
- void decrementPendingForegroundDispatches(EventEntry& entry);
+ void incrementPendingForegroundDispatches(const EventEntry& entry);
+ void decrementPendingForegroundDispatches(const EventEntry& entry);
// Key repeat tracking.
struct KeyRepeatState {
- std::shared_ptr<KeyEntry> lastKeyEntry; // or null if no repeat
+ std::shared_ptr<const KeyEntry> lastKeyEntry; // or null if no repeat
nsecs_t nextRepeatTime;
} mKeyRepeatState GUARDED_BY(mLock);
@@ -320,7 +320,7 @@
// Inbound event processing.
void drainInboundQueueLocked() REQUIRES(mLock);
void releasePendingEventLocked() REQUIRES(mLock);
- void releaseInboundEventLocked(std::shared_ptr<EventEntry> entry) REQUIRES(mLock);
+ void releaseInboundEventLocked(std::shared_ptr<const EventEntry> entry) REQUIRES(mLock);
// Dispatch state.
bool mDispatchEnabled GUARDED_BY(mLock);
@@ -431,23 +431,24 @@
const ConfigurationChangedEntry& entry) REQUIRES(mLock);
bool dispatchDeviceResetLocked(nsecs_t currentTime, const DeviceResetEntry& entry)
REQUIRES(mLock);
- bool dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
+ bool dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<const KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
- bool dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
+ bool dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<const MotionEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
- void dispatchFocusLocked(nsecs_t currentTime, std::shared_ptr<FocusEntry> entry)
+ void dispatchFocusLocked(nsecs_t currentTime, std::shared_ptr<const FocusEntry> entry)
REQUIRES(mLock);
void dispatchPointerCaptureChangedLocked(
- nsecs_t currentTime, const std::shared_ptr<PointerCaptureChangedEntry>& entry,
+ nsecs_t currentTime, const std::shared_ptr<const PointerCaptureChangedEntry>& entry,
DropReason& dropReason) REQUIRES(mLock);
void dispatchTouchModeChangeLocked(nsecs_t currentTime,
- const std::shared_ptr<TouchModeEntry>& entry)
+ const std::shared_ptr<const TouchModeEntry>& entry)
REQUIRES(mLock);
- void dispatchEventLocked(nsecs_t currentTime, std::shared_ptr<EventEntry> entry,
+ void dispatchEventLocked(nsecs_t currentTime, std::shared_ptr<const EventEntry> entry,
const std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
- void dispatchSensorLocked(nsecs_t currentTime, const std::shared_ptr<SensorEntry>& entry,
+ void dispatchSensorLocked(nsecs_t currentTime, const std::shared_ptr<const SensorEntry>& entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) REQUIRES(mLock);
- void dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<DragEntry> entry) REQUIRES(mLock);
+ void dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<const DragEntry> entry)
+ REQUIRES(mLock);
void logOutboundKeyDetails(const char* prefix, const KeyEntry& entry);
void logOutboundMotionDetails(const char* prefix, const MotionEntry& entry);
@@ -577,14 +578,15 @@
// If needed, the methods post commands to run later once the critical bits are done.
void prepareDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry>, const InputTarget& inputTarget)
- REQUIRES(mLock);
+ std::shared_ptr<const EventEntry>,
+ const InputTarget& inputTarget) REQUIRES(mLock);
void enqueueDispatchEntriesLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry>, const InputTarget& inputTarget)
- REQUIRES(mLock);
+ std::shared_ptr<const EventEntry>,
+ const InputTarget& inputTarget) REQUIRES(mLock);
void enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
- std::shared_ptr<EventEntry>, const InputTarget& inputTarget,
+ std::shared_ptr<const EventEntry>,
+ const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) REQUIRES(mLock);
status_t publishMotionEvent(Connection& connection, DispatchEntry& dispatchEntry) const;
void startDispatchCycleLocked(nsecs_t currentTime,
@@ -646,7 +648,7 @@
const std::shared_ptr<Connection>& connection, uint32_t seq,
bool handled, nsecs_t consumeTime) REQUIRES(mLock);
void doInterceptKeyBeforeDispatchingCommand(const sp<IBinder>& focusedWindowToken,
- KeyEntry& entry) REQUIRES(mLock);
+ const KeyEntry& entry) REQUIRES(mLock);
void onFocusChangedLocked(const FocusResolver::FocusChanges& changes) REQUIRES(mLock);
void sendFocusChangedCommandLocked(const sp<IBinder>& oldToken, const sp<IBinder>& newToken)
REQUIRES(mLock);
@@ -661,7 +663,7 @@
REQUIRES(mLock);
std::map<int32_t /*displayId*/, InputVerifier> mVerifiersByDisplay;
// Returns a fallback KeyEntry that should be sent to the connection, if required.
- std::unique_ptr<KeyEntry> afterKeyEventLockedInterruptable(
+ std::unique_ptr<const KeyEntry> afterKeyEventLockedInterruptable(
const std::shared_ptr<Connection>& connection, DispatchEntry& dispatchEntry,
const KeyEntry& keyEntry, bool handled) REQUIRES(mLock);
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 17f0b87..a4ac4fb 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -38,8 +38,8 @@
return false;
}
-bool InputState::trackKey(const KeyEntry& entry, int32_t action, int32_t flags) {
- switch (action) {
+bool InputState::trackKey(const KeyEntry& entry, int32_t flags) {
+ switch (entry.action) {
case AKEY_EVENT_ACTION_UP: {
if (entry.flags & AKEY_EVENT_FLAG_FALLBACK) {
std::erase_if(mFallbackKeys,
@@ -88,7 +88,7 @@
* true if the incoming event was correctly tracked,
* false if the incoming event should be dropped.
*/
-bool InputState::trackMotion(const MotionEntry& entry, int32_t action, int32_t flags) {
+bool InputState::trackMotion(const MotionEntry& entry, int32_t flags) {
// Don't track non-pointer events
if (!isFromSource(entry.source, AINPUT_SOURCE_CLASS_POINTER)) {
// This is a focus-dispatched event; we don't track its state.
@@ -104,7 +104,7 @@
}
}
- int32_t actionMasked = action & AMOTION_EVENT_ACTION_MASK;
+ int32_t actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
switch (actionMasked) {
case AMOTION_EVENT_ACTION_UP:
case AMOTION_EVENT_ACTION_CANCEL: {
@@ -281,8 +281,7 @@
return pointerProperties.size();
}
-bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry,
- int32_t resolvedAction) const {
+bool InputState::shouldCancelPreviousStream(const MotionEntry& motionEntry) const {
if (!isFromSource(motionEntry.source, AINPUT_SOURCE_CLASS_POINTER)) {
// This is a focus-dispatched event that should not affect the previous stream.
return false;
@@ -300,7 +299,7 @@
}
const MotionMemento& lastMemento = mMotionMementos.back();
- const int32_t actionMasked = MotionEvent::getActionMasked(resolvedAction);
+ const int32_t actionMasked = MotionEvent::getActionMasked(motionEntry.action);
// For compatibility, only one input device can be active at a time in the same window.
if (lastMemento.deviceId == motionEntry.deviceId) {
@@ -369,9 +368,9 @@
return false;
}
-std::unique_ptr<EventEntry> InputState::cancelConflictingInputStream(const MotionEntry& motionEntry,
- int32_t resolvedAction) {
- if (!shouldCancelPreviousStream(motionEntry, resolvedAction)) {
+std::unique_ptr<EventEntry> InputState::cancelConflictingInputStream(
+ const MotionEntry& motionEntry) {
+ if (!shouldCancelPreviousStream(motionEntry)) {
return {};
}
@@ -381,7 +380,7 @@
std::unique_ptr<MotionEntry> cancelEntry =
createCancelEntryForMemento(memento, motionEntry.eventTime);
- if (!trackMotion(*cancelEntry, cancelEntry->action, cancelEntry->flags)) {
+ if (!trackMotion(*cancelEntry, cancelEntry->flags)) {
LOG(FATAL) << "Generated inconsistent cancel event!";
}
return cancelEntry;
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index 686c432..b0e4209 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -41,16 +41,15 @@
// Records tracking information for a key event that has just been published.
// Returns true if the event should be delivered, false if it is inconsistent
// and should be skipped.
- bool trackKey(const KeyEntry& entry, int32_t action, int32_t flags);
+ bool trackKey(const KeyEntry& entry, int32_t flags);
// Records tracking information for a motion event that has just been published.
// Returns true if the event should be delivered, false if it is inconsistent
// and should be skipped.
- bool trackMotion(const MotionEntry& entry, int32_t action, int32_t flags);
+ bool trackMotion(const MotionEntry& entry, int32_t flags);
// Create cancel events for the previous stream if the current motionEntry requires it.
- std::unique_ptr<EventEntry> cancelConflictingInputStream(const MotionEntry& motionEntry,
- int32_t resolvedAction);
+ std::unique_ptr<EventEntry> cancelConflictingInputStream(const MotionEntry& motionEntry);
// Synthesizes cancelation events for the current state and resets the tracked state.
std::vector<std::unique_ptr<EventEntry>> synthesizeCancelationEvents(
@@ -127,7 +126,7 @@
static bool shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options);
static bool shouldCancelMotion(const MotionMemento& memento, const CancelationOptions& options);
- bool shouldCancelPreviousStream(const MotionEntry& motionEntry, int32_t resolvedAction) const;
+ bool shouldCancelPreviousStream(const MotionEntry& motionEntry) const;
std::unique_ptr<MotionEntry> createCancelEntryForMemento(const MotionMemento& memento,
nsecs_t eventTime) const;
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 9c87c62..2dd05f5 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -131,7 +131,7 @@
bumpGeneration();
}
}
- if (shouldSimulateStylusWithTouch() && outPointer.toolType == ToolType::FINGER) {
+ if (mShouldSimulateStylusWithTouch && outPointer.toolType == ToolType::FINGER) {
outPointer.toolType = ToolType::STYLUS;
}
@@ -177,6 +177,18 @@
mMultiTouchMotionAccumulator.finishSync();
}
+std::list<NotifyArgs> MultiTouchInputMapper::reconfigure(nsecs_t when,
+ const InputReaderConfiguration& config,
+ ConfigurationChanges changes) {
+ const bool simulateStylusWithTouch =
+ sysprop::InputProperties::simulate_stylus_with_touch().value_or(false);
+ if (simulateStylusWithTouch != mShouldSimulateStylusWithTouch) {
+ mShouldSimulateStylusWithTouch = simulateStylusWithTouch;
+ bumpGeneration();
+ }
+ return TouchInputMapper::reconfigure(when, config, changes);
+}
+
void MultiTouchInputMapper::configureRawPointerAxes() {
TouchInputMapper::configureRawPointerAxes();
@@ -211,14 +223,7 @@
bool MultiTouchInputMapper::hasStylus() const {
return mStylusMtToolSeen || mTouchButtonAccumulator.hasStylus() ||
- shouldSimulateStylusWithTouch();
-}
-
-bool MultiTouchInputMapper::shouldSimulateStylusWithTouch() const {
- static const bool SIMULATE_STYLUS_WITH_TOUCH =
- sysprop::InputProperties::simulate_stylus_with_touch().value_or(false);
- return SIMULATE_STYLUS_WITH_TOUCH &&
- mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN;
+ mShouldSimulateStylusWithTouch;
}
} // namespace android
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index 1d788df..5c173f3 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -32,6 +32,9 @@
[[nodiscard]] std::list<NotifyArgs> reset(nsecs_t when) override;
[[nodiscard]] std::list<NotifyArgs> process(const RawEvent* rawEvent) override;
+ [[nodiscard]] std::list<NotifyArgs> reconfigure(nsecs_t when,
+ const InputReaderConfiguration& config,
+ ConfigurationChanges changes) override;
protected:
void syncTouch(nsecs_t when, RawState* outState) override;
@@ -41,13 +44,6 @@
private:
explicit MultiTouchInputMapper(InputDeviceContext& deviceContext,
const InputReaderConfiguration& readerConfig);
- // simulate_stylus_with_touch is a debug mode that converts all finger pointers reported by this
- // mapper's touchscreen into stylus pointers, and adds SOURCE_STYLUS to the input device.
- // It is used to simulate stylus events for debugging and testing on a device that does not
- // support styluses. It can be enabled using
- // "adb shell setprop persist.debug.input.simulate_stylus_with_touch true",
- // and requires a reboot to take effect.
- inline bool shouldSimulateStylusWithTouch() const;
// If the slot is in use, return the bit id. Return std::nullopt otherwise.
std::optional<int32_t> getActiveBitId(const MultiTouchMotionAccumulator::Slot& inSlot);
@@ -58,6 +54,15 @@
int32_t mPointerTrackingIdMap[MAX_POINTER_ID + 1];
bool mStylusMtToolSeen{false};
+
+ // simulate_stylus_with_touch is a debug mode that converts all finger pointers reported by this
+ // mapper's touchscreen into stylus pointers, and adds SOURCE_STYLUS to the input device.
+ // It is used to simulate stylus events for debugging and testing on a device that does not
+ // support styluses. It can be enabled using
+ // "adb shell setprop debug.input.simulate_stylus_with_touch true".
+ // After enabling, the touchscreen will need to be reconfigured. A reconfiguration usually
+ // happens when turning the screen on/off or by rotating the device orientation.
+ bool mShouldSimulateStylusWithTouch{false};
};
} // namespace android
diff --git a/services/inputflinger/rust/Android.bp b/services/inputflinger/rust/Android.bp
index 23c1691..2775bcc 100644
--- a/services/inputflinger/rust/Android.bp
+++ b/services/inputflinger/rust/Android.bp
@@ -31,8 +31,8 @@
out: ["inputflinger_bootstrap.rs.h"],
}
-rust_ffi_static {
- name: "libinputflinger_rs",
+rust_defaults {
+ name: "libinputflinger_rs_defaults",
crate_name: "inputflinger",
srcs: ["lib.rs"],
rustlibs: [
@@ -45,6 +45,24 @@
host_supported: true,
}
+rust_ffi_static {
+ name: "libinputflinger_rs",
+ defaults: ["libinputflinger_rs_defaults"],
+}
+
+rust_test {
+ name: "libinputflinger_rs_test",
+ defaults: ["libinputflinger_rs_defaults"],
+ test_options: {
+ unit_test: true,
+ },
+ test_suites: ["device_tests"],
+ sanitize: {
+ address: true,
+ hwaddress: true,
+ },
+}
+
cc_library_headers {
name: "inputflinger_rs_bootstrap_cxx_headers",
host_supported: true,
diff --git a/services/inputflinger/rust/input_filter.rs b/services/inputflinger/rust/input_filter.rs
new file mode 100644
index 0000000..5851877
--- /dev/null
+++ b/services/inputflinger/rust/input_filter.rs
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2023 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.
+ */
+
+//! InputFilter manages all the filtering components that can intercept events, modify the events,
+//! block events, etc depending on the situation. This will be used support Accessibility features
+//! like Slow keys, Bounce keys, etc.
+
+use binder::{Interface, Strong};
+use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+ IInputFilter::{IInputFilter, IInputFilterCallbacks::IInputFilterCallbacks},
+ KeyEvent::KeyEvent,
+};
+
+/// The rust implementation of InputFilter
+pub struct InputFilter {
+ callbacks: Strong<dyn IInputFilterCallbacks>,
+}
+
+impl Interface for InputFilter {}
+
+impl InputFilter {
+ /// Create a new InputFilter instance.
+ pub fn new(callbacks: Strong<dyn IInputFilterCallbacks>) -> InputFilter {
+ Self { callbacks }
+ }
+}
+
+impl IInputFilter for InputFilter {
+ fn isEnabled(&self) -> binder::Result<bool> {
+ // TODO(b/294546335): Return true if any filters are to be applied, false otherwise
+ Result::Ok(false)
+ }
+ fn notifyKey(&self, event: &KeyEvent) -> binder::Result<()> {
+ // TODO(b/294546335): Handle key event and modify key events here
+ // Just send back the event without processing for now.
+ let _ = self.callbacks.sendKeyEvent(event);
+ Result::Ok(())
+ }
+ fn notifyInputDevicesChanged(&self, _device_ids: &[i32]) -> binder::Result<()> {
+ // TODO(b/294546335): Update data based on device changes here
+ Result::Ok(())
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::input_filter::InputFilter;
+ use binder::{Interface, Strong};
+ use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+ IInputFilter::IInputFilter, IInputFilter::IInputFilterCallbacks::IInputFilterCallbacks,
+ KeyEvent::KeyEvent,
+ };
+
+ struct FakeCallbacks {}
+
+ impl Interface for FakeCallbacks {}
+
+ impl IInputFilterCallbacks for FakeCallbacks {
+ fn sendKeyEvent(&self, _event: &KeyEvent) -> binder::Result<()> {
+ Result::Ok(())
+ }
+ }
+
+ #[test]
+ fn test_is_enabled() {
+ let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+ Strong::new(Box::new(FakeCallbacks {}));
+ let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+ let result = filter.isEnabled();
+ assert!(result.is_ok());
+ assert!(!result.unwrap());
+ }
+
+ #[test]
+ fn test_notify_key() {
+ let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+ Strong::new(Box::new(FakeCallbacks {}));
+ let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+ let event = create_key_event();
+ assert!(filter.notifyKey(&event).is_ok());
+ }
+
+ #[test]
+ fn test_notify_devices_changed() {
+ let fake_callbacks: Strong<dyn IInputFilterCallbacks> =
+ Strong::new(Box::new(FakeCallbacks {}));
+ let filter: Box<dyn IInputFilter> = Box::new(InputFilter::new(fake_callbacks));
+ let result = filter.notifyInputDevicesChanged(&[0]);
+ assert!(result.is_ok());
+ }
+
+ fn create_key_event() -> KeyEvent {
+ KeyEvent {
+ id: 1,
+ deviceId: 1,
+ downTime: 0,
+ readTime: 0,
+ eventTime: 0,
+ source: 0,
+ displayId: 0,
+ policyFlags: 0,
+ action: 0,
+ flags: 0,
+ keyCode: 0,
+ scanCode: 0,
+ metaState: 0,
+ }
+ }
+}
diff --git a/services/inputflinger/rust/lib.rs b/services/inputflinger/rust/lib.rs
index 501e435..a4049d5 100644
--- a/services/inputflinger/rust/lib.rs
+++ b/services/inputflinger/rust/lib.rs
@@ -19,13 +19,19 @@
//! We use cxxbridge to create IInputFlingerRust - the Rust component of inputflinger - and
//! pass it back to C++ as a local AIDL interface.
+mod input_filter;
+
+use crate::input_filter::InputFilter;
use binder::{
- unstable_api::{AIBinder, new_spibinder,},
+ unstable_api::{new_spibinder, AIBinder},
BinderFeatures, Interface, StatusCode, Strong,
};
-use com_android_server_inputflinger::aidl::com::android::server::inputflinger::IInputFlingerRust::{
- BnInputFlingerRust, IInputFlingerRust,
- IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback,
+use com_android_server_inputflinger::aidl::com::android::server::inputflinger::{
+ IInputFilter::{BnInputFilter, IInputFilter, IInputFilterCallbacks::IInputFilterCallbacks},
+ IInputFlingerRust::{
+ BnInputFlingerRust, IInputFlingerRust,
+ IInputFlingerRustBootstrapCallback::IInputFlingerRustBootstrapCallback,
+ },
};
use log::debug;
@@ -71,8 +77,8 @@
// SAFETY: Our caller guaranteed that `callback` is a valid pointer to an `AIBinder` and its
// reference count has been incremented..
let Some(callback) = (unsafe { new_spibinder(callback) }) else {
- panic!("Failed to get SpAIBinder from raw callback pointer");
- };
+ panic!("Failed to get SpAIBinder from raw callback pointer");
+ };
let callback: Result<Strong<dyn IInputFlingerRustBootstrapCallback>, StatusCode> =
callback.into_interface();
@@ -93,7 +99,19 @@
impl Interface for InputFlingerRust {}
-impl IInputFlingerRust for InputFlingerRust {}
+impl IInputFlingerRust for InputFlingerRust {
+ fn createInputFilter(
+ &self,
+ callbacks: &Strong<dyn IInputFilterCallbacks>,
+ ) -> binder::Result<Strong<dyn IInputFilter>> {
+ debug!("Creating InputFilter");
+ let filter = BnInputFilter::new_binder(
+ InputFilter::new(callbacks.clone()),
+ BinderFeatures::default(),
+ );
+ Result::Ok(filter)
+ }
+}
impl Drop for InputFlingerRust {
fn drop(&mut self) {
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 15fadbc..002177b 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -111,8 +111,6 @@
}
void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) {
- std::unordered_map<compositionengine::LayerFE*, compositionengine::LayerFECompositionState*>
- uniqueVisibleLayers;
for (const auto& output : args.outputs) {
for (auto* layer : output->getOutputLayersOrderedByZ()) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 6be57d4..9aaaa95 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -540,8 +540,9 @@
displayData.validateWasSkipped = false;
{
std::scoped_lock lock{displayData.expectedPresentLock};
- displayData.lastExpectedPresentTimestamp = TimePoint::fromNs(expectedPresentTime);
- // TODO(b/296636176) Update displayData.lastFrameInterval for present display commands
+ if (expectedPresentTime > displayData.lastExpectedPresentTimestamp.ns()) {
+ displayData.lastExpectedPresentTimestamp = TimePoint::fromNs(expectedPresentTime);
+ }
}
if (canSkipValidate) {
@@ -965,6 +966,11 @@
isExpectedPresentWithinTimeout(expectedPresentTime, lastExpectedPresentTimestamp,
timeoutOpt, threshold);
+ using fps_approx_ops::operator!=;
+ if (frameIntervalIsOnCadence && frameInterval != lastFrameInterval) {
+ displayData.lastExpectedPresentTimestamp = expectedPresentTime;
+ }
+
if (expectedPresentWithinTimeout && frameIntervalIsOnCadence) {
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5cc2985..644b6ef 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -7579,7 +7579,7 @@
args.allowProtected, args.grayscale, captureListener);
}
-void SurfaceFlinger::captureDisplay(DisplayId displayId,
+void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args,
const sp<IScreenCaptureListener>& captureListener) {
ui::LayerStack layerStack;
wp<const DisplayDevice> displayWeak;
@@ -7598,10 +7598,23 @@
size = display->getLayerStackSpaceRect().getSize();
}
+ size.width *= args.frameScaleX;
+ size.height *= args.frameScaleY;
+
+ // We could query a real value for this but it'll be a long, long time until we support
+ // displays that need upwards of 1GB per buffer so...
+ constexpr auto kMaxTextureSize = 16384;
+ if (size.width <= 0 || size.height <= 0 || size.width >= kMaxTextureSize ||
+ size.height >= kMaxTextureSize) {
+ ALOGE("capture display resolved to invalid size %d x %d", size.width, size.height);
+ invokeScreenCaptureError(BAD_VALUE, captureListener);
+ return;
+ }
+
RenderAreaFuture renderAreaFuture = ftl::defer([=] {
- return DisplayRenderArea::create(displayWeak, Rect(), size, ui::Dataspace::UNKNOWN,
+ return DisplayRenderArea::create(displayWeak, Rect(), size, args.dataspace,
false /* useIdentityTransform */,
- false /* hintForSeamlessTransition */,
+ args.hintForSeamlessTransition,
false /* captureSecureLayers */);
});
@@ -7625,8 +7638,8 @@
constexpr bool kAllowProtected = false;
constexpr bool kGrayscale = false;
- captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size,
- ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, captureListener);
+ captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, args.pixelFormat,
+ kAllowProtected, kGrayscale, captureListener);
}
void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -9425,13 +9438,14 @@
}
binder::Status SurfaceComposerAIDL::captureDisplayById(
- int64_t displayId, const sp<IScreenCaptureListener>& captureListener) {
+ int64_t displayId, const CaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) {
// status_t status;
IPCThreadState* ipc = IPCThreadState::self();
const int uid = ipc->getCallingUid();
if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId));
- mFlinger->captureDisplay(*id, captureListener);
+ mFlinger->captureDisplay(*id, args, captureListener);
} else {
invokeScreenCaptureError(PERMISSION_DENIED, captureListener);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6e1b4f4..9e6da3f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -531,7 +531,7 @@
const sp<IBinder>& layerHandle = nullptr);
void captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
- void captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
+ void captureDisplay(DisplayId, const CaptureArgs&, const sp<IScreenCaptureListener>&);
void captureLayers(const LayerCaptureArgs&, const sp<IScreenCaptureListener>&);
status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
@@ -1508,7 +1508,8 @@
binder::Status setGameContentType(const sp<IBinder>& display, bool on) override;
binder::Status captureDisplay(const DisplayCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
- binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override;
+ binder::Status captureDisplayById(int64_t, const CaptureArgs&,
+ const sp<IScreenCaptureListener>&) override;
binder::Status captureLayers(const LayerCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index a87f82f..436e6c6 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -109,6 +109,7 @@
"libnativeloader_lazy",
"libnativewindow",
"libvndksupport",
+ "libdl_android",
"android.hardware.graphics.common@1.0",
"libSurfaceFlingerProp",
],
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index cae51a5..0e45d2d 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -46,6 +46,8 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+extern "C" android_namespace_t* android_get_exported_namespace(const char*);
+
// #define ENABLE_ALLOC_CALLSTACKS 1
#if ENABLE_ALLOC_CALLSTACKS
#include <utils/CallStack.h>
@@ -159,6 +161,7 @@
"ro.board.platform",
}};
constexpr int LIB_DL_FLAGS = RTLD_LOCAL | RTLD_NOW;
+constexpr char RO_VULKAN_APEX_PROPERTY[] = "ro.vulkan.apex";
// LoadDriver returns:
// * 0 when succeed, or
@@ -166,6 +169,7 @@
// * -EINVAL when fail to find HAL_MODULE_INFO_SYM_AS_STR or
// HWVULKAN_HARDWARE_MODULE_ID in the library.
int LoadDriver(android_namespace_t* library_namespace,
+ const char* ns_name,
const hwvulkan_module_t** module) {
ATRACE_CALL();
@@ -184,10 +188,8 @@
};
so = android_dlopen_ext(lib_name.c_str(), LIB_DL_FLAGS, &dlextinfo);
if (!so) {
- ALOGE(
- "Could not load %s from updatable gfx driver namespace: "
- "%s.",
- lib_name.c_str(), dlerror());
+ ALOGE("Could not load %s from %s namespace: %s.",
+ lib_name.c_str(), ns_name, dlerror());
}
} else {
// load built-in driver
@@ -215,12 +217,30 @@
return 0;
}
+int LoadDriverFromApex(const hwvulkan_module_t** module) {
+ ATRACE_CALL();
+
+ auto apex_name = android::base::GetProperty(RO_VULKAN_APEX_PROPERTY, "");
+ if (apex_name == "") {
+ return -ENOENT;
+ }
+ // Get linker namespace for Vulkan APEX
+ std::replace(apex_name.begin(), apex_name.end(), '.', '_');
+ auto ns = android_get_exported_namespace(apex_name.c_str());
+ if (!ns) {
+ return -ENOENT;
+ }
+ android::GraphicsEnv::getInstance().setDriverToLoad(
+ android::GpuStatsInfo::Driver::VULKAN);
+ return LoadDriver(ns, apex_name.c_str(), module);
+}
+
int LoadBuiltinDriver(const hwvulkan_module_t** module) {
ATRACE_CALL();
android::GraphicsEnv::getInstance().setDriverToLoad(
android::GpuStatsInfo::Driver::VULKAN);
- return LoadDriver(nullptr, module);
+ return LoadDriver(nullptr, nullptr, module);
}
int LoadUpdatedDriver(const hwvulkan_module_t** module) {
@@ -231,7 +251,7 @@
return -ENOENT;
android::GraphicsEnv::getInstance().setDriverToLoad(
android::GpuStatsInfo::Driver::VULKAN_UPDATED);
- int result = LoadDriver(ns, module);
+ int result = LoadDriver(ns, "updatable gfx driver", module);
if (result != 0) {
LOG_ALWAYS_FATAL(
"couldn't find an updated Vulkan implementation from %s",
@@ -260,6 +280,9 @@
result = LoadUpdatedDriver(&module);
if (result == -ENOENT) {
+ result = LoadDriverFromApex(&module);
+ }
+ if (result == -ENOENT) {
result = LoadBuiltinDriver(&module);
}
if (result != 0) {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 0c48611..4f7b0f4 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1485,10 +1485,33 @@
return VK_SUCCESS;
}
+ // Look through the create_info pNext chain passed to createSwapchainKHR
+ // for an image compression control struct.
+ // if one is found AND the appropriate extensions are enabled, create a
+ // VkImageCompressionControlEXT structure to pass on to GetPhysicalDeviceImageFormatProperties2
+ void* compression_control_pNext = nullptr;
+ VkImageCompressionControlEXT image_compression = {};
+ const VkSwapchainCreateInfoKHR* create_infos = create_info;
+ while (create_infos->pNext) {
+ create_infos = reinterpret_cast<const VkSwapchainCreateInfoKHR*>(create_infos->pNext);
+ switch (create_infos->sType) {
+ case VK_STRUCTURE_TYPE_IMAGE_COMPRESSION_CONTROL_EXT: {
+ const VkImageCompressionControlEXT* compression_infos =
+ reinterpret_cast<const VkImageCompressionControlEXT*>(create_infos);
+ image_compression = *compression_infos;
+ image_compression.pNext = nullptr;
+ compression_control_pNext = &image_compression;
+ } break;
+ default:
+ // Ignore all other info structs
+ break;
+ }
+ }
+
// call GetPhysicalDeviceImageFormatProperties2KHR
VkPhysicalDeviceExternalImageFormatInfo external_image_format_info = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
- .pNext = nullptr,
+ .pNext = compression_control_pNext,
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
};