diff options
-rw-r--r-- | cmds/dumpstate/dumpstate.cpp | 18 | ||||
-rw-r--r-- | cmds/dumpstate/dumpstate.h | 3 | ||||
-rw-r--r-- | libs/binder/ndk/include_cpp/android/binder_to_string.h | 8 | ||||
-rw-r--r-- | libs/binder/ndk/include_platform/android/binder_manager.h | 61 | ||||
-rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 2 | ||||
-rw-r--r-- | libs/binder/ndk/service_manager.cpp | 62 | ||||
-rw-r--r-- | libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp | 41 | ||||
-rw-r--r-- | libs/binder/rust/Android.bp | 2 | ||||
-rw-r--r-- | libs/binder/rust/src/native.rs | 7 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 12 | ||||
-rw-r--r-- | libs/gui/include/gui/Surface.h | 5 | ||||
-rw-r--r-- | services/inputflinger/TEST_MAPPING | 3 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 11 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 53 | ||||
-rw-r--r-- | services/sensorservice/aidl/EventQueue.cpp | 1 |
15 files changed, 271 insertions, 18 deletions
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp index ee1c63a3ff..12de33f2db 100644 --- a/cmds/dumpstate/dumpstate.cpp +++ b/cmds/dumpstate/dumpstate.cpp @@ -194,6 +194,8 @@ static const std::string TOMBSTONE_DIR = "/data/tombstones/"; static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_"; static const std::string ANR_DIR = "/data/anr/"; static const std::string ANR_FILE_PREFIX = "anr_"; +static const std::string SHUTDOWN_CHECKPOINTS_DIR = "/data/system/shutdown-checkpoints/"; +static const std::string SHUTDOWN_CHECKPOINTS_FILE_PREFIX = "checkpoints-"; // TODO: temporary variables and functions used during C++ refactoring @@ -1109,6 +1111,16 @@ static void DumpIpTablesAsRoot() { RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); } +static void DumpShutdownCheckpoints() { + const bool shutdown_checkpoints_dumped = AddDumps( + ds.shutdown_checkpoints_.begin(), ds.shutdown_checkpoints_.end(), + "SHUTDOWN CHECKPOINTS", false /* add_to_zip */); + if (!shutdown_checkpoints_dumped) { + printf("*** NO SHUTDOWN CHECKPOINTS to dump in %s\n\n", + SHUTDOWN_CHECKPOINTS_DIR.c_str()); + } +} + static void DumpDynamicPartitionInfo() { if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) { return; @@ -1701,6 +1713,8 @@ static Dumpstate::RunStatus dumpstate() { DoKmsg(); + DumpShutdownCheckpoints(); + DumpIpAddrAndRules(); dump_route_tables(); @@ -1855,6 +1869,8 @@ Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() { if (!PropertiesHelper::IsDryRun()) { ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX); ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX); + ds.shutdown_checkpoints_ = GetDumpFds( + SHUTDOWN_CHECKPOINTS_DIR, SHUTDOWN_CHECKPOINTS_FILE_PREFIX); } ds.AddDir(RECOVERY_DIR, true); @@ -2907,6 +2923,7 @@ void Dumpstate::Cancel() { } tombstone_data_.clear(); anr_data_.clear(); + shutdown_checkpoints_.clear(); // Instead of shutdown the pool, we delete temporary files directly since // shutdown blocking the call. @@ -3190,6 +3207,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, tombstone_data_.clear(); anr_data_.clear(); + shutdown_checkpoints_.clear(); return (consent_callback_ != nullptr && consent_callback_->getResult() == UserConsentResult::UNAVAILABLE) diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h index 66f84cb1c1..7ffe80eba3 100644 --- a/cmds/dumpstate/dumpstate.h +++ b/cmds/dumpstate/dumpstate.h @@ -499,6 +499,9 @@ class Dumpstate { // List of open ANR dump files. std::vector<DumpData> anr_data_; + // List of open shutdown checkpoint files. + std::vector<DumpData> shutdown_checkpoints_; + // A thread pool to execute dump tasks simultaneously if the parallel run is enabled. std::unique_ptr<android::os::dumpstate::DumpPool> dump_pool_; diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h index 6a25db220f..2a00736bc3 100644 --- a/libs/binder/ndk/include_cpp/android/binder_to_string.h +++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h @@ -160,7 +160,7 @@ class ToEmptyString { template <typename _T> std::string ToString(const _T& t) { if constexpr (details::ToEmptyString<_T>::value) { - return ""; + return "<unimplemented>"; } else if constexpr (std::is_same_v<bool, _T>) { return t ? "true" : "false"; } else if constexpr (std::is_same_v<char16_t, _T>) { @@ -176,9 +176,11 @@ std::string ToString(const _T& t) { return t; #ifdef HAS_NDK_INTERFACE } else if constexpr (std::is_same_v<::ndk::SpAIBinder, _T>) { - return (t.get() == nullptr) ? "(null)" : ""; + std::stringstream ss; + ss << "binder:" << std::hex << t.get(); + return ss.str(); } else if constexpr (std::is_same_v<::ndk::ScopedFileDescriptor, _T>) { - return (t.get() == -1) ? "(null)" : ""; + return "fd:" + std::to_string(t.get()); #endif #ifdef HAS_STRING16 } else if constexpr (std::is_same_v<String16, _T>) { diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h index 36273bc769..ad4188f499 100644 --- a/libs/binder/ndk/include_platform/android/binder_manager.h +++ b/libs/binder/ndk/include_platform/android/binder_manager.h @@ -109,6 +109,67 @@ __attribute__((warn_unused_result)) AIBinder* AServiceManager_waitForService(con __INTRODUCED_IN(31); /** + * Function to call when a service is registered. The instance is passed as well as + * ownership of the binder named 'registered'. + * + * WARNING: a lock is held when this method is called in order to prevent races with + * AServiceManager_NotificationRegistration_delete. Do not make synchronous binder calls when + * implementing this method to avoid deadlocks. + * + * \param instance instance name of service registered + * \param registered ownership-passed instance of service registered + * \param cookie data passed during registration for notifications + */ +typedef void (*AServiceManager_onRegister)(const char* instance, AIBinder* registered, + void* cookie); + +/** + * Represents a registration to servicemanager which can be cleared anytime. + */ +struct AServiceManager_NotificationRegistration; + +/** + * Get notifications when a service is registered. If the service is already registered, + * you will immediately get a notification. + * + * WARNING: it is strongly recommended to use AServiceManager_waitForService API instead. + * That API will wait synchronously, which is what you usually want in cases, including + * using some feature or during boot up. There is a history of bugs where waiting for + * notifications like this races with service startup. Also, when this API is used, a service + * bug will result in silent failure (rather than a debuggable deadlock). Furthermore, there + * is a history of this API being used to know when a service is up as a proxy for whethre + * that service should be started. This should only be used if you are intending to get + * ahold of the service as a client. For lazy services, whether a service is registered + * should not be used as a proxy for when it should be registered, which is only known + * by the real client. + * + * WARNING: if you use this API, you must also ensure that you check missing services are + * started and crash otherwise. If service failures are ignored, the system rots. + * + * \param instance name of service to wait for notifications about + * \param onRegister callback for when service is registered + * \param cookie data associated with this callback + * + * \return the token for this registration. Deleting this token will unregister. + */ +__attribute__((warn_unused_result)) AServiceManager_NotificationRegistration* +AServiceManager_registerForServiceNotifications(const char* instance, + AServiceManager_onRegister onRegister, void* cookie) + __INTRODUCED_IN(34); + +/** + * Unregister for notifications and delete the object. + * + * After this method is called, the callback is guaranteed to no longer be invoked. This will block + * until any in-progress onRegister callbacks have completed. It is therefore safe to immediately + * destroy the void* cookie that was registered when this method returns. + * + * \param notification object to dismiss + */ +void AServiceManager_NotificationRegistration_delete( + AServiceManager_NotificationRegistration* notification) __INTRODUCED_IN(34); + +/** * Check if a service is declared (e.g. VINTF manifest). * * \param instance identifier of the service. diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 32ca5649dd..5c7005ceb7 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -155,6 +155,8 @@ LIBBINDER_NDK33 { # introduced=33 LIBBINDER_NDK34 { # introduced=UpsideDownCake global: AServiceManager_getUpdatableApexName; # systemapi + AServiceManager_registerForServiceNotifications; # systemapi llndk + AServiceManager_NotificationRegistration_delete; # systemapi llndk }; LIBBINDER_NDK_PLATFORM { diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp index a12d0e9e8d..e107c83d14 100644 --- a/libs/binder/ndk/service_manager.cpp +++ b/libs/binder/ndk/service_manager.cpp @@ -28,6 +28,7 @@ using ::android::IBinder; using ::android::IServiceManager; using ::android::sp; using ::android::status_t; +using ::android::statusToString; using ::android::String16; using ::android::String8; @@ -86,6 +87,67 @@ AIBinder* AServiceManager_waitForService(const char* instance) { AIBinder_incStrong(ret.get()); return ret.get(); } +typedef void (*AServiceManager_onRegister)(const char* instance, AIBinder* registered, + void* cookie); + +struct AServiceManager_NotificationRegistration + : public IServiceManager::LocalRegistrationCallback { + std::mutex m; + const char* instance = nullptr; + void* cookie = nullptr; + AServiceManager_onRegister onRegister = nullptr; + + virtual void onServiceRegistration(const String16& smInstance, const sp<IBinder>& binder) { + std::lock_guard<std::mutex> l(m); + if (onRegister == nullptr) return; + + CHECK_EQ(String8(smInstance), instance); + + sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(binder); + AIBinder_incStrong(ret.get()); + + onRegister(instance, ret.get(), cookie); + } + + void clear() { + std::lock_guard<std::mutex> l(m); + instance = nullptr; + cookie = nullptr; + onRegister = nullptr; + } +}; + +__attribute__((warn_unused_result)) AServiceManager_NotificationRegistration* +AServiceManager_registerForServiceNotifications(const char* instance, + AServiceManager_onRegister onRegister, + void* cookie) { + CHECK_NE(instance, nullptr); + CHECK_NE(onRegister, nullptr) << instance; + // cookie can be nullptr + + auto cb = sp<AServiceManager_NotificationRegistration>::make(); + cb->instance = instance; + cb->onRegister = onRegister; + cb->cookie = cookie; + + sp<IServiceManager> sm = defaultServiceManager(); + if (status_t res = sm->registerForNotifications(String16(instance), cb); res != STATUS_OK) { + LOG(ERROR) << "Failed to register for service notifications for " << instance << ": " + << statusToString(res); + return nullptr; + } + + cb->incStrong(nullptr); + return cb.get(); +} + +void AServiceManager_NotificationRegistration_delete( + AServiceManager_NotificationRegistration* notification) { + CHECK_NE(notification, nullptr); + notification->clear(); + notification->decStrong(nullptr); +} + bool AServiceManager_isDeclared(const char* instance) { if (instance == nullptr) { return false; diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index e221e4c2bb..9d5ef6805a 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -254,6 +254,47 @@ TEST(NdkBinder, CheckServiceThatDoesExist) { AIBinder_decStrong(binder); } +struct ServiceData { + std::string instance; + ndk::SpAIBinder binder; + + static void fillOnRegister(const char* instance, AIBinder* binder, void* cookie) { + ServiceData* d = reinterpret_cast<ServiceData*>(cookie); + d->instance = instance; + d->binder = ndk::SpAIBinder(binder); + } +}; + +TEST(NdkBinder, RegisterForServiceNotificationsNonExisting) { + ServiceData data; + auto* notif = AServiceManager_registerForServiceNotifications( + "DOES_NOT_EXIST", ServiceData::fillOnRegister, (void*)&data); + ASSERT_NE(notif, nullptr); + + sleep(1); // give us a chance to fail + AServiceManager_NotificationRegistration_delete(notif); + + // checking after deleting to avoid needing a mutex over the data - otherwise + // in an environment w/ multiple threads, you would need to guard access + EXPECT_EQ(data.instance, ""); + EXPECT_EQ(data.binder, nullptr); +} + +TEST(NdkBinder, RegisterForServiceNotificationsExisting) { + ServiceData data; + auto* notif = AServiceManager_registerForServiceNotifications( + kExistingNonNdkService, ServiceData::fillOnRegister, (void*)&data); + ASSERT_NE(notif, nullptr); + + sleep(1); // give us a chance to fail + AServiceManager_NotificationRegistration_delete(notif); + + // checking after deleting to avoid needing a mutex over the data - otherwise + // in an environment w/ multiple threads, you would need to guard access + EXPECT_EQ(data.instance, kExistingNonNdkService); + EXPECT_EQ(data.binder, ndk::SpAIBinder(AServiceManager_checkService(kExistingNonNdkService))); +} + TEST(NdkBinder, UnimplementedDump) { sp<IFoo> foo = IFoo::getService(IFoo::kSomeInstanceName); ASSERT_NE(foo, nullptr); diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp index 738d16ac66..afd414a7cb 100644 --- a/libs/binder/rust/Android.bp +++ b/libs/binder/rust/Android.bp @@ -17,7 +17,6 @@ rust_library { rustlibs: [ "libbinder_ndk_sys", "libdowncast_rs", - "liblazy_static", "liblibc", ], host_supported: true, @@ -160,7 +159,6 @@ rust_test { rustlibs: [ "libbinder_ndk_sys", "libdowncast_rs", - "liblazy_static", "liblibc", ], } diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs index dee05d07cf..6f686fbd93 100644 --- a/libs/binder/rust/src/native.rs +++ b/libs/binder/rust/src/native.rs @@ -22,7 +22,6 @@ use crate::parcel::{BorrowedParcel, Serialize}; use crate::proxy::SpIBinder; use crate::sys; -use lazy_static::lazy_static; use std::convert::TryFrom; use std::ffi::{c_void, CStr, CString}; use std::fs::File; @@ -508,10 +507,8 @@ pub struct LazyServiceGuard { _private: (), } -lazy_static! { - // Count of how many LazyServiceGuard objects are in existence. - static ref GUARD_COUNT: Mutex<u64> = Mutex::new(0); -} +// Count of how many LazyServiceGuard objects are in existence. +static GUARD_COUNT: Mutex<u64> = Mutex::new(0); impl LazyServiceGuard { /// Create a new LazyServiceGuard to prevent the service manager prematurely killing this diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 6b544b2b96..3b137080ab 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1107,9 +1107,12 @@ void Surface::applyGrallocMetadataLocked( ATRACE_CALL(); auto& mapper = GraphicBufferMapper::get(); mapper.setDataspace(buffer->handle, static_cast<ui::Dataspace>(queueBufferInput.dataSpace)); - mapper.setSmpte2086(buffer->handle, queueBufferInput.getHdrMetadata().getSmpte2086()); - mapper.setCta861_3(buffer->handle, queueBufferInput.getHdrMetadata().getCta8613()); - mapper.setSmpte2094_40(buffer->handle, queueBufferInput.getHdrMetadata().getHdr10Plus()); + if (mHdrMetadataIsSet & HdrMetadata::SMPTE2086) + mapper.setSmpte2086(buffer->handle, queueBufferInput.getHdrMetadata().getSmpte2086()); + if (mHdrMetadataIsSet & HdrMetadata::CTA861_3) + mapper.setCta861_3(buffer->handle, queueBufferInput.getHdrMetadata().getCta8613()); + if (mHdrMetadataIsSet & HdrMetadata::HDR10PLUS) + mapper.setSmpte2094_40(buffer->handle, queueBufferInput.getHdrMetadata().getHdr10Plus()); } void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence, @@ -2250,6 +2253,7 @@ int Surface::setBuffersDataSpace(Dataspace dataSpace) int Surface::setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metadata) { ALOGV("Surface::setBuffersSmpte2086Metadata"); Mutex::Autolock lock(mMutex); + mHdrMetadataIsSet |= HdrMetadata::SMPTE2086; if (metadata) { mHdrMetadata.smpte2086 = *metadata; mHdrMetadata.validTypes |= HdrMetadata::SMPTE2086; @@ -2262,6 +2266,7 @@ int Surface::setBuffersSmpte2086Metadata(const android_smpte2086_metadata* metad int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata) { ALOGV("Surface::setBuffersCta8613Metadata"); Mutex::Autolock lock(mMutex); + mHdrMetadataIsSet |= HdrMetadata::CTA861_3; if (metadata) { mHdrMetadata.cta8613 = *metadata; mHdrMetadata.validTypes |= HdrMetadata::CTA861_3; @@ -2274,6 +2279,7 @@ int Surface::setBuffersCta8613Metadata(const android_cta861_3_metadata* metadata int Surface::setBuffersHdr10PlusMetadata(const size_t size, const uint8_t* metadata) { ALOGV("Surface::setBuffersBlobMetadata"); Mutex::Autolock lock(mMutex); + mHdrMetadataIsSet |= HdrMetadata::HDR10PLUS; if (size > 0) { mHdrMetadata.hdr10plus.assign(metadata, metadata + size); mHdrMetadata.validTypes |= HdrMetadata::HDR10PLUS; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index ab9ebaa882..862a4adf2e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -462,6 +462,11 @@ protected: // queue operation. There is no HDR metadata by default. HdrMetadata mHdrMetadata; + // mHdrMetadataIsSet is a bitfield to track which HDR metadata has been set. + // Prevent Surface from resetting HDR metadata that was set on a bufer when + // HDR metadata is not set on this Surface. + uint32_t mHdrMetadataIsSet{0}; + // mCrop is the crop rectangle that will be used for the next buffer // that gets queued. It is set by calling setCrop. Rect mCrop; diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING index b4b617e188..8d5d8839e8 100644 --- a/services/inputflinger/TEST_MAPPING +++ b/services/inputflinger/TEST_MAPPING @@ -15,6 +15,9 @@ "name": "inputflinger_tests" }, { + "name": "libchrome-gestures_test" + }, + { "name": "libpalmrejection_test" }, { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 564acc09f9..f634ce7bd2 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4721,10 +4721,13 @@ void InputDispatcher::setInputWindowsLocked( updateWindowHandlesForDisplayLocked(windowInfoHandles, displayId); const std::vector<sp<WindowInfoHandle>>& windowHandles = getWindowHandlesLocked(displayId); - if (mLastHoverWindowHandle && - std::find(windowHandles.begin(), windowHandles.end(), mLastHoverWindowHandle) == - windowHandles.end()) { - mLastHoverWindowHandle = nullptr; + if (mLastHoverWindowHandle) { + const WindowInfo* lastHoverWindowInfo = mLastHoverWindowHandle->getInfo(); + if (lastHoverWindowInfo->displayId == displayId && + std::find(windowHandles.begin(), windowHandles.end(), mLastHoverWindowHandle) == + windowHandles.end()) { + mLastHoverWindowHandle = nullptr; + } } std::optional<FocusResolver::FocusChanges> changes = diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index df4307101f..bb8e5661b6 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -2131,6 +2131,59 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) { ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); } +TEST_F(InputDispatcherTest, HoverEnterMoveRemoveWindowsInSecondDisplay) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + sp<FakeWindowHandle> windowDefaultDisplay = + sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay", + ADISPLAY_ID_DEFAULT); + windowDefaultDisplay->setFrame(Rect(0, 0, 600, 800)); + sp<FakeWindowHandle> windowSecondDisplay = + sp<FakeWindowHandle>::make(application, mDispatcher, "SecondDisplay", + SECOND_DISPLAY_ID); + windowSecondDisplay->setFrame(Rect(0, 0, 600, 800)); + + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, + {SECOND_DISPLAY_ID, {windowSecondDisplay}}}); + + // Set cursor position in window in default display and check that hover enter and move + // events are generated. + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, + MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, + AINPUT_SOURCE_MOUSE) + .displayId(ADISPLAY_ID_DEFAULT) + .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE) + .x(300) + .y(600)) + .build())); + windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_ENTER, + ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); + windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE, + ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); + + // Remove all windows in secondary display and check that no event happens on window in + // primary display. + mDispatcher->setInputWindows({{SECOND_DISPLAY_ID, {}}}); + windowDefaultDisplay->assertNoEvents(); + + // Move cursor position in window in default display and check that only hover move + // event is generated and not hover enter event. + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {windowDefaultDisplay}}, + {SECOND_DISPLAY_ID, {windowSecondDisplay}}}); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, + MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_MOVE, + AINPUT_SOURCE_MOUSE) + .displayId(ADISPLAY_ID_DEFAULT) + .pointer(PointerBuilder(0, AMOTION_EVENT_TOOL_TYPE_MOUSE) + .x(400) + .y(700)) + .build())); + windowDefaultDisplay->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_HOVER_MOVE, + ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); + windowDefaultDisplay->assertNoEvents(); +} + TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); diff --git a/services/sensorservice/aidl/EventQueue.cpp b/services/sensorservice/aidl/EventQueue.cpp index 88ab7a7e41..c3947098c3 100644 --- a/services/sensorservice/aidl/EventQueue.cpp +++ b/services/sensorservice/aidl/EventQueue.cpp @@ -66,7 +66,6 @@ EventQueue::EventQueue(std::shared_ptr<IEventQueueCallback> callback, sp<::andro new EventQueueLooperCallback(internalQueue, callback), nullptr); } -// FIXME why was this on onLastStrongRef instead of dtor? EventQueue::~EventQueue() { mLooper->removeFd(mInternalQueue->getFd()); } |