diff options
author | 2020-07-24 16:22:36 +0000 | |
---|---|---|
committer | 2020-07-24 16:22:36 +0000 | |
commit | 1bd1fcfd858a463c507c35fb99255487f745101d (patch) | |
tree | ad941d534864481384b81875873fa56476d32dbb | |
parent | 2fc6b5f4fecf362701eedac2fcabe0fcd50407b5 (diff) | |
parent | e798b47821d07191a20bdb7a3a1fc3887b661635 (diff) |
Merge "Add setFocusedWindow function stub"
-rw-r--r-- | libs/gui/Android.bp | 1 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 19 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 15 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 7 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | libs/input/Android.bp | 1 | ||||
-rw-r--r-- | libs/input/android/FocusRequest.aidl | 39 | ||||
-rw-r--r-- | libs/input/android/os/IInputFlinger.aidl | 6 | ||||
-rw-r--r-- | services/inputflinger/InputManager.cpp | 5 | ||||
-rw-r--r-- | services/inputflinger/InputManager.h | 1 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 15 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.h | 1 | ||||
-rw-r--r-- | services/inputflinger/dispatcher/include/InputDispatcherInterface.h | 6 | ||||
-rw-r--r-- | services/inputflinger/host/InputFlinger.h | 1 | ||||
-rw-r--r-- | services/inputflinger/tests/Android.bp | 4 | ||||
-rw-r--r-- | services/inputflinger/tests/IInputFlingerQuery.aidl | 2 | ||||
-rw-r--r-- | services/inputflinger/tests/InputFlingerService_test.cpp | 61 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 13 |
18 files changed, 187 insertions, 13 deletions
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<IBinder>& token, const sp<IBinder>& 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 <math/mat4.h> #ifndef NO_INPUT +#include <android/FocusRequest.h> #include <input/InputWindow.h> #endif @@ -283,9 +284,13 @@ struct DisplayState { }; struct InputWindowCommands { +#ifndef NO_INPUT + std::vector<FocusRequest> focusRequests; +#endif bool syncInputWindows{false}; - void merge(const InputWindowCommands& other); + // Merges the passed in commands and returns true if there were any changes. + bool merge(const InputWindowCommands& other); void clear(); void write(Parcel& output) const; void read(const Parcel& input); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index eb757bad32..d5ca0f6da0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -507,6 +507,9 @@ public: #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info); + Transaction& setFocusedWindow(const sp<IBinder>& token, const sp<IBinder>& focusedToken, + nsecs_t timestampNanos); + Transaction& setFocusedWindow(const FocusRequest& request); Transaction& syncInputWindows(); #endif diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 8a9f2618b0..7dd5276958 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -60,6 +60,7 @@ cc_library { "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", + "android/FocusRequest.aidl", "android/os/IInputFlinger.aidl", "android/os/ISetInputWindowsListener.aidl", ], diff --git a/libs/input/android/FocusRequest.aidl b/libs/input/android/FocusRequest.aidl new file mode 100644 index 0000000000..a5034a4fdb --- /dev/null +++ b/libs/input/android/FocusRequest.aidl @@ -0,0 +1,39 @@ +/** + * 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; + +/** @hide */ +parcelable FocusRequest { + /** + * Input channel token used to identify the window that should gain focus. + */ + IBinder token; + /** + * The token that the caller expects currently to be focused. If the + * specified token does not match the currently focused window, this request will be dropped. + * If the specified focused token matches the currently focused window, the call will succeed. + * Set this to "null" if this call should succeed no matter what the currently focused token + * is. + */ + @nullable IBinder focusedToken; + /** + * SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm) when requesting the focus + * change. This determines which request gets precedence if there is a focus change request + * from another source such as pointer down. + */ + long timestamp; +} diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl index 44bb66d445..5eefad3f00 100644 --- a/libs/input/android/os/IInputFlinger.aidl +++ b/libs/input/android/os/IInputFlinger.aidl @@ -16,6 +16,7 @@ package android.os; +import android.FocusRequest; import android.InputChannel; import android.InputWindowInfo; import android.os.ISetInputWindowsListener; @@ -31,4 +32,9 @@ interface IInputFlinger in @nullable ISetInputWindowsListener setInputWindowsListener); void registerInputChannel(in InputChannel channel); void unregisterInputChannel(in InputChannel channel); + /** + * Sets focus to the window identified by the token. This must be called + * after updating any input window handles. + */ + oneway void setFocusedWindow(in FocusRequest request); } diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index 088c6f1f48..e49667e549 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -146,4 +146,9 @@ status_t InputManager::dump(int fd, const Vector<String16>& args) { return NO_ERROR; } +binder::Status InputManager::setFocusedWindow(const FocusRequest& request) { + mDispatcher->setFocusedWindow(request); + return binder::Status::ok(); +} + } // namespace android diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 0503e8161e..bf86a98133 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -110,6 +110,7 @@ public: binder::Status registerInputChannel(const InputChannel& channel) override; binder::Status unregisterInputChannel(const InputChannel& channel) override; + binder::Status setFocusedWindow(const FocusRequest&) override; private: sp<InputReaderInterface> mReader; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index bfaab3c041..82e0a4e15d 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -5175,4 +5175,19 @@ bool InputDispatcher::waitForIdle() { return result == std::cv_status::no_timeout; } +/** + * Sets focus to the window identified by the token. This must be called + * after updating any input window handles. + * + * Params: + * request.token - input channel token used to identify the window that should gain focus. + * request.focusedToken - the token that the caller expects currently to be focused. If the + * specified token does not match the currently focused window, this request will be dropped. + * If the specified focused token matches the currently focused window, the call will succeed. + * Set this to "null" if this call should succeed no matter what the currently focused token is. + * request.timestamp - SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm) + * when requesting the focus change. This determines which request gets + * precedence if there is a focus change request from another source such as pointer down. + */ +void InputDispatcher::setFocusedWindow(const FocusRequest&) {} } // namespace android::inputdispatcher diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index ba7ace0987..b4d1079839 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -126,6 +126,7 @@ public: virtual status_t registerInputChannel( const std::shared_ptr<InputChannel>& inputChannel) override; + virtual void setFocusedWindow(const FocusRequest&) override; virtual status_t registerInputMonitor(const std::shared_ptr<InputChannel>& inputChannel, int32_t displayId, bool isGestureMonitor) override; virtual status_t unregisterInputChannel(const InputChannel& inputChannel) override; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 272b0a6695..f97c8807ce 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -18,6 +18,7 @@ #define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H #include <InputListener.h> +#include <android/FocusRequest.h> #include <android/os/ISetInputWindowsListener.h> #include <input/InputApplication.h> #include <input/InputTransport.h> @@ -148,6 +149,11 @@ public: */ virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken) = 0; + /** + * Sets focus on the specified window. + */ + virtual void setFocusedWindow(const FocusRequest&) = 0; + /* Registers input channels that may be used as targets for input events. * * This method may be called on any thread (usually by the input manager). diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index cd655e0ff5..2a2cea52d8 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -50,6 +50,7 @@ public: } binder::Status registerInputChannel(const InputChannel&) { return binder::Status::ok(); } binder::Status unregisterInputChannel(const InputChannel&) { return binder::Status::ok(); } + binder::Status setFocusedWindow(const FocusRequest&) { return binder::Status::ok(); } private: virtual ~InputFlinger(); diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index eb9ac68839..6465cc970d 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -30,14 +30,14 @@ cc_test { "AnrTracker_test.cpp", "BlockingQueue_test.cpp", "EventHub_test.cpp", - "TestInputListener.cpp", + "IInputFlingerQuery.aidl", "InputClassifier_test.cpp", "InputClassifierConverter_test.cpp", "InputDispatcher_test.cpp", "InputReader_test.cpp", "InputFlingerService_test.cpp", + "TestInputListener.cpp", "UinputDevice.cpp", - "IInputFlingerQuery.aidl" ], aidl: { include_dirs: [ diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl index 755373b517..b5c5c9ea13 100644 --- a/services/inputflinger/tests/IInputFlingerQuery.aidl +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -14,6 +14,7 @@ * limitations under the License. */ +import android.FocusRequest; import android.InputChannel; import android.InputWindowInfo; import android.os.ISetInputWindowsListener; @@ -24,4 +25,5 @@ interface IInputFlingerQuery /* Test interfaces */ void getInputWindows(out InputWindowInfo[] inputHandles); void getInputChannels(out InputChannel[] channels); + void getLastFocusRequest(out FocusRequest request); } diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp index ce82d28ea4..d6543f2de7 100644 --- a/services/inputflinger/tests/InputFlingerService_test.cpp +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -55,6 +55,7 @@ using std::chrono_literals::operator""s; namespace android { static const sp<IBinder> TestInfoToken = new BBinder(); +static const sp<IBinder> FocusedTestInfoToken = new BBinder(); static constexpr int32_t TestInfoId = 1; static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; static constexpr Flags<InputWindowInfo::Flag> TestInfoFlags = InputWindowInfo::Flag::NOT_FOCUSABLE; @@ -102,7 +103,9 @@ public: protected: void InitializeInputFlinger(); - void setInputWindowsByInfos(std::vector<InputWindowInfo>& infos); + void setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos); + void setFocusedWindow(const sp<IBinder> token, const sp<IBinder> focusedToken, + nsecs_t timestampNanos); void setInputWindowsFinished(); void verifyInputWindowInfo(const InputWindowInfo& info) const; @@ -137,6 +140,7 @@ public: binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); binder::Status getInputChannels(std::vector<::android::InputChannel>* channels); + binder::Status getLastFocusRequest(FocusRequest*); status_t dump(int fd, const Vector<String16>& args) override; @@ -146,11 +150,13 @@ public: binder::Status registerInputChannel(const InputChannel& channel) override; binder::Status unregisterInputChannel(const InputChannel& channel) override; + binder::Status setFocusedWindow(const FocusRequest&) override; private: mutable Mutex mLock; std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>> mHandlesPerDisplay; std::vector<std::shared_ptr<InputChannel>> mInputChannels; + FocusRequest mFocusRequest; }; class TestInputQuery : public BnInputFlingerQuery { @@ -158,6 +164,7 @@ public: TestInputQuery(sp<android::TestInputManager> manager) : mManager(manager){}; binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; binder::Status getInputChannels(std::vector<::android::InputChannel>* channels) override; + binder::Status getLastFocusRequest(FocusRequest*) override; private: sp<android::TestInputManager> mManager; @@ -172,6 +179,10 @@ binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChan return mManager->getInputChannels(channels); } +binder::Status TestInputQuery::getLastFocusRequest(FocusRequest* request) { + return mManager->getLastFocusRequest(request); +} + binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { if (mCbFunc != nullptr) { mCbFunc(); @@ -251,6 +262,16 @@ binder::Status TestInputManager::getInputChannels(std::vector<::android::InputCh return binder::Status::ok(); } +binder::Status TestInputManager::getLastFocusRequest(FocusRequest* request) { + *request = mFocusRequest; + return binder::Status::ok(); +} + +binder::Status TestInputManager::setFocusedWindow(const FocusRequest& request) { + mFocusRequest = request; + return binder::Status::ok(); +} + void InputFlingerServiceTest::SetUp() { mSetInputWindowsListener = new SetInputWindowsListener([&]() { std::unique_lock<std::mutex> lock(mLock); @@ -310,13 +331,25 @@ void InputFlingerServiceTest::InitializeInputFlinger() { mQuery = interface_cast<IInputFlingerQuery>(input); } -void InputFlingerServiceTest::setInputWindowsByInfos(std::vector<InputWindowInfo>& infos) { +void InputFlingerServiceTest::setInputWindowsByInfos(const std::vector<InputWindowInfo>& infos) { std::unique_lock<std::mutex> lock(mLock); mService->setInputWindows(infos, mSetInputWindowsListener); // Verify listener call EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout); } +void InputFlingerServiceTest::setFocusedWindow(const sp<IBinder> token, + const sp<IBinder> focusedToken, + nsecs_t timestampNanos) { + FocusRequest request; + request.token = TestInfoToken; + request.focusedToken = focusedToken; + request.timestamp = timestampNanos; + mService->setFocusedWindow(request); + // call set input windows and wait for the callback to drain the queue. + setInputWindowsByInfos(std::vector<InputWindowInfo>()); +} + /** * Test InputFlinger service interface SetInputWindows */ @@ -376,6 +409,30 @@ TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) { EXPECT_EQ(channels.size(), 0UL); } +TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindow) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + setFocusedWindow(TestInfoToken, nullptr /* focusedToken */, now); + + FocusRequest request; + mQuery->getLastFocusRequest(&request); + + EXPECT_EQ(request.token, TestInfoToken); + EXPECT_EQ(request.focusedToken, nullptr); + EXPECT_EQ(request.timestamp, now); +} + +TEST_F(InputFlingerServiceTest, InputWindow_setFocusedWindowWithFocusedToken) { + nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); + setFocusedWindow(TestInfoToken, FocusedTestInfoToken, now); + + FocusRequest request; + mQuery->getLastFocusRequest(&request); + + EXPECT_EQ(request.token, TestInfoToken); + EXPECT_EQ(request.focusedToken, FocusedTestInfoToken); + EXPECT_EQ(request.timestamp, now); +} + } // namespace android int main(int argc, char** argv) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7d5cb67ebe..3b562bfc2a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2932,6 +2932,10 @@ void SurfaceFlinger::updateInputWindowInfo() { mInputFlinger->setInputWindows(inputInfos, mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener : nullptr); + for (const auto& focusRequest : mInputWindowCommands.focusRequests) { + mInputFlinger->setFocusedWindow(focusRequest); + } + mInputWindowCommands.focusRequests.clear(); } void SurfaceFlinger::commitInputWindowCommands() { @@ -3922,13 +3926,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( } uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) { - uint32_t flags = 0; - if (inputWindowCommands.syncInputWindows) { - flags |= eTraversalNeeded; - } - - mPendingInputWindowCommands.merge(inputWindowCommands); - return flags; + const bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands); + return hasChanges ? eTraversalNeeded : 0; } status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle, |