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
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 4a4510e..686e274 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -92,6 +92,7 @@
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 1030b82..117ce58 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -448,19 +448,36 @@
// ------------------------------- 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 d797a35..229a5c2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1364,6 +1364,21 @@
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 00ae220..41aad0d 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 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 eb757ba..d5ca0f6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -507,6 +507,9 @@
#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 8a9f261..7dd5276 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -60,6 +60,7 @@
"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 0000000..a5034a4
--- /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 44bb66d..5eefad3 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 @@
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);
}