Merge "Fix a missing item "String Type" in sensor info of Device Orientation." into sc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index ae96e66..8ac4ff8 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1964,6 +1964,8 @@
RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
SEC_TO_MSEC(10));
+ RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
+ SEC_TO_MSEC(10));
if (include_sensitive_info) {
// Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
@@ -3187,6 +3189,11 @@
// Since we do not have user consent to share the bugreport it does not get
// copied over to the calling app but remains in the internal directory from
// where the user can manually pull it.
+ std::string final_path = GetPath(".zip");
+ bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
+ if (copy_succeeded) {
+ android::os::UnlinkAndLogOnError(path_);
+ }
return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
}
// Unknown result; must be a programming error.
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 9881371..351e6fa 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -358,6 +358,11 @@
* enum.
*
* Available since API level 29.
+ *
+ * @deprecated Use setCrop, setPosition, setBufferTransform, and setScale instead. Those functions
+ * provide well defined behavior and allows for more control by the apps. It also allows the caller
+ * to set different properties at different times, instead of having to specify all the desired
+ * properties at once.
*/
void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, const ARect& source,
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index aaebb23..3a98cad 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -49,8 +49,6 @@
return setupSocketServer(UnixSocketAddress(path));
}
-#ifdef __BIONIC__
-
bool RpcServer::setupVsockServer(unsigned int port) {
// realizing value w/ this type at compile time to avoid ubsan abort
constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
@@ -58,8 +56,6 @@
return setupSocketServer(VsockSocketAddress(kAnyCid, port));
}
-#endif // __BIONIC__
-
bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) {
const char* kAddr = "127.0.0.1";
@@ -121,16 +117,14 @@
void RpcServer::join() {
LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
-
- std::vector<std::thread> pool;
{
std::lock_guard<std::mutex> _l(mLock);
LOG_ALWAYS_FATAL_IF(mServer.get() == -1, "RpcServer must be setup to join.");
}
while (true) {
- unique_fd clientFd(
- TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
+ unique_fd clientFd(TEMP_FAILURE_RETRY(
+ accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -138,37 +132,12 @@
}
LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
- // TODO(b/183988761): cannot trust this simple ID
- LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
- int32_t id;
- if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
- ALOGE("Could not read ID from fd %d", clientFd.get());
- continue;
- }
-
{
std::lock_guard<std::mutex> _l(mLock);
-
- sp<RpcSession> session;
- if (id == RPC_SESSION_ID_NEW) {
- // new client!
- LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
- mSessionIdCounter++;
-
- session = RpcSession::make();
- session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
-
- mSessions[mSessionIdCounter] = session;
- } else {
- auto it = mSessions.find(id);
- if (it == mSessions.end()) {
- ALOGE("Cannot add thread, no record of session with ID %d", id);
- continue;
- }
- session = it->second;
- }
-
- session->startThread(std::move(clientFd));
+ std::thread thread =
+ std::thread(&RpcServer::establishConnection, this,
+ std::move(sp<RpcServer>::fromExisting(this)), std::move(clientFd));
+ mConnectingThreads[thread.get_id()] = std::move(thread);
}
}
}
@@ -183,6 +152,56 @@
return sessions;
}
+void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) {
+ LOG_ALWAYS_FATAL_IF(this != server.get(), "Must pass same ownership object");
+
+ // TODO(b/183988761): cannot trust this simple ID
+ LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
+ int32_t id;
+ if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
+ ALOGE("Could not read ID from fd %d", clientFd.get());
+ return;
+ }
+
+ std::thread thisThread;
+ sp<RpcSession> session;
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+
+ auto threadId = mConnectingThreads.find(std::this_thread::get_id());
+ LOG_ALWAYS_FATAL_IF(threadId == mConnectingThreads.end(),
+ "Must establish connection on owned thread");
+ thisThread = std::move(threadId->second);
+ mConnectingThreads.erase(threadId);
+
+ if (id == RPC_SESSION_ID_NEW) {
+ LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
+ mSessionIdCounter++;
+
+ session = RpcSession::make();
+ session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
+
+ mSessions[mSessionIdCounter] = session;
+ } else {
+ auto it = mSessions.find(id);
+ if (it == mSessions.end()) {
+ ALOGE("Cannot add thread, no record of session with ID %d", id);
+ return;
+ }
+ session = it->second;
+ }
+ }
+
+ // avoid strong cycle
+ server = nullptr;
+ //
+ //
+ // DO NOT ACCESS MEMBER VARIABLES BELOW
+ //
+
+ session->join(std::move(thisThread), std::move(clientFd));
+}
+
bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index d9b5c73..f32aa7a 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -61,14 +61,10 @@
return setupSocketClient(UnixSocketAddress(path));
}
-#ifdef __BIONIC__
-
bool RpcSession::setupVsockClient(unsigned int cid, unsigned int port) {
return setupSocketClient(VsockSocketAddress(cid, port));
}
-#endif // __BIONIC__
-
bool RpcSession::setupInetClient(const char* addr, unsigned int port) {
auto aiStart = InetSocketAddress::getAddrInfo(addr, port);
if (aiStart == nullptr) return false;
@@ -88,7 +84,7 @@
return false;
}
- addClient(std::move(serverFd));
+ addClientConnection(std::move(serverFd));
return true;
}
@@ -97,7 +93,7 @@
return state()->getRootObject(connection.fd(), sp<RpcSession>::fromExisting(this));
}
-status_t RpcSession::getMaxThreads(size_t* maxThreads) {
+status_t RpcSession::getRemoteMaxThreads(size_t* maxThreads) {
ExclusiveConnection connection(sp<RpcSession>::fromExisting(this), ConnectionUse::CLIENT);
return state()->getMaxThreads(connection.fd(), sp<RpcSession>::fromExisting(this), maxThreads);
}
@@ -135,24 +131,14 @@
return OK;
}
-void RpcSession::startThread(unique_fd client) {
- std::lock_guard<std::mutex> _l(mMutex);
- sp<RpcSession> holdThis = sp<RpcSession>::fromExisting(this);
- int fd = client.release();
- auto thread = std::thread([=] {
- holdThis->join(unique_fd(fd));
- {
- std::lock_guard<std::mutex> _l(holdThis->mMutex);
- auto it = mThreads.find(std::this_thread::get_id());
- LOG_ALWAYS_FATAL_IF(it == mThreads.end());
- it->second.detach();
- mThreads.erase(it);
- }
- });
- mThreads[thread.get_id()] = std::move(thread);
-}
+void RpcSession::join(std::thread thread, unique_fd client) {
+ LOG_ALWAYS_FATAL_IF(thread.get_id() != std::this_thread::get_id(), "Must own this thread");
-void RpcSession::join(unique_fd client) {
+ {
+ std::lock_guard<std::mutex> _l(mMutex);
+ mThreads[thread.get_id()] = std::move(thread);
+ }
+
// must be registered to allow arbitrary client code executing commands to
// be able to do nested calls (we can't only read from it)
sp<RpcConnection> connection = assignServerToThisThread(std::move(client));
@@ -169,6 +155,14 @@
LOG_ALWAYS_FATAL_IF(!removeServerConnection(connection),
"bad state: connection object guaranteed to be in list");
+
+ {
+ std::lock_guard<std::mutex> _l(mMutex);
+ auto it = mThreads.find(std::this_thread::get_id());
+ LOG_ALWAYS_FATAL_IF(it == mThreads.end());
+ it->second.detach();
+ mThreads.erase(it);
+ }
}
void RpcSession::terminateLocked() {
@@ -205,7 +199,7 @@
// instead of all at once.
// TODO(b/186470974): first risk of blocking
size_t numThreadsAvailable;
- if (status_t status = getMaxThreads(&numThreadsAvailable); status != OK) {
+ if (status_t status = getRemoteMaxThreads(&numThreadsAvailable); status != OK) {
ALOGE("Could not get max threads after initial session to %s: %s", addr.toString().c_str(),
statusToString(status).c_str());
return false;
@@ -219,45 +213,55 @@
// we've already setup one client
for (size_t i = 0; i + 1 < numThreadsAvailable; i++) {
- // TODO(b/185167543): avoid race w/ accept4 not being called on server
- for (size_t tries = 0; tries < 5; tries++) {
- if (setupOneSocketClient(addr, mId.value())) break;
- usleep(10000);
- }
+ // TODO(b/185167543): shutdown existing connections?
+ if (!setupOneSocketClient(addr, mId.value())) return false;
}
return true;
}
bool RpcSession::setupOneSocketClient(const RpcSocketAddress& addr, int32_t id) {
- unique_fd serverFd(
- TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
- if (serverFd == -1) {
- int savedErrno = errno;
- ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
- return false;
+ for (size_t tries = 0; tries < 5; tries++) {
+ if (tries > 0) usleep(10000);
+
+ unique_fd serverFd(
+ TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ if (serverFd == -1) {
+ int savedErrno = errno;
+ ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
+ strerror(savedErrno));
+ return false;
+ }
+
+ if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
+ if (errno == ECONNRESET) {
+ ALOGW("Connection reset on %s", addr.toString().c_str());
+ continue;
+ }
+ int savedErrno = errno;
+ ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
+ strerror(savedErrno));
+ return false;
+ }
+
+ if (sizeof(id) != TEMP_FAILURE_RETRY(write(serverFd.get(), &id, sizeof(id)))) {
+ int savedErrno = errno;
+ ALOGE("Could not write id to socket at %s: %s", addr.toString().c_str(),
+ strerror(savedErrno));
+ return false;
+ }
+
+ LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
+
+ addClientConnection(std::move(serverFd));
+ return true;
}
- if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
- int savedErrno = errno;
- ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
- return false;
- }
-
- if (sizeof(id) != TEMP_FAILURE_RETRY(write(serverFd.get(), &id, sizeof(id)))) {
- int savedErrno = errno;
- ALOGE("Could not write id to socket at %s: %s", addr.toString().c_str(),
- strerror(savedErrno));
- return false;
- }
-
- LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
-
- addClient(std::move(serverFd));
- return true;
+ ALOGE("Ran out of retries to connect to %s", addr.toString().c_str());
+ return false;
}
-void RpcSession::addClient(unique_fd fd) {
+void RpcSession::addClientConnection(unique_fd fd) {
std::lock_guard<std::mutex> _l(mMutex);
sp<RpcConnection> session = sp<RpcConnection>::make();
session->fd = std::move(fd);
diff --git a/libs/binder/RpcSocketAddress.h b/libs/binder/RpcSocketAddress.h
index c6a06cf..c7ba5d9 100644
--- a/libs/binder/RpcSocketAddress.h
+++ b/libs/binder/RpcSocketAddress.h
@@ -24,9 +24,7 @@
#include <sys/types.h>
#include <sys/un.h>
-#ifdef __BIONIC__
-#include <linux/vm_sockets.h>
-#endif
+#include "vm_sockets.h"
namespace android {
@@ -59,8 +57,6 @@
sockaddr_un mAddr;
};
-#ifdef __BIONIC__
-
class VsockSocketAddress : public RpcSocketAddress {
public:
VsockSocketAddress(unsigned int cid, unsigned int port)
@@ -80,8 +76,6 @@
sockaddr_vm mAddr;
};
-#endif // __BIONIC__
-
class InetSocketAddress : public RpcSocketAddress {
public:
InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port)
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 8c9ba00..b1e5519 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -22,6 +22,7 @@
#include <utils/RefBase.h>
#include <mutex>
+#include <thread>
// WARNING: This is a feature which is still in development, and it is subject
// to radical change. Any production use of this may subject your code to any
@@ -57,12 +58,10 @@
*/
[[nodiscard]] bool setupUnixDomainServer(const char* path);
-#ifdef __BIONIC__
/**
* Creates an RPC server at the current port.
*/
[[nodiscard]] bool setupVsockServer(unsigned int port);
-#endif // __BIONIC__
/**
* Creates an RPC server at the current port using IPv4.
@@ -117,6 +116,7 @@
friend sp<RpcServer>;
RpcServer();
+ void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd);
bool setupSocketServer(const RpcSocketAddress& address);
bool mAgreedExperimental = false;
@@ -125,6 +125,7 @@
base::unique_fd mServer; // socket we are accepting sessions on
std::mutex mLock; // for below
+ std::map<std::thread::id, std::thread> mConnectingThreads;
sp<IBinder> mRootObject;
std::map<int32_t, sp<RpcSession>> mSessions;
int32_t mSessionIdCounter = 0;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index f647c95..92ee100 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -52,12 +52,10 @@
*/
[[nodiscard]] bool setupUnixDomainClient(const char* path);
-#ifdef __BIONIC__
/**
* Connects to an RPC server at the CVD & port.
*/
[[nodiscard]] bool setupVsockClient(unsigned int cvd, unsigned int port);
-#endif // __BIONIC__
/**
* Connects to an RPC server at the given address and port.
@@ -83,7 +81,7 @@
* Query the other side of the session for the maximum number of threads
* it supports (maximum number of concurrent non-nested synchronous transactions)
*/
- status_t getMaxThreads(size_t* maxThreads);
+ status_t getRemoteMaxThreads(size_t* maxThreads);
[[nodiscard]] status_t transact(const RpcAddress& address, uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -116,8 +114,7 @@
status_t readId();
- void startThread(base::unique_fd client);
- void join(base::unique_fd client);
+ void join(std::thread thread, base::unique_fd client);
void terminateLocked();
struct RpcConnection : public RefBase {
@@ -130,7 +127,7 @@
bool setupSocketClient(const RpcSocketAddress& address);
bool setupOneSocketClient(const RpcSocketAddress& address, int32_t sessionId);
- void addClient(base::unique_fd fd);
+ void addClientConnection(base::unique_fd fd);
void setForServer(const wp<RpcServer>& server, int32_t sessionId);
sp<RpcConnection> assignServerToThisThread(base::unique_fd fd);
bool removeServerConnection(const sp<RpcConnection>& connection);
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index c0f7c99..ec231b2 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -63,6 +63,9 @@
"libbinder",
"libutils",
],
+ static_libs: [
+ "libgmock",
+ ],
compile_multilib: "32",
multilib: { lib32: { suffix: "" } },
cflags: ["-DBINDER_IPC_32BIT=1"],
@@ -101,6 +104,9 @@
"libbinder",
"libutils",
],
+ static_libs: [
+ "libgmock",
+ ],
test_suites: ["device-tests", "vts"],
require_root: true,
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5676bd1..0c3fbcd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <thread>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <binder/Binder.h>
@@ -41,6 +42,13 @@
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
using namespace android;
+using testing::Not;
+
+// e.g. EXPECT_THAT(expr, StatusEq(OK)) << "additional message";
+MATCHER_P(StatusEq, expected, (negation ? "not " : "") + statusToString(expected)) {
+ *result_listener << statusToString(arg);
+ return expected == arg;
+}
static ::testing::AssertionResult IsPageAligned(void *buf) {
if (((unsigned long)buf & ((unsigned long)PAGE_SIZE - 1)) == 0)
@@ -205,19 +213,16 @@
protected:
sp<IBinder> addServerEtc(int32_t *idPtr, int code)
{
- int ret;
int32_t id;
Parcel data, reply;
sp<IBinder> binder;
- ret = m_server->transact(code, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(code, data, &reply), StatusEq(NO_ERROR));
EXPECT_FALSE(binder != nullptr);
binder = reply.readStrongBinder();
EXPECT_TRUE(binder != nullptr);
- ret = reply.readInt32(&id);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
if (idPtr)
*idPtr = id;
return binder;
@@ -401,29 +406,25 @@
};
TEST_F(BinderLibTest, NopTransaction) {
- status_t ret;
Parcel data, reply;
- ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, NopTransactionOneway) {
- status_t ret;
Parcel data, reply;
- ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, NopTransactionClear) {
- status_t ret;
Parcel data, reply;
// make sure it accepts the transaction flag
- ret = m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_CLEAR_BUF);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_CLEAR_BUF),
+ StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, Freeze) {
- status_t ret;
Parcel data, reply, replypid;
std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze");
@@ -442,9 +443,8 @@
return;
}
- ret = m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid), StatusEq(NO_ERROR));
int32_t pid = replypid.readInt32();
- EXPECT_EQ(NO_ERROR, ret);
for (int i = 0; i < 10; i++) {
EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, data, &reply, TF_ONE_WAY));
}
@@ -468,42 +468,36 @@
TEST_F(BinderLibTest, SetError) {
int32_t testValue[] = { 0, -123, 123 };
for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) {
- status_t ret;
Parcel data, reply;
data.writeInt32(testValue[i]);
- ret = m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply);
- EXPECT_EQ(testValue[i], ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_SET_ERROR_TRANSACTION, data, &reply),
+ StatusEq(testValue[i]));
}
}
TEST_F(BinderLibTest, GetId) {
- status_t ret;
int32_t id;
Parcel data, reply;
- ret = m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
- ret = reply.readInt32(&id);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GET_ID_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
+ EXPECT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(0, id);
}
TEST_F(BinderLibTest, PtrSize) {
- status_t ret;
int32_t ptrsize;
Parcel data, reply;
sp<IBinder> server = addServer();
ASSERT_TRUE(server != nullptr);
- ret = server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
- ret = reply.readInt32(&ptrsize);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
+ EXPECT_THAT(reply.readInt32(&ptrsize), StatusEq(NO_ERROR));
RecordProperty("TestPtrSize", sizeof(void *));
RecordProperty("ServerPtrSize", sizeof(void *));
}
TEST_F(BinderLibTest, IndirectGetId2)
{
- status_t ret;
int32_t id;
int32_t count;
Parcel data, reply;
@@ -521,22 +515,19 @@
datai.appendTo(&data);
}
- ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
- ret = reply.readInt32(&id);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(0, id);
- ret = reply.readInt32(&count);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR));
EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count);
for (size_t i = 0; i < (size_t)count; i++) {
BinderLibTestBundle replyi(&reply);
EXPECT_TRUE(replyi.isValid());
- ret = replyi.readInt32(&id);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(replyi.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(serverId[i], id);
EXPECT_EQ(replyi.dataSize(), replyi.dataPosition());
}
@@ -546,7 +537,6 @@
TEST_F(BinderLibTest, IndirectGetId3)
{
- status_t ret;
int32_t id;
int32_t count;
Parcel data, reply;
@@ -571,15 +561,13 @@
datai.appendTo(&data);
}
- ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
- ret = reply.readInt32(&id);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(reply.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(0, id);
- ret = reply.readInt32(&count);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(reply.readInt32(&count), StatusEq(NO_ERROR));
EXPECT_EQ(ARRAY_SIZE(serverId), (size_t)count);
for (size_t i = 0; i < (size_t)count; i++) {
@@ -587,18 +575,15 @@
BinderLibTestBundle replyi(&reply);
EXPECT_TRUE(replyi.isValid());
- ret = replyi.readInt32(&id);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(replyi.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(serverId[i], id);
- ret = replyi.readInt32(&counti);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(replyi.readInt32(&counti), StatusEq(NO_ERROR));
EXPECT_EQ(1, counti);
BinderLibTestBundle replyi2(&replyi);
EXPECT_TRUE(replyi2.isValid());
- ret = replyi2.readInt32(&id);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(replyi2.readInt32(&id), StatusEq(NO_ERROR));
EXPECT_EQ(0, id);
EXPECT_EQ(replyi2.dataSize(), replyi2.dataPosition());
@@ -610,16 +595,13 @@
TEST_F(BinderLibTest, CallBack)
{
- status_t ret;
Parcel data, reply;
sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack();
data.writeStrongBinder(callBack);
- ret = m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callBack->waitEvent(5);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callBack->getResult();
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_NOP_CALL_BACK, data, &reply, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
+ EXPECT_THAT(callBack->waitEvent(5), StatusEq(NO_ERROR));
+ EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, AddServer)
@@ -630,7 +612,6 @@
TEST_F(BinderLibTest, DeathNotificationStrongRef)
{
- status_t ret;
sp<IBinder> sbinder;
sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
@@ -638,20 +619,17 @@
{
sp<IBinder> binder = addServer();
ASSERT_TRUE(binder != nullptr);
- ret = binder->linkToDeath(testDeathRecipient);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(binder->linkToDeath(testDeathRecipient), StatusEq(NO_ERROR));
sbinder = binder;
}
{
Parcel data, reply;
- ret = sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(0, ret);
+ EXPECT_THAT(sbinder->transact(BINDER_LIB_TEST_EXIT_TRANSACTION, data, &reply, TF_ONE_WAY),
+ StatusEq(OK));
}
IPCThreadState::self()->flushCommands();
- ret = testDeathRecipient->waitEvent(5);
- EXPECT_EQ(NO_ERROR, ret);
- ret = sbinder->unlinkToDeath(testDeathRecipient);
- EXPECT_EQ(DEAD_OBJECT, ret);
+ EXPECT_THAT(testDeathRecipient->waitEvent(5), StatusEq(NO_ERROR));
+ EXPECT_THAT(sbinder->unlinkToDeath(testDeathRecipient), StatusEq(DEAD_OBJECT));
}
TEST_F(BinderLibTest, DeathNotificationMultiple)
@@ -674,8 +652,9 @@
callBack[i] = new BinderLibTestCallBack();
data.writeStrongBinder(target);
data.writeStrongBinder(callBack[i]);
- ret = linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(linkedclient[i]->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data,
+ &reply, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
}
{
Parcel data, reply;
@@ -683,8 +662,9 @@
passiveclient[i] = addServer();
ASSERT_TRUE(passiveclient[i] != nullptr);
data.writeStrongBinder(target);
- ret = passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(passiveclient[i]->transact(BINDER_LIB_TEST_ADD_STRONG_REF_TRANSACTION, data,
+ &reply, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
}
}
{
@@ -694,10 +674,8 @@
}
for (int i = 0; i < clientcount; i++) {
- ret = callBack[i]->waitEvent(5);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callBack[i]->getResult();
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(callBack[i]->waitEvent(5), StatusEq(NO_ERROR));
+ EXPECT_THAT(callBack[i]->getResult(), StatusEq(NO_ERROR));
}
}
@@ -712,8 +690,7 @@
sp<TestDeathRecipient> testDeathRecipient = new TestDeathRecipient();
- ret = target->linkToDeath(testDeathRecipient);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(target->linkToDeath(testDeathRecipient), StatusEq(NO_ERROR));
{
Parcel data, reply;
@@ -750,14 +727,13 @@
callback = new BinderLibTestCallBack();
data.writeStrongBinder(target);
data.writeStrongBinder(callback);
- ret = client->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(client->transact(BINDER_LIB_TEST_LINK_DEATH_TRANSACTION, data, &reply,
+ TF_ONE_WAY),
+ StatusEq(NO_ERROR));
}
- ret = callback->waitEvent(5);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callback->getResult();
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(callback->waitEvent(5), StatusEq(NO_ERROR));
+ EXPECT_THAT(callback->getResult(), StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, PassFile) {
@@ -773,17 +749,14 @@
Parcel data, reply;
uint8_t writebuf[1] = { write_value };
- ret = data.writeFileDescriptor(pipefd[1], true);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(data.writeFileDescriptor(pipefd[1], true), StatusEq(NO_ERROR));
- ret = data.writeInt32(sizeof(writebuf));
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(data.writeInt32(sizeof(writebuf)), StatusEq(NO_ERROR));
- ret = data.write(writebuf, sizeof(writebuf));
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(data.write(writebuf, sizeof(writebuf)), StatusEq(NO_ERROR));
- ret = m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_WRITE_FILE_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
}
ret = read(pipefd[0], buf, sizeof(buf));
@@ -864,11 +837,10 @@
}
TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
- status_t ret;
Parcel data, reply;
- ret = m_server->transact(BINDER_LIB_TEST_GET_SELF_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GET_SELF_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
const flat_binder_object *fb = reply.readObject(false);
ASSERT_TRUE(fb != nullptr);
@@ -888,8 +860,8 @@
wp<IBinder> keepFreedBinder;
{
Parcel data, reply;
- ret = server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply);
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_THAT(server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
struct flat_binder_object *freed = (struct flat_binder_object *)(reply.data());
freedHandle = freed->handle;
/* Add a weak ref to the freed binder so the driver does not
@@ -950,7 +922,6 @@
}
TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) {
- status_t ret;
Parcel data, reply;
sp<BinderLibTestCallBack> callBack = new BinderLibTestCallBack();
for (int i = 0; i < 2; i++) {
@@ -964,13 +935,12 @@
datai.appendTo(&data);
}
- ret = m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_INDIRECT_TRANSACTION, data, &reply),
+ StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, OnewayQueueing)
{
- status_t ret;
Parcel data, data2;
sp<IBinder> pollServer = addPollServer();
@@ -983,25 +953,21 @@
data2.writeStrongBinder(callBack2);
data2.writeInt32(0); // delay in us
- ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, nullptr, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data, nullptr, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
// The delay ensures that this second transaction will end up on the async_todo list
// (for a single-threaded server)
- ret = pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, nullptr, TF_ONE_WAY);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(pollServer->transact(BINDER_LIB_TEST_DELAYED_CALL_BACK, data2, nullptr, TF_ONE_WAY),
+ StatusEq(NO_ERROR));
// The server will ensure that the two transactions are handled in the expected order;
// If the ordering is not as expected, an error will be returned through the callbacks.
- ret = callBack->waitEvent(2);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callBack->getResult();
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(callBack->waitEvent(2), StatusEq(NO_ERROR));
+ EXPECT_THAT(callBack->getResult(), StatusEq(NO_ERROR));
- ret = callBack2->waitEvent(2);
- EXPECT_EQ(NO_ERROR, ret);
- ret = callBack2->getResult();
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(callBack2->waitEvent(2), StatusEq(NO_ERROR));
+ EXPECT_THAT(callBack2->getResult(), StatusEq(NO_ERROR));
}
TEST_F(BinderLibTest, WorkSourceUnsetByDefault)
@@ -1120,8 +1086,8 @@
ASSERT_TRUE(server != nullptr);
Parcel data, reply;
- status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply),
+ StatusEq(NO_ERROR));
int policy = reply.readInt32();
int priority = reply.readInt32();
@@ -1140,8 +1106,8 @@
EXPECT_EQ(0, sched_setscheduler(getpid(), SCHED_RR, ¶m));
Parcel data, reply;
- status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply),
+ StatusEq(NO_ERROR));
int policy = reply.readInt32();
int priority = reply.readInt32();
@@ -1158,10 +1124,9 @@
std::vector<uint64_t> const testValue = { std::numeric_limits<uint64_t>::max(), 0, 200 };
data.writeUint64Vector(testValue);
- status_t ret = server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply);
- EXPECT_EQ(NO_ERROR, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply), StatusEq(NO_ERROR));
std::vector<uint64_t> readValue;
- ret = reply.readUint64Vector(&readValue);
+ EXPECT_THAT(reply.readUint64Vector(&readValue), StatusEq(OK));
EXPECT_EQ(readValue, testValue);
}
@@ -1186,19 +1151,18 @@
memcpy(parcelData, &obj, sizeof(obj));
data.setDataSize(sizeof(obj));
- status_t ret = server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply);
// Either the kernel should reject this transaction (if it's correct), but
// if it's not, the server implementation should return an error if it
// finds an object in the received Parcel.
- EXPECT_NE(NO_ERROR, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply),
+ Not(StatusEq(NO_ERROR)));
}
TEST_F(BinderLibTest, GotSid) {
sp<IBinder> server = addServer();
Parcel data;
- status_t ret = server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr);
- EXPECT_EQ(OK, ret);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK));
}
class BinderLibTestService : public BBinder
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 8d10727..b3ce744 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -34,14 +34,11 @@
#include <iostream>
#include <thread>
-#ifdef __BIONIC__
-#include <linux/vm_sockets.h>
-#endif //__BIONIC__
-
#include <sys/prctl.h>
#include <unistd.h>
-#include "../RpcState.h" // for debugging
+#include "../RpcState.h" // for debugging
+#include "../vm_sockets.h" // for VMADDR_*
namespace android {
@@ -291,19 +288,15 @@
enum class SocketType {
UNIX,
-#ifdef __BIONIC__
VSOCK,
-#endif // __BIONIC__
INET,
};
static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
switch (info.param) {
case SocketType::UNIX:
return "unix_domain_socket";
-#ifdef __BIONIC__
case SocketType::VSOCK:
return "vm_socket";
-#endif // __BIONIC__
case SocketType::INET:
return "inet_socket";
default:
@@ -334,59 +327,53 @@
server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
server->setMaxThreads(numThreads);
+ unsigned int outPort = 0;
+
switch (socketType) {
case SocketType::UNIX:
CHECK(server->setupUnixDomainServer(addr.c_str())) << addr;
break;
-#ifdef __BIONIC__
case SocketType::VSOCK:
CHECK(server->setupVsockServer(vsockPort));
break;
-#endif // __BIONIC__
case SocketType::INET: {
- unsigned int outPort = 0;
CHECK(server->setupInetServer(0, &outPort));
CHECK_NE(0, outPort);
- CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort,
- sizeof(outPort)));
break;
}
default:
LOG_ALWAYS_FATAL("Unknown socket type");
}
+ CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort, sizeof(outPort)));
+
configure(server);
server->join();
}),
};
- unsigned int inetPort = 0;
+ // always read socket, so that we have waited for the server to start
+ unsigned int outPort = 0;
+ CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &outPort, sizeof(outPort)));
if (socketType == SocketType::INET) {
- CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &inetPort,
- sizeof(inetPort)));
- CHECK_NE(0, inetPort);
+ CHECK_NE(0, outPort);
}
for (size_t i = 0; i < numSessions; i++) {
sp<RpcSession> session = RpcSession::make();
- for (size_t tries = 0; tries < 10; tries++) {
- usleep(10000);
- switch (socketType) {
- case SocketType::UNIX:
- if (session->setupUnixDomainClient(addr.c_str())) goto success;
- break;
-#ifdef __BIONIC__
- case SocketType::VSOCK:
- if (session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort)) goto success;
- break;
-#endif // __BIONIC__
- case SocketType::INET:
- if (session->setupInetClient("127.0.0.1", inetPort)) goto success;
- break;
- default:
- LOG_ALWAYS_FATAL("Unknown socket type");
- }
+ switch (socketType) {
+ case SocketType::UNIX:
+ if (session->setupUnixDomainClient(addr.c_str())) goto success;
+ break;
+ case SocketType::VSOCK:
+ if (session->setupVsockClient(VMADDR_CID_LOCAL, vsockPort)) goto success;
+ break;
+ case SocketType::INET:
+ if (session->setupInetClient("127.0.0.1", outPort)) goto success;
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Unknown socket type");
}
LOG_ALWAYS_FATAL("Could not connect");
success:
@@ -934,9 +921,10 @@
INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
::testing::ValuesIn({
SocketType::UNIX,
+// TODO(b/185269356): working on host
#ifdef __BIONIC__
SocketType::VSOCK,
-#endif // __BIONIC__
+#endif
SocketType::INET,
}),
PrintSocketType);
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
similarity index 100%
rename from libs/binder/parcel_fuzzer/Android.bp
rename to libs/binder/tests/parcel_fuzzer/Android.bp
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.cpp
rename to libs/binder/tests/parcel_fuzzer/binder.cpp
diff --git a/libs/binder/parcel_fuzzer/binder.h b/libs/binder/tests/parcel_fuzzer/binder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.h
rename to libs/binder/tests/parcel_fuzzer/binder.h
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder_ndk.cpp
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
similarity index 97%
rename from libs/binder/parcel_fuzzer/binder_ndk.h
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.h
index e69d9c1..cf24ab9 100644
--- a/libs/binder/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -23,7 +23,7 @@
// libbinder_ndk doesn't export this header which breaks down its API for NDK
// and APEX users, but we need access to it to fuzz.
-#include "../ndk/parcel_internal.h"
+#include "../../ndk/parcel_internal.h"
class NdkParcelAdapter {
public:
diff --git a/libs/binder/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.cpp
rename to libs/binder/tests/parcel_fuzzer/hwbinder.cpp
diff --git a/libs/binder/parcel_fuzzer/hwbinder.h b/libs/binder/tests/parcel_fuzzer/hwbinder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.h
rename to libs/binder/tests/parcel_fuzzer/hwbinder.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
diff --git a/libs/binder/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/main.cpp
rename to libs/binder/tests/parcel_fuzzer/main.cpp
diff --git a/libs/binder/parcel_fuzzer/parcel_fuzzer.h b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/parcel_fuzzer.h
rename to libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
diff --git a/libs/binder/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/random_fd.cpp
rename to libs/binder/tests/parcel_fuzzer/random_fd.cpp
diff --git a/libs/binder/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/random_parcel.cpp
rename to libs/binder/tests/parcel_fuzzer/random_parcel.cpp
diff --git a/libs/binder/parcel_fuzzer/util.cpp b/libs/binder/tests/parcel_fuzzer/util.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.cpp
rename to libs/binder/tests/parcel_fuzzer/util.cpp
diff --git a/libs/binder/parcel_fuzzer/util.h b/libs/binder/tests/parcel_fuzzer/util.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.h
rename to libs/binder/tests/parcel_fuzzer/util.h
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
similarity index 100%
rename from libs/binder/tests/fuzzers/Android.bp
rename to libs/binder/tests/unit_fuzzers/Android.bp
diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp b/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/TextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
similarity index 100%
rename from libs/binder/tests/fuzzers/commonFuzzHelpers.h
rename to libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
diff --git a/libs/binder/vm_sockets.h b/libs/binder/vm_sockets.h
new file mode 100644
index 0000000..7d9732b
--- /dev/null
+++ b/libs/binder/vm_sockets.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** Copied and modified from bionic/libc/kernel/uapi/linux/vm_sockets.h
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#pragma once
+
+#ifdef __BIONIC__
+#include <linux/vm_sockets.h>
+#else
+
+#ifndef _UAPI_VM_SOCKETS_H
+#define _UAPI_VM_SOCKETS_H
+#define SO_VM_SOCKETS_BUFFER_SIZE 0
+#define SO_VM_SOCKETS_BUFFER_MIN_SIZE 1
+#define SO_VM_SOCKETS_BUFFER_MAX_SIZE 2
+#define SO_VM_SOCKETS_PEER_HOST_VM_ID 3
+#define SO_VM_SOCKETS_TRUSTED 5
+#define SO_VM_SOCKETS_CONNECT_TIMEOUT 6
+#define SO_VM_SOCKETS_NONBLOCK_TXRX 7
+#define VMADDR_CID_ANY (-1U)
+#define VMADDR_PORT_ANY (-1U)
+#define VMADDR_CID_HYPERVISOR 0
+#define VMADDR_CID_LOCAL 1
+#define VMADDR_CID_HOST 2
+#define VM_SOCKETS_INVALID_VERSION (-1U)
+#define VM_SOCKETS_VERSION_EPOCH(_v) (((_v)&0xFF000000) >> 24)
+#define VM_SOCKETS_VERSION_MAJOR(_v) (((_v)&0x00FF0000) >> 16)
+#define VM_SOCKETS_VERSION_MINOR(_v) (((_v)&0x0000FFFF))
+struct sockaddr_vm {
+ sa_family_t svm_family;
+ // NOLINTNEXTLINE(google-runtime-int)
+ unsigned short svm_reserved1;
+ unsigned int svm_port;
+ unsigned int svm_cid;
+ // NOLINTNEXTLINE(google-runtime-int)
+ unsigned char svm_zero[sizeof(struct sockaddr) - sizeof(sa_family_t) - sizeof(unsigned short) -
+ sizeof(unsigned int) - sizeof(unsigned int)];
+};
+#define IOCTL_VM_SOCKETS_GET_LOCAL_CID _IO(7, 0xb9)
+#ifndef AF_VSOCK
+#define AF_VSOCK 40
+#endif
+#endif
+
+#endif
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 37fb844..08800f7 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -213,7 +213,8 @@
// for this is the scale is calculated based on the requested size and buffer size.
// If there's no buffer, the scale will always be 1.
if (mLastBufferInfo.hasBuffer) {
- setMatrix(&t, mLastBufferInfo);
+ t.setDestinationFrame(mSurfaceControl,
+ Rect(0, 0, newSize.getWidth(), newSize.getHeight()));
}
applyTransaction = true;
}
@@ -416,8 +417,8 @@
t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
- setMatrix(t, mLastBufferInfo);
- t->setCrop(mSurfaceControl, crop);
+ t->setDestinationFrame(mSurfaceControl, Rect(0, 0, mSize.getWidth(), mSize.getHeight()));
+ t->setBufferCrop(mSurfaceControl, crop);
t->setTransform(mSurfaceControl, bufferItem.mTransform);
t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
if (!bufferItem.mIsAutoTimestamp) {
@@ -543,19 +544,6 @@
return mSize != bufferSize;
}
-void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t,
- const BufferInfo& bufferInfo) {
- uint32_t bufWidth = bufferInfo.crop.getWidth();
- uint32_t bufHeight = bufferInfo.crop.getHeight();
-
- float sx = mSize.width / static_cast<float>(bufWidth);
- float sy = mSize.height / static_cast<float>(bufHeight);
-
- t->setMatrix(mSurfaceControl, sx, 0, 0, sy);
- // Update position based on crop.
- t->setPosition(mSurfaceControl, bufferInfo.crop.left * sx * -1, bufferInfo.crop.top * sy * -1);
-}
-
void BLASTBufferQueue::setTransactionCompleteCallback(
uint64_t frameNumber, std::function<void(int64_t)>&& transactionCompleteCallback) {
std::lock_guard _lock{mMutex};
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 267db76..e65c721 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -64,6 +64,8 @@
fixedTransformHint(ui::Transform::ROT_INVALID),
frameNumber(0),
autoRefresh(false),
+ bufferCrop(Rect::INVALID_RECT),
+ destinationFrame(Rect::INVALID_RECT),
releaseBufferListener(nullptr) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -167,6 +169,7 @@
SAFE_PARCEL(output.write, stretchEffect);
SAFE_PARCEL(output.write, bufferCrop);
+ SAFE_PARCEL(output.write, destinationFrame);
return NO_ERROR;
}
@@ -296,6 +299,7 @@
SAFE_PARCEL(input.read, stretchEffect);
SAFE_PARCEL(input.read, bufferCrop);
+ SAFE_PARCEL(input.read, destinationFrame);
return NO_ERROR;
}
@@ -543,6 +547,10 @@
what |= eBufferCropChanged;
bufferCrop = other.bufferCrop;
}
+ if (other.what & eDestinationFrameChanged) {
+ what |= eDestinationFrameChanged;
+ destinationFrame = other.destinationFrame;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIu64 " what=0x%" PRIu64,
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 11b8eba..aa93808 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1675,6 +1675,21 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDestinationFrame(
+ const sp<SurfaceControl>& sc, const Rect& destinationFrame) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eDestinationFrameChanged;
+ s->destinationFrame = destinationFrame;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 3947f22..16430b3 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -104,7 +104,7 @@
eHasListenerCallbacksChanged = 0x20000000,
eInputInfoChanged = 0x40000000,
eCornerRadiusChanged = 0x80000000,
- /* was eFrameChanged, now available 0x1'00000000, */
+ eDestinationFrameChanged = 0x1'00000000,
eCachedBufferChanged = 0x2'00000000,
eBackgroundColorChanged = 0x4'00000000,
eMetadataChanged = 0x8'00000000,
@@ -228,6 +228,7 @@
StretchEffect stretchEffect;
Rect bufferCrop;
+ Rect destinationFrame;
// Listens to when the buffer is safe to be released. This is used for blast
// layers only. The callback includes a release fence as well as the graphic
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 35757be..0940e9d 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -554,6 +554,8 @@
const StretchEffect& stretchEffect);
Transaction& setBufferCrop(const sp<SurfaceControl>& sc, const Rect& bufferCrop);
+ Transaction& setDestinationFrame(const sp<SurfaceControl>& sc,
+ const Rect& destinationFrame);
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 446c913..8bc877f 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4747,6 +4747,40 @@
return true;
}
+// Binder call
+bool InputDispatcher::transferTouch(const sp<IBinder>& destChannelToken) {
+ sp<IBinder> fromToken;
+ { // acquire lock
+ std::scoped_lock _l(mLock);
+
+ sp<InputWindowHandle> toWindowHandle = getWindowHandleLocked(destChannelToken);
+ if (toWindowHandle == nullptr) {
+ ALOGW("Could not find window associated with token=%p", destChannelToken.get());
+ return false;
+ }
+
+ const int32_t displayId = toWindowHandle->getInfo()->displayId;
+
+ auto touchStateIt = mTouchStatesByDisplay.find(displayId);
+ if (touchStateIt == mTouchStatesByDisplay.end()) {
+ ALOGD("Could not transfer touch because the display %" PRId32 " is not being touched",
+ displayId);
+ return false;
+ }
+
+ TouchState& state = touchStateIt->second;
+ if (state.windows.size() != 1) {
+ ALOGW("Cannot transfer touch state because there are %zu windows being touched",
+ state.windows.size());
+ return false;
+ }
+ const TouchedWindow& touchedWindow = state.windows[0];
+ fromToken = touchedWindow.windowHandle->getToken();
+ } // release lock
+
+ return transferTouchFocus(fromToken, destChannelToken);
+}
+
void InputDispatcher::resetAndDropEverythingLocked(const char* reason) {
if (DEBUG_FOCUS) {
ALOGD("Resetting and dropping all events (%s).", reason);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 7ba03e8..6edc5f1 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -81,60 +81,60 @@
*/
class InputDispatcher : public android::InputDispatcherInterface {
protected:
- virtual ~InputDispatcher();
+ ~InputDispatcher() override;
public:
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
- virtual void dump(std::string& dump) override;
- virtual void monitor() override;
- virtual bool waitForIdle() override;
- virtual status_t start() override;
- virtual status_t stop() override;
+ void dump(std::string& dump) override;
+ void monitor() override;
+ bool waitForIdle() override;
+ status_t start() override;
+ status_t stop() override;
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
- virtual void notifyKey(const NotifyKeyArgs* args) override;
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
- virtual void notifySensor(const NotifySensorArgs* args) override;
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
- virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
+ void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
+ void notifyKey(const NotifyKeyArgs* args) override;
+ void notifyMotion(const NotifyMotionArgs* args) override;
+ void notifySwitch(const NotifySwitchArgs* args) override;
+ void notifySensor(const NotifySensorArgs* args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+ void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
- virtual android::os::InputEventInjectionResult injectInputEvent(
+ android::os::InputEventInjectionResult injectInputEvent(
const InputEvent* event, int32_t injectorPid, int32_t injectorUid,
android::os::InputEventInjectionSync syncMode, std::chrono::milliseconds timeout,
uint32_t policyFlags) override;
- virtual std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
+ std::unique_ptr<VerifiedInputEvent> verifyInputEvent(const InputEvent& event) override;
- virtual void setInputWindows(
- const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>&
- handlesPerDisplay) override;
- virtual void setFocusedApplication(
+ void setInputWindows(const std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>&
+ handlesPerDisplay) override;
+ void setFocusedApplication(
int32_t displayId,
const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) override;
- virtual void setFocusedDisplay(int32_t displayId) override;
- virtual void setInputDispatchMode(bool enabled, bool frozen) override;
- virtual void setInputFilterEnabled(bool enabled) override;
- virtual void setInTouchMode(bool inTouchMode) override;
- virtual void setMaximumObscuringOpacityForTouch(float opacity) override;
- virtual void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override;
+ void setFocusedDisplay(int32_t displayId) override;
+ void setInputDispatchMode(bool enabled, bool frozen) override;
+ void setInputFilterEnabled(bool enabled) override;
+ void setInTouchMode(bool inTouchMode) override;
+ void setMaximumObscuringOpacityForTouch(float opacity) override;
+ void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override;
- virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
- bool isDragDrop = false) override;
+ bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
+ bool isDragDrop = false) override;
+ bool transferTouch(const sp<IBinder>& destChannelToken) override;
- virtual base::Result<std::unique_ptr<InputChannel>> createInputChannel(
+ base::Result<std::unique_ptr<InputChannel>> createInputChannel(
const std::string& name) override;
- virtual void setFocusedWindow(const FocusRequest&) override;
- virtual base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId,
- bool isGestureMonitor,
- const std::string& name,
- int32_t pid) override;
- virtual status_t removeInputChannel(const sp<IBinder>& connectionToken) override;
- virtual status_t pilferPointers(const sp<IBinder>& token) override;
- virtual void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) override;
- virtual bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override;
+ void setFocusedWindow(const FocusRequest&) override;
+ base::Result<std::unique_ptr<InputChannel>> createInputMonitor(int32_t displayId,
+ bool isGestureMonitor,
+ const std::string& name,
+ int32_t pid) override;
+ status_t removeInputChannel(const sp<IBinder>& connectionToken) override;
+ status_t pilferPointers(const sp<IBinder>& token) override;
+ void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) override;
+ bool flushSensor(int deviceId, InputDeviceSensorType sensorType) override;
std::array<uint8_t, 32> sign(const VerifiedInputEvent& event) const;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index b601dfc..7f85e53 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -151,6 +151,14 @@
*/
virtual bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
bool isDragDrop) = 0;
+
+ /**
+ * Transfer touch focus to the provided channel, no matter where the current touch is.
+ *
+ * Return true on success, false if there was no on-going touch.
+ */
+ virtual bool transferTouch(const sp<IBinder>& destChannelToken) = 0;
+
/**
* Sets focus on the specified window.
*/
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index bbf51f6..855453e 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1714,7 +1714,13 @@
0 /*expectedFlags*/);
}
-TEST_F(InputDispatcherTest, TransferTouchFocus_OnePointer) {
+using TransferFunction =
+ std::function<bool(sp<InputDispatcher> dispatcher, sp<IBinder>, sp<IBinder>)>;
+
+class TransferTouchFixture : public InputDispatcherTest,
+ public ::testing::WithParamInterface<TransferFunction> {};
+
+TEST_P(TransferTouchFixture, TransferTouch_OnePointer) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
// Create a couple of windows
@@ -1735,8 +1741,10 @@
firstWindow->consumeMotionDown();
secondWindow->assertNoEvents();
- // Transfer touch focus to the second window
- mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
+ // Transfer touch to the second window
+ TransferFunction f = GetParam();
+ const bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
+ ASSERT_TRUE(success);
// The first window gets cancel and the second gets down
firstWindow->consumeMotionCancel();
secondWindow->consumeMotionDown();
@@ -1751,7 +1759,7 @@
secondWindow->consumeMotionUp();
}
-TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointerNoSplitTouch) {
+TEST_P(TransferTouchFixture, TransferTouch_TwoPointersNonSplitTouch) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
PointF touchPoint = {10, 10};
@@ -1786,7 +1794,9 @@
secondWindow->assertNoEvents();
// Transfer touch focus to the second window
- mDispatcher->transferTouchFocus(firstWindow->getToken(), secondWindow->getToken());
+ TransferFunction f = GetParam();
+ bool success = f(mDispatcher, firstWindow->getToken(), secondWindow->getToken());
+ ASSERT_TRUE(success);
// The first window gets cancel and the second gets down and pointer down
firstWindow->consumeMotionCancel();
secondWindow->consumeMotionDown();
@@ -1813,6 +1823,21 @@
secondWindow->consumeMotionUp();
}
+// For the cases of single pointer touch and two pointers non-split touch, the api's
+// 'transferTouch' and 'transferTouchFocus' are equivalent in behaviour. They only differ
+// for the case where there are multiple pointers split across several windows.
+INSTANTIATE_TEST_SUITE_P(TransferFunctionTests, TransferTouchFixture,
+ ::testing::Values(
+ [&](sp<InputDispatcher> dispatcher, sp<IBinder> /*ignored*/,
+ sp<IBinder> destChannelToken) {
+ return dispatcher->transferTouch(destChannelToken);
+ },
+ [&](sp<InputDispatcher> dispatcher, sp<IBinder> from,
+ sp<IBinder> to) {
+ return dispatcher->transferTouchFocus(from, to,
+ false /*isDragAndDrop*/);
+ }));
+
TEST_F(InputDispatcherTest, TransferTouchFocus_TwoPointersSplitTouch) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
@@ -1883,6 +1908,82 @@
secondWindow->consumeMotionUp();
}
+// Same as TransferTouchFocus_TwoPointersSplitTouch, but using 'transferTouch' api.
+// Unlike 'transferTouchFocus', calling 'transferTouch' when there are two windows receiving
+// touch is not supported, so the touch should continue on those windows and the transferred-to
+// window should get nothing.
+TEST_F(InputDispatcherTest, TransferTouch_TwoPointersSplitTouch) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> firstWindow =
+ new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
+ firstWindow->setFrame(Rect(0, 0, 600, 400));
+ firstWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
+
+ // Create a non touch modal window that supports split touch
+ sp<FakeWindowHandle> secondWindow =
+ new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
+ secondWindow->setFrame(Rect(0, 400, 600, 800));
+ secondWindow->setFlags(InputWindowInfo::Flag::NOT_TOUCH_MODAL |
+ InputWindowInfo::Flag::SPLIT_TOUCH);
+
+ // Add the windows to the dispatcher
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {firstWindow, secondWindow}}});
+
+ PointF pointInFirst = {300, 200};
+ PointF pointInSecond = {300, 600};
+
+ // Send down to the first window
+ NotifyMotionArgs firstDownMotionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, {pointInFirst});
+ mDispatcher->notifyMotion(&firstDownMotionArgs);
+ // Only the first window should get the down event
+ firstWindow->consumeMotionDown();
+ secondWindow->assertNoEvents();
+
+ // Send down to the second window
+ NotifyMotionArgs secondDownMotionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_DOWN |
+ (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond});
+ mDispatcher->notifyMotion(&secondDownMotionArgs);
+ // The first window gets a move and the second a down
+ firstWindow->consumeMotionMove();
+ secondWindow->consumeMotionDown();
+
+ // Transfer touch focus to the second window
+ const bool transferred = mDispatcher->transferTouch(secondWindow->getToken());
+ // The 'transferTouch' call should not succeed, because there are 2 touched windows
+ ASSERT_FALSE(transferred);
+ firstWindow->assertNoEvents();
+ secondWindow->assertNoEvents();
+
+ // The rest of the dispatch should proceed as normal
+ // Send pointer up to the second window
+ NotifyMotionArgs pointerUpMotionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_POINTER_UP |
+ (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {pointInFirst, pointInSecond});
+ mDispatcher->notifyMotion(&pointerUpMotionArgs);
+ // The first window gets MOVE and the second gets pointer up
+ firstWindow->consumeMotionMove();
+ secondWindow->consumeMotionUp();
+
+ // Send up event to the first window
+ NotifyMotionArgs upMotionArgs =
+ generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT);
+ mDispatcher->notifyMotion(&upMotionArgs);
+ // The first window gets nothing and the second gets up
+ firstWindow->consumeMotionUp();
+ secondWindow->assertNoEvents();
+}
+
TEST_F(InputDispatcherTest, FocusedWindow_ReceivesFocusEventAndKeyEvent) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> window =
diff --git a/services/stats/android.frameworks.stats@1.0-service.xml b/services/stats/android.frameworks.stats@1.0-service.xml
index 5fd361c..c564b7b 100644
--- a/services/stats/android.frameworks.stats@1.0-service.xml
+++ b/services/stats/android.frameworks.stats@1.0-service.xml
@@ -1,5 +1,5 @@
<manifest version="1.0" type="framework">
- <hal>
+ <hal max-level="5">
<name>android.frameworks.stats</name>
<transport>hwbinder</transport>
<version>1.0</version>
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 24b3599..fcf8299 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -295,12 +295,72 @@
return true;
}
+bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) {
+ if (mCurrentState.destinationFrame == destinationFrame) return false;
+
+ mCurrentState.sequence++;
+ mCurrentState.destinationFrame = destinationFrame;
+
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+// Translate destination frame into scale and position. If a destination frame is not set, use the
+// provided scale and position
+void BufferStateLayer::updateGeometry() {
+ if (mCurrentState.destinationFrame.isEmpty()) {
+ // If destination frame is not set, use the requested transform set via
+ // BufferStateLayer::setPosition and BufferStateLayer::setMatrix.
+ mCurrentState.transform = mRequestedTransform;
+ return;
+ }
+
+ Rect destRect = mCurrentState.destinationFrame;
+ int32_t destW = destRect.width();
+ int32_t destH = destRect.height();
+ if (destRect.left < 0) {
+ destRect.left = 0;
+ destRect.right = destW;
+ }
+ if (destRect.top < 0) {
+ destRect.top = 0;
+ destRect.bottom = destH;
+ }
+
+ if (!mCurrentState.buffer) {
+ ui::Transform t;
+ t.set(destRect.left, destRect.top);
+ mCurrentState.transform = t;
+ return;
+ }
+
+ uint32_t bufferWidth = mCurrentState.buffer->getBuffer()->getWidth();
+ uint32_t bufferHeight = mCurrentState.buffer->getBuffer()->getHeight();
+ // Undo any transformations on the buffer.
+ if (mCurrentState.bufferTransform & ui::Transform::ROT_90) {
+ std::swap(bufferWidth, bufferHeight);
+ }
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ if (mCurrentState.transformToDisplayInverse) {
+ if (invTransform & ui::Transform::ROT_90) {
+ std::swap(bufferWidth, bufferHeight);
+ }
+ }
+
+ float sx = destW / static_cast<float>(bufferWidth);
+ float sy = destH / static_cast<float>(bufferHeight);
+ ui::Transform t;
+ t.set(sx, 0, 0, sy);
+ t.set(destRect.left, destRect.top);
+ mCurrentState.transform = t;
+ return;
+}
+
bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
bool allowNonRectPreservingTransforms) {
- if (mCurrentState.transform.dsdx() == matrix.dsdx &&
- mCurrentState.transform.dtdy() == matrix.dtdy &&
- mCurrentState.transform.dtdx() == matrix.dtdx &&
- mCurrentState.transform.dsdy() == matrix.dsdy) {
+ if (mRequestedTransform.dsdx() == matrix.dsdx && mRequestedTransform.dtdy() == matrix.dtdy &&
+ mRequestedTransform.dtdx() == matrix.dtdx && mRequestedTransform.dsdy() == matrix.dsdy) {
return false;
}
@@ -313,7 +373,7 @@
return false;
}
- mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+ mRequestedTransform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
mCurrentState.sequence++;
mCurrentState.modified = true;
@@ -323,11 +383,11 @@
}
bool BufferStateLayer::setPosition(float x, float y) {
- if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) {
+ if (mRequestedTransform.tx() == x && mRequestedTransform.ty() == y) {
return false;
}
- mCurrentState.transform.set(x, y);
+ mRequestedTransform.set(x, y);
mCurrentState.sequence++;
mCurrentState.modified = true;
@@ -523,35 +583,35 @@
Rect BufferStateLayer::getBufferSize(const State& s) const {
// for buffer state layers we use the display frame size as the buffer size.
- if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
- return Rect(getActiveWidth(s), getActiveHeight(s));
- }
if (mBufferInfo.mBuffer == nullptr) {
return Rect::INVALID_RECT;
}
- // if the display frame is not defined, use the parent bounds as the buffer size.
- const auto& p = mDrawingParent.promote();
- if (p != nullptr) {
- Rect parentBounds = Rect(p->getBounds(Region()));
- if (!parentBounds.isEmpty()) {
- return parentBounds;
+ uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+
+ // Undo any transformations on the buffer and return the result.
+ if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
+ std::swap(bufWidth, bufHeight);
+ }
+
+ if (getTransformToDisplayInverse()) {
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
+ if (invTransform & ui::Transform::ROT_90) {
+ std::swap(bufWidth, bufHeight);
}
}
- return Rect::INVALID_RECT;
+ return Rect(0, 0, bufWidth, bufHeight);
}
FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const {
- const State& s(getDrawingState());
- // for buffer state layers we use the display frame size as the buffer size.
- if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
- return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s));
+ if (mBufferInfo.mBuffer == nullptr) {
+ return parentBounds;
}
- // if the display frame is not defined, use the parent bounds as the buffer size.
- return parentBounds;
+ return getBufferSize(getDrawingState()).toFloatRect();
}
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index a273230..2e48452 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -86,6 +86,8 @@
void setAutoRefresh(bool autoRefresh) override;
bool setBufferCrop(const Rect& bufferCrop) override;
+ bool setDestinationFrame(const Rect& destinationFrame) override;
+ void updateGeometry() override;
// -----------------------------------------------------------------------
@@ -178,6 +180,10 @@
// - If the integer decreases in setBuffer or doTransaction, a buffer was dropped
std::atomic<int32_t> mPendingBufferTransactions{0};
+ // Contains requested position and matrix updates. This will be applied if the client does
+ // not specify a destination frame.
+ ui::Transform mRequestedTransform;
+
// TODO(marissaw): support sticky transform for LEGACY camera mode
class HwcSlotGenerator : public ClientCache::ErasedRecipient {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 8692ee6..da8c080 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -268,8 +268,9 @@
StringAppendF(&result, "+ %s\n", getDebugName().c_str());
StringAppendF(&result, " powerMode=%s (%d)\n", to_string(mPowerMode).c_str(),
static_cast<int32_t>(mPowerMode));
+ const auto activeMode = getActiveMode();
StringAppendF(&result, " activeMode=%s\n",
- mSupportedModes.size() ? to_string(*getActiveMode()).c_str() : "none");
+ activeMode ? to_string(*activeMode).c_str() : "none");
result.append(" supportedModes=\n");
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 21c9d74..def2711 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -133,6 +133,7 @@
mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
mCurrentState.frameTimelineInfo = {};
mCurrentState.postTime = -1;
+ mCurrentState.destinationFrame.makeInvalid();
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -315,55 +316,6 @@
return reduce(mBounds, activeTransparentRegion);
}
-ui::Transform Layer::getBufferScaleTransform() const {
- // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g.
- // it isFixedSize) then there may be additional scaling not accounted
- // for in the layer transform.
- if (!isFixedSize() || getBuffer() == nullptr) {
- return {};
- }
-
- // If the layer is a buffer state layer, the active width and height
- // could be infinite. In that case, return the effective transform.
- const uint32_t activeWidth = getActiveWidth(getDrawingState());
- const uint32_t activeHeight = getActiveHeight(getDrawingState());
- if (activeWidth >= UINT32_MAX && activeHeight >= UINT32_MAX) {
- return {};
- }
-
- int bufferWidth = getBuffer()->getWidth();
- int bufferHeight = getBuffer()->getHeight();
-
- if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- std::swap(bufferWidth, bufferHeight);
- }
-
- float sx = activeWidth / static_cast<float>(bufferWidth);
- float sy = activeHeight / static_cast<float>(bufferHeight);
-
- ui::Transform extraParentScaling;
- extraParentScaling.set(sx, 0, 0, sy);
- return extraParentScaling;
-}
-
-ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const {
- // We need to mirror this scaling to child surfaces or we will break the contract where WM can
- // treat child surfaces as pixels in the parent surface.
- if (!isFixedSize() || getBuffer() == nullptr) {
- return mEffectiveTransform;
- }
- return mEffectiveTransform * bufferScaleTransform;
-}
-
-FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const {
- // We need the pre scaled layer bounds when computing child bounds to make sure the child is
- // cropped to its parent layer after any buffer transform scaling is applied.
- if (!isFixedSize() || getBuffer() == nullptr) {
- return mBounds;
- }
- return bufferScaleTransform.inverse().transform(mBounds);
-}
-
void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform,
float parentShadowRadius) {
const State& s(getDrawingState());
@@ -400,11 +352,8 @@
// don't pass it to its children.
const float childShadowRadius = canDrawShadows() ? 0.f : mEffectiveShadowRadius;
- // Add any buffer scaling to the layer's children.
- ui::Transform bufferScaleTransform = getBufferScaleTransform();
for (const sp<Layer>& child : mDrawingChildren) {
- child->computeBounds(getBoundsPreScaling(bufferScaleTransform),
- getTransformWithScale(bufferScaleTransform), childShadowRadius);
+ child->computeBounds(mBounds, mEffectiveTransform, childShadowRadius);
}
}
@@ -858,6 +807,11 @@
const State& s(getDrawingState());
State& c(getCurrentState());
+ // Translates dest frame into scale and position updates. This helps align geometry calculations
+ // for BufferStateLayer with other layers. This should ideally happen in the client once client
+ // has the display orientation details from WM.
+ updateGeometry();
+
if (c.width != s.width || c.height != s.height || !(c.transform == s.transform)) {
// invalidate and recompute the visible regions if needed
flags |= Layer::eVisibleRegion;
@@ -1768,8 +1722,7 @@
void Layer::setChildrenDrawingParent(const sp<Layer>& newParent) {
for (const sp<Layer>& child : mDrawingChildren) {
child->mDrawingParent = newParent;
- child->computeBounds(newParent->mBounds,
- newParent->getTransformWithScale(newParent->getBufferScaleTransform()),
+ child->computeBounds(newParent->mBounds, newParent->mEffectiveTransform,
newParent->mEffectiveShadowRadius);
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 284adbd..ad4166b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -276,6 +276,7 @@
StretchEffect stretchEffect;
Rect bufferCrop;
+ Rect destinationFrame;
};
/*
@@ -646,16 +647,6 @@
// Compute bounds for the layer and cache the results.
void computeBounds(FloatRect parentBounds, ui::Transform parentTransform, float shadowRadius);
- // Returns the buffer scale transform if a scaling mode is set.
- ui::Transform getBufferScaleTransform() const;
-
- // Get effective layer transform, taking into account all its parent transform with any
- // scaling if the parent scaling more is not NATIVE_WINDOW_SCALING_MODE_FREEZE.
- ui::Transform getTransformWithScale(const ui::Transform& bufferScaleTransform) const;
-
- // Returns the bounds of the layer without any buffer scaling.
- FloatRect getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const;
-
int32_t getSequence() const override { return sequence; }
// For tracing.
@@ -885,8 +876,10 @@
StretchEffect getStretchEffect() const;
virtual bool setBufferCrop(const Rect& /* bufferCrop */) { return false; }
+ virtual bool setDestinationFrame(const Rect& /* destinationFrame */) { return false; }
virtual std::atomic<int32_t>* getPendingBufferCounter() { return nullptr; }
virtual std::string getPendingBufferCounterName() { return ""; }
+ virtual void updateGeometry() {}
protected:
friend class impl::SurfaceInterceptor;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index beda834..3edbe1d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2816,16 +2816,19 @@
}
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) {
- /*
- * Traversal of the children
- * (perform the transaction for each of them if needed)
- */
+ // Commit display transactions
+ const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
+ if (displayTransactionNeeded) {
+ processDisplayChangesLocked();
+ processDisplayHotplugEventsLocked();
+ }
- if ((transactionFlags & eTraversalNeeded) || mForceTraversal) {
- mForceTraversal = false;
+ // Commit layer transactions. This needs to happen after display transactions are
+ // committed because some geometry logic relies on display orientation.
+ if ((transactionFlags & eTraversalNeeded) || mForceTraversal || displayTransactionNeeded) {
mCurrentState.traverse([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (!trFlags) return;
+ if (!trFlags && !displayTransactionNeeded) return;
const uint32_t flags = layer->doTransaction(0);
if (flags & Layer::eVisibleRegion)
@@ -2837,15 +2840,7 @@
});
}
- /*
- * Perform display own transactions if needed
- */
-
- if (transactionFlags & eDisplayTransactionNeeded) {
- processDisplayChangesLocked();
- processDisplayHotplugEventsLocked();
- }
-
+ // Update transform hint
if (transactionFlags & (eTransformHintUpdateNeeded | eDisplayTransactionNeeded)) {
// The transform hint might have changed for some layers
// (either because a display has changed, or because a layer
@@ -4039,6 +4034,11 @@
flags |= eTraversalNeeded;
}
}
+ if (what & layer_state_t::eDestinationFrameChanged) {
+ if (layer->setDestinationFrame(s.destinationFrame)) {
+ flags |= eTraversalNeeded;
+ }
+ }
// 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