From 63534161e49eaeb9b7dd4d40c190a764bfa98c59 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 2 Jul 2020 14:38:16 +0100 Subject: Force InputManagerService to communicate via InputManagerInterface Bug: 160010896 Test: compiles, manual Change-Id: I64f166faa5f242f22b14cb474b9187c9820f3b51 --- services/inputflinger/InputManager.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'services/inputflinger/InputManager.cpp') diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index e68946d734..f2a0014da4 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -134,8 +134,4 @@ void InputManager::unregisterInputChannel(const sp& channel) { mDispatcher->unregisterInputChannel(channel); } -void InputManager::setMotionClassifierEnabled(bool enabled) { - mClassifier->setMotionClassifierEnabled(enabled); -} - } // namespace android -- cgit v1.2.3-59-g8ed1b From 0783e99d457c9d9a3ede400bdb355ba35e828de6 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Tue, 2 Jun 2020 21:34:49 -0700 Subject: AIDL-ize InputManager IInputFlinger interface. Use AIDL interface to define the IInputFlinger interface and replace the manual interface. Bug:155425003 Test: atest libgui_test, atest libinput_test. Change-Id: Ibad036b8ceb3a3f5c6d58f8de4ea8c79379d29b5 --- include/input/IInputFlinger.h | 62 ---- include/input/ISetInputWindowsListener.h | 40 -- include/input/InputApplication.h | 12 +- include/input/InputTransport.h | 49 ++- include/input/InputWindow.h | 35 +- libs/gui/LayerState.cpp | 6 +- libs/gui/SurfaceComposerClient.cpp | 2 +- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 13 +- libs/input/Android.bp | 9 +- libs/input/IInputFlinger.cpp | 101 ----- libs/input/ISetInputWindowsListener.cpp | 53 --- libs/input/InputApplication.cpp | 41 ++- libs/input/InputTransport.cpp | 67 ++-- libs/input/InputWindow.cpp | 185 ++++++---- libs/input/android/InputChannelInfo.aidl | 20 + libs/input/android/InputWindowInfo.aidl | 20 + libs/input/android/os/IInputFlinger.aidl | 30 ++ .../input/android/os/ISetInputWindowsListener.aidl | 23 ++ libs/input/tests/InputChannel_test.cpp | 32 ++ libs/input/tests/InputWindow_test.cpp | 12 +- services/inputflinger/InputManager.cpp | 29 +- services/inputflinger/InputManager.h | 23 +- .../dispatcher/include/InputDispatcherInterface.h | 9 +- .../include/InputDispatcherPolicyInterface.h | 2 +- services/inputflinger/host/Android.bp | 3 +- services/inputflinger/host/InputFlinger.h | 20 +- services/inputflinger/tests/Android.bp | 7 + .../inputflinger/tests/IInputFlingerQuery.aidl | 27 ++ .../tests/InputFlingerService_test.cpp | 408 +++++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 40 +- services/surfaceflinger/SurfaceFlinger.h | 22 +- 32 files changed, 915 insertions(+), 489 deletions(-) delete mode 100644 include/input/IInputFlinger.h delete mode 100644 include/input/ISetInputWindowsListener.h delete mode 100644 libs/input/IInputFlinger.cpp delete mode 100644 libs/input/ISetInputWindowsListener.cpp create mode 100644 libs/input/android/InputChannelInfo.aidl create mode 100644 libs/input/android/InputWindowInfo.aidl create mode 100644 libs/input/android/os/IInputFlinger.aidl create mode 100644 libs/input/android/os/ISetInputWindowsListener.aidl create mode 100644 services/inputflinger/tests/IInputFlingerQuery.aidl create mode 100644 services/inputflinger/tests/InputFlingerService_test.cpp (limited to 'services/inputflinger/InputManager.cpp') diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h deleted file mode 100644 index d23e3b7767..0000000000 --- a/include/input/IInputFlinger.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 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 _LIBINPUT_IINPUT_FLINGER_H -#define _LIBINPUT_IINPUT_FLINGER_H - -#include -#include - -#include - -#include -#include - -namespace android { - -/* - * This class defines the Binder IPC interface for accessing various - * InputFlinger features. - */ -class IInputFlinger : public IInterface { -public: - DECLARE_META_INTERFACE(InputFlinger) - - virtual void setInputWindows(const std::vector& inputHandles, - const sp& setInputWindowsListener) = 0; - virtual void registerInputChannel(const sp& channel) = 0; - virtual void unregisterInputChannel(const sp& channel) = 0; -}; - - -/** - * Binder implementation. - */ -class BnInputFlinger : public BnInterface { -public: - enum { - SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, - REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags = 0); -}; - -} // namespace android - -#endif // _LIBINPUT_IINPUT_FLINGER_H diff --git a/include/input/ISetInputWindowsListener.h b/include/input/ISetInputWindowsListener.h deleted file mode 100644 index 15d31b25c1..0000000000 --- a/include/input/ISetInputWindowsListener.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#include -#include - -namespace android { - -class ISetInputWindowsListener : public IInterface { -public: - DECLARE_META_INTERFACE(SetInputWindowsListener) - virtual void onSetInputWindowsFinished() = 0; -}; - -class BnSetInputWindowsListener: public BnInterface { -public: - enum SetInputWindowsTag : uint32_t { - ON_SET_INPUT_WINDOWS_FINISHED - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags = 0) override; -}; - -}; // namespace android diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index ccffeb1327..b6b935329b 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -31,15 +32,17 @@ namespace android { /* * Describes the properties of an application that can receive input. */ -struct InputApplicationInfo { +struct InputApplicationInfo : public Parcelable { sp token; std::string name; std::chrono::nanoseconds dispatchingTimeout; - status_t write(Parcel& output) const; - static InputApplicationInfo read(const Parcel& from); -}; + InputApplicationInfo() = default; + + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; /* * Handle for an application that can receive input. @@ -76,6 +79,7 @@ public: * Returns true on success, or false if the handle is no longer valid. */ virtual bool updateInfo() = 0; + protected: InputApplicationHandle(); virtual ~InputApplicationHandle(); diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 7ca9031f77..0219cf7c2a 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include #include @@ -174,6 +176,18 @@ struct InputMessage { void getSanitizedCopy(InputMessage* msg) const; }; +struct InputChannelInfo : public Parcelable { + std::string mName; + android::base::unique_fd mFd; + sp mToken; + + InputChannelInfo() = default; + InputChannelInfo(const std::string& name, android::base::unique_fd fd, sp token) + : mName(name), mFd(std::move(fd)), mToken(token){}; + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; + /* * An input channel consists of a local unix domain socket used to send and receive * input messages across processes. Each channel has a descriptive name for debugging purposes. @@ -183,10 +197,10 @@ struct InputMessage { * The input channel is closed when all references to it are released. */ class InputChannel : public RefBase { -protected: +public: + InputChannel(); virtual ~InputChannel(); -public: static sp create(const std::string& name, android::base::unique_fd fd, sp token); @@ -200,8 +214,10 @@ public: static status_t openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel); - inline std::string getName() const { return mName; } - inline int getFd() const { return mFd.get(); } + inline std::string getName() const { return mInfo.mName; } + inline int getFd() const { return mInfo.mFd.get(); } + inline sp getToken() const { return mInfo.mToken; } + inline InputChannelInfo& getInfo() { return mInfo; } /* Send a message to the other endpoint. * @@ -231,8 +247,9 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ sp dup() const; - status_t write(Parcel& out) const; - static sp read(const Parcel& from); + status_t readFromParcel(const android::Parcel* parcel); + + status_t writeToParcel(android::Parcel* parcel) const; /** * The connection token is used to identify the input connection, i.e. @@ -248,12 +265,23 @@ public: */ sp getConnectionToken() const; + bool operator==(const InputChannel& inputChannel) const { + struct stat lhsInfo, rhsInfo; + if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) { + return false; + } + if (fstat(inputChannel.getFd(), &rhsInfo) != 0) { + return false; + } + // If file descriptors are pointing to same inode they are duplicated fds. + return inputChannel.getName() == getName() && + inputChannel.getConnectionToken() == mInfo.mToken && + lhsInfo.st_ino == rhsInfo.st_ino; + } + private: InputChannel(const std::string& name, android::base::unique_fd fd, sp token); - std::string mName; - android::base::unique_fd mFd; - - sp mToken; + InputChannelInfo mInfo; }; /* @@ -325,7 +353,6 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - sp mChannel; }; diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f8c759c85d..582e73d858 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -17,6 +17,8 @@ #ifndef _UI_INPUT_WINDOW_H #define _UI_INPUT_WINDOW_H +#include +#include #include #include #include @@ -27,14 +29,12 @@ #include "InputApplication.h" namespace android { -class Parcel; /* * Describes the properties of a window that can receive input. */ -struct InputWindowInfo { +struct InputWindowInfo : public Parcelable { InputWindowInfo() = default; - InputWindowInfo(const Parcel& from); // Window flags from WindowManager.LayoutParams enum : uint32_t { @@ -195,9 +195,11 @@ struct InputWindowInfo { bool overlaps(const InputWindowInfo* other) const; - status_t write(Parcel& output) const; + bool operator==(const InputWindowInfo& inputChannel) const; - static InputWindowInfo read(const Parcel& from); + status_t writeToParcel(android::Parcel* parcel) const override; + + status_t readFromParcel(const android::Parcel* parcel) override; }; std::string inputWindowFlagsToString(uint32_t flags); @@ -210,22 +212,19 @@ std::string inputWindowFlagsToString(uint32_t flags); */ class InputWindowHandle : public RefBase { public: + explicit InputWindowHandle(); + InputWindowHandle(const InputWindowHandle& other); + InputWindowHandle(const InputWindowInfo& other); - inline const InputWindowInfo* getInfo() const { - return &mInfo; - } + inline const InputWindowInfo* getInfo() const { return &mInfo; } sp getToken() const; int32_t getId() const { return mInfo.id; } - sp getApplicationToken() { - return mInfo.applicationInfo.token; - } + sp getApplicationToken() { return mInfo.applicationInfo.token; } - inline std::string getName() const { - return !mInfo.name.empty() ? mInfo.name : ""; - } + inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : ""; } inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { @@ -235,13 +234,14 @@ public: /** * Requests that the state of this object be updated to reflect * the most current available information about the application. + * As this class is created as RefBase object, no pure virtual function is allowed. * * This method should only be called from within the input dispatcher's * critical section. * * Returns true on success, or false if the handle is no longer valid. */ - virtual bool updateInfo() = 0; + virtual bool updateInfo() { return false; } /** * Updates from another input window handle. @@ -254,8 +254,11 @@ public: */ void releaseChannel(); + // Not override since this class is not derrived from Parcelable. + status_t readFromParcel(const android::Parcel* parcel); + status_t writeToParcel(android::Parcel* parcel) const; + protected: - explicit InputWindowHandle(); virtual ~InputWindowHandle(); InputWindowInfo mInfo; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e43446ac8c..1030b82f14 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -55,7 +55,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.g); output.writeFloat(color.b); #ifndef NO_INPUT - inputInfo.write(output); + inputHandle->writeToParcel(&output); #endif output.write(transparentRegion); output.writeUint32(transform); @@ -152,7 +152,7 @@ status_t layer_state_t::read(const Parcel& input) color.b = input.readFloat(); #ifndef NO_INPUT - inputInfo = InputWindowInfo::read(input); + inputHandle->readFromParcel(&input); #endif input.read(transparentRegion); @@ -404,7 +404,7 @@ void layer_state_t::merge(const layer_state_t& other) { #ifndef NO_INPUT if (other.what & eInputInfoChanged) { what |= eInputInfoChanged; - inputInfo = other.inputInfo; + inputHandle = new InputWindowHandle(*other.inputHandle); } #endif diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 16b46df4f6..d797a3547a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1359,7 +1359,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput mStatus = BAD_INDEX; return *this; } - s->inputInfo = info; + s->inputHandle = new InputWindowHandle(info); s->what |= layer_state_t::eInputInfoChanged; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e60f6777ae..00ae220906 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -201,7 +201,7 @@ struct layer_state_t { mat4 colorTransform; #ifndef NO_INPUT - InputWindowInfo inputInfo; + sp inputHandle = new InputWindowHandle(); #endif client_cache_t cachedBuffer; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 32c7fc2588..152f7ad56c 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -36,15 +36,16 @@ #include #include -#include -#include -#include +#include #include +#include +#include #include #include #include +using android::os::IInputFlinger; namespace android { namespace test { @@ -71,7 +72,7 @@ public: InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); mInputFlinger = getInputFlinger(); - mInputFlinger->registerInputChannel(mServerChannel); + mInputFlinger->registerInputChannel(mServerChannel->getInfo()); populateInputInfo(width, height); @@ -153,9 +154,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } - ~InputSurface() { - mInputFlinger->unregisterInputChannel(mServerChannel); - } + ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); } void doTransaction(std::function&)> transactionBody) { diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7037680935..ade9c25c53 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -46,14 +46,14 @@ cc_library { target: { android: { srcs: [ - "IInputFlinger.cpp", "InputApplication.cpp", "InputTransport.cpp", "InputWindow.cpp", - "ISetInputWindowsListener.cpp", "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", + "android/os/IInputFlinger.aidl", + "android/os/ISetInputWindowsListener.aidl", ], shared_libs: [ @@ -72,6 +72,11 @@ cc_library { }, }, }, + + aidl: { + local_include_dirs: ["."], + export_aidl_headers: true + }, } subdirs = ["tests"] diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp deleted file mode 100644 index 8ec51653a8..0000000000 --- a/libs/input/IInputFlinger.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 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 -#include - -#include -#include -#include - -#include - -namespace android { - -class BpInputFlinger : public BpInterface { -public: - explicit BpInputFlinger(const sp& impl) : - BpInterface(impl) { } - - virtual void setInputWindows(const std::vector& inputInfo, - const sp& setInputWindowsListener) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - - data.writeUint32(static_cast(inputInfo.size())); - for (const auto& info : inputInfo) { - info.write(data); - } - data.writeStrongBinder(IInterface::asBinder(setInputWindowsListener)); - - remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply, - IBinder::FLAG_ONEWAY); - } - - virtual void registerInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::REGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } - - virtual void unregisterInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::UNREGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger"); - -status_t BnInputFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - switch(code) { - case SET_INPUT_WINDOWS_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - size_t count = data.readUint32(); - if (count > data.dataSize()) { - return BAD_VALUE; - } - std::vector handles; - for (size_t i = 0; i < count; i++) { - handles.push_back(InputWindowInfo::read(data)); - } - const sp setInputWindowsListener = - ISetInputWindowsListener::asInterface(data.readStrongBinder()); - setInputWindows(handles, setInputWindowsListener); - break; - } - case REGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - registerInputChannel(channel); - break; - } - case UNREGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - unregisterInputChannel(channel); - break; - } - default: - return BBinder::onTransact(code, data, reply, flags); - } - return NO_ERROR; -} - -}; diff --git a/libs/input/ISetInputWindowsListener.cpp b/libs/input/ISetInputWindowsListener.cpp deleted file mode 100644 index a0330da89e..0000000000 --- a/libs/input/ISetInputWindowsListener.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 - -namespace android { - -class BpSetInputWindowsListener : public BpInterface { -public: - explicit BpSetInputWindowsListener(const sp& impl) - : BpInterface(impl) { - } - - virtual ~BpSetInputWindowsListener() = default; - - virtual void onSetInputWindowsFinished() { - Parcel data, reply; - data.writeInterfaceToken(ISetInputWindowsListener::getInterfaceDescriptor()); - remote()->transact(BnSetInputWindowsListener::ON_SET_INPUT_WINDOWS_FINISHED, data, &reply, - IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(SetInputWindowsListener, "android.input.ISetInputWindowsListener"); - -status_t BnSetInputWindowsListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags) { - switch(code) { - case ON_SET_INPUT_WINDOWS_FINISHED: { - CHECK_INTERFACE(ISetInputWindowsListener, data, reply); - onSetInputWindowsFinished(); - return NO_ERROR; - } - default: { - return BBinder::onTransact(code, data, reply, flags); - } - } -} - -} // namespace android diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp index c745c24c66..41721a7344 100644 --- a/libs/input/InputApplication.cpp +++ b/libs/input/InputApplication.cpp @@ -22,29 +22,34 @@ namespace android { -// --- InputApplicationHandle --- - -InputApplicationHandle::InputApplicationHandle() { -} - -InputApplicationHandle::~InputApplicationHandle() { +status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readUtf8FromUtf16(&name); + + return status; } -InputApplicationInfo InputApplicationInfo::read(const Parcel& from) { - InputApplicationInfo ret; - ret.token = from.readStrongBinder(); - ret.name = from.readString8().c_str(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); +status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(token) + ?: parcel->writeInt64(dispatchingTimeout.count()) + ?: parcel->writeUtf8AsUtf16(name) ; - return ret; + return status; } -status_t InputApplicationInfo::write(Parcel& output) const { - output.writeStrongBinder(token); - output.writeString8(String8(name.c_str())); - output.writeInt64(dispatchingTimeout.count()); +// --- InputApplicationHandle --- - return OK; -} +InputApplicationHandle::InputApplicationHandle() {} + +InputApplicationHandle::~InputApplicationHandle() {} } // namespace android diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 11af23e1a2..c6043ac203 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -246,6 +246,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { } } +// --- InputChannelInfo --- + +status_t InputChannelInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(mToken) + ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); + return status; +} + +status_t InputChannelInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + mToken = parcel->readStrongBinder(); + status_t status = parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); + return status; +} + // --- InputChannel --- sp InputChannel::create(const std::string& name, android::base::unique_fd fd, @@ -260,15 +282,17 @@ sp InputChannel::create(const std::string& name, android::base::un } InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp token) - : mName(name), mFd(std::move(fd)), mToken(token) { + : mInfo(name, std::move(fd), token) { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get()); } } +InputChannel::InputChannel() {} + InputChannel::~InputChannel() { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd()); } } @@ -308,7 +332,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { - nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); + nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { @@ -343,7 +367,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { - nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT); + nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { @@ -383,7 +407,7 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { sp InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { - ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), mName.c_str(), + ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding @@ -394,38 +418,19 @@ sp InputChannel::dup() const { getName().c_str()); return nullptr; } - return InputChannel::create(mName, std::move(newFd), mToken); + return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); } -status_t InputChannel::write(Parcel& out) const { - status_t s = out.writeCString(getName().c_str()); - if (s != OK) { - return s; - } - - s = out.writeStrongBinder(mToken); - if (s != OK) { - return s; - } - - s = out.writeUniqueFileDescriptor(mFd); - return s; +status_t InputChannel::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -sp InputChannel::read(const Parcel& from) { - std::string name = from.readCString(); - sp token = from.readStrongBinder(); - android::base::unique_fd rawFd; - status_t fdResult = from.readUniqueFileDescriptor(&rawFd); - if (fdResult != OK) { - return nullptr; - } - - return InputChannel::create(name, std::move(rawFd), token); +status_t InputChannel::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } sp InputChannel::getConnectionToken() const { - return mToken; + return mInfo.mToken; } // --- InputPublisher --- diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 3700e8f0f8..ae9b3f0994 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -24,9 +24,6 @@ #include -#include -#include - namespace android { const char* inputWindowFlagToString(uint32_t flag) { @@ -164,96 +161,130 @@ bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { && frameTop < other->frameBottom && frameBottom > other->frameTop; } -status_t InputWindowInfo::write(Parcel& output) const { +bool InputWindowInfo::operator==(const InputWindowInfo& info) const { + return info.token == token && info.id == id && info.name == name && + info.layoutParamsFlags == layoutParamsFlags && + info.layoutParamsType == layoutParamsType && + info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft && + info.frameTop == frameTop && info.frameRight == frameRight && + info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && + info.globalScaleFactor == globalScaleFactor && info.windowXScale == windowXScale && + info.windowYScale == windowYScale && + info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && + info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && + info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && + info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.inputFeatures == inputFeatures && info.displayId == displayId && + info.portalToDisplayId == portalToDisplayId && + info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && + info.applicationInfo.name == applicationInfo.name && + info.applicationInfo.token == applicationInfo.token && + info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout; +} + +status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } if (name.empty()) { - output.writeInt32(0); + parcel->writeInt32(0); return OK; } - output.writeInt32(1); - status_t s = output.writeStrongBinder(token); - if (s != OK) return s; + parcel->writeInt32(1); - output.writeInt32(id); - output.writeString8(String8(name.c_str())); - output.writeInt32(layoutParamsFlags); - output.writeInt32(layoutParamsType); - output.writeInt64(dispatchingTimeout.count()); - output.writeInt32(frameLeft); - output.writeInt32(frameTop); - output.writeInt32(frameRight); - output.writeInt32(frameBottom); - output.writeInt32(surfaceInset); - output.writeFloat(globalScaleFactor); - output.writeFloat(windowXScale); - output.writeFloat(windowYScale); - output.writeBool(visible); - output.writeBool(canReceiveKeys); - output.writeBool(hasFocus); - output.writeBool(hasWallpaper); - output.writeBool(paused); - output.writeBool(trustedOverlay); - output.writeInt32(ownerPid); - output.writeInt32(ownerUid); - output.writeInt32(inputFeatures); - output.writeInt32(displayId); - output.writeInt32(portalToDisplayId); - applicationInfo.write(output); - output.write(touchableRegion); - output.writeBool(replaceTouchableRegionWithCrop); - output.writeStrongBinder(touchableRegionCropHandle.promote()); - return OK; -} + status_t status = parcel->writeStrongBinder(token) ?: + parcel->writeInt64(dispatchingTimeout.count()) ?: + parcel->writeInt32(id) ?: + parcel->writeUtf8AsUtf16(name) ?: + parcel->writeInt32(layoutParamsFlags) ?: + parcel->writeInt32(layoutParamsType) ?: + parcel->writeInt32(frameLeft) ?: + parcel->writeInt32(frameTop) ?: + parcel->writeInt32(frameRight) ?: + parcel->writeInt32(frameBottom) ?: + parcel->writeInt32(surfaceInset) ?: + parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(windowXScale) ?: + parcel->writeFloat(windowYScale) ?: + parcel->writeBool(visible) ?: + parcel->writeBool(canReceiveKeys) ?: + parcel->writeBool(hasFocus) ?: + parcel->writeBool(hasWallpaper) ?: + parcel->writeBool(paused) ?: + parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(ownerPid) ?: + parcel->writeInt32(ownerUid) ?: + parcel->writeInt32(inputFeatures) ?: + parcel->writeInt32(displayId) ?: + parcel->writeInt32(portalToDisplayId) ?: + applicationInfo.writeToParcel(parcel) ?: + parcel->write(touchableRegion) ?: + parcel->writeBool(replaceTouchableRegionWithCrop) ?: + parcel->writeStrongBinder(touchableRegionCropHandle.promote()); -InputWindowInfo InputWindowInfo::read(const Parcel& from) { - InputWindowInfo ret; + return status; +} - if (from.readInt32() == 0) { - return ret; +status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + if (parcel->readInt32() == 0) { + return OK; } - ret.token = from.readStrongBinder(); - ret.id = from.readInt32(); - ret.name = from.readString8().c_str(); - ret.layoutParamsFlags = from.readInt32(); - ret.layoutParamsType = from.readInt32(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); - ret.frameLeft = from.readInt32(); - ret.frameTop = from.readInt32(); - ret.frameRight = from.readInt32(); - ret.frameBottom = from.readInt32(); - ret.surfaceInset = from.readInt32(); - ret.globalScaleFactor = from.readFloat(); - ret.windowXScale = from.readFloat(); - ret.windowYScale = from.readFloat(); - ret.visible = from.readBool(); - ret.canReceiveKeys = from.readBool(); - ret.hasFocus = from.readBool(); - ret.hasWallpaper = from.readBool(); - ret.paused = from.readBool(); - ret.trustedOverlay = from.readBool(); - ret.ownerPid = from.readInt32(); - ret.ownerUid = from.readInt32(); - ret.inputFeatures = from.readInt32(); - ret.displayId = from.readInt32(); - ret.portalToDisplayId = from.readInt32(); - ret.applicationInfo = InputApplicationInfo::read(from); - from.read(ret.touchableRegion); - ret.replaceTouchableRegionWithCrop = from.readBool(); - ret.touchableRegionCropHandle = from.readStrongBinder(); + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readInt32(&id) ?: + parcel->readUtf8FromUtf16(&name) ?: + parcel->readInt32(&layoutParamsFlags) ?: + parcel->readInt32(&layoutParamsType) ?: + parcel->readInt32(&frameLeft) ?: + parcel->readInt32(&frameTop) ?: + parcel->readInt32(&frameRight) ?: + parcel->readInt32(&frameBottom) ?: + parcel->readInt32(&surfaceInset) ?: + parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&windowXScale) ?: + parcel->readFloat(&windowYScale) ?: + parcel->readBool(&visible) ?: + parcel->readBool(&canReceiveKeys) ?: + parcel->readBool(&hasFocus) ?: + parcel->readBool(&hasWallpaper) ?: + parcel->readBool(&paused) ?: + parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&ownerPid) ?: + parcel->readInt32(&ownerUid) ?: + parcel->readInt32(&inputFeatures) ?: + parcel->readInt32(&displayId) ?: + parcel->readInt32(&portalToDisplayId) ?: + applicationInfo.readFromParcel(parcel) ?: + parcel->read(touchableRegion) ?: + parcel->readBool(&replaceTouchableRegionWithCrop); - return ret; -} + touchableRegionCropHandle = parcel->readStrongBinder(); -InputWindowInfo::InputWindowInfo(const Parcel& from) { - *this = read(from); + return status; } // --- InputWindowHandle --- -InputWindowHandle::InputWindowHandle() { +InputWindowHandle::InputWindowHandle() {} + +InputWindowHandle::~InputWindowHandle() {} + +InputWindowHandle::InputWindowHandle(const InputWindowHandle& other) : mInfo(other.mInfo) {} + +InputWindowHandle::InputWindowHandle(const InputWindowInfo& other) : mInfo(other) {} + +status_t InputWindowHandle::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -InputWindowHandle::~InputWindowHandle() { +status_t InputWindowHandle::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } void InputWindowHandle::releaseChannel() { diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannelInfo.aidl new file mode 100644 index 0000000000..2e83b966f1 --- /dev/null +++ b/libs/input/android/InputChannelInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputChannelInfo cpp_header "input/InputTransport.h"; diff --git a/libs/input/android/InputWindowInfo.aidl b/libs/input/android/InputWindowInfo.aidl new file mode 100644 index 0000000000..eeaf400227 --- /dev/null +++ b/libs/input/android/InputWindowInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputWindowInfo cpp_header "input/InputWindow.h"; diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl new file mode 100644 index 0000000000..8ff9dae47e --- /dev/null +++ b/libs/input/android/os/IInputFlinger.aidl @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlinger +{ + void setInputWindows(in InputWindowInfo[] inputHandles, + in @nullable ISetInputWindowsListener setInputWindowsListener); + void registerInputChannel(in InputChannelInfo info); + void unregisterInputChannel(in InputChannelInfo info); +} diff --git a/libs/input/android/os/ISetInputWindowsListener.aidl b/libs/input/android/os/ISetInputWindowsListener.aidl new file mode 100644 index 0000000000..bb58fb671b --- /dev/null +++ b/libs/input/android/os/ISetInputWindowsListener.aidl @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** @hide */ +oneway interface ISetInputWindowsListener +{ + void onSetInputWindowsFinished(); +} diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index ada275d014..7f4bd6eac2 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -197,5 +198,36 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { } } +TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + InputChannel chan; + Parcel parcel; + ASSERT_EQ(OK, serverChannel->writeToParcel(&parcel)); + parcel.setDataPosition(0); + chan.readFromParcel(&parcel); + + EXPECT_EQ(chan == *serverChannel, true) + << "inputchannel should be equal after parceling and unparceling.\n" + << "name " << chan.getName() << " name " << serverChannel->getName(); +} + +TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel dup", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + sp dupChan = serverChannel->dup(); + + EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication"; +} } // namespace android diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 87505323c3..cdea922bd2 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -28,13 +28,13 @@ namespace android { namespace test { TEST(InputWindowInfo, ParcellingWithoutToken) { - InputWindowInfo i; + InputWindowInfo i, i2; i.token = nullptr; Parcel p; - ASSERT_EQ(OK, i.write(p)); + ASSERT_EQ(OK, i.writeToParcel(&p)); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + i2.readFromParcel(&p); ASSERT_TRUE(i2.token == nullptr); } @@ -69,10 +69,10 @@ TEST(InputWindowInfo, Parcelling) { i.touchableRegionCropHandle = touchableRegionCropHandle; Parcel p; - i.write(p); - + i.writeToParcel(&p); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + InputWindowInfo i2; + i2.readFromParcel(&p); ASSERT_EQ(i.token, i2.token); ASSERT_EQ(i.id, i2.id); ASSERT_EQ(i.name, i2.name); diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index f2a0014da4..c5f60ade96 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -93,16 +93,15 @@ sp InputManager::getDispatcher() { class BinderWindowHandle : public InputWindowHandle { public: - BinderWindowHandle(const InputWindowInfo& info) { - mInfo = info; - } + BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; } bool updateInfo() override { return true; } }; -void InputManager::setInputWindows(const std::vector& infos, +binder::Status InputManager::setInputWindows( + const std::vector& infos, const sp& setInputWindowsListener) { std::unordered_map>> handlesPerDisplay; @@ -116,22 +115,38 @@ void InputManager::setInputWindows(const std::vector& infos, if (setInputWindowsListener) { setInputWindowsListener->onSetInputWindowsFinished(); } + return binder::Status::ok(); } // Used by tests only. -void InputManager::registerInputChannel(const sp& channel) { +binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { ALOGE("Invalid attempt to register input channel over IPC" "from non shell/root entity (PID: %d)", ipc->getCallingPid()); - return; + return binder::Status::ok(); } + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->registerInputChannel(channel); + return binder::Status::ok(); } -void InputManager::unregisterInputChannel(const sp& channel) { +binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) { + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->unregisterInputChannel(channel); + return binder::Status::ok(); +} + +status_t InputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; } } // namespace android diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 41d9478147..4993b54b5c 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -26,18 +26,23 @@ #include #include -#include +#include #include #include -#include +#include +#include #include -#include -#include #include +#include +#include + +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; namespace android { class InputChannel; +class InputDispatcherThread; /* * The input manager is the core of the system event processing. @@ -98,11 +103,13 @@ public: sp getClassifier() override; sp getDispatcher() override; - void setInputWindows(const std::vector& handles, - const sp& setInputWindowsListener) override; + status_t dump(int fd, const Vector& args) override; + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; - void registerInputChannel(const sp& channel) override; - void unregisterInputChannel(const sp& channel) override; + binder::Status registerInputChannel(const InputChannelInfo& info) override; + binder::Status unregisterInputChannel(const InputChannelInfo& info) override; private: sp mReader; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 9b002f437c..f25131c7c7 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -18,15 +18,14 @@ #define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H #include -#include +#include +#include +#include +#include #include namespace android { -class InputApplicationHandle; -class InputChannel; -class InputWindowHandle; - /* * Constants used to report the outcome of input event injection. */ diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 21255dd0d6..c886bee263 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -21,11 +21,11 @@ #include #include +#include #include namespace android { -class InputApplicationHandle; /* * Input dispatcher policy interface. diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp index b56f356dfd..2643c228ff 100644 --- a/services/inputflinger/host/Android.bp +++ b/services/inputflinger/host/Android.bp @@ -59,7 +59,8 @@ cc_binary { shared_libs: [ "libbinder", "libinputflingerhost", - "libutils" + "libutils", + "libinput" ], static_libs: [ "libarect", diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 973b4f92fa..9364a2a767 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -22,13 +22,17 @@ #include "InputHost.h" +#include +#include +#include #include -#include -#include -#include #include +#include #include +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; + namespace android { class InputFlinger : public BnInputFlinger { @@ -40,10 +44,12 @@ public: InputFlinger() ANDROID_API; virtual status_t dump(int fd, const Vector& args); - void setInputWindows(const std::vector&, - const sp&) {} - void registerInputChannel(const sp&) {} - void unregisterInputChannel(const sp&) {} + binder::Status setInputWindows(const std::vector&, + const sp&) { + return binder::Status::ok(); + } + binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } + binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } private: virtual ~InputFlinger(); diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index a0d2f4f172..eae09633af 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -35,7 +35,14 @@ cc_test { "InputClassifierConverter_test.cpp", "InputDispatcher_test.cpp", "InputReader_test.cpp", + "InputFlingerService_test.cpp", "UinputDevice.cpp", + "IInputFlingerQuery.aidl" ], + aidl: { + include_dirs: [ + "frameworks/native/libs/input", + ], + }, require_root: true, } diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl new file mode 100644 index 0000000000..1edc08965f --- /dev/null +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2020, 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. + */ + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlingerQuery +{ + /* Test interfaces */ + void getInputWindows(out InputWindowInfo[] inputHandles); + void getInputChannels(out InputChannelInfo[] infos); +} diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp new file mode 100644 index 0000000000..fd3f5627b7 --- /dev/null +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2020 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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "InputFlingerServiceTest" + +using android::os::BnInputFlinger; +using android::os::BnSetInputWindowsListener; +using android::os::IInputFlinger; +using android::os::ISetInputWindowsListener; + +using std::chrono_literals::operator""ms; +using std::chrono_literals::operator""s; + +namespace android { + +static const sp TestInfoToken = new BBinder(); +static constexpr int32_t TestInfoId = 1; +static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; +static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD; +static constexpr int32_t TestInfoLayoutParamsType = 39; +static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms; +static constexpr int32_t TestInfoFrameLeft = 93; +static constexpr int32_t TestInfoFrameTop = 34; +static constexpr int32_t TestInfoFrameRight = 16; +static constexpr int32_t TestInfoFrameBottom = 19; +static constexpr int32_t TestInfoSurfaceInset = 17; +static constexpr float TestInfoGlobalScaleFactor = 0.3; +static constexpr float TestInfoWindowXScale = 0.4; +static constexpr float TestInfoWindowYScale = 0.5; +static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */, + 450 /* bottom */}; +static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect); +static constexpr bool TestInfoVisible = false; +static constexpr bool TestInfoCanReceiveKeys = false; +static constexpr bool TestInfoTrustedOverlay = true; +static constexpr bool TestInfoHasFocus = false; +static constexpr bool TestInfoHasWallpaper = false; +static constexpr bool TestInfoPaused = false; +static constexpr int32_t TestInfoOwnerPid = 19; +static constexpr int32_t TestInfoOwnerUid = 24; +static constexpr int32_t TestInfoInputFeatures = 29; +static constexpr int32_t TestInfoDisplayId = 34; +static constexpr int32_t TestInfoPortalToDisplayId = 2; +static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true; +static const sp TestInfoTouchableRegionCropHandle = new BBinder(); + +static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo"; +static const sp TestAppInfoToken = new BBinder(); +static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms; + +static const String16 kTestServiceName = String16("InputFlingerService"); +static const String16 kQueryServiceName = String16("InputFlingerQueryService"); + +struct SetInputWindowsListener; +// --- InputFlingerServiceTest --- +class InputFlingerServiceTest : public testing::Test { +public: + void SetUp() override; + void TearDown() override; + +protected: + void InitializeInputFlinger(); + void setInputWindowsByInfos(std::vector& infos); + + void setInputWindowsFinished(); + void verifyInputWindowInfo(const InputWindowInfo& info) const; + InputWindowInfo& getInfo() const { return const_cast(mInfo); } + + sp mService; + sp mQuery; + +private: + sp mSetInputWindowsListener; + sp mServerChannel, mClientChannel; + InputWindowInfo mInfo; + std::mutex mLock; + std::condition_variable mSetInputWindowsFinishedCondition; +}; + +struct SetInputWindowsListener : BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function cbFunc) : mCbFunc(cbFunc) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mCbFunc; +}; + +class TestInputManager : public BnInputFlinger { +protected: + virtual ~TestInputManager(){}; + +public: + TestInputManager(){}; + void checkFdFlags(const android::base::unique_fd& fd); + + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos); + + status_t dump(int fd, const Vector& args) override; + + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; + + binder::Status registerInputChannel(const InputChannelInfo& channel) override; + binder::Status unregisterInputChannel(const InputChannelInfo& channel) override; + +private: + mutable Mutex mLock; + std::unordered_map>> mHandlesPerDisplay; + std::vector> mInputChannels; +}; + +class TestInputQuery : public BnInputFlingerQuery { +public: + TestInputQuery(sp manager) : mManager(manager){}; + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override; + +private: + sp mManager; +}; + +binder::Status TestInputQuery::getInputWindows( + std::vector<::android::InputWindowInfo>* inputHandles) { + return mManager->getInputWindows(inputHandles); +} + +binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + return mManager->getInputChannels(infos); +} + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mCbFunc != nullptr) { + mCbFunc(); + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::setInputWindows( + const std::vector& infos, + const sp& setInputWindowsListener) { + AutoMutex _l(mLock); + + for (const auto& info : infos) { + mHandlesPerDisplay.emplace(info.displayId, std::vector>()); + mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info)); + } + if (setInputWindowsListener) { + setInputWindowsListener->onSetInputWindowsFinished(); + } + return binder::Status::ok(); +} + +void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) { + const int result = fcntl(fd, F_GETFL); + EXPECT_NE(result, -1); + EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK); +} + +binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + mInputChannels.push_back(channel); + + return binder::Status::ok(); +} + +binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + + auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(), + [&](sp& it) { return *it == *channel; }); + if (it != mInputChannels.end()) { + mInputChannels.erase(it); + } + + return binder::Status::ok(); +} + +status_t TestInputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; +} + +binder::Status TestInputManager::getInputWindows( + std::vector<::android::InputWindowInfo>* inputInfos) { + for (auto& [displayId, inputHandles] : mHandlesPerDisplay) { + for (auto& inputHandle : inputHandles) { + inputInfos->push_back(*inputHandle->getInfo()); + } + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + infos->clear(); + for (auto& channel : mInputChannels) { + auto chanDup = channel->dup(); + infos->push_back(std::move(chanDup->getInfo())); + } + return binder::Status::ok(); +} + +void InputFlingerServiceTest::SetUp() { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { + std::unique_lock lock(mLock); + mSetInputWindowsFinishedCondition.notify_all(); + }); + InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); + + mInfo.token = TestInfoToken; + mInfo.id = TestInfoId; + mInfo.name = TestInfoName; + mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags; + mInfo.layoutParamsType = TestInfoLayoutParamsType; + mInfo.dispatchingTimeout = TestInfoDispatchingTimeout; + mInfo.frameLeft = TestInfoFrameLeft; + mInfo.frameTop = TestInfoFrameTop; + mInfo.frameRight = TestInfoFrameRight; + mInfo.frameBottom = TestInfoFrameBottom; + mInfo.surfaceInset = TestInfoSurfaceInset; + mInfo.globalScaleFactor = TestInfoGlobalScaleFactor; + mInfo.windowXScale = TestInfoWindowXScale; + mInfo.windowYScale = TestInfoWindowYScale; + mInfo.touchableRegion = TestInfoTouchableRegion; + mInfo.visible = TestInfoVisible; + mInfo.canReceiveKeys = TestInfoCanReceiveKeys; + mInfo.trustedOverlay = TestInfoTrustedOverlay; + mInfo.hasFocus = TestInfoHasFocus; + mInfo.hasWallpaper = TestInfoHasWallpaper; + mInfo.paused = TestInfoPaused; + mInfo.ownerPid = TestInfoOwnerPid; + mInfo.ownerUid = TestInfoOwnerUid; + mInfo.inputFeatures = TestInfoInputFeatures; + mInfo.displayId = TestInfoDisplayId; + mInfo.portalToDisplayId = TestInfoPortalToDisplayId; + mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop; + mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle; + + mInfo.applicationInfo.name = TestAppInfoName; + mInfo.applicationInfo.token = TestAppInfoToken; + mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout; + + InitializeInputFlinger(); +} + +void InputFlingerServiceTest::TearDown() {} + +void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const { + EXPECT_EQ(mInfo, info); +} + +void InputFlingerServiceTest::InitializeInputFlinger() { + sp input(defaultServiceManager()->waitForService(kTestServiceName)); + ASSERT_TRUE(input != nullptr); + mService = interface_cast(input); + + input = defaultServiceManager()->waitForService(kQueryServiceName); + ASSERT_TRUE(input != nullptr); + mQuery = interface_cast(input); +} + +void InputFlingerServiceTest::setInputWindowsByInfos(std::vector& infos) { + std::unique_lock lock(mLock); + mService->setInputWindows(infos, mSetInputWindowsListener); + // Verify listener call + EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout); + // Verify input windows from service + std::vector<::android::InputWindowInfo> inputHandles; + mQuery->getInputWindows(&inputHandles); + for (auto& inputInfo : inputHandles) { + verifyInputWindowInfo(inputInfo); + } +} + +/** + * Test InputFlinger service interface SetInputWindows + */ +TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) { + std::vector infos = {getInfo()}; + setInputWindowsByInfos(infos); +} + +/** + * Test InputFlinger service interface registerInputChannel + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) { + sp serverChannel, clientChannel; + + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + mService->registerInputChannel(serverChannel->getInfo()); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 1UL); + + auto& info = infos[0]; + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + EXPECT_EQ(*channel, *serverChannel); + + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +/** + * Test InputFlinger service interface registerInputChannel with invalid cases + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) { + sp serverChannel, clientChannel; + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); + + mService->registerInputChannel(InputChannelInfo()); + mService->unregisterInputChannel(clientChannel->getInfo()); + + mService->registerInputChannel(serverChannel->getInfo()); + mService->registerInputChannel(clientChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 2UL); + + mService->unregisterInputChannel(clientChannel->getInfo()); + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +} // namespace android + +int main(int argc, char** argv) { + pid_t forkPid = fork(); + + if (forkPid == 0) { + // Server process + android::sp manager = new android::TestInputManager(); + android::sp query = new android::TestInputQuery(manager); + + android::defaultServiceManager()->addService(android::kTestServiceName, manager, + false /*allowIsolated*/); + android::defaultServiceManager()->addService(android::kQueryServiceName, query, + false /*allowIsolated*/); + android::ProcessState::self()->startThreadPool(); + android::IPCThreadState::self()->joinThreadPool(); + } else { + android::ProcessState::self()->startThreadPool(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + } + return 0; +} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e5e3f48732..aa7b90348a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -256,6 +257,21 @@ private: } // namespace anonymous +struct SetInputWindowsListener : os::BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function listenerCb) : mListenerCb(listenerCb) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mListenerCb; +}; + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mListenerCb != nullptr) { + mListenerCb(); + } + return binder::Status::ok(); +} + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -321,7 +337,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)), - mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {} + mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); }); +} SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ALOGI("SurfaceFlinger is starting"); @@ -623,7 +641,7 @@ void SurfaceFlinger::bootFinished() if (input == nullptr) { ALOGE("Failed to link to input service"); } else { - mInputFlinger = interface_cast(input); + mInputFlinger = interface_cast(input); } readPersistentProperties(); @@ -2892,19 +2910,19 @@ void SurfaceFlinger::updateInputFlinger() { } void SurfaceFlinger::updateInputWindowInfo() { - std::vector inputHandles; + std::vector inputInfos; mDrawingState.traverseInReverseZOrder([&](Layer* layer) { if (layer->needsInputInfo()) { // When calculating the screen bounds we ignore the transparent region since it may // result in an unwanted offset. - inputHandles.push_back(layer->fillInputInfo()); + inputInfos.push_back(layer->fillInputInfo()); } }); - mInputFlinger->setInputWindows(inputHandles, - mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener - : nullptr); + mInputFlinger->setInputWindows(inputInfos, + mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener + : nullptr); } void SurfaceFlinger::commitInputWindowCommands() { @@ -3807,7 +3825,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eInputInfoChanged) { if (privileged) { - layer->setInputInfo(s.inputInfo); + layer->setInputInfo(*s.inputHandle->getInfo()); flags |= eTraversalNeeded; } else { ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); @@ -6059,10 +6077,6 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& display } } -void SurfaceFlinger::SetInputWindowsListener::onSetInputWindowsFinished() { - mFlinger->setInputWindowsFinished(); -} - wp SurfaceFlinger::fromHandle(const sp& handle) { Mutex::Autolock _l(mStateLock); return fromHandleLocked(handle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d8ea5016e8..7ab0729f35 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -89,8 +88,8 @@ namespace android { class Client; class EventThread; class HWComposer; +struct SetInputWindowsListener; class IGraphicBufferProducer; -class IInputFlinger; class Layer; class MessageBase; class RefreshRateOverlay; @@ -99,6 +98,10 @@ class RenderArea; class TimeStats; class FrameTracer; +namespace os { + class IInputFlinger; +} + namespace compositionengine { class DisplaySurface; class OutputLayer; @@ -336,6 +339,7 @@ public: // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; + void setInputWindowsFinished(); private: friend class BufferLayer; @@ -606,7 +610,6 @@ private: void updateInputFlinger(); void updateInputWindowInfo(); void commitInputWindowCommands() REQUIRES(mStateLock); - void setInputWindowsFinished(); void updateCursorAsync(); void initScheduler(DisplayId primaryDisplayId); @@ -1254,21 +1257,12 @@ private: const float mInternalDisplayDensity; const float mEmulatedDisplayDensity; - sp mInputFlinger; + sp mInputFlinger; InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock); // Should only be accessed by the main thread. InputWindowCommands mInputWindowCommands; - struct SetInputWindowsListener : BnSetInputWindowsListener { - explicit SetInputWindowsListener(sp flinger) - : mFlinger(std::move(flinger)) {} - - void onSetInputWindowsFinished() override; - - const sp mFlinger; - }; - - const sp mSetInputWindowsListener = new SetInputWindowsListener(this); + sp mSetInputWindowsListener; bool mPendingSyncInputWindows GUARDED_BY(mStateLock) = false; Hwc2::impl::PowerAdvisor mPowerAdvisor; -- cgit v1.2.3-59-g8ed1b From ce5ab0807a71ce53793dd2f8721f5258943b7f0a Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Thu, 9 Jul 2020 17:03:21 -0500 Subject: Use std::shared_ptr for InputChannel Modernize the code by moving away from RefBase. We can further improve this by switching to unique_ptr in some places. Current refactor is to get off of RefBase only. Test: interact with cf after device boots Bug: 142581626 Change-Id: Ib90fc721970113310b87411bcc2ba62e30ddfd01 --- include/input/InputTransport.h | 72 ++++++-------- libs/gui/tests/EndToEndNativeInputTest.cpp | 7 +- libs/input/InputTransport.cpp | 79 ++++++---------- libs/input/android/InputChannel.aidl | 20 ++++ libs/input/android/InputChannelInfo.aidl | 20 ---- libs/input/android/os/IInputFlinger.aidl | 6 +- libs/input/tests/InputChannel_test.cpp | 24 ++--- .../input/tests/InputPublisherAndConsumer_test.cpp | 6 +- services/inputflinger/InputManager.cpp | 11 +-- services/inputflinger/InputManager.h | 4 +- .../benchmarks/InputDispatcher_benchmarks.cpp | 2 +- services/inputflinger/dispatcher/Connection.cpp | 2 +- services/inputflinger/dispatcher/Connection.h | 5 +- services/inputflinger/dispatcher/Entry.h | 2 +- .../inputflinger/dispatcher/InputDispatcher.cpp | 49 +++++----- services/inputflinger/dispatcher/InputDispatcher.h | 26 +++--- services/inputflinger/dispatcher/InputTarget.h | 2 +- services/inputflinger/dispatcher/Monitor.cpp | 2 +- services/inputflinger/dispatcher/Monitor.h | 4 +- .../dispatcher/include/InputDispatcherInterface.h | 8 +- services/inputflinger/host/InputFlinger.h | 4 +- .../inputflinger/tests/IInputFlingerQuery.aidl | 4 +- .../inputflinger/tests/InputDispatcher_test.cpp | 7 +- .../tests/InputFlingerService_test.cpp | 104 ++++++++++----------- 24 files changed, 219 insertions(+), 251 deletions(-) create mode 100644 libs/input/android/InputChannel.aidl delete mode 100644 libs/input/android/InputChannelInfo.aidl (limited to 'services/inputflinger/InputManager.cpp') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 09cebefc14..f337d009a0 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -183,18 +183,6 @@ struct InputMessage { } }; -struct InputChannelInfo : public Parcelable { - std::string mName; - android::base::unique_fd mFd; - sp mToken; - - InputChannelInfo() = default; - InputChannelInfo(const std::string& name, android::base::unique_fd fd, sp token) - : mName(name), mFd(std::move(fd)), mToken(token){}; - status_t readFromParcel(const android::Parcel* parcel) override; - status_t writeToParcel(android::Parcel* parcel) const override; -}; - /* * An input channel consists of a local unix domain socket used to send and receive * input messages across processes. Each channel has a descriptive name for debugging purposes. @@ -203,14 +191,15 @@ struct InputChannelInfo : public Parcelable { * * The input channel is closed when all references to it are released. */ -class InputChannel : public RefBase { +class InputChannel : public Parcelable { public: - InputChannel(); + static std::shared_ptr create(const std::string& name, + android::base::unique_fd fd, sp token); + InputChannel() = default; + InputChannel(const InputChannel& other) + : mName(other.mName), mFd(::dup(other.mFd)), mToken(other.mToken){}; + InputChannel(const std::string name, android::base::unique_fd fd, sp token); virtual ~InputChannel(); - - static sp create(const std::string& name, android::base::unique_fd fd, - sp token); - /** * Create a pair of input channels. * The two returned input channels are equivalent, and are labeled as "server" and "client" @@ -219,12 +208,12 @@ public: * Return OK on success. */ static status_t openInputChannelPair(const std::string& name, - sp& outServerChannel, sp& outClientChannel); + std::shared_ptr& outServerChannel, + std::shared_ptr& outClientChannel); - inline std::string getName() const { return mInfo.mName; } - inline int getFd() const { return mInfo.mFd.get(); } - inline sp getToken() const { return mInfo.mToken; } - inline InputChannelInfo& getInfo() { return mInfo; } + inline std::string getName() const { return mName; } + inline const android::base::unique_fd& getFd() const { return mFd; } + inline sp getToken() const { return mToken; } /* Send a message to the other endpoint. * @@ -252,11 +241,10 @@ public: status_t receiveMessage(InputMessage* msg); /* Return a new object that has a duplicate of this channel's fd. */ - sp dup() const; - - status_t readFromParcel(const android::Parcel* parcel); + std::shared_ptr dup() const; - status_t writeToParcel(android::Parcel* parcel) const; + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; /** * The connection token is used to identify the input connection, i.e. @@ -273,22 +261,23 @@ public: sp getConnectionToken() const; bool operator==(const InputChannel& inputChannel) const { - struct stat lhsInfo, rhsInfo; - if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) { + struct stat lhs, rhs; + if (fstat(mFd.get(), &lhs) != 0) { return false; } - if (fstat(inputChannel.getFd(), &rhsInfo) != 0) { + if (fstat(inputChannel.getFd(), &rhs) != 0) { return false; } // If file descriptors are pointing to same inode they are duplicated fds. - return inputChannel.getName() == getName() && - inputChannel.getConnectionToken() == mInfo.mToken && - lhsInfo.st_ino == rhsInfo.st_ino; + return inputChannel.getName() == getName() && inputChannel.getConnectionToken() == mToken && + lhs.st_ino == rhs.st_ino; } private: - InputChannel(const std::string& name, android::base::unique_fd fd, sp token); - InputChannelInfo mInfo; + std::string mName; + android::base::unique_fd mFd; + + sp mToken; }; /* @@ -297,13 +286,13 @@ private: class InputPublisher { public: /* Creates a publisher associated with an input channel. */ - explicit InputPublisher(const sp& channel); + explicit InputPublisher(const std::shared_ptr& channel); /* Destroys the publisher and releases its input channel. */ ~InputPublisher(); /* Gets the underlying input channel. */ - inline sp getChannel() { return mChannel; } + inline std::shared_ptr getChannel() { return mChannel; } /* Publishes a key event to the input channel. * @@ -360,7 +349,7 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - sp mChannel; + std::shared_ptr mChannel; }; /* @@ -369,13 +358,13 @@ private: class InputConsumer { public: /* Creates a consumer associated with an input channel. */ - explicit InputConsumer(const sp& channel); + explicit InputConsumer(const std::shared_ptr& channel); /* Destroys the consumer and releases its input channel. */ ~InputConsumer(); /* Gets the underlying input channel. */ - inline sp getChannel() { return mChannel; } + inline std::shared_ptr getChannel() { return mChannel; } /* Consumes an input event from the input channel and copies its contents into * an InputEvent object created using the specified factory. @@ -451,8 +440,7 @@ private: // True if touch resampling is enabled. const bool mResampleTouch; - // The input channel. - sp mChannel; + std::shared_ptr mChannel; // The current input message. InputMessage mMsg; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 383d5916a4..7ec2c1a913 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -72,7 +72,7 @@ public: InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); mInputFlinger = getInputFlinger(); - mInputFlinger->registerInputChannel(mServerChannel->getInfo()); + mInputFlinger->registerInputChannel(*mServerChannel); populateInputInfo(width, height); @@ -154,7 +154,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } - ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); } + ~InputSurface() { mInputFlinger->unregisterInputChannel(*mServerChannel); } void doTransaction(std::function&)> transactionBody) { @@ -211,7 +211,8 @@ private: } public: sp mSurfaceControl; - sp mServerChannel, mClientChannel; + std::shared_ptr mServerChannel; + std::shared_ptr mClientChannel; sp mInputFlinger; InputWindowInfo mInputInfo; diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 60ad578ceb..1bbddea8db 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -241,65 +241,42 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { } } -// --- InputChannelInfo --- - -status_t InputChannelInfo::writeToParcel(android::Parcel* parcel) const { - if (parcel == nullptr) { - ALOGE("%s: Null parcel", __func__); - return BAD_VALUE; - } - status_t status = parcel->writeStrongBinder(mToken) - ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); - return status; -} - -status_t InputChannelInfo::readFromParcel(const android::Parcel* parcel) { - if (parcel == nullptr) { - ALOGE("%s: Null parcel", __func__); - return BAD_VALUE; - } - mToken = parcel->readStrongBinder(); - status_t status = parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); - return status; -} - // --- InputChannel --- -sp InputChannel::create(const std::string& name, android::base::unique_fd fd, - sp token) { +std::shared_ptr InputChannel::create(const std::string& name, + android::base::unique_fd fd, sp token) { const int result = fcntl(fd, F_SETFL, O_NONBLOCK); if (result != 0) { LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(), strerror(errno)); return nullptr; } - return new InputChannel(name, std::move(fd), token); + // using 'new' to access a non-public constructor + return std::shared_ptr(new InputChannel(name, std::move(fd), token)); } -InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp token) - : mInfo(name, std::move(fd), token) { +InputChannel::InputChannel(const std::string name, android::base::unique_fd fd, sp token) + : mName(std::move(name)), mFd(std::move(fd)), mToken(std::move(token)) { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get()); + ALOGD("Input channel constructed: name='%s', fd=%d", getName().c_str(), getFd().get()); } } -InputChannel::InputChannel() {} - InputChannel::~InputChannel() { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd()); + ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd().get()); } } status_t InputChannel::openInputChannelPair(const std::string& name, - sp& outServerChannel, sp& outClientChannel) { + std::shared_ptr& outServerChannel, + std::shared_ptr& outClientChannel) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) { status_t result = -errno; - ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", - name.c_str(), errno); - outServerChannel.clear(); - outClientChannel.clear(); + ALOGE("channel '%s' ~ Could not create socket pair. errno=%d", name.c_str(), errno); + outServerChannel.reset(); + outClientChannel.reset(); return result; } @@ -399,10 +376,10 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { return OK; } -sp InputChannel::dup() const { +std::shared_ptr InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { - ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), getName().c_str(), + ALOGE("Could not duplicate fd %i for channel %s: %s", getFd().get(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding @@ -417,22 +394,30 @@ sp InputChannel::dup() const { } status_t InputChannel::writeToParcel(android::Parcel* parcel) const { - return mInfo.writeToParcel(parcel); + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + return parcel->writeStrongBinder(mToken) + ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); } status_t InputChannel::readFromParcel(const android::Parcel* parcel) { - return mInfo.readFromParcel(parcel); + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + mToken = parcel->readStrongBinder(); + return parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); } sp InputChannel::getConnectionToken() const { - return mInfo.mToken; + return mToken; } // --- InputPublisher --- -InputPublisher::InputPublisher(const sp& channel) : - mChannel(channel) { -} +InputPublisher::InputPublisher(const std::shared_ptr& channel) : mChannel(channel) {} InputPublisher::~InputPublisher() { } @@ -596,10 +581,8 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle // --- InputConsumer --- -InputConsumer::InputConsumer(const sp& channel) : - mResampleTouch(isTouchResamplingEnabled()), - mChannel(channel), mMsgDeferred(false) { -} +InputConsumer::InputConsumer(const std::shared_ptr& channel) + : mResampleTouch(isTouchResamplingEnabled()), mChannel(channel), mMsgDeferred(false) {} InputConsumer::~InputConsumer() { } diff --git a/libs/input/android/InputChannel.aidl b/libs/input/android/InputChannel.aidl new file mode 100644 index 0000000000..c2d1112dd3 --- /dev/null +++ b/libs/input/android/InputChannel.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputChannel cpp_header "input/InputTransport.h"; diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannelInfo.aidl deleted file mode 100644 index 2e83b966f1..0000000000 --- a/libs/input/android/InputChannelInfo.aidl +++ /dev/null @@ -1,20 +0,0 @@ -/* //device/java/android/android/view/InputChannel.aidl -** -** Copyright 2020, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -package android; - -parcelable InputChannelInfo cpp_header "input/InputTransport.h"; diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl index 8ff9dae47e..4c7fddc87c 100644 --- a/libs/input/android/os/IInputFlinger.aidl +++ b/libs/input/android/os/IInputFlinger.aidl @@ -16,7 +16,7 @@ package android.os; -import android.InputChannelInfo; +import android.InputChannel; import android.InputWindowInfo; import android.os.ISetInputWindowsListener; @@ -25,6 +25,6 @@ interface IInputFlinger { void setInputWindows(in InputWindowInfo[] inputHandles, in @nullable ISetInputWindowsListener setInputWindowsListener); - void registerInputChannel(in InputChannelInfo info); - void unregisterInputChannel(in InputChannelInfo info); + void registerInputChannel(in InputChannel channel); + void unregisterInputChannel(in InputChannel channel); } diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index 4187ca95d2..cc1382bbcb 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -47,7 +47,7 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor android::base::unique_fd sendFd(pipe.sendFd); - sp inputChannel = + std::shared_ptr inputChannel = InputChannel::create("channel name", std::move(sendFd), new BBinder()); EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created"; @@ -62,14 +62,14 @@ TEST_F(InputChannelTest, ConstructorAndDestructor_TakesOwnershipOfFileDescriptor TEST_F(InputChannelTest, SetAndGetToken) { Pipe pipe; sp token = new BBinder(); - sp channel = + std::shared_ptr channel = InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd), token); EXPECT_EQ(token, channel->getConnectionToken()); } TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); @@ -120,7 +120,7 @@ TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) { } TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); @@ -134,7 +134,7 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenNoSignalPresent_ReturnsAnError) { } TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); @@ -142,7 +142,7 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; - serverChannel.clear(); // close server channel + serverChannel.reset(); // close server channel InputMessage msg; EXPECT_EQ(DEAD_OBJECT, clientChannel->receiveMessage(&msg)) @@ -150,7 +150,7 @@ TEST_F(InputChannelTest, ReceiveSignal_WhenPeerClosed_ReturnsAnError) { } TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); @@ -158,7 +158,7 @@ TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; - serverChannel.clear(); // close server channel + serverChannel.reset(); // close server channel InputMessage msg; msg.header.type = InputMessage::Type::KEY; @@ -167,7 +167,7 @@ TEST_F(InputChannelTest, SendSignal_WhenPeerClosed_ReturnsAnError) { } TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel); ASSERT_EQ(OK, result) @@ -199,7 +199,7 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { } TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel); @@ -218,14 +218,14 @@ TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) { } TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; status_t result = InputChannel::openInputChannelPair("channel dup", serverChannel, clientChannel); ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; - sp dupChan = serverChannel->dup(); + std::shared_ptr dupChan = serverChannel->dup(); EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication"; } diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp index 8e2eec85ed..3a7d20bfa2 100644 --- a/libs/input/tests/InputPublisherAndConsumer_test.cpp +++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp @@ -30,7 +30,7 @@ namespace android { class InputPublisherAndConsumerTest : public testing::Test { protected: - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; InputPublisher* mPublisher; InputConsumer* mConsumer; PreallocatedInputEventFactory mEventFactory; @@ -55,8 +55,8 @@ protected: mConsumer = nullptr; } - serverChannel.clear(); - clientChannel.clear(); + serverChannel.reset(); + clientChannel.reset(); } void PublishAndConsumeKeyEvent(); diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index c5f60ade96..088c6f1f48 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -119,7 +119,7 @@ binder::Status InputManager::setInputWindows( } // Used by tests only. -binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) { +binder::Status InputManager::registerInputChannel(const InputChannel& channel) { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { @@ -127,15 +127,12 @@ binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) "from non shell/root entity (PID: %d)", ipc->getCallingPid()); return binder::Status::ok(); } - android::base::unique_fd newFd(::dup(info.mFd)); - sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); - mDispatcher->registerInputChannel(channel); + + mDispatcher->registerInputChannel(channel.dup()); return binder::Status::ok(); } -binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) { - android::base::unique_fd newFd(::dup(info.mFd)); - sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); +binder::Status InputManager::unregisterInputChannel(const InputChannel& channel) { mDispatcher->unregisterInputChannel(channel); return binder::Status::ok(); } diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 4993b54b5c..0503e8161e 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -108,8 +108,8 @@ public: const std::vector& handles, const sp& setInputWindowsListener) override; - binder::Status registerInputChannel(const InputChannelInfo& info) override; - binder::Status unregisterInputChannel(const InputChannelInfo& info) override; + binder::Status registerInputChannel(const InputChannel& channel) override; + binder::Status unregisterInputChannel(const InputChannel& channel) override; private: sp mReader; diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp index a15b7b25ef..3d66d30d18 100644 --- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp +++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp @@ -135,7 +135,7 @@ protected: virtual ~FakeInputReceiver() {} sp mDispatcher; - sp mServerChannel, mClientChannel; + std::shared_ptr mServerChannel, mClientChannel; std::unique_ptr mConsumer; PreallocatedInputEventFactory mEventFactory; }; diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp index f5ea563311..cee9c39abd 100644 --- a/services/inputflinger/dispatcher/Connection.cpp +++ b/services/inputflinger/dispatcher/Connection.cpp @@ -20,7 +20,7 @@ namespace android::inputdispatcher { -Connection::Connection(const sp& inputChannel, bool monitor, +Connection::Connection(const std::shared_ptr& inputChannel, bool monitor, const IdGenerator& idGenerator) : status(STATUS_NORMAL), inputChannel(inputChannel), diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h index 3b33f29dff..c4262ad2d8 100644 --- a/services/inputflinger/dispatcher/Connection.h +++ b/services/inputflinger/dispatcher/Connection.h @@ -42,7 +42,7 @@ public: }; Status status; - sp inputChannel; // never null + std::shared_ptr inputChannel; // never null bool monitor; InputPublisher inputPublisher; InputState inputState; @@ -59,7 +59,8 @@ public: // yet received a "finished" response from the application. std::deque waitQueue; - Connection(const sp& inputChannel, bool monitor, const IdGenerator& idGenerator); + Connection(const std::shared_ptr& inputChannel, bool monitor, + const IdGenerator& idGenerator); inline const std::string getInputChannelName() const { return inputChannel->getName(); } diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index 6b7697dde6..4147e41510 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -262,7 +262,7 @@ struct CommandEntry { int32_t userActivityEventType; uint32_t seq; bool handled; - sp inputChannel; + std::shared_ptr inputChannel; sp oldToken; sp newToken; }; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 3bdbcce79b..da098984b1 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -433,7 +433,7 @@ InputDispatcher::~InputDispatcher() { while (!mConnectionsByFd.empty()) { sp connection = mConnectionsByFd.begin()->second; - unregisterInputChannel(connection->inputChannel); + unregisterInputChannel(*connection->inputChannel); } } @@ -1105,7 +1105,7 @@ void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, b } void InputDispatcher::dispatchFocusLocked(nsecs_t currentTime, FocusEntry* entry) { - sp channel = getInputChannelLocked(entry->connectionToken); + std::shared_ptr channel = getInputChannelLocked(entry->connectionToken); if (channel == nullptr) { return; // Window has gone away } @@ -2029,7 +2029,8 @@ void InputDispatcher::addWindowTargetLocked(const sp& windowH if (it == inputTargets.end()) { InputTarget inputTarget; - sp inputChannel = getInputChannelLocked(windowHandle->getToken()); + std::shared_ptr inputChannel = + getInputChannelLocked(windowHandle->getToken()); if (inputChannel == nullptr) { ALOGW("Window %s already unregistered input channel", windowHandle->getName().c_str()); return; @@ -2844,7 +2845,7 @@ int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) { } // Unregister the channel. - d->unregisterInputChannelLocked(connection->inputChannel, notify); + d->unregisterInputChannelLocked(*connection->inputChannel, notify); return 0; // remove the callback } // release lock } @@ -2874,7 +2875,7 @@ void InputDispatcher::synthesizeCancelationEventsForMonitorsLocked( } void InputDispatcher::synthesizeCancelationEventsForInputChannelLocked( - const sp& channel, const CancelationOptions& options) { + const std::shared_ptr& channel, const CancelationOptions& options) { sp connection = getConnectionLocked(channel->getConnectionToken()); if (connection == nullptr) { return; @@ -3690,7 +3691,8 @@ bool InputDispatcher::hasWindowHandleLocked(const sp& windowH return false; } -sp InputDispatcher::getInputChannelLocked(const sp& token) const { +std::shared_ptr InputDispatcher::getInputChannelLocked( + const sp& token) const { size_t count = mInputChannelsByToken.count(token); if (count == 0) { return nullptr; @@ -3815,7 +3817,7 @@ void InputDispatcher::setInputWindowsLocked( ALOGD("Focus left window: %s in display %" PRId32, oldFocusedWindowHandle->getName().c_str(), displayId); } - sp focusedInputChannel = + std::shared_ptr focusedInputChannel = getInputChannelLocked(oldFocusedWindowHandle->getToken()); if (focusedInputChannel != nullptr) { CancelationOptions options(CancelationOptions::CANCEL_NON_POINTER_EVENTS, @@ -3850,7 +3852,7 @@ void InputDispatcher::setInputWindowsLocked( ALOGD("Touched window was removed: %s in display %" PRId32, touchedWindow.windowHandle->getName().c_str(), displayId); } - sp touchedInputChannel = + std::shared_ptr touchedInputChannel = getInputChannelLocked(touchedWindow.windowHandle->getToken()); if (touchedInputChannel != nullptr) { CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, @@ -3929,7 +3931,7 @@ void InputDispatcher::setFocusedDisplay(int32_t displayId) { sp oldFocusedWindowHandle = getValueByKey(mFocusedWindowHandlesByDisplay, mFocusedDisplayId); if (oldFocusedWindowHandle != nullptr) { - sp inputChannel = + std::shared_ptr inputChannel = getInputChannelLocked(oldFocusedWindowHandle->getToken()); if (inputChannel != nullptr) { CancelationOptions @@ -4376,13 +4378,13 @@ void InputDispatcher::dumpMonitors(std::string& dump, const std::vector const size_t numMonitors = monitors.size(); for (size_t i = 0; i < numMonitors; i++) { const Monitor& monitor = monitors[i]; - const sp& channel = monitor.inputChannel; + const std::shared_ptr& channel = monitor.inputChannel; dump += StringPrintf(INDENT2 "%zu: '%s', ", i, channel->getName().c_str()); dump += "\n"; } } -status_t InputDispatcher::registerInputChannel(const sp& inputChannel) { +status_t InputDispatcher::registerInputChannel(const std::shared_ptr& inputChannel) { #if DEBUG_REGISTRATION ALOGD("channel '%s' ~ registerInputChannel", inputChannel->getName().c_str()); #endif @@ -4410,7 +4412,7 @@ status_t InputDispatcher::registerInputChannel(const sp& inputChan return OK; } -status_t InputDispatcher::registerInputMonitor(const sp& inputChannel, +status_t InputDispatcher::registerInputMonitor(const std::shared_ptr& inputChannel, int32_t displayId, bool isGestureMonitor) { { // acquire lock std::scoped_lock _l(mLock); @@ -4442,9 +4444,9 @@ status_t InputDispatcher::registerInputMonitor(const sp& inputChan return OK; } -status_t InputDispatcher::unregisterInputChannel(const sp& inputChannel) { +status_t InputDispatcher::unregisterInputChannel(const InputChannel& inputChannel) { #if DEBUG_REGISTRATION - ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel->getName().c_str()); + ALOGD("channel '%s' ~ unregisterInputChannel", inputChannel.getName().c_str()); #endif { // acquire lock @@ -4462,23 +4464,23 @@ status_t InputDispatcher::unregisterInputChannel(const sp& inputCh return OK; } -status_t InputDispatcher::unregisterInputChannelLocked(const sp& inputChannel, +status_t InputDispatcher::unregisterInputChannelLocked(const InputChannel& inputChannel, bool notify) { - sp connection = getConnectionLocked(inputChannel->getConnectionToken()); + sp connection = getConnectionLocked(inputChannel.getConnectionToken()); if (connection == nullptr) { ALOGW("Attempted to unregister already unregistered input channel '%s'", - inputChannel->getName().c_str()); + inputChannel.getName().c_str()); return BAD_VALUE; } removeConnectionLocked(connection); - mInputChannelsByToken.erase(inputChannel->getConnectionToken()); + mInputChannelsByToken.erase(inputChannel.getConnectionToken()); if (connection->monitor) { removeMonitorChannelLocked(inputChannel); } - mLooper->removeFd(inputChannel->getFd()); + mLooper->removeFd(inputChannel.getFd()); nsecs_t currentTime = now(); abortBrokenDispatchCycleLocked(currentTime, connection, notify); @@ -4487,19 +4489,19 @@ status_t InputDispatcher::unregisterInputChannelLocked(const sp& i return OK; } -void InputDispatcher::removeMonitorChannelLocked(const sp& inputChannel) { +void InputDispatcher::removeMonitorChannelLocked(const InputChannel& inputChannel) { removeMonitorChannelLocked(inputChannel, mGlobalMonitorsByDisplay); removeMonitorChannelLocked(inputChannel, mGestureMonitorsByDisplay); } void InputDispatcher::removeMonitorChannelLocked( - const sp& inputChannel, + const InputChannel& inputChannel, std::unordered_map>& monitorsByDisplay) { for (auto it = monitorsByDisplay.begin(); it != monitorsByDisplay.end();) { std::vector& monitors = it->second; const size_t numMonitors = monitors.size(); for (size_t i = 0; i < numMonitors; i++) { - if (monitors[i].inputChannel == inputChannel) { + if (*monitors[i].inputChannel == inputChannel) { monitors.erase(monitors.begin() + i); break; } @@ -4550,7 +4552,8 @@ status_t InputDispatcher::pilferPointers(const sp& token) { options.deviceId = deviceId; options.displayId = displayId; for (const TouchedWindow& window : state.windows) { - sp channel = getInputChannelLocked(window.windowHandle->getToken()); + std::shared_ptr channel = + getInputChannelLocked(window.windowHandle->getToken()); if (channel != nullptr) { synthesizeCancelationEventsForInputChannelLocked(channel, options); } diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index 824bbf5808..ba7ace0987 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -124,10 +124,11 @@ public: virtual bool transferTouchFocus(const sp& fromToken, const sp& toToken) override; - virtual status_t registerInputChannel(const sp& inputChannel) override; - virtual status_t registerInputMonitor(const sp& inputChannel, int32_t displayId, - bool isGestureMonitor) override; - virtual status_t unregisterInputChannel(const sp& inputChannel) override; + virtual status_t registerInputChannel( + const std::shared_ptr& inputChannel) override; + virtual status_t registerInputMonitor(const std::shared_ptr& inputChannel, + int32_t displayId, bool isGestureMonitor) override; + virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override; virtual status_t pilferPointers(const sp& token) override; private: @@ -210,8 +211,8 @@ private: return std::hash{}(b.get()); } }; - std::unordered_map, sp, IBinderHash> mInputChannelsByToken - GUARDED_BY(mLock); + std::unordered_map, std::shared_ptr, IBinderHash> + mInputChannelsByToken GUARDED_BY(mLock); // Finds the display ID of the gesture monitor identified by the provided token. std::optional findGestureMonitorDisplayByTokenLocked(const sp& token) @@ -301,7 +302,8 @@ private: REQUIRES(mLock); sp getWindowHandleLocked(const sp& windowHandleToken) const REQUIRES(mLock); - sp getInputChannelLocked(const sp& windowToken) const REQUIRES(mLock); + std::shared_ptr getInputChannelLocked(const sp& windowToken) const + REQUIRES(mLock); bool hasWindowHandleLocked(const sp& windowHandle) const REQUIRES(mLock); /* @@ -459,8 +461,8 @@ private: void synthesizeCancelationEventsForMonitorsLocked( const CancelationOptions& options, std::unordered_map>& monitorsByDisplay) REQUIRES(mLock); - void synthesizeCancelationEventsForInputChannelLocked(const sp& channel, - const CancelationOptions& options) + void synthesizeCancelationEventsForInputChannelLocked( + const std::shared_ptr& channel, const CancelationOptions& options) REQUIRES(mLock); void synthesizeCancelationEventsForConnectionLocked(const sp& connection, const CancelationOptions& options) @@ -481,11 +483,11 @@ private: void logDispatchStateLocked() REQUIRES(mLock); // Registration. - void removeMonitorChannelLocked(const sp& inputChannel) REQUIRES(mLock); + void removeMonitorChannelLocked(const InputChannel& inputChannel) REQUIRES(mLock); void removeMonitorChannelLocked( - const sp& inputChannel, + const InputChannel& inputChannel, std::unordered_map>& monitorsByDisplay) REQUIRES(mLock); - status_t unregisterInputChannelLocked(const sp& inputChannel, bool notify) + status_t unregisterInputChannelLocked(const InputChannel& inputChannel, bool notify) REQUIRES(mLock); // Interesting events that we might like to log or tell the framework about. diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h index 499a75fdac..eeb6ee8df9 100644 --- a/services/inputflinger/dispatcher/InputTarget.h +++ b/services/inputflinger/dispatcher/InputTarget.h @@ -106,7 +106,7 @@ struct InputTarget { }; // The input channel to be targeted. - sp inputChannel; + std::shared_ptr inputChannel; // Flags for the input target. int32_t flags = 0; diff --git a/services/inputflinger/dispatcher/Monitor.cpp b/services/inputflinger/dispatcher/Monitor.cpp index 289b0848bf..b34767459f 100644 --- a/services/inputflinger/dispatcher/Monitor.cpp +++ b/services/inputflinger/dispatcher/Monitor.cpp @@ -19,7 +19,7 @@ namespace android::inputdispatcher { // --- Monitor --- -Monitor::Monitor(const sp& inputChannel) : inputChannel(inputChannel) {} +Monitor::Monitor(const std::shared_ptr& inputChannel) : inputChannel(inputChannel) {} // --- TouchedMonitor --- TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset) diff --git a/services/inputflinger/dispatcher/Monitor.h b/services/inputflinger/dispatcher/Monitor.h index b67c9eb507..fc0b0200c6 100644 --- a/services/inputflinger/dispatcher/Monitor.h +++ b/services/inputflinger/dispatcher/Monitor.h @@ -22,9 +22,9 @@ namespace android::inputdispatcher { struct Monitor { - sp inputChannel; // never null + std::shared_ptr inputChannel; // never null - explicit Monitor(const sp& inputChannel); + explicit Monitor(const std::shared_ptr& inputChannel); }; // For tracking the offsets we need to apply when adding gesture monitor targets. diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index f25131c7c7..272b0a6695 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -152,7 +152,7 @@ public: * * This method may be called on any thread (usually by the input manager). */ - virtual status_t registerInputChannel(const sp& inputChannel) = 0; + virtual status_t registerInputChannel(const std::shared_ptr& inputChannel) = 0; /* Registers input channels to be used to monitor input events. * @@ -162,14 +162,14 @@ public: * * This method may be called on any thread (usually by the input manager). */ - virtual status_t registerInputMonitor(const sp& inputChannel, int32_t displayId, - bool gestureMonitor) = 0; + virtual status_t registerInputMonitor(const std::shared_ptr& inputChannel, + int32_t displayId, bool gestureMonitor) = 0; /* Unregister input channels that will no longer receive input events. * * This method may be called on any thread (usually by the input manager). */ - virtual status_t unregisterInputChannel(const sp& inputChannel) = 0; + virtual status_t unregisterInputChannel(const InputChannel& inputChannel) = 0; /* Allows an input monitor steal the current pointer stream away from normal input windows. * diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 9364a2a767..cd655e0ff5 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -48,8 +48,8 @@ public: const sp&) { return binder::Status::ok(); } - binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } - binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } + binder::Status registerInputChannel(const InputChannel&) { return binder::Status::ok(); } + binder::Status unregisterInputChannel(const InputChannel&) { return binder::Status::ok(); } private: virtual ~InputFlinger(); diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl index 1edc08965f..755373b517 100644 --- a/services/inputflinger/tests/IInputFlingerQuery.aidl +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -14,7 +14,7 @@ * limitations under the License. */ -import android.InputChannelInfo; +import android.InputChannel; import android.InputWindowInfo; import android.os.ISetInputWindowsListener; @@ -23,5 +23,5 @@ interface IInputFlingerQuery { /* Test interfaces */ void getInputWindows(out InputWindowInfo[] inputHandles); - void getInputChannels(out InputChannelInfo[] infos); + void getInputChannels(out InputChannel[] channels); } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index c749806190..89314e141c 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -602,7 +602,8 @@ public: class FakeInputReceiver { public: - explicit FakeInputReceiver(const sp& clientChannel, const std::string name) + explicit FakeInputReceiver(const std::shared_ptr& clientChannel, + const std::string name) : mName(name) { mConsumer = std::make_unique(clientChannel); } @@ -754,7 +755,7 @@ public: int32_t displayId, sp token = nullptr) : mName(name) { if (token == nullptr) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; InputChannel::openInputChannelPair(name, serverChannel, clientChannel); mInputReceiver = std::make_unique(clientChannel, name); dispatcher->registerInputChannel(serverChannel); @@ -1767,7 +1768,7 @@ class FakeMonitorReceiver { public: FakeMonitorReceiver(const sp& dispatcher, const std::string name, int32_t displayId, bool isGestureMonitor = false) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; InputChannel::openInputChannelPair(name, serverChannel, clientChannel); mInputReceiver = std::make_unique(clientChannel, name); dispatcher->registerInputMonitor(serverChannel, displayId, isGestureMonitor); diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index 193fe77878..b88bc52aa1 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -113,7 +113,7 @@ protected: private: sp mSetInputWindowsListener; - sp mServerChannel, mClientChannel; + std::shared_ptr mServerChannel, mClientChannel; InputWindowInfo mInfo; std::mutex mLock; std::condition_variable mSetInputWindowsFinishedCondition; @@ -136,7 +136,7 @@ public: void checkFdFlags(const android::base::unique_fd& fd); binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); - binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos); + binder::Status getInputChannels(std::vector<::android::InputChannel>* channels); status_t dump(int fd, const Vector& args) override; @@ -144,20 +144,20 @@ public: const std::vector& handles, const sp& setInputWindowsListener) override; - binder::Status registerInputChannel(const InputChannelInfo& channel) override; - binder::Status unregisterInputChannel(const InputChannelInfo& channel) override; + binder::Status registerInputChannel(const InputChannel& channel) override; + binder::Status unregisterInputChannel(const InputChannel& channel) override; private: mutable Mutex mLock; std::unordered_map>> mHandlesPerDisplay; - std::vector> mInputChannels; + std::vector> mInputChannels; }; class TestInputQuery : public BnInputFlingerQuery { public: TestInputQuery(sp manager) : mManager(manager){}; binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; - binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override; + binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override; private: sp mManager; @@ -168,8 +168,8 @@ binder::Status TestInputQuery::getInputWindows( return mManager->getInputWindows(inputHandles); } -binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { - return mManager->getInputChannels(infos); +binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannel>* channels) { + return mManager->getInputChannels(channels); } binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { @@ -200,27 +200,23 @@ void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) { EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK); } -binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) { +binder::Status TestInputManager::registerInputChannel(const InputChannel& channel) { AutoMutex _l(mLock); // check Fd flags - checkFdFlags(info.mFd); + checkFdFlags(channel.getFd()); - android::base::unique_fd newFd(::dup(info.mFd)); - sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); - mInputChannels.push_back(channel); + mInputChannels.push_back(channel.dup()); return binder::Status::ok(); } -binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) { +binder::Status TestInputManager::unregisterInputChannel(const InputChannel& channel) { AutoMutex _l(mLock); // check Fd flags - checkFdFlags(info.mFd); - android::base::unique_fd newFd(::dup(info.mFd)); - sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + checkFdFlags(channel.getFd()); auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(), - [&](sp& it) { return *it == *channel; }); + [&](std::shared_ptr& c) { return *c == channel; }); if (it != mInputChannels.end()) { mInputChannels.erase(it); } @@ -247,11 +243,10 @@ binder::Status TestInputManager::getInputWindows( return binder::Status::ok(); } -binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { - infos->clear(); - for (auto& channel : mInputChannels) { - auto chanDup = channel->dup(); - infos->push_back(std::move(chanDup->getInfo())); +binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannel>* channels) { + channels->clear(); + for (std::shared_ptr& channel : mInputChannels) { + channels->push_back(*channel); } return binder::Status::ok(); } @@ -320,12 +315,6 @@ void InputFlingerServiceTest::setInputWindowsByInfos(std::vectorsetInputWindows(infos, mSetInputWindowsListener); // Verify listener call EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout); - // Verify input windows from service - std::vector<::android::InputWindowInfo> inputHandles; - mQuery->getInputWindows(&inputHandles); - for (auto& inputInfo : inputHandles) { - verifyInputWindowInfo(inputInfo); - } } /** @@ -334,54 +323,57 @@ void InputFlingerServiceTest::setInputWindowsByInfos(std::vector infos = {getInfo()}; setInputWindowsByInfos(infos); + + // Verify input windows from service + std::vector<::android::InputWindowInfo> windowInfos; + mQuery->getInputWindows(&windowInfos); + for (const ::android::InputWindowInfo& windowInfo : windowInfos) { + verifyInputWindowInfo(windowInfo); + } } /** * Test InputFlinger service interface registerInputChannel */ TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); - mService->registerInputChannel(serverChannel->getInfo()); - - std::vector<::android::InputChannelInfo> infos(2); - mQuery->getInputChannels(&infos); - EXPECT_EQ(infos.size(), 1UL); + mService->registerInputChannel(*serverChannel); - auto& info = infos[0]; - android::base::unique_fd newFd(::dup(info.mFd)); - sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); - EXPECT_EQ(*channel, *serverChannel); + std::vector<::android::InputChannel> channels; + mQuery->getInputChannels(&channels); + ASSERT_EQ(channels.size(), 1UL); + EXPECT_EQ(channels[0], *serverChannel); - mService->unregisterInputChannel(serverChannel->getInfo()); - mQuery->getInputChannels(&infos); - EXPECT_EQ(infos.size(), 0UL); + mService->unregisterInputChannel(*serverChannel); + mQuery->getInputChannels(&channels); + EXPECT_EQ(channels.size(), 0UL); } /** * Test InputFlinger service interface registerInputChannel with invalid cases */ TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) { - sp serverChannel, clientChannel; + std::shared_ptr serverChannel, clientChannel; InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); - std::vector<::android::InputChannelInfo> infos(2); - mQuery->getInputChannels(&infos); - EXPECT_EQ(infos.size(), 0UL); + std::vector<::android::InputChannel> channels; + mQuery->getInputChannels(&channels); + EXPECT_EQ(channels.size(), 0UL); - mService->registerInputChannel(InputChannelInfo()); - mService->unregisterInputChannel(clientChannel->getInfo()); + mService->registerInputChannel(InputChannel()); + mService->unregisterInputChannel(*clientChannel); - mService->registerInputChannel(serverChannel->getInfo()); - mService->registerInputChannel(clientChannel->getInfo()); - mQuery->getInputChannels(&infos); - EXPECT_EQ(infos.size(), 2UL); + mService->registerInputChannel(*serverChannel); + mService->registerInputChannel(*clientChannel); + mQuery->getInputChannels(&channels); + EXPECT_EQ(channels.size(), 2UL); - mService->unregisterInputChannel(clientChannel->getInfo()); - mService->unregisterInputChannel(serverChannel->getInfo()); - mQuery->getInputChannels(&infos); - EXPECT_EQ(infos.size(), 0UL); + mService->unregisterInputChannel(*clientChannel); + mService->unregisterInputChannel(*serverChannel); + mQuery->getInputChannels(&channels); + EXPECT_EQ(channels.size(), 0UL); } } // namespace android -- cgit v1.2.3-59-g8ed1b From e798b47821d07191a20bdb7a3a1fc3887b661635 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 23 Jul 2020 13:52:21 -0700 Subject: Add setFocusedWindow function stub This function, once implemented, will set focus on the specified window. This is the first step in changing focus selection from setInputWindows and using explicit call which will help us more easily decouple z-order from focus selection and support focus for SurfaceViewHost surfaces. Bug: 151179149 Test: presubmit Test: go/wm-smoke Test: atest inputflinger_tests Change-Id: Ib2254b4ab3ba8d579dfe49ddf3286f8ce2eecf9e --- libs/gui/Android.bp | 1 + libs/gui/LayerState.cpp | 19 ++++++- libs/gui/SurfaceComposerClient.cpp | 15 ++++++ libs/gui/include/gui/LayerState.h | 7 ++- libs/gui/include/gui/SurfaceComposerClient.h | 3 ++ libs/input/Android.bp | 1 + libs/input/android/FocusRequest.aidl | 39 ++++++++++++++ libs/input/android/os/IInputFlinger.aidl | 6 +++ services/inputflinger/InputManager.cpp | 5 ++ services/inputflinger/InputManager.h | 1 + .../inputflinger/dispatcher/InputDispatcher.cpp | 15 ++++++ services/inputflinger/dispatcher/InputDispatcher.h | 1 + .../dispatcher/include/InputDispatcherInterface.h | 6 +++ services/inputflinger/host/InputFlinger.h | 1 + services/inputflinger/tests/Android.bp | 4 +- .../inputflinger/tests/IInputFlingerQuery.aidl | 2 + .../tests/InputFlingerService_test.cpp | 61 +++++++++++++++++++++- services/surfaceflinger/SurfaceFlinger.cpp | 13 +++-- 18 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 libs/input/android/FocusRequest.aidl (limited to 'services/inputflinger/InputManager.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 4a4510e047..686e274a11 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -92,6 +92,7 @@ cc_library_shared { export_shared_lib_headers: [ "libbinder", + "libinput", ], // bufferhub is not used when building libgui for vendors diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 1030b82f14..117ce58719 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -448,19 +448,36 @@ void layer_state_t::merge(const layer_state_t& other) { // ------------------------------- InputWindowCommands ---------------------------------------- -void InputWindowCommands::merge(const InputWindowCommands& other) { +bool InputWindowCommands::merge(const InputWindowCommands& other) { + bool changes = false; +#ifndef NO_INPUT + changes |= !other.focusRequests.empty(); + focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()), + std::make_move_iterator(other.focusRequests.end())); +#endif + changes |= other.syncInputWindows && !syncInputWindows; syncInputWindows |= other.syncInputWindows; + return changes; } void InputWindowCommands::clear() { +#ifndef NO_INPUT + focusRequests.clear(); +#endif syncInputWindows = false; } void InputWindowCommands::write(Parcel& output) const { +#ifndef NO_INPUT + output.writeParcelableVector(focusRequests); +#endif output.writeBool(syncInputWindows); } void InputWindowCommands::read(const Parcel& input) { +#ifndef NO_INPUT + input.readParcelableVector(&focusRequests); +#endif syncInputWindows = input.readBool(); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d797a3547a..229a5c2e62 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1364,6 +1364,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( + const sp& token, const sp& focusedToken, nsecs_t timestampNanos) { + FocusRequest request; + request.token = token; + request.focusedToken = focusedToken; + request.timestamp = timestampNanos; + return setFocusedWindow(request); +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( + const FocusRequest& request) { + mInputWindowCommands.focusRequests.push_back(request); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() { mInputWindowCommands.syncInputWindows = true; return *this; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 00ae220906..41aad0d309 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,6 +26,7 @@ #include #ifndef NO_INPUT +#include #include