diff options
23 files changed, 753 insertions, 460 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp index 59c19d174e..138428588d 100644 --- a/cmds/installd/InstalldNativeService.cpp +++ b/cmds/installd/InstalldNativeService.cpp @@ -569,31 +569,6 @@ binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::st remove_path_xattr(path, kXattrInodeCodeCache); } } - - auto extPath = findDataMediaPath(uuid, userId); - if (flags & FLAG_CLEAR_CACHE_ONLY) { - // Clear only cached data from shared storage - path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname); - if (delete_dir_contents(path, true) != 0) { - res = error("Failed to delete contents of " + path); - } - } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { - // No code cache on shared storage - } else { - // Clear everything on shared storage - path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); - if (delete_dir_contents(path, true) != 0) { - res = error("Failed to delete contents of " + path); - } - path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); - if (delete_dir_contents(path, true) != 0) { - res = error("Failed to delete contents of " + path); - } - path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); - if (delete_dir_contents(path, true) != 0) { - res = error("Failed to delete contents of " + path); - } - } } if (flags & FLAG_STORAGE_DE) { std::string suffix = ""; @@ -613,6 +588,41 @@ binder::Status InstalldNativeService::clearAppData(const std::unique_ptr<std::st } } } + if (flags & FLAG_STORAGE_EXTERNAL) { + std::lock_guard<std::recursive_mutex> lock(mMountsLock); + for (const auto& n : mStorageMounts) { + auto extPath = n.second; + if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) { + extPath += StringPrintf("/%d", userId); + } else if (userId != 0) { + // TODO: support devices mounted under secondary users + continue; + } + if (flags & FLAG_CLEAR_CACHE_ONLY) { + // Clear only cached data from shared storage + auto path = StringPrintf("%s/Android/data/%s/cache", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) { + // No code cache on shared storage + } else { + // Clear everything on shared storage + auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); + if (delete_dir_contents(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + } + } + } return res; } @@ -662,20 +672,6 @@ binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std:: if (delete_dir_contents_and_dir(path) != 0) { res = error("Failed to delete " + path); } - - auto extPath = findDataMediaPath(uuid, userId); - path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); - if (delete_dir_contents_and_dir(path, true) != 0) { - res = error("Failed to delete " + path); - } - path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); - if (delete_dir_contents_and_dir(path, true) != 0) { - res = error("Failed to delete " + path); - } - path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); - if (delete_dir_contents_and_dir(path, true) != 0) { - res = error("Failed to delete " + path); - } } if (flags & FLAG_STORAGE_DE) { auto path = create_data_user_de_package_path(uuid_, userId, pkgname); @@ -688,6 +684,30 @@ binder::Status InstalldNativeService::destroyAppData(const std::unique_ptr<std:: // Verify if it's ok to do that. destroy_app_reference_profile(packageName); } + if (flags & FLAG_STORAGE_EXTERNAL) { + std::lock_guard<std::recursive_mutex> lock(mMountsLock); + for (const auto& n : mStorageMounts) { + auto extPath = n.second; + if (n.first.compare(0, 14, "/mnt/media_rw/") != 0) { + extPath += StringPrintf("/%d", userId); + } else if (userId != 0) { + // TODO: support devices mounted under secondary users + continue; + } + auto path = StringPrintf("%s/Android/data/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/media/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + path = StringPrintf("%s/Android/obb/%s", extPath.c_str(), pkgname); + if (delete_dir_contents_and_dir(path, true) != 0) { + res = error("Failed to delete contents of " + path); + } + } + } return res; } diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 63c9765a39..4610a66e18 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -114,6 +114,7 @@ interface IInstalld { const int FLAG_STORAGE_DE = 0x1; const int FLAG_STORAGE_CE = 0x2; + const int FLAG_STORAGE_EXTERNAL = 0x4; const int FLAG_CLEAR_CACHE_ONLY = 0x10; const int FLAG_CLEAR_CODE_CACHE_ONLY = 0x20; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 4a7848020f..ff1ba0ad17 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -391,6 +391,25 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { parentSurface->expectTap(1, 1); } +// Ensure a surface whose insets are scaled, handles the touch offset correctly. +TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { + std::unique_ptr<InputSurface> bgSurface = makeSurface(100, 100); + std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); + bgSurface->showAt(100, 100); + + fgSurface->mInputInfo.surfaceInset = 5; + fgSurface->showAt(100, 100); + + fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); + + // expect = touch / scale - inset + injectTap(112, 124); + fgSurface->expectTap(1, 1); + + injectTap(101, 101); + bgSurface->expectTap(1, 1); +} + // Ensure we ignore transparent region when getting screen bounds when positioning input frame. TEST_F(InputSurfacesTest, input_ignores_transparent_region) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index 340231d352..bdfe04b0dd 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -279,8 +279,8 @@ void FenceTimeline::push(const std::shared_ptr<FenceTime>& fence) { } void FenceTimeline::updateSignalTimes() { + std::lock_guard<std::mutex> lock(mMutex); while (!mQueue.empty()) { - std::lock_guard<std::mutex> lock(mMutex); std::shared_ptr<FenceTime> fence = mQueue.front().lock(); if (!fence) { // The shared_ptr no longer exists and no one cares about the diff --git a/libs/ui/include/ui/FenceTime.h b/libs/ui/include/ui/FenceTime.h index a5a1fcbde7..ecba7f73e8 100644 --- a/libs/ui/include/ui/FenceTime.h +++ b/libs/ui/include/ui/FenceTime.h @@ -19,6 +19,7 @@ #include <ui/Fence.h> #include <utils/Flattenable.h> +#include <utils/Mutex.h> #include <utils/Timers.h> #include <atomic> @@ -159,7 +160,7 @@ public: private: mutable std::mutex mMutex; - std::queue<std::weak_ptr<FenceTime>> mQueue; + std::queue<std::weak_ptr<FenceTime>> mQueue GUARDED_BY(mMutex); }; // Used by test code to create or get FenceTimes for a given Fence. diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 63e759c0f8..8dd4d1df63 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -29,6 +29,7 @@ cc_library_shared { srcs: [ "InputClassifier.cpp", + "InputClassifierConverter.cpp", "InputDispatcher.cpp", "InputManager.cpp", ], diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp index 4a6efa67a7..ef1a2247e9 100644 --- a/services/inputflinger/InputClassifier.cpp +++ b/services/inputflinger/InputClassifier.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "InputClassifier" #include "InputClassifier.h" +#include "InputClassifierConverter.h" #include <algorithm> #include <android-base/stringprintf.h> @@ -64,373 +65,6 @@ static V getValueForKey(const std::unordered_map<K, V>& map, K key, V defaultVal return it->second; } -static common::V1_0::Source getSource(uint32_t source) { - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) == - common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) == - common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) == - common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) == - common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) == - common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) == - common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) == - common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) == - common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) == - common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) == - common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) == - common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) == - common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) == - common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) == - common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch"); - static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) == - common::V1_0::Source::ANY, "SOURCE_ANY mismatch"); - return static_cast<common::V1_0::Source>(source); -} - -static common::V1_0::Action getAction(int32_t actionMasked) { - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) == - common::V1_0::Action::DOWN, "ACTION_DOWN mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) == - common::V1_0::Action::UP, "ACTION_UP mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) == - common::V1_0::Action::MOVE, "ACTION_MOVE mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) == - common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) == - common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) == - common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) == - common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch"); - static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) == - common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) == - common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) == - common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) == - common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) == - common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch"); - static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) == - common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch"); - return static_cast<common::V1_0::Action>(actionMasked); -} - -static common::V1_0::Button getActionButton(int32_t actionButton) { - static_assert(static_cast<common::V1_0::Button>(0) == - common::V1_0::Button::NONE, "BUTTON_NONE mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) == - common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) == - common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) == - common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) == - common::V1_0::Button::BACK, "BUTTON_BACK mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) == - common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) == - common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch"); - static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) == - common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch"); - return static_cast<common::V1_0::Button>(actionButton); -} - -static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) { - static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) == - common::V1_0::Flag::WINDOW_IS_OBSCURED); - static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) == - common::V1_0::Flag::IS_GENERATED_GESTURE); - static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) == - common::V1_0::Flag::TAINTED); - return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags); -} - -static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) { - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) == - common::V1_0::PolicyFlag::WAKE); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) == - common::V1_0::PolicyFlag::VIRTUAL); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) == - common::V1_0::PolicyFlag::FUNCTION); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) == - common::V1_0::PolicyFlag::GESTURE); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) == - common::V1_0::PolicyFlag::INJECTED); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) == - common::V1_0::PolicyFlag::TRUSTED); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) == - common::V1_0::PolicyFlag::FILTERED); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) == - common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) == - common::V1_0::PolicyFlag::INTERACTIVE); - static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) == - common::V1_0::PolicyFlag::PASS_TO_USER); - return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags); -} - -static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) { - static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) == - common::V1_0::EdgeFlag::NONE); - static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) == - common::V1_0::EdgeFlag::TOP); - static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) == - common::V1_0::EdgeFlag::BOTTOM); - static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) == - common::V1_0::EdgeFlag::LEFT); - static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) == - common::V1_0::EdgeFlag::RIGHT); - return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags); -} - -static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) { - static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) == - common::V1_0::Meta::NONE); - static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) == - common::V1_0::Meta::ALT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) == - common::V1_0::Meta::ALT_LEFT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) == - common::V1_0::Meta::ALT_RIGHT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) == - common::V1_0::Meta::SHIFT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) == - common::V1_0::Meta::SHIFT_LEFT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) == - common::V1_0::Meta::SHIFT_RIGHT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) == - common::V1_0::Meta::SYM_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) == - common::V1_0::Meta::FUNCTION_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) == - common::V1_0::Meta::CTRL_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) == - common::V1_0::Meta::CTRL_LEFT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) == - common::V1_0::Meta::CTRL_RIGHT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) == - common::V1_0::Meta::META_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) == - common::V1_0::Meta::META_LEFT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) == - common::V1_0::Meta::META_RIGHT_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) == - common::V1_0::Meta::CAPS_LOCK_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) == - common::V1_0::Meta::NUM_LOCK_ON); - static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) == - common::V1_0::Meta::SCROLL_LOCK_ON); - return static_cast<hidl_bitfield<common::V1_0::Meta>>(state); -} - -static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) { - // No need for static_assert here. - // The button values have already been asserted in getActionButton(..) above - return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState); -} - -static common::V1_0::ToolType getToolType(int32_t toolType) { - static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) == - common::V1_0::ToolType::UNKNOWN); - static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) == - common::V1_0::ToolType::FINGER); - static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) == - common::V1_0::ToolType::STYLUS); - static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) == - common::V1_0::ToolType::MOUSE); - static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) == - common::V1_0::ToolType::ERASER); - return static_cast<common::V1_0::ToolType>(toolType); -} - -static common::V1_0::Axis getAxis(uint64_t axis) { - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) == - common::V1_0::Axis::X); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) == - common::V1_0::Axis::Y); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) == - common::V1_0::Axis::PRESSURE); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) == - common::V1_0::Axis::SIZE); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) == - common::V1_0::Axis::TOUCH_MAJOR); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) == - common::V1_0::Axis::TOUCH_MINOR); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) == - common::V1_0::Axis::TOOL_MAJOR); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) == - common::V1_0::Axis::TOOL_MINOR); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) == - common::V1_0::Axis::ORIENTATION); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) == - common::V1_0::Axis::VSCROLL); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) == - common::V1_0::Axis::HSCROLL); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) == - common::V1_0::Axis::Z); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) == - common::V1_0::Axis::RX); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) == - common::V1_0::Axis::RY); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) == - common::V1_0::Axis::RZ); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) == - common::V1_0::Axis::HAT_X); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) == - common::V1_0::Axis::HAT_Y); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) == - common::V1_0::Axis::LTRIGGER); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) == - common::V1_0::Axis::RTRIGGER); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) == - common::V1_0::Axis::THROTTLE); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) == - common::V1_0::Axis::RUDDER); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) == - common::V1_0::Axis::WHEEL); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) == - common::V1_0::Axis::GAS); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) == - common::V1_0::Axis::BRAKE); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) == - common::V1_0::Axis::DISTANCE); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) == - common::V1_0::Axis::TILT); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) == - common::V1_0::Axis::SCROLL); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) == - common::V1_0::Axis::RELATIVE_X); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) == - common::V1_0::Axis::RELATIVE_Y); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) == - common::V1_0::Axis::GENERIC_1); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) == - common::V1_0::Axis::GENERIC_2); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) == - common::V1_0::Axis::GENERIC_3); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) == - common::V1_0::Axis::GENERIC_4); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) == - common::V1_0::Axis::GENERIC_5); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) == - common::V1_0::Axis::GENERIC_6); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) == - common::V1_0::Axis::GENERIC_7); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) == - common::V1_0::Axis::GENERIC_8); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) == - common::V1_0::Axis::GENERIC_9); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) == - common::V1_0::Axis::GENERIC_10); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) == - common::V1_0::Axis::GENERIC_11); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) == - common::V1_0::Axis::GENERIC_12); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == - common::V1_0::Axis::GENERIC_13); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == - common::V1_0::Axis::GENERIC_14); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == - common::V1_0::Axis::GENERIC_15); - static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == - common::V1_0::Axis::GENERIC_16); - return static_cast<common::V1_0::Axis>(axis); -} - -static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) { - common::V1_0::VideoFrame out; - out.width = frame.getWidth(); - out.height = frame.getHeight(); - out.data = frame.getData(); - struct timeval timestamp = frame.getTimestamp(); - out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) + - microseconds_to_nanoseconds(timestamp.tv_usec); - return out; -} - -static std::vector<common::V1_0::VideoFrame> convertVideoFrames( - const std::vector<TouchVideoFrame>& frames) { - std::vector<common::V1_0::VideoFrame> out; - for (const TouchVideoFrame& frame : frames) { - out.push_back(getHalVideoFrame(frame)); - } - return out; -} - -static uint8_t getActionIndex(int32_t action) { - return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> - AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; -} - -static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args, - std::vector<common::V1_0::PointerProperties>* outPointerProperties, - std::vector<common::V1_0::PointerCoords>* outPointerCoords) { - outPointerProperties->reserve(args.pointerCount); - outPointerCoords->reserve(args.pointerCount); - for (size_t i = 0; i < args.pointerCount; i++) { - common::V1_0::PointerProperties properties; - properties.id = args.pointerProperties[i].id; - properties.toolType = getToolType(args.pointerProperties[i].toolType); - outPointerProperties->push_back(properties); - - common::V1_0::PointerCoords coords; - BitSet64 bits (args.pointerCoords[i].bits); - std::vector<float> values; - size_t index = 0; - while (!bits.isEmpty()) { - uint32_t axis = bits.clearFirstMarkedBit(); - coords.bits |= 1 << static_cast<uint64_t>(getAxis(axis)); - float value = args.pointerCoords[i].values[index++]; - values.push_back(value); - } - coords.values = values; - outPointerCoords->push_back(coords); - } -} - -static common::V1_0::MotionEvent getMotionEvent(const NotifyMotionArgs& args) { - common::V1_0::MotionEvent event; - event.deviceId = args.deviceId; - event.source = getSource(args.source); - event.displayId = args.displayId; - event.downTime = args.downTime; - event.eventTime = args.eventTime; - event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK); - event.actionIndex = getActionIndex(args.action); - event.actionButton = getActionButton(args.actionButton); - event.flags = getFlags(args.flags); - event.policyFlags = getPolicyFlags(args.policyFlags); - event.edgeFlags = getEdgeFlags(args.edgeFlags); - event.metaState = getMetastate(args.metaState); - event.buttonState = getButtonState(args.buttonState); - event.xPrecision = args.xPrecision; - event.yPrecision = args.yPrecision; - - std::vector<common::V1_0::PointerProperties> pointerProperties; - std::vector<common::V1_0::PointerCoords> pointerCoords; - getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords); - event.pointerProperties = pointerProperties; - event.pointerCoords = pointerCoords; - - event.deviceTimestamp = args.deviceTimestamp; - event.frames = convertVideoFrames(args.videoFrames); - - return event; -} - static MotionClassification getMotionClassification(common::V1_0::Classification classification) { static_assert(MotionClassification::NONE == static_cast<MotionClassification>(common::V1_0::Classification::NONE)); @@ -602,7 +236,8 @@ void MotionClassifier::callInputClassifierHal() { switch (event.type) { case ClassifierEventType::MOTION: { NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get()); - common::V1_0::MotionEvent motionEvent = getMotionEvent(*motionArgs); + common::V1_0::MotionEvent motionEvent = + notifyMotionArgsToHalMotionEvent(*motionArgs); Return<common::V1_0::Classification> response = mService->classify(motionEvent); halResponseOk = response.isOk(); if (halResponseOk) { diff --git a/services/inputflinger/InputClassifierConverter.cpp b/services/inputflinger/InputClassifierConverter.cpp new file mode 100644 index 0000000000..f82c8ef1fd --- /dev/null +++ b/services/inputflinger/InputClassifierConverter.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2019 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 "InputClassifierConverter.h" + +using android::hardware::hidl_bitfield; +using namespace android::hardware::input; + +namespace android { + +static common::V1_0::Source getSource(uint32_t source) { + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_UNKNOWN) == + common::V1_0::Source::UNKNOWN, "SOURCE_UNKNOWN mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_KEYBOARD) == + common::V1_0::Source::KEYBOARD, "SOURCE_KEYBOARD mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_DPAD) == + common::V1_0::Source::DPAD, "SOURCE_DPAD mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_GAMEPAD) == + common::V1_0::Source::GAMEPAD, "SOURCE_GAMEPAD mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHSCREEN) == + common::V1_0::Source::TOUCHSCREEN, "SOURCE_TOUCHSCREEN mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE) == + common::V1_0::Source::MOUSE, "SOURCE_MOUSE mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_STYLUS) == + common::V1_0::Source::STYLUS, "SOURCE_STYLUS mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_BLUETOOTH_STYLUS) == + common::V1_0::Source::BLUETOOTH_STYLUS, "SOURCE_BLUETOOTH_STYLUS mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TRACKBALL) == + common::V1_0::Source::TRACKBALL, "SOURCE_TRACKBALL mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_MOUSE_RELATIVE) == + common::V1_0::Source::MOUSE_RELATIVE, "SOURCE_MOUSE_RELATIVE mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCHPAD) == + common::V1_0::Source::TOUCHPAD, "SOURCE_TOUCHPAD mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_TOUCH_NAVIGATION) == + common::V1_0::Source::TOUCH_NAVIGATION, "SOURCE_TOUCH_NAVIGATION mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_JOYSTICK) == + common::V1_0::Source::JOYSTICK, "SOURCE_JOYSTICK mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ROTARY_ENCODER) == + common::V1_0::Source::ROTARY_ENCODER, "SOURCE_ROTARY_ENCODER mismatch"); + static_assert(static_cast<common::V1_0::Source>(AINPUT_SOURCE_ANY) == + common::V1_0::Source::ANY, "SOURCE_ANY mismatch"); + return static_cast<common::V1_0::Source>(source); +} + +static common::V1_0::Action getAction(int32_t actionMasked) { + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_DOWN) == + common::V1_0::Action::DOWN, "ACTION_DOWN mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_UP) == + common::V1_0::Action::UP, "ACTION_UP mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_MOVE) == + common::V1_0::Action::MOVE, "ACTION_MOVE mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_CANCEL) == + common::V1_0::Action::CANCEL, "ACTION_CANCEL mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_OUTSIDE) == + common::V1_0::Action::OUTSIDE, "ACTION_OUTSIDE mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_DOWN) == + common::V1_0::Action::POINTER_DOWN, "ACTION_POINTER_DOWN mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_POINTER_UP) == + common::V1_0::Action::POINTER_UP, "ACTION_POINTER_UP mismatch"); + static_assert(static_cast<common::V1_0::Action>( AMOTION_EVENT_ACTION_HOVER_MOVE) == + common::V1_0::Action::HOVER_MOVE, "ACTION_HOVER_MOVE mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_SCROLL) == + common::V1_0::Action::SCROLL, "ACTION_SCROLL mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_ENTER) == + common::V1_0::Action::HOVER_ENTER, "ACTION_HOVER_ENTER mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_HOVER_EXIT) == + common::V1_0::Action::HOVER_EXIT, "ACTION_HOVER_EXIT mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_PRESS) == + common::V1_0::Action::BUTTON_PRESS, "ACTION_BUTTON_PRESS mismatch"); + static_assert(static_cast<common::V1_0::Action>(AMOTION_EVENT_ACTION_BUTTON_RELEASE) == + common::V1_0::Action::BUTTON_RELEASE, "ACTION_BUTTON_RELEASE mismatch"); + return static_cast<common::V1_0::Action>(actionMasked); +} + +static common::V1_0::Button getActionButton(int32_t actionButton) { + static_assert(static_cast<common::V1_0::Button>(0) == + common::V1_0::Button::NONE, "BUTTON_NONE mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_PRIMARY) == + common::V1_0::Button::PRIMARY, "BUTTON_PRIMARY mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_SECONDARY) == + common::V1_0::Button::SECONDARY, "BUTTON_SECONDARY mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_TERTIARY) == + common::V1_0::Button::TERTIARY, "BUTTON_TERTIARY mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_BACK) == + common::V1_0::Button::BACK, "BUTTON_BACK mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_FORWARD) == + common::V1_0::Button::FORWARD, "BUTTON_FORWARD mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_PRIMARY) == + common::V1_0::Button::STYLUS_PRIMARY, "BUTTON_STYLUS_PRIMARY mismatch"); + static_assert(static_cast<common::V1_0::Button>(AMOTION_EVENT_BUTTON_STYLUS_SECONDARY) == + common::V1_0::Button::STYLUS_SECONDARY, "BUTTON_STYLUS_SECONDARY mismatch"); + return static_cast<common::V1_0::Button>(actionButton); +} + +static hidl_bitfield<common::V1_0::Flag> getFlags(int32_t flags) { + static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED) == + common::V1_0::Flag::WINDOW_IS_OBSCURED); + static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_IS_GENERATED_GESTURE) == + common::V1_0::Flag::IS_GENERATED_GESTURE); + static_assert(static_cast<common::V1_0::Flag>(AMOTION_EVENT_FLAG_TAINTED) == + common::V1_0::Flag::TAINTED); + return static_cast<hidl_bitfield<common::V1_0::Flag>>(flags); +} + +static hidl_bitfield<common::V1_0::PolicyFlag> getPolicyFlags(int32_t flags) { + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_WAKE) == + common::V1_0::PolicyFlag::WAKE); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_VIRTUAL) == + common::V1_0::PolicyFlag::VIRTUAL); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FUNCTION) == + common::V1_0::PolicyFlag::FUNCTION); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_GESTURE) == + common::V1_0::PolicyFlag::GESTURE); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INJECTED) == + common::V1_0::PolicyFlag::INJECTED); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_TRUSTED) == + common::V1_0::PolicyFlag::TRUSTED); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_FILTERED) == + common::V1_0::PolicyFlag::FILTERED); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_DISABLE_KEY_REPEAT) == + common::V1_0::PolicyFlag::DISABLE_KEY_REPEAT); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_INTERACTIVE) == + common::V1_0::PolicyFlag::INTERACTIVE); + static_assert(static_cast<common::V1_0::PolicyFlag>(POLICY_FLAG_PASS_TO_USER) == + common::V1_0::PolicyFlag::PASS_TO_USER); + return static_cast<hidl_bitfield<common::V1_0::PolicyFlag>>(flags); +} + +static hidl_bitfield<common::V1_0::EdgeFlag> getEdgeFlags(int32_t flags) { + static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_NONE) == + common::V1_0::EdgeFlag::NONE); + static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_TOP) == + common::V1_0::EdgeFlag::TOP); + static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_BOTTOM) == + common::V1_0::EdgeFlag::BOTTOM); + static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_LEFT) == + common::V1_0::EdgeFlag::LEFT); + static_assert(static_cast<common::V1_0::EdgeFlag>(AMOTION_EVENT_EDGE_FLAG_RIGHT) == + common::V1_0::EdgeFlag::RIGHT); + return static_cast<hidl_bitfield<common::V1_0::EdgeFlag>>(flags); +} + +static hidl_bitfield<common::V1_0::Meta> getMetastate(int32_t state) { + static_assert(static_cast<common::V1_0::Meta>(AMETA_NONE) == + common::V1_0::Meta::NONE); + static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_ON) == + common::V1_0::Meta::ALT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_LEFT_ON) == + common::V1_0::Meta::ALT_LEFT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_ALT_RIGHT_ON) == + common::V1_0::Meta::ALT_RIGHT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_ON) == + common::V1_0::Meta::SHIFT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_LEFT_ON) == + common::V1_0::Meta::SHIFT_LEFT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_SHIFT_RIGHT_ON) == + common::V1_0::Meta::SHIFT_RIGHT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_SYM_ON) == + common::V1_0::Meta::SYM_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_FUNCTION_ON) == + common::V1_0::Meta::FUNCTION_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_ON) == + common::V1_0::Meta::CTRL_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_LEFT_ON) == + common::V1_0::Meta::CTRL_LEFT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_CTRL_RIGHT_ON) == + common::V1_0::Meta::CTRL_RIGHT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_META_ON) == + common::V1_0::Meta::META_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_META_LEFT_ON) == + common::V1_0::Meta::META_LEFT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_META_RIGHT_ON) == + common::V1_0::Meta::META_RIGHT_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_CAPS_LOCK_ON) == + common::V1_0::Meta::CAPS_LOCK_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_NUM_LOCK_ON) == + common::V1_0::Meta::NUM_LOCK_ON); + static_assert(static_cast<common::V1_0::Meta>(AMETA_SCROLL_LOCK_ON) == + common::V1_0::Meta::SCROLL_LOCK_ON); + return static_cast<hidl_bitfield<common::V1_0::Meta>>(state); +} + +static hidl_bitfield<common::V1_0::Button> getButtonState(int32_t buttonState) { + // No need for static_assert here. + // The button values have already been asserted in getActionButton(..) above + return static_cast<hidl_bitfield<common::V1_0::Button>>(buttonState); +} + +static common::V1_0::ToolType getToolType(int32_t toolType) { + static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_UNKNOWN) == + common::V1_0::ToolType::UNKNOWN); + static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_FINGER) == + common::V1_0::ToolType::FINGER); + static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_STYLUS) == + common::V1_0::ToolType::STYLUS); + static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_MOUSE) == + common::V1_0::ToolType::MOUSE); + static_assert(static_cast<common::V1_0::ToolType>(AMOTION_EVENT_TOOL_TYPE_ERASER) == + common::V1_0::ToolType::ERASER); + return static_cast<common::V1_0::ToolType>(toolType); +} + +// MotionEvent axes asserts +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_X) == + common::V1_0::Axis::X); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Y) == + common::V1_0::Axis::Y); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_PRESSURE) == + common::V1_0::Axis::PRESSURE); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SIZE) == + common::V1_0::Axis::SIZE); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MAJOR) == + common::V1_0::Axis::TOUCH_MAJOR); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOUCH_MINOR) == + common::V1_0::Axis::TOUCH_MINOR); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MAJOR) == + common::V1_0::Axis::TOOL_MAJOR); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TOOL_MINOR) == + common::V1_0::Axis::TOOL_MINOR); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_ORIENTATION) == + common::V1_0::Axis::ORIENTATION); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_VSCROLL) == + common::V1_0::Axis::VSCROLL); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HSCROLL) == + common::V1_0::Axis::HSCROLL); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_Z) == + common::V1_0::Axis::Z); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RX) == + common::V1_0::Axis::RX); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RY) == + common::V1_0::Axis::RY); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RZ) == + common::V1_0::Axis::RZ); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_X) == + common::V1_0::Axis::HAT_X); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_HAT_Y) == + common::V1_0::Axis::HAT_Y); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_LTRIGGER) == + common::V1_0::Axis::LTRIGGER); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RTRIGGER) == + common::V1_0::Axis::RTRIGGER); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_THROTTLE) == + common::V1_0::Axis::THROTTLE); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RUDDER) == + common::V1_0::Axis::RUDDER); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_WHEEL) == + common::V1_0::Axis::WHEEL); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GAS) == + common::V1_0::Axis::GAS); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_BRAKE) == + common::V1_0::Axis::BRAKE); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_DISTANCE) == + common::V1_0::Axis::DISTANCE); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_TILT) == + common::V1_0::Axis::TILT); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_SCROLL) == + common::V1_0::Axis::SCROLL); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_X) == + common::V1_0::Axis::RELATIVE_X); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_RELATIVE_Y) == + common::V1_0::Axis::RELATIVE_Y); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_1) == + common::V1_0::Axis::GENERIC_1); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_2) == + common::V1_0::Axis::GENERIC_2); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_3) == + common::V1_0::Axis::GENERIC_3); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_4) == + common::V1_0::Axis::GENERIC_4); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_5) == + common::V1_0::Axis::GENERIC_5); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_6) == + common::V1_0::Axis::GENERIC_6); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_7) == + common::V1_0::Axis::GENERIC_7); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_8) == + common::V1_0::Axis::GENERIC_8); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_9) == + common::V1_0::Axis::GENERIC_9); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_10) == + common::V1_0::Axis::GENERIC_10); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_11) == + common::V1_0::Axis::GENERIC_11); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_12) == + common::V1_0::Axis::GENERIC_12); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_13) == + common::V1_0::Axis::GENERIC_13); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_14) == + common::V1_0::Axis::GENERIC_14); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_15) == + common::V1_0::Axis::GENERIC_15); +static_assert(static_cast<common::V1_0::Axis>(AMOTION_EVENT_AXIS_GENERIC_16) == + common::V1_0::Axis::GENERIC_16); + +static common::V1_0::VideoFrame getHalVideoFrame(const TouchVideoFrame& frame) { + common::V1_0::VideoFrame out; + out.width = frame.getWidth(); + out.height = frame.getHeight(); + out.data = frame.getData(); + struct timeval timestamp = frame.getTimestamp(); + out.timestamp = seconds_to_nanoseconds(timestamp.tv_sec) + + microseconds_to_nanoseconds(timestamp.tv_usec); + return out; +} + +static std::vector<common::V1_0::VideoFrame> convertVideoFrames( + const std::vector<TouchVideoFrame>& frames) { + std::vector<common::V1_0::VideoFrame> out; + for (const TouchVideoFrame& frame : frames) { + out.push_back(getHalVideoFrame(frame)); + } + return out; +} + +static uint8_t getActionIndex(int32_t action) { + return (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> + AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; +} + +static void getHidlPropertiesAndCoords(const NotifyMotionArgs& args, + std::vector<common::V1_0::PointerProperties>* outPointerProperties, + std::vector<common::V1_0::PointerCoords>* outPointerCoords) { + outPointerProperties->reserve(args.pointerCount); + outPointerCoords->reserve(args.pointerCount); + for (size_t i = 0; i < args.pointerCount; i++) { + common::V1_0::PointerProperties properties; + properties.id = args.pointerProperties[i].id; + properties.toolType = getToolType(args.pointerProperties[i].toolType); + outPointerProperties->push_back(properties); + + common::V1_0::PointerCoords coords; + // OK to copy bits because we have static_assert for pointerCoords axes + coords.bits = args.pointerCoords[i].bits; + coords.values = std::vector<float>( + args.pointerCoords[i].values, + args.pointerCoords[i].values + BitSet64::count(args.pointerCoords[i].bits)); + outPointerCoords->push_back(coords); + } +} + +common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent(const NotifyMotionArgs& args) { + common::V1_0::MotionEvent event; + event.deviceId = args.deviceId; + event.source = getSource(args.source); + event.displayId = args.displayId; + event.downTime = args.downTime; + event.eventTime = args.eventTime; + event.action = getAction(args.action & AMOTION_EVENT_ACTION_MASK); + event.actionIndex = getActionIndex(args.action); + event.actionButton = getActionButton(args.actionButton); + event.flags = getFlags(args.flags); + event.policyFlags = getPolicyFlags(args.policyFlags); + event.edgeFlags = getEdgeFlags(args.edgeFlags); + event.metaState = getMetastate(args.metaState); + event.buttonState = getButtonState(args.buttonState); + event.xPrecision = args.xPrecision; + event.yPrecision = args.yPrecision; + + std::vector<common::V1_0::PointerProperties> pointerProperties; + std::vector<common::V1_0::PointerCoords> pointerCoords; + getHidlPropertiesAndCoords(args, /*out*/&pointerProperties, /*out*/&pointerCoords); + event.pointerProperties = pointerProperties; + event.pointerCoords = pointerCoords; + + event.deviceTimestamp = args.deviceTimestamp; + event.frames = convertVideoFrames(args.videoFrames); + + return event; +} + +} // namespace android diff --git a/services/inputflinger/InputClassifierConverter.h b/services/inputflinger/InputClassifierConverter.h new file mode 100644 index 0000000000..5154b0bd06 --- /dev/null +++ b/services/inputflinger/InputClassifierConverter.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 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_CLASSIFIER_CONVERTER_H +#define _UI_INPUT_CLASSIFIER_CONVERTER_H + +#include "InputListener.h" +#include <android/hardware/input/common/1.0/types.h> + + +namespace android { + +/** + * Convert from framework's NotifyMotionArgs to hidl's common::V1_0::MotionEvent + */ +::android::hardware::input::common::V1_0::MotionEvent notifyMotionArgsToHalMotionEvent( + const NotifyMotionArgs& args); + +} // namespace android + +#endif // _UI_INPUT_CLASSIFIER_CONVERTER_H diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index 1835449b5d..9054316204 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -6,6 +6,7 @@ cc_test { "BlockingQueue_test.cpp", "TestInputListener.cpp", "InputClassifier_test.cpp", + "InputClassifierConverter_test.cpp", "InputDispatcher_test.cpp", "InputReader_test.cpp", ], diff --git a/services/inputflinger/tests/InputClassifierConverter_test.cpp b/services/inputflinger/tests/InputClassifierConverter_test.cpp new file mode 100644 index 0000000000..813b69edbb --- /dev/null +++ b/services/inputflinger/tests/InputClassifierConverter_test.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2019 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 "../InputClassifierConverter.h" + +#include <gtest/gtest.h> +#include <utils/BitSet.h> + + +using namespace android::hardware::input; + +namespace android { + +// --- InputClassifierConverterTest --- + +static NotifyMotionArgs generateBasicMotionArgs() { + // Create a basic motion event for testing + PointerProperties properties; + properties.id = 0; + properties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER; + + PointerCoords coords; + coords.clear(); + coords.setAxisValue(AMOTION_EVENT_AXIS_X, 1); + coords.setAxisValue(AMOTION_EVENT_AXIS_Y, 2); + coords.setAxisValue(AMOTION_EVENT_AXIS_SIZE, 0.5); + static constexpr nsecs_t downTime = 2; + NotifyMotionArgs motionArgs(1/*sequenceNum*/, downTime/*eventTime*/, 3/*deviceId*/, + AINPUT_SOURCE_ANY, ADISPLAY_ID_DEFAULT, 4/*policyFlags*/, AMOTION_EVENT_ACTION_DOWN, + 0/*actionButton*/, 0/*flags*/, AMETA_NONE, 0/*buttonState*/, MotionClassification::NONE, + AMOTION_EVENT_EDGE_FLAG_NONE, 5/*deviceTimestamp*/, + 1/*pointerCount*/, &properties, &coords, 0/*xPrecision*/, 0/*yPrecision*/, + downTime, {}/*videoFrames*/); + return motionArgs; +} + +static float getMotionEventAxis(common::V1_0::PointerCoords coords, + common::V1_0::Axis axis) { + uint32_t index = BitSet64::getIndexOfBit(static_cast<uint64_t>(coords.bits), + static_cast<uint64_t>(axis)); + return coords.values[index]; +} + +/** + * Check that coordinates get converted properly from the framework's PointerCoords + * to the hidl PointerCoords in input::common. + */ +TEST(InputClassifierConverterTest, PointerCoordsAxes) { + const NotifyMotionArgs motionArgs = generateBasicMotionArgs(); + ASSERT_EQ(1, motionArgs.pointerCoords[0].getX()); + ASSERT_EQ(2, motionArgs.pointerCoords[0].getY()); + ASSERT_EQ(0.5, motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE)); + ASSERT_EQ(3U, BitSet64::count(motionArgs.pointerCoords[0].bits)); + + common::V1_0::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs); + + ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::X), + motionArgs.pointerCoords[0].getX()); + ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::Y), + motionArgs.pointerCoords[0].getY()); + ASSERT_EQ(getMotionEventAxis(motionEvent.pointerCoords[0], common::V1_0::Axis::SIZE), + motionArgs.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_SIZE)); + ASSERT_EQ(BitSet64::count(motionArgs.pointerCoords[0].bits), + BitSet64::count(motionEvent.pointerCoords[0].bits)); +} + +} // namespace android diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 06caf1e2dc..a2b6ab6b4d 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -97,8 +97,11 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } bool BufferLayer::isVisible() const { - return !(isHiddenByPolicy()) && getAlpha() > 0.0f && + bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && (mActiveBuffer != nullptr || mSidebandStream != nullptr); + mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); + + return visible; } bool BufferLayer::isFixedSize() const { @@ -427,7 +430,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) sp<GraphicBuffer> oldBuffer = mActiveBuffer; if (!allTransactionsSignaled()) { - mFlinger->signalLayerUpdate(); + mFlinger->setTransactionFlags(eTraversalNeeded); return false; } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 3d51ec33b2..bd0b55f688 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -443,7 +443,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { { // Autolock scope if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->addLayerPresentTime(mSchedulerLayerHandle, presentTime); + mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, + item.mHdrMetadata.validTypes != 0); } Mutex::Autolock lock(mQueueItemLock); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index a740afbe7e..05c721f141 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -227,7 +227,8 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, nsecs_t postTi if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = (mDesiredPresentTime == -1) ? 0 : mDesiredPresentTime; - mFlinger->mScheduler->addLayerPresentTime(mSchedulerLayerHandle, presentTime); + mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, + mCurrentState.hdrMetadata.validTypes != 0); } return true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cbe8b299db..379b004f9e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2004,10 +2004,14 @@ InputWindowInfo Layer::fillInputInfo() { ui::Transform t = getTransform(); const float xScale = t.sx(); const float yScale = t.sy(); + float xSurfaceInset = info.surfaceInset; + float ySurfaceInset = info.surfaceInset; if (xScale != 1.0f || yScale != 1.0f) { info.windowXScale *= 1.0f / xScale; info.windowYScale *= 1.0f / yScale; info.touchableRegion.scaleSelf(xScale, yScale); + xSurfaceInset *= xScale; + ySurfaceInset *= yScale; } // Transform layer size to screen space and inset it by surface insets. @@ -2019,7 +2023,7 @@ InputWindowInfo Layer::fillInputInfo() { layerBounds = getCroppedBufferSize(getDrawingState()); } layerBounds = t.transform(layerBounds); - layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset); + layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset); // Input coordinate should match the layer bounds. info.frameLeft = layerBounds.left; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 1e5c25fb93..5b4bec96ea 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -37,9 +37,16 @@ bool RefreshRateOverlay::createLayer() { return false; } + Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true); - mLayer->setLayer(INT32_MAX - 2); + + // setting Layer's Z requires resorting layersSortedByZ + ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); + if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) { + mFlinger.mCurrentState.layersSortedByZ.removeAt(idx); + mFlinger.mCurrentState.layersSortedByZ.add(mLayer); + } return true; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 8e36ae9dc0..1db43a32cd 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -67,7 +67,8 @@ void LayerHistory::destroyLayer(const int64_t id) { } } -void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime) { +void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, + bool isHdr) { std::shared_ptr<LayerInfo> layerInfo; { std::lock_guard lock(mLock); @@ -88,9 +89,36 @@ void LayerHistory::insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs } } layerInfo->setLastPresentTime(presentTime); + layerInfo->setHDRContent(isHdr); } -float LayerHistory::getDesiredRefreshRate() { +void LayerHistory::setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible) { + std::shared_ptr<LayerInfo> layerInfo; + { + std::lock_guard lock(mLock); + auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); + if (layerInfoIterator != mInactiveLayerInfos.end()) { + layerInfo = layerInfoIterator->second; + if (visible) { + mInactiveLayerInfos.erase(layerInfoIterator); + mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); + } + } else { + layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); + if (layerInfoIterator != mActiveLayerInfos.end()) { + layerInfo = layerInfoIterator->second; + } else { + ALOGW("Inserting information about layer that is not registered: %" PRId64, + layerHandle->mId); + return; + } + } + } + layerInfo->setVisibility(visible); +} + +std::pair<float, bool> LayerHistory::getDesiredRefreshRateAndHDR() { + bool isHDR = false; float newRefreshRate = 0.f; std::lock_guard lock(mLock); @@ -108,12 +136,13 @@ float LayerHistory::getDesiredRefreshRate() { if (layerInfo->isRecentlyActive() && layerRefreshRate > newRefreshRate) { newRefreshRate = layerRefreshRate; } + isHDR |= layerInfo->getHDRContent(); } if (mTraceEnabled) { ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate); } - return newRefreshRate; + return {newRefreshRate, isHDR}; } void LayerHistory::removeIrrelevantLayers() { @@ -122,7 +151,9 @@ void LayerHistory::removeIrrelevantLayers() { auto it = mActiveLayerInfos.begin(); while (it != mActiveLayerInfos.end()) { // If last updated was before the obsolete time, remove it. - if (it->second->getLastUpdatedTime() < obsoleteEpsilon) { + // Keep HDR layer around as long as they are visible. + if (!it->second->isVisible() || + (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) { // erase() function returns the iterator of the next // to last deleted element. if (mTraceEnabled) { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 39061e7fdf..adc5ce5f64 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -56,10 +56,13 @@ public: std::unique_ptr<LayerHandle> createLayer(const std::string name, float maxRefreshRate); // Method for inserting layers and their requested present time into the unordered map. - void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime); + void insert(const std::unique_ptr<LayerHandle>& layerHandle, nsecs_t presentTime, bool isHdr); + // Method for setting layer visibility + void setVisibility(const std::unique_ptr<LayerHandle>& layerHandle, bool visible); + // Returns the desired refresh rate, which is a max refresh rate of all the current // layers. See go/content-fps-detection-in-scheduler for more information. - float getDesiredRefreshRate(); + std::pair<float, bool> getDesiredRefreshRateAndHDR(); // Removes the handle and the object from the map. void destroyLayer(const int64_t id); diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 1970a47701..02b6aefa2b 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -115,6 +115,16 @@ public: // updated time, the updated time is the present time. void setLastPresentTime(nsecs_t lastPresentTime); + void setHDRContent(bool isHdr) { + std::lock_guard lock(mLock); + mIsHDR = isHdr; + } + + void setVisibility(bool visible) { + std::lock_guard lock(mLock); + mIsVisible = visible; + } + // Checks the present time history to see whether the layer is relevant. bool isRecentlyActive() const { std::lock_guard lock(mLock); @@ -127,6 +137,16 @@ public: return mRefreshRateHistory.getRefreshRateAvg(); } + bool getHDRContent() { + std::lock_guard lock(mLock); + return mIsHDR; + } + + bool isVisible() { + std::lock_guard lock(mLock); + return mIsVisible; + } + // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. nsecs_t getLastUpdatedTime() { @@ -150,6 +170,8 @@ private: nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock); PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock); + bool mIsHDR GUARDED_BY(mLock) = false; + bool mIsVisible GUARDED_BY(mLock) = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index b91c66eb0b..3f9a88df75 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -317,10 +317,15 @@ std::unique_ptr<scheduler::LayerHistory::LayerHandle> Scheduler::registerLayer( return mLayerHistory.createLayer(name, fps); } -void Scheduler::addLayerPresentTime( +void Scheduler::addLayerPresentTimeAndHDR( const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, - nsecs_t presentTime) { - mLayerHistory.insert(layerHandle, presentTime); + nsecs_t presentTime, bool isHDR) { + mLayerHistory.insert(layerHandle, presentTime, isHDR); +} + +void Scheduler::setLayerVisibility( + const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, bool visible) { + mLayerHistory.setVisibility(layerHandle, visible); } void Scheduler::withPrimaryDispSync(std::function<void(DispSync&)> const& fn) { @@ -328,18 +333,23 @@ void Scheduler::withPrimaryDispSync(std::function<void(DispSync&)> const& fn) { } void Scheduler::updateFpsBasedOnContent() { - uint32_t refreshRate = std::round(mLayerHistory.getDesiredRefreshRate()); + auto [refreshRate, isHDR] = mLayerHistory.getDesiredRefreshRateAndHDR(); + const uint32_t refreshRateRound = std::round(refreshRate); RefreshRateType newRefreshRateType; { std::lock_guard<std::mutex> lock(mFeatureStateLock); - if (mContentRefreshRate == refreshRate) { + if (mContentRefreshRate == refreshRateRound && mIsHDRContent == isHDR) { return; } - mContentRefreshRate = refreshRate; + mContentRefreshRate = refreshRateRound; ATRACE_INT("ContentFPS", mContentRefreshRate); - mCurrentContentFeatureState = refreshRate > 0 ? ContentFeatureState::CONTENT_DETECTION_ON - : ContentFeatureState::CONTENT_DETECTION_OFF; + mIsHDRContent = isHDR; + ATRACE_INT("ContentHDR", mIsHDRContent); + + mCurrentContentFeatureState = refreshRateRound > 0 + ? ContentFeatureState::CONTENT_DETECTION_ON + : ContentFeatureState::CONTENT_DETECTION_OFF; newRefreshRateType = calculateRefreshRateType(); if (mRefreshRateType == newRefreshRateType) { return; @@ -429,6 +439,11 @@ Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { return RefreshRateType::DEFAULT; } + // HDR content is not supported on PERFORMANCE mode + if (mForceHDRContentToDefaultRefreshRate && mIsHDRContent) { + return RefreshRateType::DEFAULT; + } + // If content detection is off we choose performance as we don't know the content fps if (mCurrentContentFeatureState == ContentFeatureState::CONTENT_DETECTION_OFF) { return RefreshRateType::PERFORMANCE; diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index c8ff3779f2..7c8adf0036 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -150,9 +150,12 @@ public: int windowType); // Stores present time for a layer. - void addLayerPresentTime( + void addLayerPresentTimeAndHDR( const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, - nsecs_t presentTime); + nsecs_t presentTime, bool isHDR); + // Stores visibility for a layer. + void setLayerVisibility( + const std::unique_ptr<scheduler::LayerHistory::LayerHandle>& layerHandle, bool visible); // Updates FPS based on the most content presented. void updateFpsBasedOnContent(); // Callback that gets invoked when Scheduler wants to change the refresh rate. @@ -267,8 +270,12 @@ private: IdleTimerState mCurrentIdleTimerState GUARDED_BY(mFeatureStateLock) = IdleTimerState::RESET; uint32_t mContentRefreshRate GUARDED_BY(mFeatureStateLock); RefreshRateType mRefreshRateType GUARDED_BY(mFeatureStateLock); + bool mIsHDRContent GUARDED_BY(mFeatureStateLock) = false; const scheduler::RefreshRateConfigs& mRefreshRateConfigs; + + // Global config to force HDR content to work on DEFAULT refreshRate + static constexpr bool mForceHDRContentToDefaultRefreshRate = true; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 897f7b4e64..3f2240ee57 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3568,7 +3568,7 @@ bool SurfaceFlinger::flushTransactionQueues() { it = mTransactionQueues.erase(it); mTransactionCV.broadcast(); } else { - std::next(it, 1); + it = std::next(it, 1); } } } @@ -5104,7 +5104,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_SCREEN_BY_ID: { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); - if ((uid == AID_GRAPHICS) || (uid == AID_SYSTEM) || (uid == AID_SHELL)) { + if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) { return OK; } return PERMISSION_DENIED; @@ -5436,9 +5436,13 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r // TODO(b/129297325): expose this via developer menu option n = data.readInt32(); if (n && !mRefreshRateOverlay) { - std::lock_guard<std::mutex> lock(mActiveConfigLock); + RefreshRateType type; + { + std::lock_guard<std::mutex> lock(mActiveConfigLock); + type = mDesiredActiveConfig.type; + } mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*this); - mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); + mRefreshRateOverlay->changeRefreshRate(type); } else if (!n) { mRefreshRateOverlay.reset(); } diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index e51121fcf7..2b1dfa8f38 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -37,74 +37,93 @@ namespace { TEST_F(LayerHistoryTest, oneLayer) { std::unique_ptr<LayerHistory::LayerHandle> testLayer = mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(testLayer, true); - mLayerHistory->insert(testLayer, 0); - EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRate()); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); // This is still 0, because the layer is not considered recently active if it // has been present in less than 10 frames. - EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRate()); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); - mLayerHistory->insert(testLayer, 0); + EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); // This should be MAX_REFRESH_RATE as we have more than 10 samples - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); +} + +TEST_F(LayerHistoryTest, oneHDRLayer) { + std::unique_ptr<LayerHistory::LayerHandle> testLayer = + mLayerHistory->createLayer("TestHDRLayer", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(testLayer, true); + + mLayerHistory->insert(testLayer, 0, true /*isHDR*/); + EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + EXPECT_EQ(true, mLayerHistory->getDesiredRefreshRateAndHDR().second); + + mLayerHistory->setVisibility(testLayer, false); + EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + EXPECT_EQ(false, mLayerHistory->getDesiredRefreshRateAndHDR().second); } TEST_F(LayerHistoryTest, explicitTimestamp) { std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer = mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(test30FpsLayer, true); nsecs_t startTime = systemTime(); for (int i = 0; i < 31; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333)); + mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/); } - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); } TEST_F(LayerHistoryTest, multipleLayers) { std::unique_ptr<LayerHistory::LayerHandle> testLayer = mLayerHistory->createLayer("TestLayer", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(testLayer, true); std::unique_ptr<LayerHistory::LayerHandle> test30FpsLayer = mLayerHistory->createLayer("30FpsLayer", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(test30FpsLayer, true); std::unique_ptr<LayerHistory::LayerHandle> testLayer2 = mLayerHistory->createLayer("TestLayer2", MAX_REFRESH_RATE); + mLayerHistory->setVisibility(testLayer2, true); nsecs_t startTime = systemTime(); for (int i = 0; i < 10; i++) { - mLayerHistory->insert(testLayer, 0); + mLayerHistory->insert(testLayer, 0, false /*isHDR*/); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); startTime = systemTime(); for (int i = 0; i < 10; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333)); + mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); for (int i = 10; i < 30; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333)); + mLayerHistory->insert(test30FpsLayer, startTime + (i * 33333333), false /*isHDR*/); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); // This frame is only around for 9 occurrences, so it doesn't throw // anything off. for (int i = 0; i < 9; i++) { - mLayerHistory->insert(testLayer2, 0); + mLayerHistory->insert(testLayer2, 0, false /*isHDR*/); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRate()); + EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); // After 100 ms frames become obsolete. std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Insert the 31st frame. - mLayerHistory->insert(test30FpsLayer, startTime + (30 * 33333333)); - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRate()); + mLayerHistory->insert(test30FpsLayer, startTime + (30 * 33333333), false /*isHDR*/); + EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); } } // namespace |