Merge "SF: Temporarily expose primary display id"
diff --git a/include/input/Input.h b/include/input/Input.h
index f170f0f..d397313 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -579,9 +579,7 @@
void setCursorPosition(float x, float y);
- uint32_t getDisplayOrientation() const { return mDisplayOrientation; }
-
- int2 getDisplaySize() const { return {mDisplayWidth, mDisplayHeight}; }
+ ui::Transform getRawTransform() const { return mRawTransform; }
static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); }
@@ -757,8 +755,8 @@
int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, const ui::Transform& transform,
float xPrecision, float yPrecision, float rawXCursorPosition,
- float rawYCursorPosition, uint32_t displayOrientation, int32_t displayWidth,
- int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime, size_t pointerCount,
+ float rawYCursorPosition, const ui::Transform& rawTransform, nsecs_t downTime,
+ nsecs_t eventTime, size_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords);
void copyFrom(const MotionEvent* other, bool keepHistory);
@@ -816,9 +814,7 @@
float mYPrecision;
float mRawXCursorPosition;
float mRawYCursorPosition;
- uint32_t mDisplayOrientation;
- int32_t mDisplayWidth;
- int32_t mDisplayHeight;
+ ui::Transform mRawTransform;
nsecs_t mDownTime;
Vector<PointerProperties> mPointerProperties;
std::vector<nsecs_t> mSampleEventTimes;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 7632b30..d655b28 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -114,7 +114,7 @@
struct Motion {
int32_t eventId;
- uint32_t empty1;
+ uint32_t pointerCount;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -129,20 +129,22 @@
uint8_t empty2[3]; // 3 bytes to fill gap created by classification
int32_t edgeFlags;
nsecs_t downTime __attribute__((aligned(8)));
- float dsdx;
- float dtdx;
- float dtdy;
- float dsdy;
- float tx;
- float ty;
+ float dsdx; // Begin window transform
+ float dtdx; //
+ float dtdy; //
+ float dsdy; //
+ float tx; //
+ float ty; // End window transform
float xPrecision;
float yPrecision;
float xCursorPosition;
float yCursorPosition;
- uint32_t displayOrientation;
- int32_t displayWidth;
- int32_t displayHeight;
- uint32_t pointerCount;
+ float dsdxRaw; // Begin raw transform
+ float dtdxRaw; //
+ float dtdyRaw; //
+ float dsdyRaw; //
+ float txRaw; //
+ float tyRaw; // End raw transform
/**
* The "pointers" field must be the last field of the struct InputMessage.
* When we send the struct InputMessage across the socket, we are not
@@ -367,9 +369,8 @@
int32_t metaState, int32_t buttonState,
MotionClassification classification, const ui::Transform& transform,
float xPrecision, float yPrecision, float xCursorPosition,
- float yCursorPosition, uint32_t displayOrientation,
- int32_t displayWidth, int32_t displayHeight, nsecs_t downTime,
- nsecs_t eventTime, uint32_t pointerCount,
+ float yCursorPosition, const ui::Transform& rawTransform,
+ nsecs_t downTime, nsecs_t eventTime, uint32_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 06594d7..a86515a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -250,13 +250,16 @@
export_header_lib_headers: [
"libbinder_headers",
],
+ export_shared_lib_headers: [
+ "libssl",
+ ],
export_include_dirs: ["include_tls"],
static_libs: [
"libbase",
],
srcs: [
"RpcTransportTls.cpp",
- "RpcCertificateUtils.cpp",
+ "RpcTlsUtils.cpp",
],
}
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index ecf13dc..49f83ff 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -53,7 +53,7 @@
continue;
}
if (pfd[1].revents & POLLHUP) {
- return -ECANCELED;
+ return DEAD_OBJECT;
}
return pfd[0].revents & event ? OK : DEAD_OBJECT;
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 11a083a..dcba837 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -323,6 +323,7 @@
status != OK) {
LOG_RPC_DETAIL("Failed to read %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
connection->rpcTransport.get(), statusToString(status).c_str());
+ (void)session->shutdownAndWait(false);
return status;
}
@@ -531,8 +532,8 @@
const sp<RpcSession>& session, Parcel* reply) {
RpcWireHeader command;
while (true) {
- if (status_t status =
- rpcRec(connection, session, "command header", &command, sizeof(command));
+ if (status_t status = rpcRec(connection, session, "command header (for reply)", &command,
+ sizeof(command));
status != OK)
return status;
@@ -601,7 +602,8 @@
LOG_RPC_DETAIL("getAndExecuteCommand on RpcTransport %p", connection->rpcTransport.get());
RpcWireHeader command;
- if (status_t status = rpcRec(connection, session, "command header", &command, sizeof(command));
+ if (status_t status = rpcRec(connection, session, "command header (for server)", &command,
+ sizeof(command));
status != OK)
return status;
diff --git a/libs/binder/RpcCertificateUtils.cpp b/libs/binder/RpcTlsUtils.cpp
similarity index 96%
rename from libs/binder/RpcCertificateUtils.cpp
rename to libs/binder/RpcTlsUtils.cpp
index d91736c..483cc7c 100644
--- a/libs/binder/RpcCertificateUtils.cpp
+++ b/libs/binder/RpcTlsUtils.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#define LOG_TAG "RpcCertificateUtils"
+#define LOG_TAG "RpcTlsUtils"
#include <log/log.h>
-#include <binder/RpcCertificateUtils.h>
+#include <binder/RpcTlsUtils.h>
#include "Utils.h"
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 23088ad..f8cd71d 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -22,7 +22,7 @@
#include <openssl/bn.h>
#include <openssl/ssl.h>
-#include <binder/RpcCertificateUtils.h>
+#include <binder/RpcTlsUtils.h>
#include <binder/RpcTransportTls.h>
#include "FdTrigger.h"
@@ -44,8 +44,6 @@
namespace android {
namespace {
-constexpr const int kCertValidDays = 30;
-
// Implement BIO for socket that ignores SIGPIPE.
int socketNew(BIO* bio) {
BIO_set_data(bio, reinterpret_cast<void*>(-1));
@@ -100,49 +98,6 @@
return ret;
}
-bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert() {
- bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
- if (ec_key == nullptr || !EC_KEY_generate_key(ec_key.get())) {
- ALOGE("Failed to generate key pair.");
- return nullptr;
- }
- bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
- // Use set1 instead of assign to avoid leaking ec_key when assign fails. set1 increments
- // the refcount of the ec_key, so it is okay to release it at the end of this function.
- if (evp_pkey == nullptr || !EVP_PKEY_set1_EC_KEY(evp_pkey.get(), ec_key.get())) {
- ALOGE("Failed to assign key pair.");
- return nullptr;
- }
- return evp_pkey;
-}
-
-bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* evp_pkey, const int valid_days) {
- bssl::UniquePtr<X509> x509(X509_new());
- bssl::UniquePtr<BIGNUM> serial(BN_new());
- bssl::UniquePtr<BIGNUM> serialLimit(BN_new());
- TEST_AND_RETURN(nullptr, BN_lshift(serialLimit.get(), BN_value_one(), 128));
- TEST_AND_RETURN(nullptr, BN_rand_range(serial.get(), serialLimit.get()));
- TEST_AND_RETURN(nullptr, BN_to_ASN1_INTEGER(serial.get(), X509_get_serialNumber(x509.get())));
- TEST_AND_RETURN(nullptr, X509_gmtime_adj(X509_getm_notBefore(x509.get()), 0));
- TEST_AND_RETURN(nullptr,
- X509_gmtime_adj(X509_getm_notAfter(x509.get()), 60 * 60 * 24 * valid_days));
-
- X509_NAME* subject = X509_get_subject_name(x509.get());
- TEST_AND_RETURN(nullptr,
- X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
- reinterpret_cast<const uint8_t*>("Android"), -1, -1,
- 0));
- TEST_AND_RETURN(nullptr,
- X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
- reinterpret_cast<const uint8_t*>("BinderRPC"), -1,
- -1, 0));
- TEST_AND_RETURN(nullptr, X509_set_issuer_name(x509.get(), subject));
-
- TEST_AND_RETURN(nullptr, X509_set_pubkey(x509.get(), evp_pkey));
- TEST_AND_RETURN(nullptr, X509_sign(x509.get(), evp_pkey, EVP_sha256()));
- return x509;
-}
-
[[maybe_unused]] void sslDebugLog(const SSL* ssl, int type, int value) {
switch (type) {
case SSL_CB_HANDSHAKE_START:
@@ -241,7 +196,7 @@
status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger,
const char* fnString) {
status_t ret = fdTrigger->triggerablePoll(fd, event);
- if (ret != OK && ret != DEAD_OBJECT && ret != -ECANCELED) {
+ if (ret != OK && ret != DEAD_OBJECT) {
ALOGE("triggerablePoll error while poll()-ing after %s(): %s", fnString,
statusToString(ret).c_str());
}
@@ -348,7 +303,7 @@
// Before doing any I/O, check trigger once. This ensures the trigger is checked at least
// once. The trigger is also checked via triggerablePoll() after every SSL_write().
- if (fdTrigger->isTriggered()) return -ECANCELED;
+ if (fdTrigger->isTriggered()) return DEAD_OBJECT;
while (buffer < end) {
size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
@@ -379,7 +334,7 @@
// Before doing any I/O, check trigger once. This ensures the trigger is checked at least
// once. The trigger is also checked via triggerablePoll() after every SSL_write().
- if (fdTrigger->isTriggered()) return -ECANCELED;
+ if (fdTrigger->isTriggered()) return DEAD_OBJECT;
while (buffer < end) {
size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
@@ -437,7 +392,7 @@
template <typename Impl,
typename = std::enable_if_t<std::is_base_of_v<RpcTransportCtxTls, Impl>>>
static std::unique_ptr<RpcTransportCtxTls> create(
- std::shared_ptr<RpcCertificateVerifier> verifier);
+ std::shared_ptr<RpcCertificateVerifier> verifier, RpcAuth* auth);
std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
FdTrigger* fdTrigger) const override;
std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override;
@@ -460,17 +415,13 @@
LOG_ALWAYS_FATAL_IF(outAlert == nullptr);
const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
- bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
- LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
- "%s: libssl should not ask to verify non-existing cert", logPrefix);
-
auto ctx = SSL_get_SSL_CTX(ssl); // Does not set error queue
LOG_ALWAYS_FATAL_IF(ctx == nullptr);
// void* -> RpcTransportCtxTls*
auto rpcTransportCtxTls = reinterpret_cast<RpcTransportCtxTls*>(SSL_CTX_get_app_data(ctx));
LOG_ALWAYS_FATAL_IF(rpcTransportCtxTls == nullptr);
- status_t verifyStatus = rpcTransportCtxTls->mCertVerifier->verify(peerCert.get(), outAlert);
+ status_t verifyStatus = rpcTransportCtxTls->mCertVerifier->verify(ssl, outAlert);
if (verifyStatus == OK) {
return ssl_verify_ok;
}
@@ -483,16 +434,15 @@
// provided as a template argument so that this function can initialize an |Impl| object.
template <typename Impl, typename>
std::unique_ptr<RpcTransportCtxTls> RpcTransportCtxTls::create(
- std::shared_ptr<RpcCertificateVerifier> verifier) {
+ std::shared_ptr<RpcCertificateVerifier> verifier, RpcAuth* auth) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
TEST_AND_RETURN(nullptr, ctx != nullptr);
- auto evp_pkey = makeKeyPairForSelfSignedCert();
- TEST_AND_RETURN(nullptr, evp_pkey != nullptr);
- auto cert = makeSelfSignedCert(evp_pkey.get(), kCertValidDays);
- TEST_AND_RETURN(nullptr, cert != nullptr);
- TEST_AND_RETURN(nullptr, SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get()));
- TEST_AND_RETURN(nullptr, SSL_CTX_use_certificate(ctx.get(), cert.get()));
+ if (status_t authStatus = auth->configure(ctx.get()); authStatus != OK) {
+ ALOGE("%s: Failed to configure auth info: %s", __PRETTY_FUNCTION__,
+ statusToString(authStatus).c_str());
+ return nullptr;
+ };
// Enable two-way authentication by setting SSL_VERIFY_FAIL_IF_NO_PEER_CERT on server.
// Client ignores SSL_VERIFY_FAIL_IF_NO_PEER_CERT flag.
@@ -542,11 +492,13 @@
} // namespace
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
- return android::RpcTransportCtxTls::create<RpcTransportCtxTlsServer>(mCertVerifier);
+ return android::RpcTransportCtxTls::create<RpcTransportCtxTlsServer>(mCertVerifier,
+ mAuth.get());
}
std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newClientCtx() const {
- return android::RpcTransportCtxTls::create<RpcTransportCtxTlsClient>(mCertVerifier);
+ return android::RpcTransportCtxTls::create<RpcTransportCtxTlsClient>(mCertVerifier,
+ mAuth.get());
}
const char* RpcTransportCtxFactoryTls::toCString() const {
@@ -554,13 +506,17 @@
}
std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTls::make(
- std::shared_ptr<RpcCertificateVerifier> verifier) {
+ std::shared_ptr<RpcCertificateVerifier> verifier, std::unique_ptr<RpcAuth> auth) {
if (verifier == nullptr) {
ALOGE("%s: Must provide a certificate verifier", __PRETTY_FUNCTION__);
return nullptr;
}
+ if (auth == nullptr) {
+ ALOGE("%s: Must provide an auth provider", __PRETTY_FUNCTION__);
+ return nullptr;
+ }
return std::unique_ptr<RpcTransportCtxFactoryTls>(
- new RpcTransportCtxFactoryTls(std::move(verifier)));
+ new RpcTransportCtxFactoryTls(std::move(verifier), std::move(auth)));
}
} // namespace android
diff --git a/libs/binder/include_tls/binder/RpcAuth.h b/libs/binder/include_tls/binder/RpcAuth.h
new file mode 100644
index 0000000..4c2f296
--- /dev/null
+++ b/libs/binder/include_tls/binder/RpcAuth.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 <openssl/ssl.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+// An interface with a function that configures the SSL_CTX object with authentication information,
+// including certificates and private keys.
+class RpcAuth {
+public:
+ virtual ~RpcAuth() = default;
+
+ // The keys and certificates to provide is up to the implementation. Multiple calls to
+ // |configure()| may configure |ctx| with the same keys / certificates, or generate a
+ // different key / certificate every time |configure()| is called.
+ //
+ // It is guaranteed that, when a context object (RpcTransportCtx) is created,
+ // libbinder_tls calls |configure()| on server RpcAuth exactly once.
+ //
+ // The implementation may use the following function to set the private
+ // keys and certificates:
+ // - SSL_CTX_use_PrivateKey
+ // - SSL_CTX_use_certificate
+ // - SSL_CTX_set*_chain
+ // - SSL_CTX_add0_chain_cert
+ virtual status_t configure(SSL_CTX* ctx) = 0;
+};
+
+} // namespace android
diff --git a/libs/binder/include/binder/RpcCertificateVerifier.h b/libs/binder/include_tls/binder/RpcCertificateVerifier.h
similarity index 64%
rename from libs/binder/include/binder/RpcCertificateVerifier.h
rename to libs/binder/include_tls/binder/RpcCertificateVerifier.h
index 97af31c..800e375 100644
--- a/libs/binder/include/binder/RpcCertificateVerifier.h
+++ b/libs/binder/include_tls/binder/RpcCertificateVerifier.h
@@ -26,7 +26,18 @@
class RpcCertificateVerifier {
public:
virtual ~RpcCertificateVerifier() = default;
- virtual status_t verify(const X509* peerCert, uint8_t* outAlert) = 0;
+
+ // The implementation may use the following function to get
+ // the peer certificate and chain:
+ // - SSL_get_peer_certificate
+ // - SSL_get_peer_cert_chain
+ // - SSL_get_peer_full_cert_chain
+ //
+ // The implementation should return OK on success or error codes on error. For example:
+ // - PERMISSION_DENIED for rejected certificates
+ // - NO_INIT for not presenting a certificate when requested
+ // - UNKNOWN_ERROR for other errors
+ virtual status_t verify(const SSL* ssl, uint8_t* outAlert) = 0;
};
} // namespace android
diff --git a/libs/binder/include_tls/binder/RpcCertificateUtils.h b/libs/binder/include_tls/binder/RpcTlsUtils.h
similarity index 100%
rename from libs/binder/include_tls/binder/RpcCertificateUtils.h
rename to libs/binder/include_tls/binder/RpcTlsUtils.h
diff --git a/libs/binder/include_tls/binder/RpcTransportTls.h b/libs/binder/include_tls/binder/RpcTransportTls.h
index f26a3e9..8a11125 100644
--- a/libs/binder/include_tls/binder/RpcTransportTls.h
+++ b/libs/binder/include_tls/binder/RpcTransportTls.h
@@ -18,6 +18,7 @@
#pragma once
+#include <binder/RpcAuth.h>
#include <binder/RpcCertificateVerifier.h>
#include <binder/RpcTransport.h>
@@ -26,17 +27,20 @@
// RpcTransportCtxFactory with TLS enabled with self-signed certificate.
class RpcTransportCtxFactoryTls : public RpcTransportCtxFactory {
public:
- static std::unique_ptr<RpcTransportCtxFactory> make(std::shared_ptr<RpcCertificateVerifier>);
+ static std::unique_ptr<RpcTransportCtxFactory> make(std::shared_ptr<RpcCertificateVerifier>,
+ std::unique_ptr<RpcAuth>);
std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
const char* toCString() const override;
private:
- RpcTransportCtxFactoryTls(std::shared_ptr<RpcCertificateVerifier> verifier)
- : mCertVerifier(std::move(verifier)){};
+ RpcTransportCtxFactoryTls(std::shared_ptr<RpcCertificateVerifier> verifier,
+ std::unique_ptr<RpcAuth> auth)
+ : mCertVerifier(std::move(verifier)), mAuth(std::move(auth)){};
std::shared_ptr<RpcCertificateVerifier> mCertVerifier;
+ std::unique_ptr<RpcAuth> mAuth;
};
} // namespace android
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index 179b7c8..f71a686 100644
--- a/libs/binder/rust/src/parcel/file_descriptor.rs
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -23,7 +23,7 @@
use crate::sys;
use std::fs::File;
-use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
/// Rust version of the Java class android.os.ParcelFileDescriptor
#[derive(Debug)]
@@ -54,6 +54,12 @@
}
}
+impl IntoRawFd for ParcelFileDescriptor {
+ fn into_raw_fd(self) -> RawFd {
+ self.0.into_raw_fd()
+ }
+}
+
impl Serialize for ParcelFileDescriptor {
fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
let fd = self.0.as_raw_fd();
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 1968058..6f3c6e2 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -153,6 +153,7 @@
srcs: [
"binderRpcTest.cpp",
+ "RpcAuthTesting.cpp",
"RpcCertificateVerifierSimple.cpp",
],
shared_libs: [
diff --git a/libs/binder/tests/RpcAuthTesting.cpp b/libs/binder/tests/RpcAuthTesting.cpp
new file mode 100644
index 0000000..76f7bce
--- /dev/null
+++ b/libs/binder/tests/RpcAuthTesting.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 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 "RpcAuthTesting.h"
+#include "../Utils.h" // for TEST_AND_RETURN
+
+namespace android {
+
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert() {
+ bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ if (ec_key == nullptr || !EC_KEY_generate_key(ec_key.get())) {
+ ALOGE("Failed to generate key pair.");
+ return nullptr;
+ }
+ bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
+ // Use set1 instead of assign to avoid leaking ec_key when assign fails. set1 increments
+ // the refcount of the ec_key, so it is okay to release it at the end of this function.
+ if (pkey == nullptr || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
+ ALOGE("Failed to assign key pair.");
+ return nullptr;
+ }
+ return pkey;
+}
+
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pkey, const uint32_t validSeconds) {
+ bssl::UniquePtr<X509> x509(X509_new());
+ bssl::UniquePtr<BIGNUM> serial(BN_new());
+ bssl::UniquePtr<BIGNUM> serialLimit(BN_new());
+ TEST_AND_RETURN(nullptr, BN_lshift(serialLimit.get(), BN_value_one(), 128));
+ TEST_AND_RETURN(nullptr, BN_rand_range(serial.get(), serialLimit.get()));
+ TEST_AND_RETURN(nullptr, BN_to_ASN1_INTEGER(serial.get(), X509_get_serialNumber(x509.get())));
+ TEST_AND_RETURN(nullptr, X509_gmtime_adj(X509_getm_notBefore(x509.get()), 0));
+ TEST_AND_RETURN(nullptr, X509_gmtime_adj(X509_getm_notAfter(x509.get()), validSeconds));
+
+ X509_NAME* subject = X509_get_subject_name(x509.get());
+ TEST_AND_RETURN(nullptr,
+ X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
+ reinterpret_cast<const uint8_t*>("Android"), -1, -1,
+ 0));
+ TEST_AND_RETURN(nullptr,
+ X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
+ reinterpret_cast<const uint8_t*>("BinderRPC"), -1,
+ -1, 0));
+ TEST_AND_RETURN(nullptr, X509_set_issuer_name(x509.get(), subject));
+
+ TEST_AND_RETURN(nullptr, X509_set_pubkey(x509.get(), pkey));
+ TEST_AND_RETURN(nullptr, X509_sign(x509.get(), pkey, EVP_sha256()));
+ return x509;
+}
+
+status_t RpcAuthSelfSigned::configure(SSL_CTX* ctx) {
+ auto pkey = makeKeyPairForSelfSignedCert();
+ TEST_AND_RETURN(UNKNOWN_ERROR, pkey != nullptr);
+ auto cert = makeSelfSignedCert(pkey.get(), mValidSeconds);
+ TEST_AND_RETURN(UNKNOWN_ERROR, cert != nullptr);
+ TEST_AND_RETURN(INVALID_OPERATION, SSL_CTX_use_PrivateKey(ctx, pkey.get()));
+ TEST_AND_RETURN(INVALID_OPERATION, SSL_CTX_use_certificate(ctx, cert.get()));
+ return OK;
+}
+
+} // namespace android
diff --git a/libs/binder/tests/RpcAuthTesting.h b/libs/binder/tests/RpcAuthTesting.h
new file mode 100644
index 0000000..fdc731d
--- /dev/null
+++ b/libs/binder/tests/RpcAuthTesting.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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 <binder/RpcAuth.h>
+
+namespace android {
+
+constexpr const uint32_t kCertValidSeconds = 30 * (60 * 60 * 24); // 30 days
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert();
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pKey, uint32_t validSeconds);
+
+// An implementation of RpcAuth that generates a key pair and a self-signed
+// certificate every time configure() is called.
+class RpcAuthSelfSigned : public RpcAuth {
+public:
+ RpcAuthSelfSigned(uint32_t validSeconds = kCertValidSeconds) : mValidSeconds(validSeconds) {}
+ status_t configure(SSL_CTX* ctx) override;
+
+private:
+ const uint32_t mValidSeconds;
+};
+
+} // namespace android
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.cpp b/libs/binder/tests/RpcCertificateVerifierSimple.cpp
index 4694d1b..1f74adc 100644
--- a/libs/binder/tests/RpcCertificateVerifierSimple.cpp
+++ b/libs/binder/tests/RpcCertificateVerifierSimple.cpp
@@ -16,16 +16,21 @@
#define LOG_TAG "RpcCertificateVerifierSimple"
#include <log/log.h>
-#include <binder/RpcCertificateUtils.h>
+#include <binder/RpcTlsUtils.h>
#include "RpcCertificateVerifierSimple.h"
namespace android {
-status_t RpcCertificateVerifierSimple::verify(const X509* peerCert, uint8_t* outAlert) {
+status_t RpcCertificateVerifierSimple::verify(const SSL* ssl, uint8_t* outAlert) {
+ const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
+ bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
+ LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
+ "%s: libssl should not ask to verify non-existing cert", logPrefix);
+
std::lock_guard<std::mutex> lock(mMutex);
for (const auto& trustedCert : mTrustedPeerCertificates) {
- if (0 == X509_cmp(trustedCert.get(), peerCert)) {
+ if (0 == X509_cmp(trustedCert.get(), peerCert.get())) {
return OK;
}
}
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.h b/libs/binder/tests/RpcCertificateVerifierSimple.h
index 1f2e531..bdb2426 100644
--- a/libs/binder/tests/RpcCertificateVerifierSimple.h
+++ b/libs/binder/tests/RpcCertificateVerifierSimple.h
@@ -35,7 +35,7 @@
// certificate being added.
class RpcCertificateVerifierSimple : public RpcCertificateVerifier {
public:
- status_t verify(const X509*, uint8_t*) override;
+ status_t verify(const SSL*, uint8_t*) override;
// Add a trusted peer certificate. Peers presenting this certificate are accepted.
//
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 6bcf102..2fd1a2a 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -48,8 +48,9 @@
#include "../FdTrigger.h"
#include "../RpcSocketAddress.h" // for testing preconnected clients
-#include "../RpcState.h" // for debugging
-#include "../vm_sockets.h" // for VMADDR_*
+#include "../RpcState.h" // for debugging
+#include "../vm_sockets.h" // for VMADDR_*
+#include "RpcAuthTesting.h"
#include "RpcCertificateVerifierSimple.h"
using namespace std::chrono_literals;
@@ -71,7 +72,8 @@
}
static inline std::unique_ptr<RpcTransportCtxFactory> newFactory(
- RpcSecurity rpcSecurity, std::shared_ptr<RpcCertificateVerifier> verifier = nullptr) {
+ RpcSecurity rpcSecurity, std::shared_ptr<RpcCertificateVerifier> verifier = nullptr,
+ std::unique_ptr<RpcAuth> auth = nullptr) {
switch (rpcSecurity) {
case RpcSecurity::RAW:
return RpcTransportCtxFactoryRaw::make();
@@ -79,7 +81,10 @@
if (verifier == nullptr) {
verifier = std::make_shared<RpcCertificateVerifierSimple>();
}
- return RpcTransportCtxFactoryTls::make(std::move(verifier));
+ if (auth == nullptr) {
+ auth = std::make_unique<RpcAuthSelfSigned>();
+ }
+ return RpcTransportCtxFactoryTls::make(std::move(verifier), std::move(auth));
}
default:
LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", rpcSecurity);
@@ -1036,6 +1041,14 @@
for (auto& t : threads) t.join();
}
+static void saturateThreadPool(size_t threadCount, const sp<IBinderRpcTest>& iface) {
+ std::vector<std::thread> threads;
+ for (size_t i = 0; i < threadCount; i++) {
+ threads.push_back(std::thread([&] { EXPECT_OK(iface->sleepMs(500)); }));
+ }
+ for (auto& t : threads) t.join();
+}
+
TEST_P(BinderRpc, OnewayStressTest) {
constexpr size_t kNumClientThreads = 10;
constexpr size_t kNumServerThreads = 10;
@@ -1049,13 +1062,12 @@
for (size_t j = 0; j < kNumCalls; j++) {
EXPECT_OK(proc.rootIface->sendString("a"));
}
-
- // check threads are not stuck
- EXPECT_OK(proc.rootIface->sleepMs(250));
}));
}
for (auto& t : threads) t.join();
+
+ saturateThreadPool(kNumServerThreads, proc.rootIface);
}
TEST_P(BinderRpc, OnewayCallDoesNotWait) {
@@ -1082,26 +1094,23 @@
EXPECT_OK(proc.rootIface->lock());
- for (size_t i = 0; i < kNumSleeps; i++) {
- // these should be processed serially
+ size_t epochMsBefore = epochMillis();
+
+ // all these *Async commands should be queued on the server sequentially,
+ // even though there are multiple threads.
+ for (size_t i = 0; i + 1 < kNumSleeps; i++) {
proc.rootIface->sleepMsAsync(kSleepMs);
}
- // should also be processesed serially
EXPECT_OK(proc.rootIface->unlockInMsAsync(kSleepMs));
- size_t epochMsBefore = epochMillis();
+ // this can only return once the final async call has unlocked
EXPECT_OK(proc.rootIface->lockUnlock());
+
size_t epochMsAfter = epochMillis();
EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps);
- // pending oneway transactions hold ref, make sure we read data on all
- // sockets
- std::vector<std::thread> threads;
- for (size_t i = 0; i < 1 + kNumExtraServerThreads; i++) {
- threads.push_back(std::thread([&] { EXPECT_OK(proc.rootIface->sleepMs(250)); }));
- }
- for (auto& t : threads) t.join();
+ saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
}
TEST_P(BinderRpc, OnewayCallExhaustion) {
@@ -1794,9 +1803,9 @@
}
status = serverTransport->interruptableWriteFully(fdTrigger, msg2.data(), msg2.size());
- if (status != -ECANCELED)
+ if (status != DEAD_OBJECT)
return AssertionFailure() << "When FdTrigger is shut down, interruptableWriteFully "
- "should return -ECANCELLED, but it is "
+ "should return DEAD_OBJECT, but it is "
<< statusToString(status);
return AssertionSuccess();
};
@@ -1830,7 +1839,7 @@
}
writeCv.notify_all();
// After this line, server thread unblocks and attempts to write the second message, but
- // shutdown is triggered, so write should failed with -ECANCELLED. See |serverPostConnect|.
+ // shutdown is triggered, so write should failed with DEAD_OBJECT. See |serverPostConnect|.
// On the client side, second read fails with DEAD_OBJECT
ASSERT_FALSE(client.readMessage(msg2));
}
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index 9323bd5..be55eba 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -14,6 +14,7 @@
fuzz_config: {
cc: ["smoreland@google.com"],
},
+ dictionary: "binder_rpc_fuzzer.dict",
srcs: [
"main.cpp",
diff --git a/libs/binder/tests/rpc_fuzzer/binder_rpc_fuzzer.dict b/libs/binder/tests/rpc_fuzzer/binder_rpc_fuzzer.dict
new file mode 100644
index 0000000..b110a02
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/binder_rpc_fuzzer.dict
@@ -0,0 +1,2 @@
+# connection okay header
+"cci"
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index 230f5c7..c848798 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -87,8 +87,7 @@
size_t idx = provider.ConsumeIntegralInRange<size_t>(0, connections.size() - 1);
if (provider.ConsumeBool()) {
- std::vector<uint8_t> writeData = provider.ConsumeBytes<uint8_t>(
- provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));
+ std::string writeData = provider.ConsumeRandomLengthString();
ssize_t size = TEMP_FAILURE_RETRY(send(connections.at(idx).get(), writeData.data(),
writeData.size(), MSG_NOSIGNAL));
CHECK(errno == EPIPE || size == writeData.size())
@@ -101,7 +100,7 @@
if (hangupBeforeShutdown) {
connections.clear();
- while (!server->listSessions().empty() && server->numUninitializedSessions()) {
+ while (!server->listSessions().empty() || server->numUninitializedSessions()) {
// wait for all threads to finish processing existing information
usleep(1);
}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 2d1f5a1..8c359c7 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -55,6 +55,7 @@
filegroup {
name: "guiconstants_aidl",
srcs: [
+ "android/gui/DropInputMode.aidl",
"android/**/TouchOcclusionMode.aidl",
],
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 1fd9d13..a419a63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -69,7 +69,8 @@
isTrustedOverlay(false),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
- releaseBufferListener(nullptr) {
+ releaseBufferListener(nullptr),
+ dropInputMode(gui::DropInputMode::NONE) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -174,6 +175,7 @@
SAFE_PARCEL(output.writeBool, isTrustedOverlay);
SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
+ SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
return NO_ERROR;
}
@@ -304,6 +306,10 @@
SAFE_PARCEL(input.readBool, &isTrustedOverlay);
SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
+
+ uint32_t mode;
+ SAFE_PARCEL(input.readUint32, &mode);
+ dropInputMode = static_cast<gui::DropInputMode>(mode);
return NO_ERROR;
}
@@ -558,6 +564,10 @@
if (other.what & eProducerDisconnect) {
what |= eProducerDisconnect;
}
+ if (other.what & eDropInputModeChanged) {
+ what |= eDropInputModeChanged;
+ dropInputMode = other.dropInputMode;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIX64 " what=0x%" PRIX64 " unmerged flags=0x%" PRIX64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 364820e..bbd3cca 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1743,6 +1743,21 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDropInputMode(
+ const sp<SurfaceControl>& sc, gui::DropInputMode mode) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eDropInputModeChanged;
+ s->dropInputMode = mode;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/android/gui/DropInputMode.aidl b/libs/gui/android/gui/DropInputMode.aidl
new file mode 100644
index 0000000..2b31744
--- /dev/null
+++ b/libs/gui/android/gui/DropInputMode.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2021, 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.gui;
+
+
+/**
+ * Input event drop modes: Input event drop options for windows and its children.
+ *
+ * @hide
+ */
+@Backing(type="int")
+enum DropInputMode {
+ /**
+ * Default mode, input events are sent to the target as usual.
+ */
+ NONE,
+
+ /**
+ * Window and its children will not receive any input even if it has a valid input channel.
+ * Touches and keys will be dropped. If a window is focused, it will remain focused but will
+ * not receive any keys. If the window has a touchable region and is the target of an input
+ * event, the event will be dropped and will not go to the window behind. ref: b/197296414
+ */
+ ALL,
+
+ /**
+ * Similar to DROP but input events are only dropped if the window is considered to be
+ * obscured. ref: b/197364677
+ */
+ OBSCURED
+}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index f14127c..b27102b 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -26,6 +26,7 @@
#include <gui/ITransactionCompletedListener.h>
#include <math/mat4.h>
+#include <android/gui/DropInputMode.h>
#include <android/gui/FocusRequest.h>
#include <gui/ISurfaceComposer.h>
@@ -118,6 +119,7 @@
eAutoRefreshChanged = 0x1000'00000000,
eStretchChanged = 0x2000'00000000,
eTrustedOverlayChanged = 0x4000'00000000,
+ eDropInputModeChanged = 0x8000'00000000,
};
layer_state_t();
@@ -248,6 +250,9 @@
// releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
// was called with.
sp<IBinder> releaseBufferEndpoint;
+
+ // Force inputflinger to drop all input events for the layer and its children.
+ gui::DropInputMode dropInputMode;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 450e9a0..403ca0a 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -563,6 +563,7 @@
Transaction& setBufferCrop(const sp<SurfaceControl>& sc, const Rect& bufferCrop);
Transaction& setDestinationFrame(const sp<SurfaceControl>& sc,
const Rect& destinationFrame);
+ Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode);
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 037849e..30e5d5b 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -76,36 +76,13 @@
return result;
}
-// Rotates the given point to the specified orientation. If the display width and height are
-// provided, the point is rotated in the screen space. Otherwise, the point is rotated about the
-// origin. This helper is used to avoid the extra overhead of creating new Transforms.
-vec2 rotatePoint(uint32_t orientation, float x, float y, int32_t displayWidth = 0,
- int32_t displayHeight = 0) {
- if (orientation == ui::Transform::ROT_0) {
- return {x, y};
- }
-
- vec2 xy(x, y);
- if (orientation == ui::Transform::ROT_90) {
- xy.x = displayHeight - y;
- xy.y = x;
- } else if (orientation == ui::Transform::ROT_180) {
- xy.x = displayWidth - x;
- xy.y = displayHeight - y;
- } else if (orientation == ui::Transform::ROT_270) {
- xy.x = y;
- xy.y = displayWidth - x;
- }
- return xy;
-}
-
-vec2 applyTransformWithoutTranslation(const ui::Transform& transform, float x, float y) {
+vec2 transformWithoutTranslation(const ui::Transform& transform, float x, float y) {
const vec2 transformedXy = transform.transform(x, y);
const vec2 transformedOrigin = transform.transform(0, 0);
return transformedXy - transformedOrigin;
}
-bool shouldDisregardWindowTranslation(uint32_t source) {
+bool shouldDisregardTranslation(uint32_t source) {
// Pointer events are the only type of events that refer to absolute coordinates on the display,
// so we should apply the entire window transform. For other types of events, we should make
// sure to not apply the window translation/offset.
@@ -431,8 +408,7 @@
int32_t buttonState, MotionClassification classification,
const ui::Transform& transform, float xPrecision, float yPrecision,
float rawXCursorPosition, float rawYCursorPosition,
- uint32_t displayOrientation, int32_t displayWidth,
- int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime,
+ const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
size_t pointerCount, const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
InputEvent::initialize(id, deviceId, source, displayId, hmac);
@@ -448,9 +424,7 @@
mYPrecision = yPrecision;
mRawXCursorPosition = rawXCursorPosition;
mRawYCursorPosition = rawYCursorPosition;
- mDisplayOrientation = displayOrientation;
- mDisplayWidth = displayWidth;
- mDisplayHeight = displayHeight;
+ mRawTransform = rawTransform;
mDownTime = downTime;
mPointerProperties.clear();
mPointerProperties.appendArray(pointerProperties, pointerCount);
@@ -474,9 +448,7 @@
mYPrecision = other->mYPrecision;
mRawXCursorPosition = other->mRawXCursorPosition;
mRawYCursorPosition = other->mRawYCursorPosition;
- mDisplayOrientation = other->mDisplayOrientation;
- mDisplayWidth = other->mDisplayWidth;
- mDisplayHeight = other->mDisplayHeight;
+ mRawTransform = other->mRawTransform;
mDownTime = other->mDownTime;
mPointerProperties = other->mPointerProperties;
@@ -542,20 +514,19 @@
if (!isPerWindowInputRotationEnabled()) return coords->getAxisValue(axis);
if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
- // For compatibility, convert raw coordinates into "oriented screen space". Once app
- // developers are educated about getRaw, we can consider removing this.
- const vec2 xy = shouldDisregardWindowTranslation(mSource)
- ? rotatePoint(mDisplayOrientation, coords->getX(), coords->getY())
- : rotatePoint(mDisplayOrientation, coords->getX(), coords->getY(), mDisplayWidth,
- mDisplayHeight);
+ // For compatibility, convert raw coordinates into logical display space.
+ const vec2 xy = shouldDisregardTranslation(mSource)
+ ? transformWithoutTranslation(mRawTransform, coords->getX(), coords->getY())
+ : mRawTransform.transform(coords->getX(), coords->getY());
static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
return xy[axis];
}
if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
- // For compatibility, since we convert raw coordinates into "oriented screen space", we
+ // For compatibility, since we report raw coordinates in logical display space, we
// need to convert the relative axes into the same orientation for consistency.
- const vec2 relativeXy = rotatePoint(mDisplayOrientation,
+ const vec2 relativeXy =
+ transformWithoutTranslation(mRawTransform,
coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
@@ -569,8 +540,8 @@
const PointerCoords* coords = getHistoricalRawPointerCoords(pointerIndex, historicalIndex);
if (axis == AMOTION_EVENT_AXIS_X || axis == AMOTION_EVENT_AXIS_Y) {
- const vec2 xy = shouldDisregardWindowTranslation(mSource)
- ? applyTransformWithoutTranslation(mTransform, coords->getX(), coords->getY())
+ const vec2 xy = shouldDisregardTranslation(mSource)
+ ? transformWithoutTranslation(mTransform, coords->getX(), coords->getY())
: mTransform.transform(coords->getXYValue());
static_assert(AMOTION_EVENT_AXIS_X == 0 && AMOTION_EVENT_AXIS_Y == 1);
return xy[axis];
@@ -578,11 +549,9 @@
if (axis == AMOTION_EVENT_AXIS_RELATIVE_X || axis == AMOTION_EVENT_AXIS_RELATIVE_Y) {
const vec2 relativeXy =
- applyTransformWithoutTranslation(mTransform,
- coords->getAxisValue(
- AMOTION_EVENT_AXIS_RELATIVE_X),
- coords->getAxisValue(
- AMOTION_EVENT_AXIS_RELATIVE_Y));
+ transformWithoutTranslation(mTransform,
+ coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+ coords->getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
return axis == AMOTION_EVENT_AXIS_RELATIVE_X ? relativeXy.x : relativeXy.y;
}
@@ -607,6 +576,8 @@
void MotionEvent::scale(float globalScaleFactor) {
mTransform.set(mTransform.tx() * globalScaleFactor, mTransform.ty() * globalScaleFactor);
+ mRawTransform.set(mRawTransform.tx() * globalScaleFactor,
+ mRawTransform.ty() * globalScaleFactor);
mXPrecision *= globalScaleFactor;
mYPrecision *= globalScaleFactor;
@@ -708,9 +679,11 @@
mYPrecision = parcel->readFloat();
mRawXCursorPosition = parcel->readFloat();
mRawYCursorPosition = parcel->readFloat();
- mDisplayOrientation = parcel->readUint32();
- mDisplayWidth = parcel->readInt32();
- mDisplayHeight = parcel->readInt32();
+
+ result = android::readFromParcel(mRawTransform, *parcel);
+ if (result != OK) {
+ return result;
+ }
mDownTime = parcel->readInt64();
mPointerProperties.clear();
@@ -770,9 +743,11 @@
parcel->writeFloat(mYPrecision);
parcel->writeFloat(mRawXCursorPosition);
parcel->writeFloat(mRawYCursorPosition);
- parcel->writeUint32(mDisplayOrientation);
- parcel->writeInt32(mDisplayWidth);
- parcel->writeInt32(mDisplayHeight);
+
+ result = android::writeToParcel(mRawTransform, *parcel);
+ if (result != OK) {
+ return result;
+ }
parcel->writeInt64(mDownTime);
for (size_t i = 0; i < pointerCount; i++) {
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 91ab008..02a5a08 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -203,6 +203,8 @@
case InputMessage::Type::MOTION: {
// int32_t eventId
msg->body.motion.eventId = body.motion.eventId;
+ // uint32_t pointerCount
+ msg->body.motion.pointerCount = body.motion.pointerCount;
// nsecs_t eventTime
msg->body.motion.eventTime = body.motion.eventTime;
// int32_t deviceId
@@ -245,14 +247,14 @@
msg->body.motion.xCursorPosition = body.motion.xCursorPosition;
// float yCursorPosition
msg->body.motion.yCursorPosition = body.motion.yCursorPosition;
- // uint32_t displayOrientation
- msg->body.motion.displayOrientation = body.motion.displayOrientation;
- // int32_t displayWidth
- msg->body.motion.displayWidth = body.motion.displayWidth;
- // int32_t displayHeight
- msg->body.motion.displayHeight = body.motion.displayHeight;
- // uint32_t pointerCount
- msg->body.motion.pointerCount = body.motion.pointerCount;
+
+ msg->body.motion.dsdxRaw = body.motion.dsdxRaw;
+ msg->body.motion.dtdxRaw = body.motion.dtdxRaw;
+ msg->body.motion.dtdyRaw = body.motion.dtdyRaw;
+ msg->body.motion.dsdyRaw = body.motion.dsdyRaw;
+ msg->body.motion.txRaw = body.motion.txRaw;
+ msg->body.motion.tyRaw = body.motion.tyRaw;
+
//struct Pointer pointers[MAX_POINTERS]
for (size_t i = 0; i < body.motion.pointerCount; i++) {
// PointerProperties properties
@@ -542,8 +544,8 @@
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, const ui::Transform& transform, float xPrecision,
- float yPrecision, float xCursorPosition, float yCursorPosition, uint32_t displayOrientation,
- int32_t displayWidth, int32_t displayHeight, nsecs_t downTime, nsecs_t eventTime,
+ float yPrecision, float xCursorPosition, float yCursorPosition,
+ const ui::Transform& rawTransform, nsecs_t downTime, nsecs_t eventTime,
uint32_t pointerCount, const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
if (ATRACE_ENABLED()) {
@@ -603,9 +605,12 @@
msg.body.motion.yPrecision = yPrecision;
msg.body.motion.xCursorPosition = xCursorPosition;
msg.body.motion.yCursorPosition = yCursorPosition;
- msg.body.motion.displayOrientation = displayOrientation;
- msg.body.motion.displayWidth = displayWidth;
- msg.body.motion.displayHeight = displayHeight;
+ msg.body.motion.dsdxRaw = rawTransform.dsdx();
+ msg.body.motion.dtdxRaw = rawTransform.dtdx();
+ msg.body.motion.dtdyRaw = rawTransform.dtdy();
+ msg.body.motion.dsdyRaw = rawTransform.dsdy();
+ msg.body.motion.txRaw = rawTransform.tx();
+ msg.body.motion.tyRaw = rawTransform.ty();
msg.body.motion.downTime = downTime;
msg.body.motion.eventTime = eventTime;
msg.body.motion.pointerCount = pointerCount;
@@ -1391,6 +1396,10 @@
ui::Transform transform;
transform.set({msg->body.motion.dsdx, msg->body.motion.dtdx, msg->body.motion.tx,
msg->body.motion.dtdy, msg->body.motion.dsdy, msg->body.motion.ty, 0, 0, 1});
+ ui::Transform displayTransform;
+ displayTransform.set({msg->body.motion.dsdxRaw, msg->body.motion.dtdxRaw,
+ msg->body.motion.txRaw, msg->body.motion.dtdyRaw,
+ msg->body.motion.dsdyRaw, msg->body.motion.tyRaw, 0, 0, 1});
event->initialize(msg->body.motion.eventId, msg->body.motion.deviceId, msg->body.motion.source,
msg->body.motion.displayId, msg->body.motion.hmac, msg->body.motion.action,
msg->body.motion.actionButton, msg->body.motion.flags,
@@ -1398,9 +1407,8 @@
msg->body.motion.buttonState, msg->body.motion.classification, transform,
msg->body.motion.xPrecision, msg->body.motion.yPrecision,
msg->body.motion.xCursorPosition, msg->body.motion.yCursorPosition,
- msg->body.motion.displayOrientation, msg->body.motion.displayWidth,
- msg->body.motion.displayHeight, msg->body.motion.downTime,
- msg->body.motion.eventTime, pointerCount, pointerProperties, pointerCoords);
+ displayTransform, msg->body.motion.downTime, msg->body.motion.eventTime,
+ pointerCount, pointerProperties, pointerCoords);
}
void InputConsumer::initializeTouchModeEvent(TouchModeEvent* event, const InputMessage* msg) {
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index b1ef753..7e7dfd5 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -226,11 +226,16 @@
static constexpr float Y_SCALE = 3.0;
static constexpr float X_OFFSET = 1;
static constexpr float Y_OFFSET = 1.1;
+ static constexpr float RAW_X_SCALE = 4.0;
+ static constexpr float RAW_Y_SCALE = -5.0;
+ static constexpr float RAW_X_OFFSET = 12;
+ static constexpr float RAW_Y_OFFSET = -41.1;
static const std::optional<bool> INITIAL_PER_WINDOW_INPUT_ROTATION_FLAG_VALUE;
int32_t mId;
ui::Transform mTransform;
+ ui::Transform mRawTransform;
void SetUp() override;
void TearDown() override;
@@ -259,6 +264,7 @@
void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
mId = InputEvent::nextId();
mTransform.set({X_SCALE, 0, X_OFFSET, 0, Y_SCALE, Y_OFFSET, 0, 0, 1});
+ mRawTransform.set({RAW_X_SCALE, 0, RAW_X_OFFSET, 0, RAW_Y_SCALE, RAW_Y_OFFSET, 0, 0, 1});
PointerProperties pointerProperties[2];
pointerProperties[0].clear();
@@ -294,9 +300,8 @@
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
MotionClassification::NONE, mTransform, 2.0f, 2.1f,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties,
- pointerCoords);
+ mRawTransform, ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2,
+ pointerProperties, pointerCoords);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, 110);
pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, 111);
@@ -373,39 +378,37 @@
ASSERT_EQ(ARBITRARY_EVENT_TIME + 1, event->getHistoricalEventTime(1));
ASSERT_EQ(ARBITRARY_EVENT_TIME + 2, event->getEventTime());
- ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(211, event->getRawPointerCoords(0)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(221, event->getRawPointerCoords(1)->
- getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(11, event->getHistoricalRawPointerCoords(0, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(21, event->getHistoricalRawPointerCoords(1, 0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(111, event->getHistoricalRawPointerCoords(0, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(121, event->getHistoricalRawPointerCoords(1, 1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(211, event->getRawPointerCoords(0)->getAxisValue(AMOTION_EVENT_AXIS_Y));
+ ASSERT_EQ(221, event->getRawPointerCoords(1)->getAxisValue(AMOTION_EVENT_AXIS_Y));
- ASSERT_EQ(11, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
- ASSERT_EQ(21, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
- ASSERT_EQ(111, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
- ASSERT_EQ(121, event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
- ASSERT_EQ(211, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
- ASSERT_EQ(221, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
+ ASSERT_EQ(RAW_Y_OFFSET + 11 * RAW_Y_SCALE,
+ event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 0));
+ ASSERT_EQ(RAW_Y_OFFSET + 21 * RAW_Y_SCALE,
+ event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 0));
+ ASSERT_EQ(RAW_Y_OFFSET + 111 * RAW_Y_SCALE,
+ event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 0, 1));
+ ASSERT_EQ(RAW_Y_OFFSET + 121 * RAW_Y_SCALE,
+ event->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y, 1, 1));
+ ASSERT_EQ(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 0));
+ ASSERT_EQ(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawAxisValue(AMOTION_EVENT_AXIS_Y, 1));
- ASSERT_EQ(10, event->getHistoricalRawX(0, 0));
- ASSERT_EQ(20, event->getHistoricalRawX(1, 0));
- ASSERT_EQ(110, event->getHistoricalRawX(0, 1));
- ASSERT_EQ(120, event->getHistoricalRawX(1, 1));
- ASSERT_EQ(210, event->getRawX(0));
- ASSERT_EQ(220, event->getRawX(1));
+ ASSERT_EQ(RAW_X_OFFSET + 10 * RAW_X_SCALE, event->getHistoricalRawX(0, 0));
+ ASSERT_EQ(RAW_X_OFFSET + 20 * RAW_X_SCALE, event->getHistoricalRawX(1, 0));
+ ASSERT_EQ(RAW_X_OFFSET + 110 * RAW_X_SCALE, event->getHistoricalRawX(0, 1));
+ ASSERT_EQ(RAW_X_OFFSET + 120 * RAW_X_SCALE, event->getHistoricalRawX(1, 1));
+ ASSERT_EQ(RAW_X_OFFSET + 210 * RAW_X_SCALE, event->getRawX(0));
+ ASSERT_EQ(RAW_X_OFFSET + 220 * RAW_X_SCALE, event->getRawX(1));
- ASSERT_EQ(11, event->getHistoricalRawY(0, 0));
- ASSERT_EQ(21, event->getHistoricalRawY(1, 0));
- ASSERT_EQ(111, event->getHistoricalRawY(0, 1));
- ASSERT_EQ(121, event->getHistoricalRawY(1, 1));
- ASSERT_EQ(211, event->getRawY(0));
- ASSERT_EQ(221, event->getRawY(1));
+ ASSERT_EQ(RAW_Y_OFFSET + 11 * RAW_Y_SCALE, event->getHistoricalRawY(0, 0));
+ ASSERT_EQ(RAW_Y_OFFSET + 21 * RAW_Y_SCALE, event->getHistoricalRawY(1, 0));
+ ASSERT_EQ(RAW_Y_OFFSET + 111 * RAW_Y_SCALE, event->getHistoricalRawY(0, 1));
+ ASSERT_EQ(RAW_Y_OFFSET + 121 * RAW_Y_SCALE, event->getHistoricalRawY(1, 1));
+ ASSERT_EQ(RAW_Y_OFFSET + 211 * RAW_Y_SCALE, event->getRawY(0));
+ ASSERT_EQ(RAW_Y_OFFSET + 221 * RAW_Y_SCALE, event->getRawY(1));
ASSERT_EQ(X_OFFSET + 10 * X_SCALE, event->getHistoricalX(0, 0));
ASSERT_EQ(X_OFFSET + 20 * X_SCALE, event->getHistoricalX(1, 0));
@@ -543,8 +546,8 @@
ASSERT_EQ(X_OFFSET * 2, event.getXOffset());
ASSERT_EQ(Y_OFFSET * 2, event.getYOffset());
- ASSERT_EQ(210 * 2, event.getRawX(0));
- ASSERT_EQ(211 * 2, event.getRawY(0));
+ ASSERT_EQ((RAW_X_OFFSET + 210 * RAW_X_SCALE) * 2, event.getRawX(0));
+ ASSERT_EQ((RAW_Y_OFFSET + 211 * RAW_Y_SCALE) * 2, event.getRawY(0));
ASSERT_EQ((X_OFFSET + 210 * X_SCALE) * 2, event.getX(0));
ASSERT_EQ((Y_OFFSET + 211 * Y_SCALE) * 2, event.getY(0));
ASSERT_EQ(212, event.getPressure(0));
@@ -592,10 +595,10 @@
// The geometrical representation is irrelevant to the test, it's just easy to generate
// and check rotation. We set the orientation to the same angle.
// Coordinate system: down is increasing Y, right is increasing X.
- const float PI_180 = float(M_PI / 180);
- const float RADIUS = 10;
- const float ARC = 36;
- const float ROTATION = ARC * 2;
+ static constexpr float PI_180 = float(M_PI / 180);
+ static constexpr float RADIUS = 10;
+ static constexpr float ARC = 36;
+ static constexpr float ROTATION = ARC * 2;
const size_t pointerCount = 11;
PointerProperties pointerProperties[pointerCount];
@@ -616,9 +619,8 @@
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
0 /*yPrecision*/, 3 + RADIUS /*xCursorPosition*/, 2 /*yCursorPosition*/,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties,
- pointerCoords);
+ identityTransform, 0 /*downTime*/, 0 /*eventTime*/, pointerCount,
+ pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
@@ -661,7 +663,7 @@
MotionEvent createTouchDownEvent(float x, float y, float dx, float dy,
const ui::Transform& transform,
- uint32_t displayOrientation = ui::Transform::ROT_0) {
+ const ui::Transform& rawTransform) {
std::vector<PointerProperties> pointerProperties;
pointerProperties.push_back(PointerProperties{/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER});
std::vector<PointerCoords> pointerCoords;
@@ -677,19 +679,18 @@
/* actionButton */ 0, /* flags */ 0, /* edgeFlags */ 0, AMETA_NONE,
/* buttonState */ 0, MotionClassification::NONE, transform,
/* xPrecision */ 0, /* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, displayOrientation,
- /* displayWidth */ 400,
- /* displayHeight */ 800, eventTime, eventTime, pointerCoords.size(),
- pointerProperties.data(), pointerCoords.data());
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, rawTransform, eventTime, eventTime,
+ pointerCoords.size(), pointerProperties.data(), pointerCoords.data());
return event;
}
TEST_F(MotionEventTest, ApplyTransform) {
// Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
ui::Transform identity;
- ui::Transform xform(ui::Transform::ROT_90, 800, 400);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);
+ ui::Transform transform(ui::Transform::ROT_90, 800, 400);
+ transform.set(transform.tx() + 20, transform.ty() + 40);
+ ui::Transform rawTransform(ui::Transform::ROT_90, 800, 400);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, transform, rawTransform);
ASSERT_EQ(700, event.getRawX(0));
ASSERT_EQ(60, event.getRawY(0));
ASSERT_NE(event.getRawX(0), event.getX(0));
@@ -698,10 +699,10 @@
ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- MotionEvent changedEvent = createTouchDownEvent(60, 100, 42, 96, identity);
- const std::array<float, 9> rowMajor{xform[0][0], xform[1][0], xform[2][0],
- xform[0][1], xform[1][1], xform[2][1],
- xform[0][2], xform[1][2], xform[2][2]};
+ MotionEvent changedEvent = createTouchDownEvent(60, 100, 42, 96, identity, identity);
+ const std::array<float, 9> rowMajor{transform[0][0], transform[1][0], transform[2][0],
+ transform[0][1], transform[1][1], transform[2][1],
+ transform[0][2], transform[1][2], transform[2][2]};
changedEvent.applyTransform(rowMajor);
// transformContent effectively rotates the raw coordinates, so those should now include
@@ -727,9 +728,9 @@
AINPUT_SOURCE_JOYSTICK};
for (uint32_t source : NON_POINTER_SOURCES) {
// Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
- ui::Transform xform(ui::Transform::ROT_90, 800, 400);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);
+ ui::Transform transform(ui::Transform::ROT_90, 800, 400);
+ transform.set(transform.tx() + 20, transform.ty() + 40);
+ MotionEvent event = createTouchDownEvent(60, 100, 42, 96, transform, transform);
event.setSource(source);
// Since this event comes from a non-pointer source, it should include rotation but not
@@ -741,72 +742,34 @@
}
}
-TEST_F(MotionEventTest, RawCompatTransform) {
- {
- // Make sure raw is raw regardless of transform translation.
- ui::Transform xform;
- xform.set(20, 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform);
- ASSERT_EQ(60, event.getRawX(0));
- ASSERT_EQ(100, event.getRawY(0));
- ASSERT_NE(event.getRawX(0), event.getX(0));
- ASSERT_NE(event.getRawY(0), event.getY(0));
- // Relative values should not be modified.
- ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
- ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- }
+TEST_F(MotionEventTest, AxesAreCorrectlyTransformed) {
+ const ui::Transform identity;
+ ui::Transform transform;
+ transform.set({1.1, -2.2, 3.3, -4.4, 5.5, -6.6, 0, 0, 1});
+ ui::Transform rawTransform;
+ rawTransform.set({-6.6, 5.5, -4.4, 3.3, -2.2, 1.1, 0, 0, 1});
+ auto transformWithoutTranslation = [](const ui::Transform& t, float x, float y) {
+ auto newPoint = t.transform(x, y);
+ auto newOrigin = t.transform(0, 0);
+ return newPoint - newOrigin;
+ };
- // Next check that getRaw contains rotation (for compatibility) but otherwise is still
- // "Screen-space". The following tests check all 3 rotations.
- {
- // Create a rotate-90 transform with an offset (like a window which isn't fullscreen).
- ui::Transform xform(ui::Transform::ROT_90, 800, 400);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);
- ASSERT_EQ(700, event.getRawX(0));
- ASSERT_EQ(60, event.getRawY(0));
- ASSERT_NE(event.getRawX(0), event.getX(0));
- ASSERT_NE(event.getRawY(0), event.getY(0));
- // Relative values should be rotated but not translated.
- ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
- ASSERT_EQ(42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- }
+ const MotionEvent event = createTouchDownEvent(60, 100, 42, 96, transform, rawTransform);
- {
- // Same as above, but check rotate-180.
- ui::Transform xform(ui::Transform::ROT_180, 400, 800);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_180);
- ASSERT_EQ(340, event.getRawX(0));
- ASSERT_EQ(700, event.getRawY(0));
- // Relative values should be rotated but not translated.
- ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
- ASSERT_EQ(-96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- }
+ // The x and y axes should have the window transform applied.
+ const auto newPoint = transform.transform(60, 100);
+ ASSERT_EQ(newPoint.x, event.getX(0));
+ ASSERT_EQ(newPoint.y, event.getY(0));
- {
- // Same as above, but check rotate-270.
- ui::Transform xform(ui::Transform::ROT_270, 800, 400);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_270);
- ASSERT_EQ(100, event.getRawX(0));
- ASSERT_EQ(340, event.getRawY(0));
- // Relative values should be rotated but not translated.
- ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
- ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- }
+ // The raw values should have the display transform applied.
+ const auto raw = rawTransform.transform(60, 100);
+ ASSERT_EQ(raw.x, event.getRawX(0));
+ ASSERT_EQ(raw.y, event.getRawY(0));
- {
- // Finally, check that raw isn't effected by transform
- ui::Transform xform(ui::Transform::ROT_270, 800, 400);
- xform.set(xform.tx() + 20, xform.ty() + 40);
- MotionEvent event = createTouchDownEvent(60, 100, 42, 96, xform, ui::Transform::ROT_90);
- ASSERT_EQ(700, event.getRawX(0));
- ASSERT_EQ(60, event.getRawY(0));
- // Relative values should be rotated but not translated.
- ASSERT_EQ(96, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
- ASSERT_EQ(-42, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
- }
+ // Relative values should have the window transform applied without any translation.
+ const auto rel = transformWithoutTranslation(transform, 42, 96);
+ ASSERT_EQ(rel.x, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, 0));
+ ASSERT_EQ(rel.y, event.getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, 0));
}
TEST_F(MotionEventTest, Initialize_SetsClassification) {
@@ -832,8 +795,7 @@
DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, 0 /*downTime*/,
0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(classification, event.getClassification());
}
@@ -854,9 +816,9 @@
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID,
INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE,
AMETA_NONE, 0, MotionClassification::NONE, identityTransform, 0, 0,
- 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/, 0 /*eventTime*/,
- pointerCount, pointerProperties, pointerCoords);
+ 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, identityTransform,
+ 0 /*downTime*/, 0 /*eventTime*/, pointerCount, pointerProperties,
+ pointerCoords);
event.offsetLocation(20, 60);
ASSERT_EQ(280, event.getRawXCursorPosition());
ASSERT_EQ(540, event.getRawYCursorPosition());
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 8db5bf1..d09f2ac 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -160,13 +160,14 @@
constexpr float yScale = 3;
constexpr float xOffset = -10;
constexpr float yOffset = -20;
+ constexpr float rawXScale = 4;
+ constexpr float rawYScale = -5;
+ constexpr float rawXOffset = -11;
+ constexpr float rawYOffset = 42;
constexpr float xPrecision = 0.25;
constexpr float yPrecision = 0.5;
constexpr float xCursorPosition = 1.3;
constexpr float yCursorPosition = 50.6;
- constexpr uint32_t displayOrientation = ui::Transform::ROT_0;
- constexpr int32_t displayWidth = 1000;
- constexpr int32_t displayHeight = 2000;
constexpr nsecs_t downTime = 3;
constexpr size_t pointerCount = 3;
constexpr nsecs_t eventTime = 4;
@@ -192,12 +193,14 @@
ui::Transform transform;
transform.set({xScale, 0, xOffset, 0, yScale, yOffset, 0, 0, 1});
+ ui::Transform rawTransform;
+ rawTransform.set({rawXScale, 0, rawXOffset, 0, rawYScale, rawYOffset, 0, 0, 1});
status = mPublisher->publishMotionEvent(seq, eventId, deviceId, source, displayId, hmac, action,
actionButton, flags, edgeFlags, metaState, buttonState,
classification, transform, xPrecision, yPrecision,
- xCursorPosition, yCursorPosition, displayOrientation,
- displayWidth, displayHeight, downTime, eventTime,
- pointerCount, pointerProperties, pointerCoords);
+ xCursorPosition, yCursorPosition, rawTransform,
+ downTime, eventTime, pointerCount, pointerProperties,
+ pointerCoords);
ASSERT_EQ(OK, status)
<< "publisher publishMotionEvent should return OK";
@@ -234,9 +237,7 @@
EXPECT_EQ(yCursorPosition, motionEvent->getRawYCursorPosition());
EXPECT_EQ(xCursorPosition * xScale + xOffset, motionEvent->getXCursorPosition());
EXPECT_EQ(yCursorPosition * yScale + yOffset, motionEvent->getYCursorPosition());
- EXPECT_EQ(displayOrientation, motionEvent->getDisplayOrientation());
- EXPECT_EQ(displayWidth, motionEvent->getDisplaySize().x);
- EXPECT_EQ(displayHeight, motionEvent->getDisplaySize().y);
+ EXPECT_EQ(rawTransform, motionEvent->getRawTransform());
EXPECT_EQ(downTime, motionEvent->getDownTime());
EXPECT_EQ(eventTime, motionEvent->getEventTime());
EXPECT_EQ(pointerCount, motionEvent->getPointerCount());
@@ -247,28 +248,18 @@
EXPECT_EQ(pointerProperties[i].id, motionEvent->getPointerId(i));
EXPECT_EQ(pointerProperties[i].toolType, motionEvent->getToolType(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
- motionEvent->getRawX(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
- motionEvent->getRawY(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X) * xScale + xOffset,
- motionEvent->getX(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y) * yScale + yOffset,
- motionEvent->getY(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
- motionEvent->getPressure(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
- motionEvent->getSize(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
- motionEvent->getTouchMajor(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
- motionEvent->getTouchMinor(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
- motionEvent->getToolMajor(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
- motionEvent->getToolMinor(i));
- EXPECT_EQ(pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
- motionEvent->getOrientation(i));
+ const auto& pc = pointerCoords[i];
+ EXPECT_EQ(pc.getX() * rawXScale + rawXOffset, motionEvent->getRawX(i));
+ EXPECT_EQ(pc.getY() * rawYScale + rawYOffset, motionEvent->getRawY(i));
+ EXPECT_EQ(pc.getX() * xScale + xOffset, motionEvent->getX(i));
+ EXPECT_EQ(pc.getY() * yScale + yOffset, motionEvent->getY(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE), motionEvent->getPressure(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_SIZE), motionEvent->getSize(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR), motionEvent->getTouchMajor(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR), motionEvent->getTouchMinor(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR), motionEvent->getToolMajor(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR), motionEvent->getToolMinor(i));
+ EXPECT_EQ(pc.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION), motionEvent->getOrientation(i));
}
status = mConsumer->sendFinishedSignal(seq, false);
@@ -505,12 +496,12 @@
}
ui::Transform identityTransform;
- status = mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, identityTransform,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount,
- pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
+ 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -522,12 +513,12 @@
PointerCoords pointerCoords[pointerCount];
ui::Transform identityTransform;
- status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, identityTransform,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount,
- pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
+ 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
@@ -544,12 +535,12 @@
}
ui::Transform identityTransform;
- status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
- 0, 0, 0, MotionClassification::NONE, identityTransform,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, 0, 0, 0, 0, pointerCount,
- pointerProperties, pointerCoords);
+ status =
+ mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, identityTransform,
+ 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
+ 0, 0, pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(BAD_VALUE, status)
<< "publisher publishMotionEvent should return BAD_VALUE";
}
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index 18289a5..2f88704 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -49,7 +49,7 @@
CHECK_OFFSET(InputMessage::Body::Key, downTime, 88);
CHECK_OFFSET(InputMessage::Body::Motion, eventId, 0);
- CHECK_OFFSET(InputMessage::Body::Motion, empty1, 4);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 4);
CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
@@ -74,11 +74,13 @@
CHECK_OFFSET(InputMessage::Body::Motion, yPrecision, 124);
CHECK_OFFSET(InputMessage::Body::Motion, xCursorPosition, 128);
CHECK_OFFSET(InputMessage::Body::Motion, yCursorPosition, 132);
- CHECK_OFFSET(InputMessage::Body::Motion, displayOrientation, 136);
- CHECK_OFFSET(InputMessage::Body::Motion, displayWidth, 140);
- CHECK_OFFSET(InputMessage::Body::Motion, displayHeight, 144);
- CHECK_OFFSET(InputMessage::Body::Motion, pointerCount, 148);
- CHECK_OFFSET(InputMessage::Body::Motion, pointers, 152);
+ CHECK_OFFSET(InputMessage::Body::Motion, dsdxRaw, 136);
+ CHECK_OFFSET(InputMessage::Body::Motion, dtdxRaw, 140);
+ CHECK_OFFSET(InputMessage::Body::Motion, dtdyRaw, 144);
+ CHECK_OFFSET(InputMessage::Body::Motion, dsdyRaw, 148);
+ CHECK_OFFSET(InputMessage::Body::Motion, txRaw, 152);
+ CHECK_OFFSET(InputMessage::Body::Motion, tyRaw, 156);
+ CHECK_OFFSET(InputMessage::Body::Motion, pointers, 160);
CHECK_OFFSET(InputMessage::Body::Focus, eventId, 0);
CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 13e2b02..3039362 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -184,8 +184,7 @@
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, identityTransform, 0 /*xPrecision*/,
0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 0 /*downTime*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, 0 /*downTime*/,
entry.eventTime.count(), pointerCount, properties, coords);
events.emplace_back(event);
diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp
index b29c9a4..f2b59ea 100644
--- a/libs/input/tests/VerifiedInputEvent_test.cpp
+++ b/libs/input/tests/VerifiedInputEvent_test.cpp
@@ -43,12 +43,12 @@
ui::Transform transform;
transform.set({2, 0, 4, 0, 3, 5, 0, 0, 1});
+ ui::Transform identity;
event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT,
INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, transform, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/,
- 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, 100 /*downTime*/,
+ 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, identity, 100 /*downTime*/,
200 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
return event;
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index ba5a64f..04ba485 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -86,6 +86,7 @@
export_include_dirs: [
"include",
+ "include_mock",
"include_private",
"include_types",
],
diff --git a/libs/ui/include/ui/Fence.h b/libs/ui/include/ui/Fence.h
index 6efecd3..7634007 100644
--- a/libs/ui/include/ui/Fence.h
+++ b/libs/ui/include/ui/Fence.h
@@ -26,6 +26,10 @@
namespace android {
+namespace mock {
+class MockFence;
+}
+
class String8;
// ===========================================================================
@@ -109,7 +113,7 @@
// fence transitioned to the signaled state. If the fence is not signaled
// then SIGNAL_TIME_PENDING is returned. If the fence is invalid or if an
// error occurs then SIGNAL_TIME_INVALID is returned.
- nsecs_t getSignalTime() const;
+ virtual nsecs_t getSignalTime() const;
enum class Status {
Invalid, // Fence is invalid
@@ -144,7 +148,10 @@
private:
// Only allow instantiation using ref counting.
friend class LightRefBase<Fence>;
- ~Fence() = default;
+ virtual ~Fence() = default;
+
+ // Allow mocking for unit testing
+ friend class mock::MockFence;
base::unique_fd mFenceFd;
};
diff --git a/libs/binder/include/binder/RpcCertificateVerifier.h b/libs/ui/include_mock/ui/MockFence.h
similarity index 61%
copy from libs/binder/include/binder/RpcCertificateVerifier.h
copy to libs/ui/include_mock/ui/MockFence.h
index 97af31c..162ec02 100644
--- a/libs/binder/include/binder/RpcCertificateVerifier.h
+++ b/libs/ui/include_mock/ui/MockFence.h
@@ -16,17 +16,17 @@
#pragma once
-#include <openssl/ssl.h>
-#include <utils/Errors.h>
+#include <gmock/gmock.h>
+#include <ui/Fence.h>
-namespace android {
+namespace android::mock {
-// An interface with a function that verifies a peer certificate. It is a wrapper over the custom
-// verify function (see SSL_CTX_set_custom_verify).
-class RpcCertificateVerifier {
+class MockFence : public android::Fence {
public:
- virtual ~RpcCertificateVerifier() = default;
- virtual status_t verify(const X509* peerCert, uint8_t* outAlert) = 0;
+ MockFence() = default;
+ virtual ~MockFence() = default;
+
+ MOCK_METHOD(nsecs_t, getSignalTime, (), (const, override));
};
-} // namespace android
+}; // namespace android::mock
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 516aad8..a87740a 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -115,3 +115,12 @@
srcs: ["Size_test.cpp"],
cflags: ["-Wall", "-Werror"],
}
+
+cc_test {
+ name: "MockFence_test",
+ shared_libs: ["libui"],
+ static_libs: ["libgmock"],
+ srcs: ["MockFence_test.cpp"],
+ cflags: ["-Wall", "-Werror"],
+}
+
diff --git a/libs/ui/tests/MockFence_test.cpp b/libs/ui/tests/MockFence_test.cpp
new file mode 100644
index 0000000..6e520b1
--- /dev/null
+++ b/libs/ui/tests/MockFence_test.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 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 <ui/MockFence.h>
+
+#include <gtest/gtest.h>
+
+namespace android::ui {
+
+using testing::Return;
+
+class MockFenceTest : public testing::Test {
+public:
+ sp<Fence> getFenceForTesting() const { return mMockFence; }
+
+ const mock::MockFence& getMockFence() const { return *mMockFence; }
+
+private:
+ sp<mock::MockFence> mMockFence = sp<mock::MockFence>::make();
+};
+
+TEST_F(MockFenceTest, getSignalTime) {
+ sp<Fence> fence = getFenceForTesting();
+
+ EXPECT_CALL(getMockFence(), getSignalTime).WillOnce(Return(Fence::SIGNAL_TIME_PENDING));
+ EXPECT_EQ(Fence::SIGNAL_TIME_PENDING, fence->getSignalTime());
+
+ EXPECT_CALL(getMockFence(), getSignalTime).WillOnce(Return(1234));
+ EXPECT_EQ(1234, fence->getSignalTime());
+}
+
+} // namespace android::ui
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 4c07c22..f053568 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -30,7 +30,6 @@
#include <input/InputTransport.h>
#include <android/os/BnInputFlinger.h>
-#include <android/os/IInputFlinger.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 6ce0313..68d25f9 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -236,8 +236,8 @@
/* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
identityTransform, /* xPrecision */ 0,
/* yPrecision */ 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, currentTime, currentTime,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, currentTime,
+ currentTime,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
return event;
}
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index 571c126..bcb0071 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -309,15 +309,14 @@
volatile int32_t DispatchEntry::sNextSeqAtomic;
DispatchEntry::DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags,
- ui::Transform transform, float globalScaleFactor,
- uint32_t displayOrientation, int2 displaySize)
+ const ui::Transform& transform, const ui::Transform& rawTransform,
+ float globalScaleFactor)
: seq(nextSeq()),
eventEntry(std::move(eventEntry)),
targetFlags(targetFlags),
transform(transform),
+ rawTransform(rawTransform),
globalScaleFactor(globalScaleFactor),
- displayOrientation(displayOrientation),
- displaySize(displaySize),
deliveryTime(0),
resolvedAction(0),
resolvedFlags(0) {}
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index 5365a78..7a121ce 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -226,9 +226,8 @@
std::shared_ptr<EventEntry> eventEntry; // the event to dispatch
int32_t targetFlags;
ui::Transform transform;
+ ui::Transform rawTransform;
float globalScaleFactor;
- uint32_t displayOrientation;
- int2 displaySize;
// Both deliveryTime and timeoutTime are only populated when the entry is sent to the app,
// and will be undefined before that.
nsecs_t deliveryTime; // time when the event was actually delivered
@@ -241,8 +240,8 @@
int32_t resolvedFlags;
DispatchEntry(std::shared_ptr<EventEntry> eventEntry, int32_t targetFlags,
- ui::Transform transform, float globalScaleFactor, uint32_t displayOrientation,
- int2 displaySize);
+ const ui::Transform& transform, const ui::Transform& rawTransform,
+ float globalScaleFactor);
inline bool hasForegroundTarget() const { return targetFlags & InputTarget::FLAG_FOREGROUND; }
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index da3e237..5f48c1d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -346,18 +346,15 @@
// Use identity transform for joystick and position-based (touchpad) events because they
// don't depend on the window transform.
return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, identityTransform,
- 1.0f /*globalScaleFactor*/,
- inputTarget.displayOrientation,
- inputTarget.displaySize);
+ identityTransform, 1.0f /*globalScaleFactor*/);
}
}
if (inputTarget.useDefaultPointerTransform()) {
const ui::Transform& transform = inputTarget.getDefaultPointerTransform();
return std::make_unique<DispatchEntry>(eventEntry, inputTargetFlags, transform,
- inputTarget.globalScaleFactor,
- inputTarget.displayOrientation,
- inputTarget.displaySize);
+ inputTarget.displayTransform,
+ inputTarget.globalScaleFactor);
}
ALOG_ASSERT(eventEntry->type == EventEntry::Type::MOTION);
@@ -408,24 +405,11 @@
std::unique_ptr<DispatchEntry> dispatchEntry =
std::make_unique<DispatchEntry>(std::move(combinedMotionEntry), inputTargetFlags,
- firstPointerTransform, inputTarget.globalScaleFactor,
- inputTarget.displayOrientation,
- inputTarget.displaySize);
+ firstPointerTransform, inputTarget.displayTransform,
+ inputTarget.globalScaleFactor);
return dispatchEntry;
}
-void addGestureMonitors(const std::vector<Monitor>& monitors,
- std::vector<TouchedMonitor>& outTouchedMonitors, float xOffset = 0,
- float yOffset = 0) {
- if (monitors.empty()) {
- return;
- }
- outTouchedMonitors.reserve(monitors.size() + outTouchedMonitors.size());
- for (const Monitor& monitor : monitors) {
- outTouchedMonitors.emplace_back(monitor, xOffset, yOffset);
- }
-}
-
status_t openInputChannelPair(const std::string& name, std::shared_ptr<InputChannel>& serverChannel,
std::unique_ptr<InputChannel>& clientChannel) {
std::unique_ptr<InputChannel> uniqueServerChannel;
@@ -947,10 +931,9 @@
}
// Alternatively, maybe there's a gesture monitor that could handle this event
- std::vector<TouchedMonitor> gestureMonitors = findTouchedGestureMonitorsLocked(displayId);
- for (TouchedMonitor& gestureMonitor : gestureMonitors) {
+ for (const auto& monitor : getValueByKey(mGestureMonitorsByDisplay, displayId)) {
sp<Connection> connection =
- getConnectionLocked(gestureMonitor.monitor.inputChannel->getConnectionToken());
+ getConnectionLocked(monitor.inputChannel->getConnectionToken());
if (connection != nullptr && connection->responsive) {
// This monitor could take more input. Drop all events preceding this
// event, so that gesture monitor could get a chance to receive the stream
@@ -1077,15 +1060,6 @@
return nullptr;
}
-std::vector<TouchedMonitor> InputDispatcher::findTouchedGestureMonitorsLocked(
- int32_t displayId) const {
- std::vector<TouchedMonitor> touchedMonitors;
-
- std::vector<Monitor> monitors = getValueByKey(mGestureMonitorsByDisplay, displayId);
- addGestureMonitors(monitors, touchedMonitors);
- return touchedMonitors;
-}
-
void InputDispatcher::dropInboundEventLocked(const EventEntry& entry, DropReason dropReason) {
const char* reason;
switch (dropReason) {
@@ -1947,16 +1921,16 @@
* Given a list of monitors, remove the ones we cannot find a connection for, and the ones
* that are currently unresponsive.
*/
-std::vector<TouchedMonitor> InputDispatcher::selectResponsiveMonitorsLocked(
- const std::vector<TouchedMonitor>& monitors) const {
- std::vector<TouchedMonitor> responsiveMonitors;
+std::vector<Monitor> InputDispatcher::selectResponsiveMonitorsLocked(
+ const std::vector<Monitor>& monitors) const {
+ std::vector<Monitor> responsiveMonitors;
std::copy_if(monitors.begin(), monitors.end(), std::back_inserter(responsiveMonitors),
- [this](const TouchedMonitor& monitor) REQUIRES(mLock) {
- sp<Connection> connection = getConnectionLocked(
- monitor.monitor.inputChannel->getConnectionToken());
+ [this](const Monitor& monitor) REQUIRES(mLock) {
+ sp<Connection> connection =
+ getConnectionLocked(monitor.inputChannel->getConnectionToken());
if (connection == nullptr) {
ALOGE("Could not find connection for monitor %s",
- monitor.monitor.inputChannel->getName().c_str());
+ monitor.inputChannel->getName().c_str());
return false;
}
if (!connection->responsive) {
@@ -2057,14 +2031,10 @@
x = int32_t(entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_X));
y = int32_t(entry.pointerCoords[pointerIndex].getAxisValue(AMOTION_EVENT_AXIS_Y));
}
- bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
+ const bool isDown = maskedAction == AMOTION_EVENT_ACTION_DOWN;
newTouchedWindowHandle = findTouchedWindowAtLocked(displayId, x, y, &tempTouchState,
isDown /*addOutsideTargets*/);
- std::vector<TouchedMonitor> newGestureMonitors = isDown
- ? findTouchedGestureMonitorsLocked(displayId)
- : std::vector<TouchedMonitor>{};
-
// Figure out whether splitting will be allowed for this window.
if (newTouchedWindowHandle != nullptr &&
newTouchedWindowHandle->getInfo()->supportsSplitTouch()) {
@@ -2124,8 +2094,10 @@
newTouchedWindowHandle = nullptr;
}
- // Also don't send the new touch event to unresponsive gesture monitors
- newGestureMonitors = selectResponsiveMonitorsLocked(newGestureMonitors);
+ const std::vector<Monitor> newGestureMonitors = isDown
+ ? selectResponsiveMonitorsLocked(
+ getValueByKey(mGestureMonitorsByDisplay, displayId))
+ : std::vector<Monitor>{};
if (newTouchedWindowHandle == nullptr && newGestureMonitors.empty()) {
ALOGI("Dropping event because there is no touchable window or gesture monitor at "
@@ -2345,9 +2317,8 @@
touchedWindow.pointerIds, inputTargets);
}
- for (const TouchedMonitor& touchedMonitor : tempTouchState.gestureMonitors) {
- addMonitoringTargetLocked(touchedMonitor.monitor, touchedMonitor.xOffset,
- touchedMonitor.yOffset, inputTargets);
+ for (const auto& monitor : tempTouchState.gestureMonitors) {
+ addMonitoringTargetLocked(monitor, displayId, inputTargets);
}
// Drop the outside or hover touch windows since we will not care about them
@@ -2526,9 +2497,7 @@
inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
const auto& displayInfoIt = mDisplayInfos.find(windowInfo->displayId);
if (displayInfoIt != mDisplayInfos.end()) {
- const auto& displayInfo = displayInfoIt->second;
- inputTarget.displayOrientation = displayInfo.transform.getOrientation();
- inputTarget.displaySize = int2(displayInfo.logicalWidth, displayInfo.logicalHeight);
+ inputTarget.displayTransform = displayInfoIt->second.transform;
} else {
ALOGI_IF(isPerWindowInputRotationEnabled(),
"DisplayInfo not found for window on display: %d", windowInfo->displayId);
@@ -2544,27 +2513,44 @@
}
void InputDispatcher::addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets,
- int32_t displayId, float xOffset,
- float yOffset) {
+ int32_t displayId) {
std::unordered_map<int32_t, std::vector<Monitor>>::const_iterator it =
mGlobalMonitorsByDisplay.find(displayId);
if (it != mGlobalMonitorsByDisplay.end()) {
const std::vector<Monitor>& monitors = it->second;
for (const Monitor& monitor : monitors) {
- addMonitoringTargetLocked(monitor, xOffset, yOffset, inputTargets);
+ addMonitoringTargetLocked(monitor, displayId, inputTargets);
}
}
}
-void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, float xOffset,
- float yOffset,
+void InputDispatcher::addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId,
std::vector<InputTarget>& inputTargets) {
InputTarget target;
target.inputChannel = monitor.inputChannel;
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
ui::Transform t;
- t.set(xOffset, yOffset);
+ if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
+ // Input monitors always get un-rotated display coordinates. We undo the display
+ // rotation that is present in the display transform so that display rotation is not
+ // applied to these input targets.
+ const auto& displayInfo = it->second;
+ int32_t width = displayInfo.logicalWidth;
+ int32_t height = displayInfo.logicalHeight;
+ const auto orientation = displayInfo.transform.getOrientation();
+ uint32_t inverseOrientation = orientation;
+ if (orientation == ui::Transform::ROT_90) {
+ inverseOrientation = ui::Transform::ROT_270;
+ std::swap(width, height);
+ } else if (orientation == ui::Transform::ROT_270) {
+ inverseOrientation = ui::Transform::ROT_90;
+ std::swap(width, height);
+ }
+ target.displayTransform =
+ ui::Transform(inverseOrientation, width, height) * displayInfo.transform;
+ t = t * target.displayTransform;
+ }
target.setDefaultPointerTransform(t);
inputTargets.push_back(target);
}
@@ -3250,9 +3236,7 @@
motionEntry.xPrecision, motionEntry.yPrecision,
motionEntry.xCursorPosition,
motionEntry.yCursorPosition,
- dispatchEntry->displayOrientation,
- dispatchEntry->displaySize.x,
- dispatchEntry->displaySize.y,
+ dispatchEntry->rawTransform,
motionEntry.downTime, motionEntry.eventTime,
motionEntry.pointerCount,
motionEntry.pointerProperties, usingCoords);
@@ -3981,14 +3965,14 @@
mLock.unlock();
MotionEvent event;
- ui::Transform transform;
+ ui::Transform identityTransform;
event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
args->action, args->actionButton, args->flags, args->edgeFlags,
- args->metaState, args->buttonState, args->classification, transform,
- args->xPrecision, args->yPrecision, args->xCursorPosition,
- args->yCursorPosition, ui::Transform::ROT_0, INVALID_DISPLAY_SIZE,
- INVALID_DISPLAY_SIZE, args->downTime, args->eventTime,
- args->pointerCount, args->pointerProperties, args->pointerCoords);
+ args->metaState, args->buttonState, args->classification,
+ identityTransform, args->xPrecision, args->yPrecision,
+ args->xCursorPosition, args->yCursorPosition, identityTransform,
+ args->downTime, args->eventTime, args->pointerCount,
+ args->pointerProperties, args->pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
@@ -5479,9 +5463,9 @@
TouchState& state = stateIt->second;
std::shared_ptr<InputChannel> requestingChannel;
std::optional<int32_t> foundDeviceId;
- for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) {
- if (touchedMonitor.monitor.inputChannel->getConnectionToken() == token) {
- requestingChannel = touchedMonitor.monitor.inputChannel;
+ for (const auto& monitor : state.gestureMonitors) {
+ if (monitor.inputChannel->getConnectionToken() == token) {
+ requestingChannel = monitor.inputChannel;
foundDeviceId = state.deviceId;
}
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 4f6d0d2..51ec551 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -516,18 +516,16 @@
android::os::InputEventInjectionResult findTouchedWindowTargetsLocked(
nsecs_t currentTime, const MotionEntry& entry, std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime, bool* outConflictingPointerActions) REQUIRES(mLock);
- std::vector<TouchedMonitor> findTouchedGestureMonitorsLocked(int32_t displayId) const
- REQUIRES(mLock);
- std::vector<TouchedMonitor> selectResponsiveMonitorsLocked(
- const std::vector<TouchedMonitor>& gestureMonitors) const REQUIRES(mLock);
+ std::vector<Monitor> selectResponsiveMonitorsLocked(
+ const std::vector<Monitor>& gestureMonitors) const REQUIRES(mLock);
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds,
std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
- void addMonitoringTargetLocked(const Monitor& monitor, float xOffset, float yOffset,
+ void addMonitoringTargetLocked(const Monitor& monitor, int32_t displayId,
std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
- void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId,
- float xOffset = 0, float yOffset = 0) REQUIRES(mLock);
+ void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId)
+ REQUIRES(mLock);
void pokeUserActivityLocked(const EventEntry& eventEntry) REQUIRES(mLock);
bool checkInjectionPermission(const sp<android::gui::WindowInfoHandle>& windowHandle,
const InjectionState* injectionState);
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 7c463c8..5b76eee 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -101,11 +101,8 @@
// (ignored for KeyEvents)
float globalScaleFactor = 1.0f;
- // Current display orientation
- uint32_t displayOrientation = ui::Transform::ROT_0;
-
- // Display-size in its natural rotation. Used for compatibility transform of raw coordinates.
- int2 displaySize = {INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE};
+ // Current display transform. Used for compatibility for raw coordinates.
+ ui::Transform displayTransform;
// The subset of pointer ids to include in motion events dispatched to this input target
// if FLAG_SPLIT is set.
diff --git a/services/inputflinger/dispatcher/Monitor.cpp b/services/inputflinger/dispatcher/Monitor.cpp
index bbce759..43a82d5 100644
--- a/services/inputflinger/dispatcher/Monitor.cpp
+++ b/services/inputflinger/dispatcher/Monitor.cpp
@@ -22,8 +22,4 @@
Monitor::Monitor(const std::shared_ptr<InputChannel>& inputChannel, int32_t pid)
: inputChannel(inputChannel), pid(pid) {}
-// --- TouchedMonitor ---
-TouchedMonitor::TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset)
- : monitor(monitor), xOffset(xOffset), yOffset(yOffset) {}
-
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Monitor.h b/services/inputflinger/dispatcher/Monitor.h
index 7be0760..365d5be 100644
--- a/services/inputflinger/dispatcher/Monitor.h
+++ b/services/inputflinger/dispatcher/Monitor.h
@@ -29,15 +29,6 @@
explicit Monitor(const std::shared_ptr<InputChannel>& inputChannel, int32_t pid);
};
-// For tracking the offsets we need to apply when adding gesture monitor targets.
-struct TouchedMonitor {
- Monitor monitor;
- float xOffset = 0.f;
- float yOffset = 0.f;
-
- explicit TouchedMonitor(const Monitor& monitor, float xOffset, float yOffset);
-};
-
} // namespace android::inputdispatcher
#endif // _UI_INPUT_INPUTDISPATCHER_MONITOR_H
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 4a50a68..759b3e7 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -75,7 +75,7 @@
windows.push_back(touchedWindow);
}
-void TouchState::addGestureMonitors(const std::vector<TouchedMonitor>& newMonitors) {
+void TouchState::addGestureMonitors(const std::vector<Monitor>& newMonitors) {
const size_t newSize = gestureMonitors.size() + newMonitors.size();
gestureMonitors.reserve(newSize);
gestureMonitors.insert(std::end(gestureMonitors), std::begin(newMonitors),
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 7dcf55d..4a62051 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -36,7 +36,7 @@
int32_t displayId; // id to the display that currently has a touch, others are rejected
std::vector<TouchedWindow> windows;
- std::vector<TouchedMonitor> gestureMonitors;
+ std::vector<Monitor> gestureMonitors;
TouchState();
~TouchState();
@@ -45,7 +45,7 @@
void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds);
void addPortalWindow(const sp<android::gui::WindowInfoHandle>& windowHandle);
- void addGestureMonitors(const std::vector<TouchedMonitor>& monitors);
+ void addGestureMonitors(const std::vector<Monitor>& monitors);
void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
void filterNonMonitors();
diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h
index 827e31a..0dfe7f1 100644
--- a/services/inputflinger/reader/Macros.h
+++ b/services/inputflinger/reader/Macros.h
@@ -31,7 +31,7 @@
#define DEBUG_VIRTUAL_KEYS 0
// Log debug messages about pointers.
-#define DEBUG_POINTERS 0
+static constexpr bool DEBUG_POINTERS = false;
// Log debug messages about pointer assignment calculations.
#define DEBUG_POINTER_ASSIGNMENT 0
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index fab7f4c..4bd1cd8 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -95,13 +95,13 @@
}
if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
-#if DEBUG_POINTERS
- if (newSlot) {
- ALOGW("MultiTouch device emitted invalid slot index %d but it "
- "should be between 0 and %zd; ignoring this slot.",
- mCurrentSlot, mSlotCount - 1);
+ if (DEBUG_POINTERS) {
+ if (newSlot) {
+ ALOGW("MultiTouch device emitted invalid slot index %d but it "
+ "should be between 0 and %zd; ignoring this slot.",
+ mCurrentSlot, mSlotCount - 1);
+ }
}
-#endif
} else {
Slot* slot = &mSlots[mCurrentSlot];
// If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
@@ -273,19 +273,19 @@
if (id) {
outState->rawPointerData.canceledIdBits.markBit(id.value());
}
-#if DEBUG_POINTERS
- ALOGI("Stop processing slot %zu for it received a palm event from device %s", inIndex,
- getDeviceName().c_str());
-#endif
+ if (DEBUG_POINTERS) {
+ ALOGI("Stop processing slot %zu for it received a palm event from device %s",
+ inIndex, getDeviceName().c_str());
+ }
continue;
}
if (outCount >= MAX_POINTERS) {
-#if DEBUG_POINTERS
- ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
- "ignoring the rest.",
- getDeviceName().c_str(), MAX_POINTERS);
-#endif
+ if (DEBUG_POINTERS) {
+ ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
+ "ignoring the rest.",
+ getDeviceName().c_str(), MAX_POINTERS);
+ }
break; // too many fingers!
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 903f337..e9d45b2 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -542,8 +542,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
/*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -556,8 +556,7 @@
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -569,8 +568,7 @@
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -583,8 +581,7 @@
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -596,8 +593,7 @@
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, identityTransform, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- ui::Transform::ROT_0, INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE,
- ARBITRARY_TIME, ARBITRARY_TIME,
+ identityTransform, ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -608,8 +604,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -619,8 +615,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -632,8 +628,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -644,8 +640,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -658,8 +654,8 @@
event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- INVALID_DISPLAY_SIZE, INVALID_DISPLAY_SIZE, ARBITRARY_TIME, ARBITRARY_TIME,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, ARBITRARY_TIME,
+ ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(InputEventInjectionResult::FAILED,
mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
@@ -1296,9 +1292,8 @@
mAction, mActionButton, mFlags, /* edgeFlags */ 0, AMETA_NONE,
mButtonState, MotionClassification::NONE, identityTransform,
/* xPrecision */ 0, /* yPrecision */ 0, mRawXCursorPosition,
- mRawYCursorPosition, mDisplayOrientation, mDisplayWidth, mDisplayHeight,
- mEventTime, mEventTime, mPointers.size(), pointerProperties.data(),
- pointerCoords.data());
+ mRawYCursorPosition, identityTransform, mEventTime, mEventTime,
+ mPointers.size(), pointerProperties.data(), pointerCoords.data());
return event;
}
@@ -1313,9 +1308,6 @@
int32_t mFlags{0};
float mRawXCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
float mRawYCursorPosition{AMOTION_EVENT_INVALID_CURSOR_POSITION};
- uint32_t mDisplayOrientation{ui::Transform::ROT_0};
- int32_t mDisplayWidth{INVALID_DISPLAY_SIZE};
- int32_t mDisplayHeight{INVALID_DISPLAY_SIZE};
std::vector<PointerBuilder> mPointers;
};
@@ -3622,8 +3614,7 @@
DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, MotionClassification::NONE,
identityTransform, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ui::Transform::ROT_0,
- 0 /*INVALID_DISPLAY_SIZE*/, 0 /*INVALID_DISPLAY_SIZE*/, eventTime,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, eventTime,
eventTime,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index e4f642e..d51db88 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -17,7 +17,6 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
#undef LOG_TAG
#define LOG_TAG "BufferQueueLayer"
@@ -171,7 +170,7 @@
expectedPresentTime = 0;
}
- for (int i = 1; i < mQueueItems.size(); i++) {
+ for (size_t i = 1; i < mQueueItems.size(); i++) {
const bool fenceSignaled =
mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
if (!fenceSignaled) {
@@ -243,7 +242,7 @@
uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
{
Mutex::Autolock lock(mQueueItemLock);
- for (int i = 0; i < mQueueItems.size(); i++) {
+ for (size_t i = 0; i < mQueueItems.size(); i++) {
bool fenceSignaled =
mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
if (!fenceSignaled) {
@@ -629,4 +628,4 @@
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ef6f115..d549fe9 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -135,6 +135,7 @@
mDrawingState.postTime = -1;
mDrawingState.destinationFrame.makeInvalid();
mDrawingState.isTrustedOverlay = false;
+ mDrawingState.dropInputMode = gui::DropInputMode::NONE;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -2541,6 +2542,14 @@
return handle->owner;
}
+bool Layer::setDropInputMode(gui::DropInputMode mode) {
+ if (mDrawingState.dropInputMode == mode) {
+ return false;
+ }
+ mDrawingState.dropInputMode = mode;
+ return true;
+}
+
// ---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3c3c7d0..b70d5d4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,6 +17,7 @@
#pragma once
+#include <android/gui/DropInputMode.h>
#include <compositionengine/LayerFE.h>
#include <gui/BufferQueue.h>
#include <gui/ISurfaceComposerClient.h>
@@ -277,6 +278,8 @@
Rect destinationFrame;
sp<IBinder> releaseBufferEndpoint;
+
+ gui::DropInputMode dropInputMode;
};
/*
@@ -442,6 +445,8 @@
virtual bool setFrameRateSelectionPriority(int32_t priority);
virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
virtual void setAutoRefresh(bool /* autoRefresh */) {}
+ bool setDropInputMode(gui::DropInputMode);
+
// If the variable is not set on the layer, it traverses up the tree to inherit the frame
// rate priority from its parent.
virtual int32_t getFrameRateSelectionPriority() const;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index b00423e..3f6bd6f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -133,27 +133,10 @@
return true;
}
-float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer,
- const RefreshRate& refreshRate,
- bool isSeamlessSwitch) const {
- if (!isVoteAllowed(layer, refreshRate)) {
- return 0;
- }
-
+float RefreshRateConfigs::calculateNonExactMatchingLayerScoreLocked(
+ const LayerRequirement& layer, const RefreshRate& refreshRate) const {
constexpr float kScoreForFractionalPairs = .8f;
- // Slightly prefer seamless switches.
- constexpr float kSeamedSwitchPenalty = 0.95f;
- const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
-
- // If the layer wants Max, give higher score to the higher refresh rate
- if (layer.vote == LayerVoteType::Max) {
- const auto ratio = refreshRate.getFps().getValue() /
- mAppRequestRefreshRates.back()->getFps().getValue();
- // use ratio^2 to get a lower score the more we get further from peak
- return ratio * ratio;
- }
-
const auto displayPeriod = refreshRate.getVsyncPeriod();
const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs();
if (layer.vote == LayerVoteType::ExplicitDefault) {
@@ -178,7 +161,7 @@
if (layer.vote == LayerVoteType::ExplicitExactOrMultiple ||
layer.vote == LayerVoteType::Heuristic) {
if (isFractionalPairOrMultiple(refreshRate.getFps(), layer.desiredRefreshRate)) {
- return kScoreForFractionalPairs * seamlessness;
+ return kScoreForFractionalPairs;
}
// Calculate how many display vsyncs we need to present a single frame for this
@@ -188,7 +171,7 @@
static constexpr size_t MAX_FRAMES_TO_FIT = 10; // Stop calculating when score < 0.1
if (displayFramesRemainder == 0) {
// Layer desired refresh rate matches the display rate.
- return 1.0f * seamlessness;
+ return 1.0f;
}
if (displayFramesQuotient == 0) {
@@ -206,7 +189,29 @@
iter++;
}
- return (1.0f / iter) * seamlessness;
+ return (1.0f / iter);
+ }
+
+ return 0;
+}
+
+float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer,
+ const RefreshRate& refreshRate,
+ bool isSeamlessSwitch) const {
+ if (!isVoteAllowed(layer, refreshRate)) {
+ return 0;
+ }
+
+ // Slightly prefer seamless switches.
+ constexpr float kSeamedSwitchPenalty = 0.95f;
+ const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty;
+
+ // If the layer wants Max, give higher score to the higher refresh rate
+ if (layer.vote == LayerVoteType::Max) {
+ const auto ratio = refreshRate.getFps().getValue() /
+ mAppRequestRefreshRates.back()->getFps().getValue();
+ // use ratio^2 to get a lower score the more we get further from peak
+ return ratio * ratio;
}
if (layer.vote == LayerVoteType::ExplicitExact) {
@@ -221,7 +226,18 @@
return divider == 1;
}
- return 0;
+ // If the layer frame rate is a divider of the refresh rate it should score
+ // the highest score.
+ if (getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate) > 0) {
+ return 1.0f * seamlessness;
+ }
+
+ // The layer frame rate is not a divider of the refresh rate,
+ // there is a small penalty attached to the score to favor the frame rates
+ // the exactly matches the display refresh rate or a multiple.
+ constexpr float kNonExactMatchingPenalty = 0.99f;
+ return calculateNonExactMatchingLayerScoreLocked(layer, refreshRate) * seamlessness *
+ kNonExactMatchingPenalty;
}
struct RefreshRateScore {
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 3713587..ffaa029 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -409,6 +409,9 @@
float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
bool isSeamlessSwitch) const REQUIRES(mLock);
+ float calculateNonExactMatchingLayerScoreLocked(const LayerRequirement&,
+ const RefreshRate&) const REQUIRES(mLock);
+
void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
// The list of refresh rates, indexed by display modes ID. This may change after this
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index bc2ef40..da2204e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1716,7 +1716,15 @@
void SurfaceFlinger::onComposerHalVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp,
std::optional<hal::VsyncPeriodNanos> vsyncPeriod) {
- ATRACE_CALL();
+ const std::string tracePeriod = [vsyncPeriod]() {
+ if (ATRACE_ENABLED() && vsyncPeriod) {
+ std::stringstream ss;
+ ss << "(" << *vsyncPeriod << ")";
+ return ss.str();
+ }
+ return std::string();
+ }();
+ ATRACE_FORMAT("onComposerHalVsync%s", tracePeriod.c_str());
Mutex::Autolock lock(mStateLock);
const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId);
@@ -4153,6 +4161,16 @@
flags |= eTraversalNeeded;
}
}
+ if (what & layer_state_t::eDropInputModeChanged) {
+ if (privileged) {
+ if (layer->setDropInputMode(s.dropInputMode)) {
+ flags |= eTraversalNeeded;
+ mInputInfoChanged = true;
+ }
+ } else {
+ ALOGE("Attempt to update DropInputMode without permission ACCESS_SURFACE_FLINGER");
+ }
+ }
// This has to happen after we reparent children because when we reparent to null we remove
// child layers from current state and remove its relative z. If the children are reparented in
// the same transaction, then we have to make sure we reparent the children first so we do not
@@ -5152,7 +5170,8 @@
continue;
}
- StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
+ StringAppendF(&result, "Display %s (%s) HWC layers:\n", to_string(*displayId).c_str(),
+ (isDisplayActiveLocked(display) ? "active" : "inactive"));
Layer::miniDumpHeader(result);
const DisplayDevice& ref = *display;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5960be1..141d7ac 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1016,7 +1016,7 @@
sp<DisplayDevice> getDisplayWithInputByLayer(Layer* layer) const REQUIRES(mStateLock);
- bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) REQUIRES(mStateLock) {
+ bool isDisplayActiveLocked(const sp<const DisplayDevice>& display) const REQUIRES(mStateLock) {
return display->getDisplayToken() == mActiveDisplayToken;
}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 618c10d..a8e3e5e 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -175,7 +175,6 @@
RefreshRate mExpected30Config = {mConfig30, RefreshRate::ConstructorTag(0)};
RefreshRate mExpected120Config = {mConfig120, RefreshRate::ConstructorTag(0)};
-private:
DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
ui::Size resolution = ui::Size());
};
@@ -2179,6 +2178,44 @@
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
}
+// b/190578904
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_deviceWithCloseRefreshRates) {
+ constexpr int kMinRefreshRate = 10;
+ constexpr int kMaxRefreshRate = 240;
+
+ DisplayModes displayModes;
+ for (int fps = kMinRefreshRate; fps < kMaxRefreshRate; fps++) {
+ constexpr int32_t kGroup = 0;
+ const auto refreshRate = Fps(static_cast<float>(fps));
+ displayModes.push_back(
+ createDisplayMode(DisplayModeId(fps), kGroup, refreshRate.getPeriodNsecs()));
+ }
+
+ const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(displayModes,
+ /*currentConfigId=*/displayModes[0]->getId());
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ const auto testRefreshRate = [&](Fps fps, LayerVoteType vote) {
+ layers[0].desiredRefreshRate = fps;
+ layers[0].vote = vote;
+ EXPECT_EQ(fps.getIntValue(),
+ refreshRateConfigs->getBestRefreshRate(layers, globalSignals)
+ .getFps()
+ .getIntValue())
+ << "Failed for " << RefreshRateConfigs::layerVoteTypeString(vote);
+ };
+
+ for (int fps = kMinRefreshRate; fps < kMaxRefreshRate; fps++) {
+ const auto refreshRate = Fps(static_cast<float>(fps));
+ testRefreshRate(refreshRate, LayerVoteType::Heuristic);
+ testRefreshRate(refreshRate, LayerVoteType::ExplicitDefault);
+ testRefreshRate(refreshRate, LayerVoteType::ExplicitExactOrMultiple);
+ testRefreshRate(refreshRate, LayerVoteType::ExplicitExact);
+ }
+}
+
TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
EXPECT_TRUE(mExpected60Config < mExpected90Config);
EXPECT_FALSE(mExpected60Config < mExpected60Config);