Merge "Tune RefreshRateConfigs for fractional refresh rates"
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index f8fdaa0..3d2bdf1 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -21,7 +21,9 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+#include <binder/BpBinder.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <binder/Stability.h>
@@ -58,27 +60,30 @@
}
static void usage() {
- fprintf(stderr,
- "usage: dumpsys\n"
- " To dump all services.\n"
- "or:\n"
- " dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--help | "
- "-l | --skip SERVICES "
- "| SERVICE [ARGS]]\n"
- " --help: shows this help\n"
- " -l: only list services, do not dump them\n"
- " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
- " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
- " --dump: ask the service to dump itself (this is the default)\n"
- " --pid: dump PID instead of usual dump\n"
- " --proto: filter services that support dumping data in proto format. Dumps\n"
- " will be in proto format.\n"
- " --priority LEVEL: filter services based on specified priority\n"
- " LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
- " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
- " --stability: dump binder stability information instead of usual dump\n"
- " --thread: dump thread usage instead of usual dump\n"
- " SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
+ fprintf(
+ stderr,
+ "usage: dumpsys\n"
+ " To dump all services.\n"
+ "or:\n"
+ " dumpsys [-t TIMEOUT] [--priority LEVEL] [--clients] [--dump] [--pid] [--thread] "
+ "[--help | "
+ "-l | --skip SERVICES "
+ "| SERVICE [ARGS]]\n"
+ " --help: shows this help\n"
+ " -l: only list services, do not dump them\n"
+ " -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
+ " -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+ " --clients: dump client PIDs instead of usual dump\n"
+ " --dump: ask the service to dump itself (this is the default)\n"
+ " --pid: dump PID instead of usual dump\n"
+ " --proto: filter services that support dumping data in proto format. Dumps\n"
+ " will be in proto format.\n"
+ " --priority LEVEL: filter services based on specified priority\n"
+ " LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
+ " --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
+ " --stability: dump binder stability information instead of usual dump\n"
+ " --thread: dump thread usage instead of usual dump\n"
+ " SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
}
static bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
@@ -131,15 +136,12 @@
int dumpTypeFlags = 0;
int timeoutArgMs = 10000;
int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
- static struct option longOptions[] = {{"help", no_argument, 0, 0},
- {"dump", no_argument, 0, 0},
- {"pid", no_argument, 0, 0},
- {"priority", required_argument, 0, 0},
- {"proto", no_argument, 0, 0},
- {"skip", no_argument, 0, 0},
- {"stability", no_argument, 0, 0},
- {"thread", no_argument, 0, 0},
- {0, 0, 0, 0}};
+ static struct option longOptions[] = {
+ {"help", no_argument, 0, 0}, {"clients", no_argument, 0, 0},
+ {"dump", no_argument, 0, 0}, {"pid", no_argument, 0, 0},
+ {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0},
+ {"skip", no_argument, 0, 0}, {"stability", no_argument, 0, 0},
+ {"thread", no_argument, 0, 0}, {0, 0, 0, 0}};
// Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
// happens on test cases).
@@ -178,6 +180,8 @@
dumpTypeFlags |= TYPE_STABILITY;
} else if (!strcmp(longOptions[optionIndex].name, "thread")) {
dumpTypeFlags |= TYPE_THREAD;
+ } else if (!strcmp(longOptions[optionIndex].name, "clients")) {
+ dumpTypeFlags |= TYPE_CLIENTS;
}
break;
@@ -373,6 +377,35 @@
return OK;
}
+static status_t dumpClientsToFd(const sp<IBinder>& service, const unique_fd& fd) {
+ std::string clientPids;
+ const auto remoteBinder = service->remoteBinder();
+ if (remoteBinder == nullptr) {
+ WriteStringToFd("Client PIDs are not available for local binders.\n", fd.get());
+ return OK;
+ }
+ const auto handle = remoteBinder->getDebugBinderHandle();
+ if (handle == std::nullopt) {
+ return OK;
+ }
+ std::vector<pid_t> pids;
+ pid_t myPid = getpid();
+ pid_t servicePid;
+ status_t status = service->getDebugPid(&servicePid);
+ if (status != OK) {
+ return status;
+ }
+ status =
+ getBinderClientPids(BinderDebugContext::BINDER, myPid, servicePid, handle.value(), &pids);
+ if (status != OK) {
+ return status;
+ }
+ pids.erase(std::remove_if(pids.begin(), pids.end(), [&](pid_t pid) { return pid == myPid; }),
+ pids.end());
+ WriteStringToFd("Client PIDs: " + ::android::base::Join(pids, ", ") + "\n", fd.get());
+ return OK;
+}
+
static void reportDumpError(const String16& serviceName, status_t error, const char* context) {
if (error == OK) return;
@@ -413,6 +446,10 @@
status_t err = dumpThreadsToFd(service, remote_end);
reportDumpError(serviceName, err, "dumping thread info");
}
+ if (dumpTypeFlags & TYPE_CLIENTS) {
+ status_t err = dumpClientsToFd(service, remote_end);
+ reportDumpError(serviceName, err, "dumping clients info");
+ }
// other types always act as a header, this is usually longer
if (dumpTypeFlags & TYPE_DUMP) {
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 05c5d5e..6ab1a7d 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,10 +52,11 @@
static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
enum Type {
- TYPE_DUMP = 0x1, // dump using `dump` function
- TYPE_PID = 0x2, // dump pid of server only
- TYPE_STABILITY = 0x4, // dump stability information of server
- TYPE_THREAD = 0x8, // dump thread usage of server only
+ TYPE_DUMP = 0x1, // dump using `dump` function
+ TYPE_PID = 0x2, // dump pid of server only
+ TYPE_STABILITY = 0x4, // dump stability information of server
+ TYPE_THREAD = 0x8, // dump thread usage of server only
+ TYPE_CLIENTS = 0x10, // dump pid of clients
};
/**
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 312f4d7..fa63db5 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -627,6 +627,29 @@
AssertOutputFormat(format);
}
+// Tests 'dumpsys --clients'
+TEST_F(DumpsysTest, ListAllServicesWithClients) {
+ ExpectListServices({"Locksmith", "Valet"});
+ ExpectCheckService("Locksmith");
+ ExpectCheckService("Valet");
+
+ CallMain({"--clients"});
+
+ AssertRunningServices({"Locksmith", "Valet"});
+
+ const std::string format("(.|\n)*((Client PIDs are not available for local binders.)(.|\n)*){2}");
+ AssertOutputFormat(format);
+}
+
+// Tests 'dumpsys --clients service_name'
+TEST_F(DumpsysTest, ListServiceWithClients) {
+ ExpectCheckService("Locksmith");
+
+ CallMain({"--clients", "Locksmith"});
+
+ const std::string format("Client PIDs are not available for local binders.\n");
+ AssertOutputFormat(format);
+}
// Tests 'dumpsys --thread --stability'
TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) {
ExpectListServices({"Locksmith", "Valet"});
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index cfd42fe..3f7c7d6 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -528,7 +528,7 @@
void Replayer::setLayerStack(SurfaceComposerClient::Transaction& t,
layer_id id, const LayerStackChange& lsc) {
ALOGV("Layer %d: Setting LayerStack -- layer_stack=%d", id, lsc.layer_stack());
- t.setLayerStack(mLayers[id], lsc.layer_stack());
+ t.setLayerStack(mLayers[id], ui::LayerStack::fromValue(lsc.layer_stack()));
}
void Replayer::setHiddenFlag(SurfaceComposerClient::Transaction& t,
@@ -566,7 +566,7 @@
void Replayer::setDisplayLayerStack(SurfaceComposerClient::Transaction& t,
display_id id, const LayerStackChange& lsc) {
- t.setDisplayLayerStack(mDisplays[id], lsc.layer_stack());
+ t.setDisplayLayerStack(mDisplays[id], ui::LayerStack::fromValue(lsc.layer_stack()));
}
void Replayer::setDisplaySize(SurfaceComposerClient::Transaction& t,
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index c18b1ce..20bf301 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -101,6 +101,7 @@
"BpBinder.cpp",
"BufferedTextOutput.cpp",
"Debug.cpp",
+ "FdTrigger.cpp",
"IInterface.cpp",
"IMemory.cpp",
"IPCThreadState.cpp",
@@ -231,6 +232,42 @@
},
}
+cc_defaults {
+ name: "libbinder_tls_shared_deps",
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ "liblog",
+ "libssl",
+ "libutils",
+ ],
+}
+
+cc_defaults {
+ name: "libbinder_tls_defaults",
+ defaults: ["libbinder_tls_shared_deps"],
+ host_supported: true,
+
+ header_libs: [
+ "libbinder_headers",
+ ],
+ export_header_lib_headers: [
+ "libbinder_headers",
+ ],
+ export_include_dirs: ["include_tls"],
+ static_libs: [
+ "libbase",
+ ],
+ srcs: [
+ "RpcTransportTls.cpp",
+ ],
+}
+
+cc_library_shared {
+ name: "libbinder_tls",
+ defaults: ["libbinder_tls_defaults"],
+}
+
// AIDL interface between libbinder and framework.jar
filegroup {
name: "libbinder_aidl",
@@ -249,6 +286,9 @@
"aidl/android/content/pm/IPackageChangeObserver.aidl",
"aidl/android/content/pm/IPackageManagerNative.aidl",
"aidl/android/content/pm/PackageChangeEvent.aidl",
+ "aidl/android/content/pm/IStagedApexObserver.aidl",
+ "aidl/android/content/pm/ApexStagedEvent.aidl",
+ "aidl/android/content/pm/StagedApexInfo.aidl",
],
path: "aidl",
}
@@ -356,5 +396,6 @@
"libbinder",
"liblog",
"libutils",
+ "android.debug_aidl-cpp",
],
}
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 765e21c..55566e2 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -188,6 +188,14 @@
return std::get<BinderHandle>(mHandle).handle;
}
+std::optional<int32_t> BpBinder::getDebugBinderHandle() const {
+ if (!isRpcBinder()) {
+ return binderHandle();
+ } else {
+ return std::nullopt;
+ }
+}
+
bool BpBinder::isDescriptorCached() const {
Mutex::Autolock _l(mLock);
return mDescriptorCache.size() ? true : false;
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
new file mode 100644
index 0000000..b197a6a
--- /dev/null
+++ b/libs/binder/FdTrigger.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FdTrigger"
+#include <log/log.h>
+
+#include <poll.h>
+
+#include <android-base/macros.h>
+
+#include "FdTrigger.h"
+namespace android {
+
+std::unique_ptr<FdTrigger> FdTrigger::make() {
+ auto ret = std::make_unique<FdTrigger>();
+ if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) {
+ ALOGE("Could not create pipe %s", strerror(errno));
+ return nullptr;
+ }
+ return ret;
+}
+
+void FdTrigger::trigger() {
+ mWrite.reset();
+}
+
+bool FdTrigger::isTriggered() {
+ return mWrite == -1;
+}
+
+status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
+ while (true) {
+ pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
+ {.fd = mRead.get(), .events = 0, .revents = 0}};
+ int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
+ if (ret < 0) {
+ return -errno;
+ }
+ if (ret == 0) {
+ continue;
+ }
+ if (pfd[1].revents & POLLHUP) {
+ return -ECANCELED;
+ }
+ return pfd[0].revents & event ? OK : DEAD_OBJECT;
+ }
+}
+
+android::base::Result<bool> FdTrigger::isTriggeredPolled() {
+ pollfd pfd{.fd = mRead.get(), .events = 0, .revents = 0};
+ int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 0));
+ if (ret < 0) {
+ return android::base::ErrnoError() << "FdTrigger::isTriggeredPolled: Error in poll()";
+ }
+ if (ret == 0) {
+ return false;
+ }
+ if (pfd.revents & POLLHUP) {
+ return true;
+ }
+ return android::base::Error() << "FdTrigger::isTriggeredPolled: poll() returns " << pfd.revents;
+}
+
+} // namespace android
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
new file mode 100644
index 0000000..a428417
--- /dev/null
+++ b/libs/binder/FdTrigger.h
@@ -0,0 +1,67 @@
+/*
+ * 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 <memory>
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+/** This is not a pipe. */
+class FdTrigger {
+public:
+ /** Returns nullptr for error case */
+ static std::unique_ptr<FdTrigger> make();
+
+ /**
+ * Close the write end of the pipe so that the read end receives POLLHUP.
+ * Not threadsafe.
+ */
+ void trigger();
+
+ /**
+ * Check whether this has been triggered by checking the write end.
+ */
+ bool isTriggered();
+
+ /**
+ * Poll for a read event.
+ *
+ * event - for pollfd
+ *
+ * Return:
+ * true - time to read!
+ * false - trigger happened
+ */
+ status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
+
+ /**
+ * Check whether this has been triggered by poll()ing the read end.
+ *
+ * Return:
+ * true - triggered
+ * false - not triggered
+ * error - error when polling
+ */
+ android::base::Result<bool> isTriggeredPolled();
+
+private:
+ base::unique_fd mWrite;
+ base::unique_fd mRead;
+};
+} // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 650a108..52a6cf1 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -409,7 +409,7 @@
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
if (result == -1) {
- ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+ ALOGV("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 4fa99c0..a20445b 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -29,6 +29,7 @@
#include <binder/RpcTransportRaw.h>
#include <log/log.h>
+#include "FdTrigger.h"
#include "RpcSocketAddress.h"
#include "RpcState.h"
#include "RpcWireFormat.h"
@@ -156,7 +157,7 @@
LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
mJoinThreadRunning = true;
- mShutdownTrigger = RpcSession::FdTrigger::make();
+ mShutdownTrigger = FdTrigger::make();
LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler");
mCtx = mRpcTransportCtxFactory->newServerCtx();
@@ -167,7 +168,7 @@
status_t status;
while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
unique_fd clientFd(TEMP_FAILURE_RETRY(
- accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+ accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK)));
if (clientFd < 0) {
ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -259,7 +260,7 @@
status_t status = OK;
int clientFdForLog = clientFd.get();
- auto client = server->mCtx->newTransport(std::move(clientFd));
+ auto client = server->mCtx->newTransport(std::move(clientFd), server->mShutdownTrigger.get());
if (client == nullptr) {
ALOGE("Dropping accept4()-ed socket because sslAccept fails");
status = DEAD_OBJECT;
@@ -270,8 +271,8 @@
RpcConnectionHeader header;
if (status == OK) {
- status = server->mShutdownTrigger->interruptableReadFully(client.get(), &header,
- sizeof(header));
+ status = client->interruptableReadFully(server->mShutdownTrigger.get(), &header,
+ sizeof(header));
if (status != OK) {
ALOGE("Failed to read ID for client connecting to RPC server: %s",
statusToString(status).c_str());
@@ -296,8 +297,8 @@
.version = protocolVersion,
};
- status = server->mShutdownTrigger->interruptableWriteFully(client.get(), &response,
- sizeof(response));
+ status = client->interruptableWriteFully(server->mShutdownTrigger.get(), &response,
+ sizeof(response));
if (status != OK) {
ALOGE("Failed to send new session response: %s", statusToString(status).c_str());
// still need to cleanup before we can return
@@ -387,8 +388,8 @@
LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
- unique_fd serverFd(
- TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+ unique_fd serverFd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (serverFd == -1) {
int savedErrno = errno;
ALOGE("Could not create socket: %s", strerror(savedErrno));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 107210b..4c47005 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -35,9 +35,11 @@
#include <jni.h>
#include <utils/String8.h>
+#include "FdTrigger.h"
#include "RpcSocketAddress.h"
#include "RpcState.h"
#include "RpcWireFormat.h"
+#include "Utils.h"
#ifdef __GLIBC__
extern "C" pid_t gettid();
@@ -133,12 +135,18 @@
fd = request();
if (!fd.ok()) return BAD_VALUE;
}
+ if (auto res = setNonBlocking(fd); !res.ok()) {
+ ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
+ return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
+ }
return initAndAddConnection(std::move(fd), sessionId, incoming);
});
}
status_t RpcSession::addNullDebuggingClient() {
// Note: only works on raw sockets.
+ if (auto status = initShutdownTrigger(); status != OK) return status;
+
unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
if (serverFd == -1) {
@@ -152,7 +160,7 @@
ALOGE("Unable to create RpcTransportCtx for null debugging client");
return NO_MEMORY;
}
- auto server = ctx->newTransport(std::move(serverFd));
+ auto server = ctx->newTransport(std::move(serverFd), mShutdownTrigger.get());
if (server == nullptr) {
ALOGE("Unable to set up RpcTransport");
return UNKNOWN_ERROR;
@@ -216,91 +224,6 @@
return state()->sendDecStrong(connection.get(), sp<RpcSession>::fromExisting(this), address);
}
-std::unique_ptr<RpcSession::FdTrigger> RpcSession::FdTrigger::make() {
- auto ret = std::make_unique<RpcSession::FdTrigger>();
- if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) {
- ALOGE("Could not create pipe %s", strerror(errno));
- return nullptr;
- }
- return ret;
-}
-
-void RpcSession::FdTrigger::trigger() {
- mWrite.reset();
-}
-
-bool RpcSession::FdTrigger::isTriggered() {
- return mWrite == -1;
-}
-
-status_t RpcSession::FdTrigger::triggerablePoll(RpcTransport* rpcTransport, int16_t event) {
- return triggerablePoll(rpcTransport->pollSocket(), event);
-}
-
-status_t RpcSession::FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
- while (true) {
- pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
- {.fd = mRead.get(), .events = POLLHUP, .revents = 0}};
- int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
- if (ret < 0) {
- return -errno;
- }
- if (ret == 0) {
- continue;
- }
- if (pfd[1].revents & POLLHUP) {
- return -ECANCELED;
- }
- return pfd[0].revents & event ? OK : DEAD_OBJECT;
- }
-}
-
-status_t RpcSession::FdTrigger::interruptableWriteFully(RpcTransport* rpcTransport,
- const void* data, size_t size) {
- const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data);
- const uint8_t* end = buffer + size;
-
- MAYBE_WAIT_IN_FLAKE_MODE;
-
- status_t status;
- while ((status = triggerablePoll(rpcTransport, POLLOUT)) == OK) {
- auto writeSize = rpcTransport->send(buffer, end - buffer);
- if (!writeSize.ok()) {
- LOG_RPC_DETAIL("RpcTransport::send(): %s", writeSize.error().message().c_str());
- return writeSize.error().code() == 0 ? UNKNOWN_ERROR : -writeSize.error().code();
- }
-
- if (*writeSize == 0) return DEAD_OBJECT;
-
- buffer += *writeSize;
- if (buffer == end) return OK;
- }
- return status;
-}
-
-status_t RpcSession::FdTrigger::interruptableReadFully(RpcTransport* rpcTransport, void* data,
- size_t size) {
- uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
- uint8_t* end = buffer + size;
-
- MAYBE_WAIT_IN_FLAKE_MODE;
-
- status_t status;
- while ((status = triggerablePoll(rpcTransport, POLLIN)) == OK) {
- auto readSize = rpcTransport->recv(buffer, end - buffer);
- if (!readSize.ok()) {
- LOG_RPC_DETAIL("RpcTransport::recv(): %s", readSize.error().message().c_str());
- return readSize.error().code() == 0 ? UNKNOWN_ERROR : -readSize.error().code();
- }
-
- if (*readSize == 0) return DEAD_OBJECT; // EOF
-
- buffer += *readSize;
- if (buffer == end) return OK;
- }
- return status;
-}
-
status_t RpcSession::readId() {
{
std::lock_guard<std::mutex> _l(mMutex);
@@ -484,6 +407,7 @@
"Must only setup session once, but already has %zu clients",
mOutgoingConnections.size());
}
+ if (auto status = initShutdownTrigger(); status != OK) return status;
if (status_t status = connectAndInit(RpcAddress::zero(), false /*incoming*/); status != OK)
return status;
@@ -550,8 +474,8 @@
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)));
+ unique_fd serverFd(TEMP_FAILURE_RETRY(
+ socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
if (serverFd == -1) {
int savedErrno = errno;
ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
@@ -564,10 +488,34 @@
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 -savedErrno;
+ if (errno != EAGAIN && errno != EINPROGRESS) {
+ int savedErrno = errno;
+ ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
+ strerror(savedErrno));
+ return -savedErrno;
+ }
+ // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
+ // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
+ status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
+ if (pollStatus != OK) {
+ ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
+ statusToString(pollStatus).c_str());
+ return pollStatus;
+ }
+ int soError;
+ socklen_t soErrorLen = sizeof(soError);
+ int ret = getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &soError, &soErrorLen);
+ if (ret == -1) {
+ int savedErrno = errno;
+ ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s",
+ strerror(savedErrno));
+ return -savedErrno;
+ }
+ if (soError != 0) {
+ ALOGE("After connect(), getsockopt() returns error for socket at %s: %s",
+ addr.toString().c_str(), strerror(soError));
+ return -soError;
+ }
}
LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
@@ -580,13 +528,14 @@
status_t RpcSession::initAndAddConnection(unique_fd fd, const RpcAddress& sessionId,
bool incoming) {
+ LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
auto ctx = mRpcTransportCtxFactory->newClientCtx();
if (ctx == nullptr) {
ALOGE("Unable to create client RpcTransportCtx with %s sockets",
mRpcTransportCtxFactory->toCString());
return NO_MEMORY;
}
- auto server = ctx->newTransport(std::move(fd));
+ auto server = ctx->newTransport(std::move(fd), mShutdownTrigger.get());
if (server == nullptr) {
ALOGE("Unable to set up RpcTransport in %s context", mRpcTransportCtxFactory->toCString());
return UNKNOWN_ERROR;
@@ -602,16 +551,12 @@
if (incoming) header.options |= RPC_CONNECTION_OPTION_INCOMING;
- auto sentHeader = server->send(&header, sizeof(header));
- if (!sentHeader.ok()) {
+ auto sendHeaderStatus =
+ server->interruptableWriteFully(mShutdownTrigger.get(), &header, sizeof(header));
+ if (sendHeaderStatus != OK) {
ALOGE("Could not write connection header to socket: %s",
- sentHeader.error().message().c_str());
- return -sentHeader.error().code();
- }
- if (*sentHeader != sizeof(header)) {
- ALOGE("Could not write connection header to socket: sent %zd bytes, expected %zd",
- *sentHeader, sizeof(header));
- return UNKNOWN_ERROR;
+ statusToString(sendHeaderStatus).c_str());
+ return sendHeaderStatus;
}
LOG_RPC_DETAIL("Socket at client: header sent");
@@ -652,19 +597,21 @@
return OK;
}
+status_t RpcSession::initShutdownTrigger() {
+ // first client connection added, but setForServer not called, so
+ // initializaing for a client.
+ if (mShutdownTrigger == nullptr) {
+ mShutdownTrigger = FdTrigger::make();
+ mEventListener = mShutdownListener = sp<WaitForShutdownListener>::make();
+ if (mShutdownTrigger == nullptr) return INVALID_OPERATION;
+ }
+ return OK;
+}
+
status_t RpcSession::addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTransport, bool init) {
sp<RpcConnection> connection = sp<RpcConnection>::make();
{
std::lock_guard<std::mutex> _l(mMutex);
-
- // first client connection added, but setForServer not called, so
- // initializaing for a client.
- if (mShutdownTrigger == nullptr) {
- mShutdownTrigger = FdTrigger::make();
- mEventListener = mShutdownListener = sp<WaitForShutdownListener>::make();
- if (mShutdownTrigger == nullptr) return INVALID_OPERATION;
- }
-
connection->rpcTransport = std::move(rpcTransport);
connection->exclusiveTid = gettid();
mOutgoingConnections.push_back(connection);
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 23382c3..b58f1b3 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -283,8 +283,8 @@
}
if (status_t status =
- session->mShutdownTrigger->interruptableWriteFully(connection->rpcTransport.get(),
- data, size);
+ connection->rpcTransport->interruptableWriteFully(session->mShutdownTrigger.get(),
+ data, size);
status != OK) {
LOG_RPC_DETAIL("Failed to write %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
connection->rpcTransport.get(), statusToString(status).c_str());
@@ -305,8 +305,8 @@
}
if (status_t status =
- session->mShutdownTrigger->interruptableReadFully(connection->rpcTransport.get(),
- data, size);
+ connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(),
+ data, size);
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());
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 2fc1945..d77fc52 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -17,8 +17,11 @@
#define LOG_TAG "RpcRawTransport"
#include <log/log.h>
+#include <poll.h>
+
#include <binder/RpcTransportRaw.h>
+#include "FdTrigger.h"
#include "RpcState.h"
using android::base::ErrnoError;
@@ -32,14 +35,14 @@
class RpcTransportRaw : public RpcTransport {
public:
explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
- Result<size_t> send(const void *buf, size_t size) override {
+ Result<size_t> send(const void* buf, size_t size) {
ssize_t ret = TEMP_FAILURE_RETRY(::send(mSocket.get(), buf, size, MSG_NOSIGNAL));
if (ret < 0) {
return ErrnoError() << "send()";
}
return ret;
}
- Result<size_t> recv(void *buf, size_t size) override {
+ Result<size_t> recv(void* buf, size_t size) {
ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_NOSIGNAL));
if (ret < 0) {
return ErrnoError() << "recv()";
@@ -47,14 +50,56 @@
return ret;
}
Result<size_t> peek(void *buf, size_t size) override {
- ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK | MSG_DONTWAIT));
+ ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
if (ret < 0) {
return ErrnoError() << "recv(MSG_PEEK)";
}
return ret;
}
- bool pending() override { return false; }
- android::base::borrowed_fd pollSocket() const override { return mSocket; }
+
+ status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override {
+ const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data);
+ const uint8_t* end = buffer + size;
+
+ MAYBE_WAIT_IN_FLAKE_MODE;
+
+ status_t status;
+ while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLOUT)) == OK) {
+ auto writeSize = this->send(buffer, end - buffer);
+ if (!writeSize.ok()) {
+ LOG_RPC_DETAIL("RpcTransport::send(): %s", writeSize.error().message().c_str());
+ return writeSize.error().code() == 0 ? UNKNOWN_ERROR : -writeSize.error().code();
+ }
+
+ if (*writeSize == 0) return DEAD_OBJECT;
+
+ buffer += *writeSize;
+ if (buffer == end) return OK;
+ }
+ return status;
+ }
+
+ status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override {
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
+ uint8_t* end = buffer + size;
+
+ MAYBE_WAIT_IN_FLAKE_MODE;
+
+ status_t status;
+ while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLIN)) == OK) {
+ auto readSize = this->recv(buffer, end - buffer);
+ if (!readSize.ok()) {
+ LOG_RPC_DETAIL("RpcTransport::recv(): %s", readSize.error().message().c_str());
+ return readSize.error().code() == 0 ? UNKNOWN_ERROR : -readSize.error().code();
+ }
+
+ if (*readSize == 0) return DEAD_OBJECT; // EOF
+
+ buffer += *readSize;
+ if (buffer == end) return OK;
+ }
+ return status;
+ }
private:
android::base::unique_fd mSocket;
@@ -63,7 +108,7 @@
// RpcTransportCtx with TLS disabled.
class RpcTransportCtxRaw : public RpcTransportCtx {
public:
- std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd) const {
+ std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
return std::make_unique<RpcTransportRaw>(std::move(fd));
}
};
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
new file mode 100644
index 0000000..a102913
--- /dev/null
+++ b/libs/binder/RpcTransportTls.cpp
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RpcTransportTls"
+#include <log/log.h>
+
+#include <poll.h>
+
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+
+#include <binder/RpcTransportTls.h>
+
+#include "FdTrigger.h"
+#include "RpcState.h"
+
+#define SHOULD_LOG_TLS_DETAIL false
+
+#if SHOULD_LOG_TLS_DETAIL
+#define LOG_TLS_DETAIL(...) ALOGI(__VA_ARGS__)
+#else
+#define LOG_TLS_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
+#endif
+
+#define TEST_AND_RETURN(value, expr) \
+ do { \
+ if (!(expr)) { \
+ ALOGE("Failed to call: %s", #expr); \
+ return value; \
+ } \
+ } while (0)
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+
+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));
+ BIO_set_init(bio, 0);
+ return 1;
+}
+int socketFree(BIO* bio) {
+ LOG_ALWAYS_FATAL_IF(bio == nullptr);
+ return 1;
+}
+int socketRead(BIO* bio, char* buf, int size) {
+ android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+ int ret = TEMP_FAILURE_RETRY(::recv(fd.get(), buf, size, MSG_NOSIGNAL));
+ BIO_clear_retry_flags(bio);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ BIO_set_retry_read(bio);
+ }
+ return ret;
+}
+
+int socketWrite(BIO* bio, const char* buf, int size) {
+ android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+ int ret = TEMP_FAILURE_RETRY(::send(fd.get(), buf, size, MSG_NOSIGNAL));
+ BIO_clear_retry_flags(bio);
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ BIO_set_retry_write(bio);
+ }
+ return ret;
+}
+
+long socketCtrl(BIO* bio, int cmd, long num, void*) { // NOLINT
+ android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+ if (cmd == BIO_CTRL_FLUSH) return 1;
+ LOG_ALWAYS_FATAL("sockCtrl(fd=%d, %d, %ld)", fd.get(), cmd, num);
+ return 0;
+}
+
+bssl::UniquePtr<BIO> newSocketBio(android::base::borrowed_fd fd) {
+ static const BIO_METHOD* gMethods = ([] {
+ auto methods = BIO_meth_new(BIO_get_new_index(), "socket_no_signal");
+ LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_write(methods, socketWrite), "BIO_meth_set_write");
+ LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_read(methods, socketRead), "BIO_meth_set_read");
+ LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_ctrl(methods, socketCtrl), "BIO_meth_set_ctrl");
+ LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_create(methods, socketNew), "BIO_meth_set_create");
+ LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_destroy(methods, socketFree), "BIO_meth_set_destroy");
+ return methods;
+ })();
+ bssl::UniquePtr<BIO> ret(BIO_new(gMethods));
+ if (ret == nullptr) return nullptr;
+ BIO_set_data(ret.get(), reinterpret_cast<void*>(fd.get()));
+ BIO_set_init(ret.get(), 1);
+ 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:
+ LOG_TLS_DETAIL("Handshake started.");
+ break;
+ case SSL_CB_HANDSHAKE_DONE:
+ LOG_TLS_DETAIL("Handshake done.");
+ break;
+ case SSL_CB_ACCEPT_LOOP:
+ LOG_TLS_DETAIL("Handshake progress: %s", SSL_state_string_long(ssl));
+ break;
+ default:
+ LOG_TLS_DETAIL("SSL Debug Log: type = %d, value = %d", type, value);
+ break;
+ }
+}
+
+// Handles libssl's error queue.
+//
+// Call into any of its member functions to ensure the error queue is properly handled or cleared.
+// If the error queue is not handled or cleared, the destructor will abort.
+class ErrorQueue {
+public:
+ ~ErrorQueue() { LOG_ALWAYS_FATAL_IF(!mHandled); }
+
+ // Clear the error queue.
+ void clear() {
+ ERR_clear_error();
+ mHandled = true;
+ }
+
+ // Stores the error queue in |ssl| into a string, then clears the error queue.
+ std::string toString() {
+ std::stringstream ss;
+ ERR_print_errors_cb(
+ [](const char* str, size_t len, void* ctx) {
+ auto ss = (std::stringstream*)ctx;
+ (*ss) << std::string_view(str, len) << "\n";
+ return 1; // continue
+ },
+ &ss);
+ // Though ERR_print_errors_cb should have cleared it, it is okay to clear again.
+ clear();
+ return ss.str();
+ }
+
+ // |sslError| should be from Ssl::getError().
+ // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
+ // return error. Also return error if |fdTrigger| is triggered before or during poll().
+ status_t pollForSslError(android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger,
+ const char* fnString, int additionalEvent = 0) {
+ switch (sslError) {
+ case SSL_ERROR_WANT_READ:
+ return handlePoll(POLLIN | additionalEvent, fd, fdTrigger, fnString);
+ case SSL_ERROR_WANT_WRITE:
+ return handlePoll(POLLOUT | additionalEvent, fd, fdTrigger, fnString);
+ case SSL_ERROR_SYSCALL: {
+ auto queue = toString();
+ LOG_TLS_DETAIL("%s(): %s. Treating as DEAD_OBJECT. Error queue: %s", fnString,
+ SSL_error_description(sslError), queue.c_str());
+ return DEAD_OBJECT;
+ }
+ default: {
+ auto queue = toString();
+ ALOGE("%s(): %s. Error queue: %s", fnString, SSL_error_description(sslError),
+ queue.c_str());
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+private:
+ bool mHandled = false;
+
+ 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) {
+ ALOGE("triggerablePoll error while poll()-ing after %s(): %s", fnString,
+ statusToString(ret).c_str());
+ }
+ clear();
+ return ret;
+ }
+};
+
+// Helper to call a function, with its return value instantiable.
+template <typename Fn, typename... Args>
+struct FuncCaller {
+ struct Monostate {};
+ static constexpr bool sIsVoid = std::is_void_v<std::invoke_result_t<Fn, Args...>>;
+ using Result = std::conditional_t<sIsVoid, Monostate, std::invoke_result_t<Fn, Args...>>;
+ static inline Result call(Fn fn, Args&&... args) {
+ if constexpr (std::is_void_v<std::invoke_result_t<Fn, Args...>>) {
+ std::invoke(fn, std::forward<Args>(args)...);
+ return {};
+ } else {
+ return std::invoke(fn, std::forward<Args>(args)...);
+ }
+ }
+};
+
+// Helper to Ssl::call(). Returns the result to the SSL_* function as well as an ErrorQueue object.
+template <typename Fn, typename... Args>
+struct SslCaller {
+ using RawCaller = FuncCaller<Fn, SSL*, Args...>;
+ struct ResultAndErrorQueue {
+ typename RawCaller::Result result;
+ ErrorQueue errorQueue;
+ };
+ static inline ResultAndErrorQueue call(Fn fn, SSL* ssl, Args&&... args) {
+ LOG_ALWAYS_FATAL_IF(ssl == nullptr);
+ auto result = RawCaller::call(fn, std::forward<SSL*>(ssl), std::forward<Args>(args)...);
+ return ResultAndErrorQueue{std::move(result), ErrorQueue()};
+ }
+};
+
+// A wrapper over bssl::UniquePtr<SSL>. This class ensures that all SSL_* functions are called
+// through call(), which returns an ErrorQueue object that requires the caller to either handle
+// or clear it.
+// Example:
+// auto [ret, errorQueue] = ssl.call(SSL_read, buf, size);
+// if (ret >= 0) errorQueue.clear();
+// else ALOGE("%s", errorQueue.toString().c_str());
+class Ssl {
+public:
+ explicit Ssl(bssl::UniquePtr<SSL> ssl) : mSsl(std::move(ssl)) {
+ LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+ }
+
+ template <typename Fn, typename... Args>
+ inline typename SslCaller<Fn, Args...>::ResultAndErrorQueue call(Fn fn, Args&&... args) {
+ return SslCaller<Fn, Args...>::call(fn, mSsl.get(), std::forward<Args>(args)...);
+ }
+
+ int getError(int ret) {
+ LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+ return SSL_get_error(mSsl.get(), ret);
+ }
+
+private:
+ bssl::UniquePtr<SSL> mSsl;
+};
+
+class RpcTransportTls : public RpcTransport {
+public:
+ RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
+ : mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
+ Result<size_t> peek(void* buf, size_t size) override;
+ status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override;
+ status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override;
+
+private:
+ android::base::unique_fd mSocket;
+ Ssl mSsl;
+
+ static status_t isTriggered(FdTrigger* fdTrigger);
+};
+
+// Error code is errno.
+Result<size_t> RpcTransportTls::peek(void* buf, size_t size) {
+ size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
+ auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
+ if (ret < 0) {
+ int err = mSsl.getError(ret);
+ if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+ // Seen EAGAIN / EWOULDBLOCK on recv(2) / send(2).
+ // Like RpcTransportRaw::peek(), don't handle it here.
+ return Error(EWOULDBLOCK) << "SSL_peek(): " << errorQueue.toString();
+ }
+ return Error() << "SSL_peek(): " << errorQueue.toString();
+ }
+ errorQueue.clear();
+ LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
+ return ret;
+}
+
+status_t RpcTransportTls::isTriggered(FdTrigger* fdTrigger) {
+ auto ret = fdTrigger->isTriggeredPolled();
+ if (!ret.ok()) {
+ ALOGE("%s: %s", __PRETTY_FUNCTION__, ret.error().message().c_str());
+ return ret.error().code() == 0 ? UNKNOWN_ERROR : -ret.error().code();
+ }
+ return OK;
+}
+
+status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, const void* data,
+ size_t size) {
+ auto buffer = reinterpret_cast<const uint8_t*>(data);
+ const uint8_t* end = buffer + size;
+
+ MAYBE_WAIT_IN_FLAKE_MODE;
+
+ // 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 (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+ while (buffer < end) {
+ size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+ auto [writeSize, errorQueue] = mSsl.call(SSL_write, buffer, todo);
+ if (writeSize > 0) {
+ buffer += writeSize;
+ errorQueue.clear();
+ continue;
+ }
+ // SSL_write() should never return 0 unless BIO_write were to return 0.
+ int sslError = mSsl.getError(writeSize);
+ // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
+ // triggerablePoll()-ed. Then additionalEvent is no longer necessary.
+ status_t pollStatus =
+ errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_write", POLLIN);
+ if (pollStatus != OK) return pollStatus;
+ // Do not advance buffer. Try SSL_write() again.
+ }
+ LOG_TLS_DETAIL("TLS: Sent %zu bytes!", size);
+ return OK;
+}
+
+status_t RpcTransportTls::interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) {
+ auto buffer = reinterpret_cast<uint8_t*>(data);
+ uint8_t* end = buffer + size;
+
+ MAYBE_WAIT_IN_FLAKE_MODE;
+
+ // 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 (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+ while (buffer < end) {
+ size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+ auto [readSize, errorQueue] = mSsl.call(SSL_read, buffer, todo);
+ if (readSize > 0) {
+ buffer += readSize;
+ errorQueue.clear();
+ continue;
+ }
+ if (readSize == 0) {
+ // SSL_read() only returns 0 on EOF.
+ errorQueue.clear();
+ return DEAD_OBJECT;
+ }
+ int sslError = mSsl.getError(readSize);
+ status_t pollStatus =
+ errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_read");
+ if (pollStatus != OK) return pollStatus;
+ // Do not advance buffer. Try SSL_read() again.
+ }
+ LOG_TLS_DETAIL("TLS: Received %zu bytes!", size);
+ return OK;
+}
+
+// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
+bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) {
+ bssl::UniquePtr<BIO> bio = newSocketBio(fd);
+ TEST_AND_RETURN(false, bio != nullptr);
+ auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
+ (void)bio.release(); // SSL_set_bio takes ownership.
+ errorQueue.clear();
+
+ MAYBE_WAIT_IN_FLAKE_MODE;
+
+ while (true) {
+ auto [ret, errorQueue] = ssl->call(SSL_do_handshake);
+ if (ret > 0) {
+ errorQueue.clear();
+ return true;
+ }
+ if (ret == 0) {
+ // SSL_do_handshake() only returns 0 on EOF.
+ ALOGE("SSL_do_handshake(): EOF: %s", errorQueue.toString().c_str());
+ return false;
+ }
+ int sslError = ssl->getError(ret);
+ status_t pollStatus =
+ errorQueue.pollForSslError(fd, sslError, fdTrigger, "SSL_do_handshake");
+ if (pollStatus != OK) return false;
+ }
+}
+
+class RpcTransportCtxTlsServer : public RpcTransportCtx {
+public:
+ static std::unique_ptr<RpcTransportCtxTlsServer> create();
+ std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd acceptedFd,
+ FdTrigger* fdTrigger) const override;
+
+private:
+ bssl::UniquePtr<SSL_CTX> mCtx;
+};
+
+std::unique_ptr<RpcTransportCtxTlsServer> RpcTransportCtxTlsServer::create() {
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+ TEST_AND_RETURN(nullptr, ctx != nullptr);
+
+ // Server use self-signing cert
+ 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()));
+ // Require at least TLS 1.3
+ TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
+
+ if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
+ SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
+ }
+
+ auto rpcTransportTlsServerCtx = std::make_unique<RpcTransportCtxTlsServer>();
+ rpcTransportTlsServerCtx->mCtx = std::move(ctx);
+ return rpcTransportTlsServerCtx;
+}
+
+std::unique_ptr<RpcTransport> RpcTransportCtxTlsServer::newTransport(
+ android::base::unique_fd acceptedFd, FdTrigger* fdTrigger) const {
+ bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
+ TEST_AND_RETURN(nullptr, ssl != nullptr);
+ Ssl wrapped(std::move(ssl));
+
+ wrapped.call(SSL_set_accept_state).errorQueue.clear();
+ TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, acceptedFd, fdTrigger));
+ return std::make_unique<RpcTransportTls>(std::move(acceptedFd), std::move(wrapped));
+}
+
+class RpcTransportCtxTlsClient : public RpcTransportCtx {
+public:
+ static std::unique_ptr<RpcTransportCtxTlsClient> create();
+ std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd connectedFd,
+ FdTrigger* fdTrigger) const override;
+
+private:
+ bssl::UniquePtr<SSL_CTX> mCtx;
+};
+
+std::unique_ptr<RpcTransportCtxTlsClient> RpcTransportCtxTlsClient::create() {
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+ TEST_AND_RETURN(nullptr, ctx != nullptr);
+
+ // TODO(b/195166979): server should send certificate in a different channel, and client
+ // should verify it here.
+ SSL_CTX_set_custom_verify(ctx.get(), SSL_VERIFY_PEER,
+ [](SSL*, uint8_t*) -> ssl_verify_result_t { return ssl_verify_ok; });
+
+ // Require at least TLS 1.3
+ TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
+
+ if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
+ SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
+ }
+
+ auto rpcTransportTlsClientCtx = std::make_unique<RpcTransportCtxTlsClient>();
+ rpcTransportTlsClientCtx->mCtx = std::move(ctx);
+ return rpcTransportTlsClientCtx;
+}
+
+std::unique_ptr<RpcTransport> RpcTransportCtxTlsClient::newTransport(
+ android::base::unique_fd connectedFd, FdTrigger* fdTrigger) const {
+ bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
+ TEST_AND_RETURN(nullptr, ssl != nullptr);
+ Ssl wrapped(std::move(ssl));
+
+ wrapped.call(SSL_set_connect_state).errorQueue.clear();
+ TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, connectedFd, fdTrigger));
+ return std::make_unique<RpcTransportTls>(std::move(connectedFd), std::move(wrapped));
+}
+
+} // namespace
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
+ return android::RpcTransportCtxTlsServer::create();
+}
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newClientCtx() const {
+ return android::RpcTransportCtxTlsClient::create();
+}
+
+const char* RpcTransportCtxFactoryTls::toCString() const {
+ return "tls";
+}
+
+std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTls::make() {
+ return std::unique_ptr<RpcTransportCtxFactoryTls>(new RpcTransportCtxFactoryTls());
+}
+
+} // namespace android
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
index 90a4502..d2a5be1 100644
--- a/libs/binder/Utils.cpp
+++ b/libs/binder/Utils.cpp
@@ -18,10 +18,24 @@
#include <string.h>
+using android::base::ErrnoError;
+using android::base::Result;
+
namespace android {
void zeroMemory(uint8_t* data, size_t size) {
memset(data, 0, size);
}
-} // namespace android
+Result<void> setNonBlocking(android::base::borrowed_fd fd) {
+ int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL));
+ if (flags == -1) {
+ return ErrnoError() << "Could not get flags for fd";
+ }
+ if (int ret = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK)); ret == -1) {
+ return ErrnoError() << "Could not set non-blocking flag for fd";
+ }
+ return {};
+}
+
+} // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index f94b158..1e383da 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -17,9 +17,14 @@
#include <cstdint>
#include <stddef.h>
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+
namespace android {
// avoid optimizations
void zeroMemory(uint8_t* data, size_t size);
+android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd);
+
} // namespace android
diff --git a/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
new file mode 100644
index 0000000..75f8753
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.content.pm;
+
+/**
+ * This event is designed for notification to native code listener about
+ * any changes to set of apex packages staged for installation on next boot.
+ *
+ * @hide
+ */
+parcelable ApexStagedEvent {
+ @utf8InCpp String[] stagedApexModuleNames;
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index c20d9f6..d71f496 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -18,6 +18,8 @@
package android.content.pm;
import android.content.pm.IPackageChangeObserver;
+import android.content.pm.IStagedApexObserver;
+import android.content.pm.StagedApexInfo;
/**
* Parallel implementation of certain {@link PackageManager} APIs that need to
@@ -123,4 +125,24 @@
* requested version.
*/
boolean hasSystemFeature(in String featureName, in int version);
+
+ /** Register a observer for change in set of staged APEX ready for installation */
+ void registerStagedApexObserver(in IStagedApexObserver observer);
+
+ /**
+ * Unregister an existing staged apex observer.
+ * This does nothing if this observer was not already registered.
+ */
+ void unregisterStagedApexObserver(in IStagedApexObserver observer);
+
+ /**
+ * Get APEX module names of all APEX that are staged ready for installation
+ */
+ @utf8InCpp String[] getStagedApexModuleNames();
+
+ /**
+ * Get information of APEX which is staged ready for installation.
+ * Returns null if no such APEX is found.
+ */
+ StagedApexInfo getStagedApexInfo(in @utf8InCpp String moduleName);
}
diff --git a/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
new file mode 100644
index 0000000..9906436
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.content.pm;
+
+import android.content.pm.ApexStagedEvent;
+
+/**
+ * This is a non-blocking notification when set of staged apex has changed
+ *
+ * @hide
+ */
+oneway interface IStagedApexObserver {
+ void onApexStaged(in ApexStagedEvent event);
+}
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
new file mode 100644
index 0000000..ece7989
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.content.pm;
+
+/**
+ * This object is designed for returning information regarding
+ * staged APEX that are ready to be installed on next reboot.
+ *
+ * @hide
+ */
+parcelable StagedApexInfo {
+ @utf8InCpp String moduleName;
+ @utf8InCpp String diskImagePath;
+ long versionCode;
+ @utf8InCpp String versionName;
+}
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index c69bb9e..a6d35c7 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -90,6 +90,8 @@
static void setLimitCallback(binder_proxy_limit_callback cb);
static void setBinderProxyCountWatermarks(int high, int low);
+ std::optional<int32_t> getDebugBinderHandle() const;
+
class ObjectManager {
public:
ObjectManager();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 02052ad..fd8ac62 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -245,9 +245,10 @@
template<typename T>
status_t writeNullableParcelable(const std::optional<T>& parcelable)
{ return writeData(parcelable); }
- template<typename T>
- status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
- { return writeData(parcelable); }
+ template <typename T>
+ status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
+ return writeData(parcelable);
+ }
status_t writeParcelable(const Parcelable& parcelable);
@@ -401,9 +402,10 @@
template<typename T>
status_t readParcelable(std::optional<T>* parcelable) const
{ return readData(parcelable); }
- template<typename T>
- status_t readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
- { return readData(parcelable); }
+ template <typename T>
+ status_t readParcelable(std::unique_ptr<T>* parcelable) const {
+ return readData(parcelable);
+ }
// If strong binder would be nullptr, readStrongBinder() returns an error.
// TODO: T must be derived from IInterface, fix for clarity.
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index f79d85f..bf3e7e0 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -32,6 +32,7 @@
namespace android {
+class FdTrigger;
class RpcSocketAddress;
/**
@@ -190,7 +191,7 @@
sp<IBinder> mRootObject;
wp<IBinder> mRootObjectWeak;
std::map<RpcAddress, sp<RpcSession>> mSessions;
- std::unique_ptr<RpcSession::FdTrigger> mShutdownTrigger;
+ std::unique_ptr<FdTrigger> mShutdownTrigger;
std::condition_variable mShutdownCv;
std::unique_ptr<RpcTransportCtx> mCtx;
};
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 7ed6e43..6e6eb74 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -18,7 +18,6 @@
#include <android-base/unique_fd.h>
#include <binder/IBinder.h>
#include <binder/RpcAddress.h>
-#include <binder/RpcSession.h>
#include <binder/RpcTransport.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -39,6 +38,7 @@
class RpcSocketAddress;
class RpcState;
class RpcTransport;
+class FdTrigger;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 0;
constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
@@ -161,50 +161,6 @@
friend RpcState;
explicit RpcSession(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
- /** This is not a pipe. */
- struct FdTrigger {
- /** Returns nullptr for error case */
- static std::unique_ptr<FdTrigger> make();
-
- /**
- * Close the write end of the pipe so that the read end receives POLLHUP.
- * Not threadsafe.
- */
- void trigger();
-
- /**
- * Whether this has been triggered.
- */
- bool isTriggered();
-
- /**
- * Poll for a read event.
- *
- * event - for pollfd
- *
- * Return:
- * true - time to read!
- * false - trigger happened
- */
- status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
-
- /**
- * Read (or write), but allow to be interrupted by this trigger.
- *
- * Return:
- * true - succeeded in completely processing 'size'
- * false - interrupted (failure or trigger)
- */
- status_t interruptableReadFully(RpcTransport* rpcTransport, void* data, size_t size);
- status_t interruptableWriteFully(RpcTransport* rpcTransport, const void* data, size_t size);
-
- private:
- status_t triggerablePoll(RpcTransport* rpcTransport, int16_t event);
-
- base::unique_fd mWrite;
- base::unique_fd mRead;
- };
-
class EventListener : public virtual RefBase {
public:
virtual void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) = 0;
@@ -271,6 +227,8 @@
std::unique_ptr<RpcTransport> rpcTransport);
[[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
+ status_t initShutdownTrigger();
+
enum class ConnectionUse {
CLIENT,
CLIENT_ASYNC,
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 1164600..1b69519 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -23,42 +23,30 @@
#include <android-base/result.h>
#include <android-base/unique_fd.h>
+#include <utils/Errors.h>
namespace android {
+class FdTrigger;
+
// Represents a socket connection.
class RpcTransport {
public:
virtual ~RpcTransport() = default;
- // replacement of ::send(). errno may not be set if TLS is enabled.
- virtual android::base::Result<size_t> send(const void *buf, size_t size) = 0;
-
- // replacement of ::recv(). errno may not be set if TLS is enabled.
- virtual android::base::Result<size_t> recv(void *buf, size_t size) = 0;
-
- // replacement of ::recv(MSG_PEEK). errno may not be set if TLS is enabled.
- //
- // Implementation details:
- // - For TLS, this may invoke syscalls and read data from the transport
- // into an internal buffer in userspace. After that, pending() == true.
- // - For raw sockets, this calls ::recv(MSG_PEEK), which leaves the data in the kernel buffer;
- // pending() is always false.
+ // replacement of ::recv(MSG_PEEK). Error code may not be set if TLS is enabled.
virtual android::base::Result<size_t> peek(void *buf, size_t size) = 0;
- // Returns true if there are data pending in a userspace buffer that RpcTransport holds.
- //
- // Implementation details:
- // - For TLS, this does not invoke any syscalls or read any data from the
- // transport. This only returns whether there are data pending in the internal buffer in
- // userspace.
- // - For raw sockets, this always returns false.
- virtual bool pending() = 0;
-
- // Returns fd for polling.
- //
- // Do not directly read / write on this raw fd!
- [[nodiscard]] virtual android::base::borrowed_fd pollSocket() const = 0;
+ /**
+ * Read (or write), but allow to be interrupted by a trigger.
+ *
+ * Return:
+ * OK - succeeded in completely processing 'size'
+ * error - interrupted (failure or trigger)
+ */
+ virtual status_t interruptableWriteFully(FdTrigger *fdTrigger, const void *buf,
+ size_t size) = 0;
+ virtual status_t interruptableReadFully(FdTrigger *fdTrigger, void *buf, size_t size) = 0;
protected:
RpcTransport() = default;
@@ -68,8 +56,13 @@
class RpcTransportCtx {
public:
virtual ~RpcTransportCtx() = default;
+
+ // Create a new RpcTransport object.
+ //
+ // Implemenion details: for TLS, this function may incur I/O. |fdTrigger| may be used
+ // to interrupt I/O. This function blocks until handshake is finished.
[[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
- android::base::unique_fd fd) const = 0;
+ android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0;
protected:
RpcTransportCtx() = default;
diff --git a/libs/binder/include_tls/binder/RpcTransportTls.h b/libs/binder/include_tls/binder/RpcTransportTls.h
new file mode 100644
index 0000000..531aaa9
--- /dev/null
+++ b/libs/binder/include_tls/binder/RpcTransportTls.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.
+ */
+
+// Wraps the transport layer of RPC. Implementation uses TLS.
+
+#pragma once
+
+#include <binder/RpcTransport.h>
+
+namespace android {
+
+// RpcTransportCtxFactory with TLS enabled with self-signed certificate.
+class RpcTransportCtxFactoryTls : public RpcTransportCtxFactory {
+public:
+ static std::unique_ptr<RpcTransportCtxFactory> make();
+
+ std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
+ std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
+ const char* toCString() const override;
+
+private:
+ RpcTransportCtxFactoryTls() = default;
+};
+
+} // namespace android
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 785e032..717beec 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -82,8 +82,8 @@
const String16& currentDescriptor = mClazz->getInterfaceDescriptor();
if (newDescriptor == currentDescriptor) {
LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
- << "' match during associateClass, but they are different class objects. "
- "Class descriptor collision?";
+ << "' match during associateClass, but they are different class objects ("
+ << clazz << " vs " << mClazz << "). Class descriptor collision?";
} else {
LOG(ERROR) << __func__
<< ": Class cannot be associated on object which already has a class. "
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 6c44726..5de64f8 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -55,6 +55,12 @@
std::call_once(mFlagThis, [&]() {
__assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
});
+
+ if (ref() != nullptr) {
+ __assert(__FILE__, __LINE__,
+ "SharedRefBase: destructed but still able to lock weak_ptr. Is this object "
+ "double-owned?");
+ }
}
/**
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 5092d87..563d011 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -469,6 +469,22 @@
}
/**
+ * Convenience API for writing a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
+ const std::unique_ptr<P>& p) {
+ if (!p) {
+ return AParcel_writeInt32(parcel, 0); // null
+ }
+ binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null
+ if (status != STATUS_OK) {
+ return status;
+ }
+ return p->writeToParcel(parcel);
+}
+
+/**
* Convenience API for reading a nullable parcelable.
*/
template <typename P>
@@ -488,6 +504,25 @@
}
/**
+ * Convenience API for reading a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
+ std::unique_ptr<P>* p) {
+ int32_t null;
+ binder_status_t status = AParcel_readInt32(parcel, &null);
+ if (status != STATUS_OK) {
+ return status;
+ }
+ if (null == 0) {
+ p->reset();
+ return STATUS_OK;
+ }
+ *p = std::make_unique<P>();
+ return (*p)->readFromParcel(parcel);
+}
+
+/**
* Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
*/
template <typename P>
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index ce12ccf..4b36530 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -224,6 +224,17 @@
return true;
}
+TEST(NdkBinder, DetectDoubleOwn) {
+ auto badService = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
+ EXPECT_DEATH(std::shared_ptr<MyBinderNdkUnitTest>(badService.get()),
+ "Is this object double-owned?");
+}
+
+TEST(NdkBinder, DetectNoSharedRefBaseCreated) {
+ EXPECT_DEATH(std::make_shared<MyBinderNdkUnitTest>(),
+ "SharedRefBase: no ref created during lifetime");
+}
+
TEST(NdkBinder, GetServiceThatDoesntExist) {
sp<IFoo> foo = IFoo::getService("asdfghkl;");
EXPECT_EQ(nullptr, foo.get());
diff --git a/libs/binder/run_rpc_tests.sh b/libs/binder/run_rpc_tests.sh
new file mode 100755
index 0000000..7ba682d
--- /dev/null
+++ b/libs/binder/run_rpc_tests.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+set -ex
+
+if [ $# -eq 0 ]; then
+ :
+elif [ $# -eq 1 ] && [[ "$1" =~ ^host|device$ ]]; then
+ :
+else
+ echo "usage: $0 [device|host]"
+ false
+fi
+
+# Script maintained for RPC development, while it is active, to quickly run
+# tests. Generally, to match VTS/presubmit behavior, 'atest' should be used.
+
+function dtest () { adb shell /data/nativetest64/$1/$@; }
+function hbench () { $AT/out/host/linux-x86/benchmarktest/$1/$@; }
+function hfuzz () { time $ANDROID_HOST_OUT/fuzz/x86_64/$1/$@; }
+function htest () { time $ANDROID_BUILD_TOP/out/host/linux-x86/nativetest/$1/$@; }
+function pdtest () { adb wait-for-device && adb shell mkdir -p /data/nativetest64/$1 && adb push $OUT/data/nativetest64/$1/$1 /data/nativetest64/$1/$1 && dtest $@; }
+function dbench () { adb shell /data/benchmarktest64/$1/$@; }
+function pdbench () { adb wait-for-device && adb shell mkdir -p /data/benchmarktest64/$1 && adb push $OUT/data/benchmarktest64/$1/$1 /data/benchmarktest64/$1/$1 && dbench $@; }
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+ binderRpcTest \
+ binder_rpc_fuzzer \
+ binder_parcel_fuzzer \
+ binderLibTest \
+ binderRpcBenchmark
+
+if ! [ "$1" = "device" ]; then
+ htest binderRpcTest
+ hbench binderRpcBenchmark
+ hfuzz binder_rpc_fuzzer -max_total_time=30
+ hfuzz binder_parcel_fuzzer -max_total_time=30
+fi
+
+if ! [ "$1" = "host" ]; then
+ pdtest binderRpcTest
+ pdtest binderLibTest
+ pdbench binderRpcBenchmark
+fi
+
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
index 20e9178..179b7c8 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};
+use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
/// Rust version of the Java class android.os.ParcelFileDescriptor
#[derive(Debug)]
@@ -48,6 +48,12 @@
}
}
+impl AsRawFd for ParcelFileDescriptor {
+ fn as_raw_fd(&self) -> RawFd {
+ self.0.as_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/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 956ecfe..56c6165 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -764,6 +764,30 @@
}
}
+impl<T: Serialize> Serialize for Box<T> {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Serialize::serialize(&**self, parcel)
+ }
+}
+
+impl<T: Deserialize> Deserialize for Box<T> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ Deserialize::deserialize(parcel).map(Box::new)
+ }
+}
+
+impl<T: SerializeOption> SerializeOption for Box<T> {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.map(|inner| &**inner), parcel)
+ }
+}
+
+impl<T: DeserializeOption> DeserializeOption for Box<T> {
+ fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+ DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new))
+ }
+}
+
#[test]
fn test_custom_parcelable() {
use crate::binder::Interface;
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 48fc60a..9811cdf 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -23,9 +23,12 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android/debug/BnAdbCallback.h>
+#include <android/debug/IAdbManager.h>
#include <android/os/BnServiceManager.h>
#include <android/os/IServiceManager.h>
#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
#include <binder/RpcServer.h>
using android::BBinder;
@@ -50,6 +53,7 @@
const char* kLocalInetAddress = "127.0.0.1";
using ServiceRetriever = decltype(&android::IServiceManager::checkService);
+using android::debug::IAdbManager;
int Usage(const char* program) {
auto basename = Basename(program);
@@ -213,6 +217,25 @@
__builtin_unreachable();
}
+class AdbCallback : public android::debug::BnAdbCallback {
+public:
+ android::binder::Status onDebuggingChanged(bool enabled,
+ android::debug::AdbTransportType) override {
+ if (!enabled) {
+ LOG(ERROR) << "ADB debugging disabled, exiting.";
+ exit(EX_SOFTWARE);
+ }
+ return android::binder::Status::ok();
+ }
+};
+
+void exitOnAdbDebuggingDisabled() {
+ auto adb = android::waitForService<IAdbManager>(String16("adb"));
+ CHECK(adb != nullptr) << "Unable to retrieve service adb";
+ auto status = adb->registerCallback(sp<AdbCallback>::make());
+ CHECK(status.isOk()) << "Unable to call IAdbManager::registerCallback: " << status;
+}
+
// Log to logd. For warning and more severe messages, also log to stderr.
class ServiceDispatcherLogger {
public:
@@ -253,6 +276,10 @@
}
}
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ exitOnAdbDebuggingDisabled();
+
if (optind + 1 != argc) return Usage(argv[0]);
auto name = argv[optind];
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 0c452ff..e430c28 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -153,7 +153,7 @@
{64, 1024, 2048, 4096, 8182, 16364, 32728, 65535, 65536, 65537}});
void BM_repeatBinder(benchmark::State& state) {
- sp<IBinder> binder = gSession->getRootObject();
+ sp<IBinder> binder = getBinderForOptions(state);
CHECK(binder != nullptr);
sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
CHECK(iface != nullptr);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 6dd4019..15ccae9 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1196,7 +1196,12 @@
unsigned int vsockPort = allocateVsockPort();
sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make());
server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
- CHECK_EQ(OK, server->setupVsockServer(vsockPort));
+ if (status_t status = server->setupVsockServer(vsockPort); status != OK) {
+ if (status == -EAFNOSUPPORT) {
+ return false;
+ }
+ LOG_ALWAYS_FATAL("Could not setup vsock server: %s", statusToString(status).c_str());
+ }
server->start();
sp<RpcSession> session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
index b435dba..d086b49 100644
--- a/libs/binderdebug/BinderDebug.cpp
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <binder/Binder.h>
@@ -116,4 +117,60 @@
return ret;
}
+status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
+ int32_t handle, std::vector<pid_t>* pids) {
+ std::smatch match;
+ static const std::regex kNodeNumber("^\\s+ref \\d+:\\s+desc\\s+(\\d+)\\s+node\\s+(\\d+).*");
+ std::string contextStr = contextToString(context);
+ int32_t node;
+ status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
+ if (std::regex_search(line, match, kNodeNumber)) {
+ const std::string& descString = match.str(1);
+ int32_t desc;
+ if (!::android::base::ParseInt(descString.c_str(), &desc)) {
+ LOG(ERROR) << "Failed to parse desc int: " << descString;
+ return;
+ }
+ if (handle != desc) {
+ return;
+ }
+ const std::string& nodeString = match.str(2);
+ if (!::android::base::ParseInt(nodeString.c_str(), &node)) {
+ LOG(ERROR) << "Failed to parse node int: " << nodeString;
+ return;
+ }
+ return;
+ }
+ return;
+ });
+ if (ret != OK) {
+ return ret;
+ }
+ static const std::regex kClients("^\\s+node\\s+(\\d+).*proc\\s+([\\d+\\s*]*)");
+ ret = scanBinderContext(servicePid, contextStr, [&](const std::string& line) {
+ if (std::regex_search(line, match, kClients)) {
+ const std::string nodeString = match.str(1);
+ int32_t matchedNode;
+ if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
+ LOG(ERROR) << "Failed to parse node int: " << nodeString;
+ return;
+ }
+ if (node != matchedNode) {
+ return;
+ }
+ const std::string clients = match.str(2);
+ for (const std::string& pidStr : base::Split(clients, " ")) {
+ int32_t pid;
+ if (!::android::base::ParseInt(pidStr, &pid)) {
+ return;
+ }
+ pids->push_back(pid);
+ }
+ return;
+ }
+ return;
+ });
+ return ret;
+}
+
} // namespace android
diff --git a/libs/binderdebug/include/binderdebug/BinderDebug.h b/libs/binderdebug/include/binderdebug/BinderDebug.h
index 14a0ef3..dfd5a7c 100644
--- a/libs/binderdebug/include/binderdebug/BinderDebug.h
+++ b/libs/binderdebug/include/binderdebug/BinderDebug.h
@@ -32,6 +32,14 @@
VNDBINDER,
};
+/**
+ * pid is the pid of the service
+ */
status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo);
+/**
+ * pid is typically the pid of this process that is making the query
+ */
+status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
+ int32_t handle, std::vector<pid_t>* pids);
} // namespace android
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 23895c0..1fd9d13 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -41,7 +41,6 @@
z(0),
w(0),
h(0),
- layerStack(0),
alpha(0),
flags(0),
mask(0),
@@ -86,7 +85,7 @@
SAFE_PARCEL(output.writeInt32, z);
SAFE_PARCEL(output.writeUint32, w);
SAFE_PARCEL(output.writeUint32, h);
- SAFE_PARCEL(output.writeUint32, layerStack);
+ SAFE_PARCEL(output.writeUint32, layerStack.id);
SAFE_PARCEL(output.writeFloat, alpha);
SAFE_PARCEL(output.writeUint32, flags);
SAFE_PARCEL(output.writeUint32, mask);
@@ -174,6 +173,7 @@
SAFE_PARCEL(output.write, destinationFrame);
SAFE_PARCEL(output.writeBool, isTrustedOverlay);
+ SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
return NO_ERROR;
}
@@ -187,7 +187,7 @@
SAFE_PARCEL(input.readInt32, &z);
SAFE_PARCEL(input.readUint32, &w);
SAFE_PARCEL(input.readUint32, &h);
- SAFE_PARCEL(input.readUint32, &layerStack);
+ SAFE_PARCEL(input.readUint32, &layerStack.id);
SAFE_PARCEL(input.readFloat, &alpha);
SAFE_PARCEL(input.readUint32, &flags);
@@ -303,6 +303,7 @@
SAFE_PARCEL(input.read, destinationFrame);
SAFE_PARCEL(input.readBool, &isTrustedOverlay);
+ SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
return NO_ERROR;
}
@@ -314,21 +315,14 @@
return state.read(input);
}
-DisplayState::DisplayState()
- : what(0),
- layerStack(0),
- flags(0),
- layerStackSpaceRect(Rect::EMPTY_RECT),
- orientedDisplaySpaceRect(Rect::EMPTY_RECT),
- width(0),
- height(0) {}
+DisplayState::DisplayState() = default;
status_t DisplayState::write(Parcel& output) const {
SAFE_PARCEL(output.writeStrongBinder, token);
SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(surface));
SAFE_PARCEL(output.writeUint32, what);
- SAFE_PARCEL(output.writeUint32, layerStack);
SAFE_PARCEL(output.writeUint32, flags);
+ SAFE_PARCEL(output.writeUint32, layerStack.id);
SAFE_PARCEL(output.writeUint32, toRotationInt(orientation));
SAFE_PARCEL(output.write, layerStackSpaceRect);
SAFE_PARCEL(output.write, orientedDisplaySpaceRect);
@@ -344,8 +338,8 @@
surface = interface_cast<IGraphicBufferProducer>(tmpBinder);
SAFE_PARCEL(input.readUint32, &what);
- SAFE_PARCEL(input.readUint32, &layerStack);
SAFE_PARCEL(input.readUint32, &flags);
+ SAFE_PARCEL(input.readUint32, &layerStack.id);
uint32_t tmpUint = 0;
SAFE_PARCEL(input.readUint32, &tmpUint);
orientation = ui::toRotation(tmpUint);
@@ -461,6 +455,7 @@
if (other.what & eBufferChanged) {
what |= eBufferChanged;
buffer = other.buffer;
+ releaseBufferEndpoint = other.releaseBufferEndpoint;
}
if (other.what & eAcquireFenceChanged) {
what |= eAcquireFenceChanged;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index f620f5a..05554ca 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -147,8 +147,16 @@
return mCallbackIdCounter++;
}
+sp<TransactionCompletedListener> TransactionCompletedListener::sInstance = nullptr;
+
+void TransactionCompletedListener::setInstance(const sp<TransactionCompletedListener>& listener) {
+ sInstance = listener;
+}
+
sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
- static sp<TransactionCompletedListener> sInstance = new TransactionCompletedListener;
+ if (sInstance == nullptr) {
+ sInstance = new TransactionCompletedListener;
+ }
return sInstance;
}
@@ -1087,7 +1095,7 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayerStack(
- const sp<SurfaceControl>& sc, uint32_t layerStack) {
+ const sp<SurfaceControl>& sc, ui::LayerStack layerStack) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
@@ -1274,6 +1282,7 @@
removeReleaseBufferCallback(s);
s->what |= layer_state_t::eBufferChanged;
s->buffer = buffer;
+ s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance());
if (mIsAutoTimestamp) {
mDesiredPresentTime = systemTime();
}
@@ -1751,7 +1760,7 @@
}
void SurfaceComposerClient::Transaction::setDisplayLayerStack(const sp<IBinder>& token,
- uint32_t layerStack) {
+ ui::LayerStack layerStack) {
DisplayState& s(getDisplayState(token));
s.layerStack = layerStack;
s.what |= DisplayState::eLayerStackChanged;
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index ff0bb8a..b2ef7aa 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -54,8 +54,8 @@
info.frameLeft == frameLeft && info.frameTop == frameTop &&
info.frameRight == frameRight && info.frameBottom == frameBottom &&
info.surfaceInset == surfaceInset && info.globalScaleFactor == globalScaleFactor &&
- info.transform == transform && info.displayWidth == displayWidth &&
- info.displayHeight == displayHeight &&
+ info.transform == transform && info.displayOrientation == displayOrientation &&
+ info.displayWidth == displayWidth && info.displayHeight == displayHeight &&
info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible &&
info.trustedOverlay == trustedOverlay && info.focusable == focusable &&
info.touchOcclusionMode == touchOcclusionMode && info.hasWallpaper == hasWallpaper &&
@@ -97,6 +97,7 @@
parcel->writeFloat(transform.dtdy()) ?:
parcel->writeFloat(transform.dsdy()) ?:
parcel->writeFloat(transform.ty()) ?:
+ parcel->writeUint32(displayOrientation) ?:
parcel->writeInt32(displayWidth) ?:
parcel->writeInt32(displayHeight) ?:
parcel->writeBool(visible) ?:
@@ -114,7 +115,8 @@
applicationInfo.writeToParcel(parcel) ?:
parcel->write(touchableRegion) ?:
parcel->writeBool(replaceTouchableRegionWithCrop) ?:
- parcel->writeStrongBinder(touchableRegionCropHandle.promote());
+ parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
+ parcel->writeStrongBinder(windowToken);
// clang-format on
return status;
}
@@ -153,6 +155,7 @@
parcel->readFloat(&dtdy) ?:
parcel->readFloat(&dsdy) ?:
parcel->readFloat(&ty) ?:
+ parcel->readUint32(&displayOrientation) ?:
parcel->readInt32(&displayWidth) ?:
parcel->readInt32(&displayHeight) ?:
parcel->readBool(&visible) ?:
@@ -188,7 +191,8 @@
touchableRegionCropHandle = parcel->readStrongBinder();
transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
- return OK;
+ status = parcel->readNullableStrongBinder(&windowToken);
+ return status;
}
// --- WindowInfoHandle ---
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b27d9cf..f14127c 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -35,6 +35,7 @@
#include <math/vec3.h>
#include <ui/BlurRegion.h>
#include <ui/GraphicTypes.h>
+#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Rotation.h>
@@ -143,7 +144,7 @@
int32_t z;
uint32_t w;
uint32_t h;
- uint32_t layerStack;
+ ui::LayerStack layerStack = ui::DEFAULT_LAYER_STACK;
float alpha;
uint32_t flags;
uint32_t mask;
@@ -242,6 +243,11 @@
// is used to remove the old callback from the client process map if it is
// overwritten by another setBuffer call.
ReleaseCallbackId releaseCallbackId;
+
+ // Stores which endpoint the release information should be sent to. We don't want to send the
+ // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
+ // was called with.
+ sp<IBinder> releaseBufferEndpoint;
};
struct ComposerState {
@@ -262,11 +268,12 @@
DisplayState();
void merge(const DisplayState& other);
- uint32_t what;
+ uint32_t what = 0;
+ uint32_t flags = 0;
sp<IBinder> token;
sp<IGraphicBufferProducer> surface;
- uint32_t layerStack;
- uint32_t flags;
+
+ ui::LayerStack layerStack = ui::DEFAULT_LAYER_STACK;
// These states define how layers are projected onto the physical display.
//
@@ -280,10 +287,11 @@
// will be additionally rotated by 90 degrees around the origin clockwise and translated by (W,
// 0).
ui::Rotation orientation = ui::ROTATION_0;
- Rect layerStackSpaceRect;
- Rect orientedDisplaySpaceRect;
+ Rect layerStackSpaceRect = Rect::EMPTY_RECT;
+ Rect orientedDisplaySpaceRect = Rect::EMPTY_RECT;
- uint32_t width, height;
+ uint32_t width = 0;
+ uint32_t height = 0;
status_t write(Parcel& output) const;
status_t read(const Parcel& input);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 869cef6..a980ce2 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -456,7 +456,7 @@
int backgroundBlurRadius);
Transaction& setBlurRegions(const sp<SurfaceControl>& sc,
const std::vector<BlurRegion>& regions);
- Transaction& setLayerStack(const sp<SurfaceControl>& sc, uint32_t layerStack);
+ Transaction& setLayerStack(const sp<SurfaceControl>&, ui::LayerStack);
Transaction& setMetadata(const sp<SurfaceControl>& sc, uint32_t key, const Parcel& p);
/// Reparents the current layer to the new parent handle. The new parent must not be null.
@@ -566,7 +566,7 @@
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
- void setDisplayLayerStack(const sp<IBinder>& token, uint32_t layerStack);
+ void setDisplayLayerStack(const sp<IBinder>& token, ui::LayerStack);
void setDisplayFlags(const sp<IBinder>& token, uint32_t flags);
@@ -652,8 +652,10 @@
};
class TransactionCompletedListener : public BnTransactionCompletedListener {
+public:
TransactionCompletedListener();
+protected:
int64_t getNextIdLocked() REQUIRES(mMutex);
std::mutex mMutex;
@@ -731,8 +733,12 @@
void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t transformHint,
uint32_t currentMaxAcquiredBufferCount) override;
+ // For Testing Only
+ static void setInstance(const sp<TransactionCompletedListener>&);
+
private:
ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
+ static sp<TransactionCompletedListener> sInstance;
};
} // namespace android
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index 7af1f0e..f090c63 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -132,6 +132,10 @@
// This value should NOT be used to uniquely identify the window. There may be different
// input windows that have the same token.
sp<IBinder> token;
+
+ // The token that identifies which client window this WindowInfo was created for.
+ sp<IBinder> windowToken;
+
// This uniquely identifies the input window.
int32_t id = -1;
std::string name;
@@ -164,7 +168,7 @@
// Transform applied to individual windows.
ui::Transform transform;
- // Display orientation. Used for compatibility raw coordinates.
+ // Display orientation as ui::Transform::RotationFlags. Used for compatibility raw coordinates.
uint32_t displayOrientation = ui::Transform::ROT_0;
// Display size in its natural rotation. Used to rotate raw coordinates for compatibility.
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 9082d27..26d902d 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -128,7 +128,7 @@
mDisplayToken = mClient->getInternalDisplayToken();
ASSERT_NE(nullptr, mDisplayToken.get());
Transaction t;
- t.setDisplayLayerStack(mDisplayToken, 0);
+ t.setDisplayLayerStack(mDisplayToken, ui::DEFAULT_LAYER_STACK);
t.apply();
t.clear();
@@ -142,7 +142,7 @@
mDisplayHeight, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState,
/*parent*/ nullptr);
- t.setLayerStack(mSurfaceControl, 0)
+ t.setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK)
.setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
.show(mSurfaceControl)
.setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB)
@@ -490,7 +490,7 @@
ISurfaceComposerClient::eFXSurfaceEffect);
ASSERT_NE(nullptr, bg.get());
Transaction t;
- t.setLayerStack(bg, 0)
+ t.setLayerStack(bg, ui::DEFAULT_LAYER_STACK)
.setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
.setColor(bg, half3{0, 0, 0})
.setLayer(bg, 0)
@@ -545,7 +545,7 @@
ISurfaceComposerClient::eFXSurfaceEffect);
ASSERT_NE(nullptr, bg.get());
Transaction t;
- t.setLayerStack(bg, 0)
+ t.setLayerStack(bg, ui::DEFAULT_LAYER_STACK)
.setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
.setColor(bg, half3{0, 0, 0})
.setLayer(bg, 0)
@@ -612,7 +612,7 @@
ISurfaceComposerClient::eFXSurfaceEffect);
ASSERT_NE(nullptr, bg.get());
Transaction t;
- t.setLayerStack(bg, 0)
+ t.setLayerStack(bg, ui::DEFAULT_LAYER_STACK)
.setCrop(bg, Rect(0, 0, mDisplayWidth, mDisplayHeight))
.setColor(bg, half3{0, 0, 0})
.setLayer(bg, 0)
@@ -733,7 +733,7 @@
ISurfaceComposerClient::eFXSurfaceBufferState);
ASSERT_NE(nullptr, bgSurface.get());
Transaction t;
- t.setLayerStack(bgSurface, 0)
+ t.setLayerStack(bgSurface, ui::DEFAULT_LAYER_STACK)
.show(bgSurface)
.setDataspace(bgSurface, ui::Dataspace::V0_SRGB)
.setLayer(bgSurface, std::numeric_limits<int32_t>::max() - 1)
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index 58f3981..a4f436c 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -46,6 +46,7 @@
sp<IBinder> touchableRegionCropHandle = new BBinder();
WindowInfo i;
i.token = new BBinder();
+ i.windowToken = new BBinder();
i.id = 1;
i.name = "Foobar";
i.flags = WindowInfo::Flag::SLIPPERY;
@@ -85,6 +86,7 @@
WindowInfo i2;
i2.readFromParcel(&p);
ASSERT_EQ(i.token, i2.token);
+ ASSERT_EQ(i.windowToken, i2.windowToken);
ASSERT_EQ(i.id, i2.id);
ASSERT_EQ(i.name, i2.name);
ASSERT_EQ(i.flags, i2.flags);
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 6eaa84e..bac44c9 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -272,10 +272,11 @@
status_t attachToContext(uint32_t tex);
sp<GraphicBuffer> dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
- float* outTransformMatrix, bool* outQueueEmpty,
+ float* outTransformMatrix, uint32_t* outTransform,
+ bool* outQueueEmpty,
SurfaceTexture_createReleaseFence createFence,
SurfaceTexture_fenceWait fenceWait,
- void* fencePassThroughHandle);
+ void* fencePassThroughHandle, ARect* currentCrop);
/**
* takeConsumerOwnership attaches a SurfaceTexture that is currently in the
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index 85fe42f..e85009c 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -84,10 +84,11 @@
*/
AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
android_dataspace* outDataspace,
- float* outTransformMatrix, bool* outNewContent,
+ float* outTransformMatrix, uint32_t* outTransform,
+ bool* outNewContent,
ASurfaceTexture_createReleaseFence createFence,
ASurfaceTexture_fenceWait fenceWait,
- void* fencePassThroughHandle);
+ void* fencePassThroughHandle, ARect* currentCrop);
} // namespace android
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index 62db6d0..3535e67 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -464,10 +464,11 @@
}
sp<GraphicBuffer> SurfaceTexture::dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
- float* outTransformMatrix, bool* outQueueEmpty,
+ float* outTransformMatrix, uint32_t* outTransform,
+ bool* outQueueEmpty,
SurfaceTexture_createReleaseFence createFence,
SurfaceTexture_fenceWait fenceWait,
- void* fencePassThroughHandle) {
+ void* fencePassThroughHandle, ARect* currentCrop) {
Mutex::Autolock _l(mMutex);
sp<GraphicBuffer> buffer;
@@ -484,6 +485,8 @@
buffer = mImageConsumer.dequeueBuffer(outSlotid, outDataspace, outQueueEmpty, *this,
createFence, fenceWait, fencePassThroughHandle);
memcpy(outTransformMatrix, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+ *outTransform = mCurrentTransform;
+ *currentCrop = mCurrentCrop;
return buffer;
}
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index c214ab7..cc0a12d 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -194,15 +194,18 @@
AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
android_dataspace* outDataspace,
- float* outTransformMatrix, bool* outNewContent,
+ float* outTransformMatrix, uint32_t* outTransform,
+ bool* outNewContent,
ASurfaceTexture_createReleaseFence createFence,
- ASurfaceTexture_fenceWait fenceWait, void* handle) {
+ ASurfaceTexture_fenceWait fenceWait, void* handle,
+ ARect* currentCrop) {
sp<GraphicBuffer> buffer;
*outNewContent = false;
bool queueEmpty;
do {
buffer = st->consumer->dequeueBuffer(outSlotid, outDataspace, outTransformMatrix,
- &queueEmpty, createFence, fenceWait, handle);
+ outTransform, &queueEmpty, createFence, fenceWait,
+ handle, currentCrop);
if (!queueEmpty) {
*outNewContent = true;
}
diff --git a/libs/ui/include/ui/DisplayState.h b/libs/ui/include/ui/DisplayState.h
index 70a0d50..98ee356 100644
--- a/libs/ui/include/ui/DisplayState.h
+++ b/libs/ui/include/ui/DisplayState.h
@@ -16,21 +16,18 @@
#pragma once
+#include <ui/LayerStack.h>
#include <ui/Rotation.h>
#include <ui/Size.h>
-#include <cstdint>
#include <type_traits>
namespace android::ui {
-using LayerStack = uint32_t;
-constexpr LayerStack NO_LAYER_STACK = static_cast<LayerStack>(-1);
-
// Transactional state of physical or virtual display. Note that libgui defines
// android::DisplayState as a superset of android::ui::DisplayState.
struct DisplayState {
- LayerStack layerStack = NO_LAYER_STACK;
+ LayerStack layerStack;
Rotation orientation = ROTATION_0;
Size layerStackSpaceRect;
};
diff --git a/libs/ui/include/ui/LayerStack.h b/libs/ui/include/ui/LayerStack.h
new file mode 100644
index 0000000..d6ffeb7
--- /dev/null
+++ b/libs/ui/include/ui/LayerStack.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <ftl/cast.h>
+#include <ftl/string.h>
+#include <log/log.h>
+
+namespace android::ui {
+
+// A LayerStack identifies a Z-ordered group of layers. A layer can only be associated to a single
+// LayerStack, but a LayerStack can be associated to multiple displays, mirroring the same content.
+struct LayerStack {
+ uint32_t id = UINT32_MAX;
+
+ template <typename T>
+ static constexpr LayerStack fromValue(T v) {
+ if (ftl::cast_safety<uint32_t>(v) == ftl::CastSafety::kSafe) {
+ return {static_cast<uint32_t>(v)};
+ }
+
+ ALOGW("Invalid layer stack %s", ftl::to_string(v).c_str());
+ return {};
+ }
+};
+
+constexpr LayerStack INVALID_LAYER_STACK;
+constexpr LayerStack DEFAULT_LAYER_STACK{0u};
+
+inline bool operator==(LayerStack lhs, LayerStack rhs) {
+ return lhs.id == rhs.id;
+}
+
+inline bool operator!=(LayerStack lhs, LayerStack rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator>(LayerStack lhs, LayerStack rhs) {
+ return lhs.id > rhs.id;
+}
+
+// A LayerFilter determines if a layer is included for output to a display.
+struct LayerFilter {
+ LayerStack layerStack;
+
+ // True if the layer is only output to internal displays, i.e. excluded from screenshots, screen
+ // recordings, and mirroring to virtual or external displays. Used for display cutout overlays.
+ bool toInternalDisplay = false;
+
+ // Returns true if the input filter can be output to this filter.
+ bool includes(LayerFilter other) const {
+ // The layer stacks must match.
+ if (other.layerStack == INVALID_LAYER_STACK || other.layerStack != layerStack) {
+ return false;
+ }
+
+ // The output must be to an internal display if the input filter has that constraint.
+ return !other.toInternalDisplay || toInternalDisplay;
+ }
+};
+
+} // namespace android::ui
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 1478a3c..59cb419 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -5047,12 +5047,13 @@
windowInfo->inputFeatures.string().c_str());
dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64
"ms, trustedOverlay=%s, hasToken=%s, "
- "touchOcclusionMode=%s\n",
+ "touchOcclusionMode=%s, displayOrientation=%d\n",
windowInfo->ownerPid, windowInfo->ownerUid,
millis(windowInfo->dispatchingTimeout),
toString(windowInfo->trustedOverlay),
toString(windowInfo->token != nullptr),
- toString(windowInfo->touchOcclusionMode).c_str());
+ toString(windowInfo->touchOcclusionMode).c_str(),
+ windowInfo->displayOrientation);
windowInfo->transform.dump(dump, "transform", INDENT4);
}
} else {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index af02844..a9f0247 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -896,6 +896,13 @@
mTiltXScale = M_PI / 180;
mTiltYScale = M_PI / 180;
+ if (mRawPointerAxes.tiltX.resolution) {
+ mTiltXScale = 1.0 / mRawPointerAxes.tiltX.resolution;
+ }
+ if (mRawPointerAxes.tiltY.resolution) {
+ mTiltYScale = 1.0 / mRawPointerAxes.tiltY.resolution;
+ }
+
mOrientedRanges.haveTilt = true;
mOrientedRanges.tilt.axis = AMOTION_EVENT_AXIS_TILT;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 50e1854..0fc4708 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,6 +16,7 @@
#include "../dispatcher/InputDispatcher.h"
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
#include <binder/Binder.h>
@@ -678,7 +679,11 @@
// --- InputDispatcherTest SetInputWindowTest ---
static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
-static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
+// Default input dispatching timeout if there is no focused application or paused window
+// from which to determine an appropriate dispatching timeout.
+static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
+ android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
+ android::base::HwTimeoutMultiplier());
class FakeApplicationHandle : public InputApplicationHandle {
public:
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c233bf0..c351676 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -168,7 +168,7 @@
}
}
- // Sanity check and clamp power if it is 0 (or close)
+ // Check and clamp power if it is 0 (or close)
constexpr float MIN_POWER_MA = 0.001; // 1 microAmp
if (sensor.power < MIN_POWER_MA) {
ALOGI("%s's reported power %f invalid, clamped to %f",
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 9ce8d9b..c58e992 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -867,7 +867,7 @@
} else if (numBytesRead == sizeof(uint32_t)) {
uint32_t numAcks = 0;
memcpy(&numAcks, buf, numBytesRead);
- // Sanity check to ensure there are no read errors in recv, numAcks is always
+ // Check to ensure there are no read errors in recv, numAcks is always
// within the range and not zero. If any of the above don't hold reset
// mWakeLockRefCount to zero.
if (numAcks > 0 && numAcks < mWakeLockRefCount) {
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 726fe8e..3081b1a 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -1197,7 +1197,7 @@
// We have a dynamic sensor.
if (!sHmacGlobalKeyIsValid) {
- // Rather than risk exposing UUIDs, we cripple dynamic sensors.
+ // Rather than risk exposing UUIDs, we slow down dynamic sensors.
ALOGW("HMAC key failure; dynamic sensor getId() will be wrong.");
return 0;
}
@@ -1223,7 +1223,7 @@
sHmacGlobalKey, sizeof(sHmacGlobalKey),
uuidAndApp, sizeof(uuidAndApp),
hash, &hashLen) == nullptr) {
- // Rather than risk exposing UUIDs, we cripple dynamic sensors.
+ // Rather than risk exposing UUIDs, we slow down dynamic sensors.
ALOGW("HMAC failure; dynamic sensor getId() will be wrong.");
return 0;
}
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 8bc51df..4d86598 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-// 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"
-
//#define LOG_NDEBUG 0
#undef LOG_TAG
#define LOG_TAG "BufferStateLayer"
@@ -158,7 +153,8 @@
// transaction doesn't need a previous release fence.
sp<CallbackHandle> ch;
for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer) {
+ if (handle->releasePreviousBuffer &&
+ mDrawingState.releaseBufferEndpoint == handle->listener) {
ch = handle;
break;
}
@@ -199,14 +195,9 @@
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
}
- // If there are multiple transactions in this frame, set the previous id on the earliest
- // transacton. We don't need to pass in the released buffer id to multiple transactions.
- // The buffer id does not have to correspond to any particular transaction as long as the
- // listening end point is the same but the client expects the first transaction callback that
- // replaces the presented buffer to contain the release fence. This follows the same logic.
- // see BufferStateLayer::onLayerDisplayed.
for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer) {
+ if (handle->releasePreviousBuffer &&
+ mDrawingState.releaseBufferEndpoint == handle->listener) {
handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
break;
}
@@ -420,7 +411,8 @@
nsecs_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& clientCacheId, uint64_t frameNumber,
std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
- const sp<ITransactionCompletedListener>& releaseBufferListener) {
+ const sp<ITransactionCompletedListener>& releaseBufferListener,
+ const sp<IBinder>& releaseBufferEndpoint) {
ATRACE_CALL();
if (mDrawingState.buffer) {
@@ -485,6 +477,7 @@
mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
+ mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint;
return true;
}
@@ -598,7 +591,7 @@
return true;
}
-Rect BufferStateLayer::getBufferSize(const State& s) const {
+Rect BufferStateLayer::getBufferSize(const State& /*s*/) const {
// for buffer state layers we use the display frame size as the buffer size.
if (mBufferInfo.mBuffer == nullptr) {
@@ -620,7 +613,7 @@
}
}
- return Rect(0, 0, bufWidth, bufHeight);
+ return Rect(0, 0, static_cast<int32_t>(bufWidth), static_cast<int32_t>(bufHeight));
}
FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const {
@@ -819,7 +812,7 @@
eraseBufferLocked(clientCacheId);
}
-uint32_t BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
+int BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
std::lock_guard<std::mutex> lock(mMutex);
auto itr = mCachedBuffers.find(clientCacheId);
if (itr == mCachedBuffers.end()) {
@@ -830,7 +823,7 @@
return hwcCacheSlot;
}
-uint32_t BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
+int BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
REQUIRES(mMutex) {
if (!clientCacheId.isValid()) {
ALOGE("invalid process, returning invalid slot");
@@ -839,17 +832,17 @@
ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this));
- uint32_t hwcCacheSlot = getFreeHwcCacheSlot();
+ int hwcCacheSlot = getFreeHwcCacheSlot();
mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++};
return hwcCacheSlot;
}
-uint32_t BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
+int BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
if (mFreeHwcCacheSlots.empty()) {
evictLeastRecentlyUsed();
}
- uint32_t hwcCacheSlot = mFreeHwcCacheSlots.top();
+ int hwcCacheSlot = mFreeHwcCacheSlots.top();
mFreeHwcCacheSlots.pop();
return hwcCacheSlot;
}
@@ -936,8 +929,8 @@
return false;
}
- uint32_t bufferWidth = s.buffer->getBuffer()->width;
- uint32_t bufferHeight = s.buffer->getBuffer()->height;
+ int32_t bufferWidth = s.buffer->getBuffer()->width;
+ int32_t bufferHeight = s.buffer->getBuffer()->height;
// Undo any transformations on the buffer and return the result.
if (s.bufferTransform & ui::Transform::ROT_90) {
@@ -996,6 +989,3 @@
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index cab4899..124e91a 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -59,7 +59,8 @@
const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber,
std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
- const sp<ITransactionCompletedListener>& transactionListener) override;
+ const sp<ITransactionCompletedListener>& transactionListener,
+ const sp<IBinder>& releaseBufferEndpoint) override;
bool setAcquireFence(const sp<Fence>& fence) override;
bool setDataspace(ui::Dataspace dataspace) override;
bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
@@ -177,19 +178,19 @@
class HwcSlotGenerator : public ClientCache::ErasedRecipient {
public:
HwcSlotGenerator() {
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
mFreeHwcCacheSlots.push(i);
}
}
void bufferErased(const client_cache_t& clientCacheId);
- uint32_t getHwcCacheSlot(const client_cache_t& clientCacheId);
+ int getHwcCacheSlot(const client_cache_t& clientCacheId);
private:
friend class SlotGenerationTest;
- uint32_t addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
- uint32_t getFreeHwcCacheSlot() REQUIRES(mMutex);
+ int addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+ int getFreeHwcCacheSlot() REQUIRES(mMutex);
void evictLeastRecentlyUsed() REQUIRES(mMutex);
void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex);
@@ -201,11 +202,10 @@
std::mutex mMutex;
- std::unordered_map<client_cache_t,
- std::pair<uint32_t /*HwcCacheSlot*/, uint32_t /*counter*/>,
+ std::unordered_map<client_cache_t, std::pair<int /*HwcCacheSlot*/, uint64_t /*counter*/>,
CachedBufferHash>
mCachedBuffers GUARDED_BY(mMutex);
- std::stack<uint32_t /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
+ std::stack<int /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
// The cache increments this counter value when a slot is updated or used.
// Used to track the least recently-used buffer
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 554e2f4..95d553d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -47,9 +47,6 @@
// All the layers that have queued updates.
Layers layersWithQueuedFrames;
- // If true, forces the entire display to be considered dirty and repainted
- bool repaintEverything{false};
-
// Controls how the color mode is chosen for an output
OutputColorSetting outputColorSetting{OutputColorSetting::kEnhanced};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
index 526e7da..98c4af4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
@@ -36,18 +36,12 @@
struct DisplayCreationArgs {
DisplayId id;
- // Unset for virtual displays
- std::optional<ui::DisplayConnectionType> connectionType;
-
// Size of the display in pixels
ui::Size pixels = ui::kInvalidSize;
// True if this display should be considered secure
bool isSecure = false;
- // Gives the initial layer stack id to be used for the display
- uint32_t layerStackId = ~0u;
-
// Optional pointer to the power advisor interface, if one is needed for
// this display.
Hwc2::PowerAdvisor* powerAdvisor = nullptr;
@@ -69,11 +63,6 @@
return *this;
}
- DisplayCreationArgsBuilder& setConnectionType(ui::DisplayConnectionType connectionType) {
- mArgs.connectionType = connectionType;
- return *this;
- }
-
DisplayCreationArgsBuilder& setPixels(ui::Size pixels) {
mArgs.pixels = pixels;
return *this;
@@ -84,11 +73,6 @@
return *this;
}
- DisplayCreationArgsBuilder& setLayerStackId(uint32_t layerStackId) {
- mArgs.layerStackId = layerStackId;
- return *this;
- }
-
DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) {
mArgs.powerAdvisor = powerAdvisor;
return *this;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index a45be8a..ecb4e6d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -22,6 +22,7 @@
#include <math/mat4.h>
#include <ui/BlurRegion.h>
#include <ui/FloatRect.h>
+#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Transform.h>
@@ -93,11 +94,9 @@
/*
* Visibility state
*/
- // the layer stack this layer belongs to
- std::optional<uint32_t> layerStackId;
- // If true, this layer should be only visible on the internal display
- bool internalOnly{false};
+ // The filter that determines which outputs include this layer
+ ui::LayerFilter outputFilter;
// If false, this layer should not be considered visible
bool isVisible{true};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 15a86af..a33b57d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -28,6 +28,7 @@
#include <renderengine/LayerSettings.h>
#include <ui/Fence.h>
#include <ui/GraphicTypes.h>
+#include <ui/LayerStack.h>
#include <ui/Region.h>
#include <ui/Transform.h>
#include <utils/StrongPointer.h>
@@ -180,9 +181,8 @@
// output.
virtual ui::Transform::RotationFlags getTransformHint() const = 0;
- // Sets the layer stack filtering settings for this output. See
- // belongsInOutput for full details.
- virtual void setLayerStackFilter(uint32_t layerStackId, bool isInternal) = 0;
+ // Sets the filter for this output. See Output::includesLayer.
+ virtual void setLayerFilter(ui::LayerFilter) = 0;
// Sets the output color mode
virtual void setColorProfile(const ColorProfile&) = 0;
@@ -221,20 +221,12 @@
virtual OutputCompositionState& editState() = 0;
// Gets the dirty region in layer stack space.
- // If repaintEverything is true, this will be the full display bounds.
- virtual Region getDirtyRegion(bool repaintEverything) const = 0;
+ virtual Region getDirtyRegion() const = 0;
- // Tests whether a given layerStackId belongs in this output.
- // A layer belongs to the output if its layerStackId matches the of the output layerStackId,
- // unless the layer should display on the primary output only and this is not the primary output
-
- // A layer belongs to the output if its layerStackId matches. Additionally
- // if the layer should only show in the internal (primary) display only and
- // this output allows that.
- virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;
-
- // Determines if a layer belongs to the output.
- virtual bool belongsInOutput(const sp<LayerFE>&) const = 0;
+ // Returns whether the output includes a layer, based on their respective filters.
+ // See Output::setLayerFilter.
+ virtual bool includesLayer(ui::LayerFilter) const = 0;
+ virtual bool includesLayer(const sp<LayerFE>&) const = 0;
// Returns a pointer to the output layer corresponding to the given layer on
// this output, or nullptr if the layer does not have one
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index bb540ea..b407267 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -83,9 +83,8 @@
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
private:
- bool mIsVirtual = false;
- bool mIsDisconnected = false;
DisplayId mId;
+ bool mIsDisconnected = false;
Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
index 6b9597b..7521324 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DumpHelpers.h
@@ -22,6 +22,7 @@
#include <math/mat4.h>
#include <ui/FloatRect.h>
+#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/StretchEffect.h>
@@ -52,13 +53,14 @@
dumpVal(out, name, valueName, static_cast<std::underlying_type_t<EnumType>>(value));
}
-void dumpVal(std::string& out, const char* name, const FloatRect& rect);
-void dumpVal(std::string& out, const char* name, const Rect& rect);
-void dumpVal(std::string& out, const char* name, const Region& region);
-void dumpVal(std::string& out, const char* name, const ui::Transform&);
-void dumpVal(std::string& out, const char* name, const ui::Size&);
+void dumpVal(std::string& out, const char* name, ui::LayerFilter);
+void dumpVal(std::string& out, const char* name, ui::Size);
-void dumpVal(std::string& out, const char* name, const mat4& tr);
+void dumpVal(std::string& out, const char* name, const FloatRect&);
+void dumpVal(std::string& out, const char* name, const Rect&);
+void dumpVal(std::string& out, const char* name, const Region&);
+void dumpVal(std::string& out, const char* name, const ui::Transform&);
+void dumpVal(std::string& out, const char* name, const mat4&);
void dumpVal(std::string& out, const char* name, const StretchEffect&);
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 14f2163..6d49ce6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -23,6 +23,7 @@
#include <compositionengine/impl/planner/Planner.h>
#include <renderengine/DisplaySettings.h>
#include <renderengine/LayerSettings.h>
+
#include <memory>
#include <utility>
#include <vector>
@@ -45,7 +46,7 @@
void setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
const Rect& orientedDisplaySpaceRect) override;
void setDisplaySize(const ui::Size&) override;
- void setLayerStackFilter(uint32_t layerStackId, bool isInternal) override;
+ void setLayerFilter(ui::LayerFilter) override;
ui::Transform::RotationFlags getTransformHint() const override;
void setColorTransform(const compositionengine::CompositionRefreshArgs&) override;
@@ -64,9 +65,10 @@
compositionengine::RenderSurface* getRenderSurface() const override;
void setRenderSurface(std::unique_ptr<compositionengine::RenderSurface>) override;
- Region getDirtyRegion(bool repaintEverything) const override;
- bool belongsInOutput(std::optional<uint32_t>, bool) const override;
- bool belongsInOutput(const sp<LayerFE>&) const override;
+ Region getDirtyRegion() const override;
+
+ bool includesLayer(ui::LayerFilter) const override;
+ bool includesLayer(const sp<LayerFE>&) const override;
compositionengine::OutputLayer* getOutputLayerForLayer(const sp<LayerFE>&) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index f34cb94..44f754f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -32,6 +32,7 @@
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
#include <compositionengine/ProjectionSpace.h>
+#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Transform.h>
@@ -59,11 +60,8 @@
// If true, the current frame reused the buffer from a previous client composition
bool reusedClientComposition{false};
- // If true, this output displays layers that are internal-only
- bool layerStackInternal{false};
-
- // The layer stack to display on this display
- uint32_t layerStackId{~0u};
+ // The conditions for including a layer on this output
+ ui::LayerFilter layerFilter;
// The common space for all layers in the layer stack. layerStackSpace.content is the Rect
// which gets projected on the display. The orientation of this space is always ROTATION_0.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 216019f..344b2f9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -40,9 +40,12 @@
MOCK_METHOD1(setLayerCachingTexturePoolEnabled, void(bool));
MOCK_METHOD3(setProjection, void(ui::Rotation, const Rect&, const Rect&));
MOCK_METHOD1(setDisplaySize, void(const ui::Size&));
- MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool));
MOCK_CONST_METHOD0(getTransformHint, ui::Transform::RotationFlags());
+ MOCK_METHOD(void, setLayerFilter, (ui::LayerFilter));
+ MOCK_METHOD(bool, includesLayer, (ui::LayerFilter), (const));
+ MOCK_METHOD(bool, includesLayer, (const sp<compositionengine::LayerFE>&), (const));
+
MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
MOCK_METHOD2(setDisplayBrightness, void(float, float));
@@ -62,9 +65,7 @@
MOCK_CONST_METHOD0(getState, const OutputCompositionState&());
MOCK_METHOD0(editState, OutputCompositionState&());
- MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
- MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional<uint32_t>, bool));
- MOCK_CONST_METHOD1(belongsInOutput, bool(const sp<compositionengine::LayerFE>&));
+ MOCK_METHOD(Region, getDirtyRegion, (), (const));
MOCK_CONST_METHOD1(getOutputLayerForLayer,
compositionengine::OutputLayer*(const sp<compositionengine::LayerFE>&));
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 2f2c686..6b9ea87 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -51,12 +51,9 @@
void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
mId = args.id;
- mIsVirtual = !args.connectionType;
mPowerAdvisor = args.powerAdvisor;
editState().isSecure = args.isSecure;
editState().displaySpace.bounds = Rect(args.pixels);
- setLayerStackFilter(args.layerStackId,
- args.connectionType == ui::DisplayConnectionType::Internal);
setName(args.name);
}
@@ -73,7 +70,7 @@
}
bool Display::isVirtual() const {
- return mIsVirtual;
+ return VirtualDisplayId::tryCast(mId).has_value();
}
std::optional<DisplayId> Display::getDisplayId() const {
@@ -117,8 +114,8 @@
return;
}
- if (mIsVirtual) {
- ALOGW("%s: Invalid operation on virtual display", __FUNCTION__);
+ if (isVirtual()) {
+ ALOGW("%s: Invalid operation on virtual display", __func__);
return;
}
@@ -136,7 +133,7 @@
StringAppendF(&out, " Composition Display State: [\"%s\"]", getName().c_str());
out.append("\n ");
- dumpVal(out, "isVirtual", mIsVirtual);
+ dumpVal(out, "isVirtual", isVirtual());
dumpVal(out, "DisplayId", to_string(mId));
out.append("\n");
@@ -364,8 +361,7 @@
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
// 2) There is work to be done (the dirty region isn't empty)
- if (GpuVirtualDisplayId::tryCast(mId) &&
- getDirtyRegion(refreshArgs.repaintEverything).isEmpty()) {
+ if (GpuVirtualDisplayId::tryCast(mId) && getDirtyRegion().isEmpty()) {
ALOGV("Skipping display composition");
return;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
index 5565396..01c368d 100644
--- a/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DumpHelpers.cpp
@@ -63,6 +63,18 @@
dumpVal(out, name, valueName.c_str(), value);
}
+void dumpVal(std::string& out, const char* name, ui::LayerFilter filter) {
+ out.append(name);
+ out.append("={");
+ dumpVal(out, "layerStack", filter.layerStack.id);
+ dumpVal(out, "toInternalDisplay", filter.toInternalDisplay);
+ out.push_back('}');
+}
+
+void dumpVal(std::string& out, const char* name, ui::Size size) {
+ StringAppendF(&out, "%s=[%d %d] ", name, size.width, size.height);
+}
+
void dumpVal(std::string& out, const char* name, const FloatRect& rect) {
StringAppendF(&out, "%s=[%f %f %f %f] ", name, rect.left, rect.top, rect.right, rect.bottom);
}
@@ -80,10 +92,6 @@
out.append(" ");
}
-void dumpVal(std::string& out, const char* name, const ui::Size& size) {
- StringAppendF(&out, "%s=[%d %d] ", name, size.width, size.height);
-}
-
void dumpVal(std::string& out, const char* name, const mat4& tr) {
StringAppendF(&out,
"%s=["
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 6ac488b..0ff5eca 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -227,11 +227,8 @@
return static_cast<ui::Transform::RotationFlags>(getState().transform.getOrientation());
}
-void Output::setLayerStackFilter(uint32_t layerStackId, bool isInternal) {
- auto& outputState = editState();
- outputState.layerStackId = layerStackId;
- outputState.layerStackInternal = isInternal;
-
+void Output::setLayerFilter(ui::LayerFilter filter) {
+ editState().layerFilter = filter;
dirtyEntireOutput();
}
@@ -371,26 +368,18 @@
mRenderSurface = std::move(surface);
}
-Region Output::getDirtyRegion(bool repaintEverything) const {
+Region Output::getDirtyRegion() const {
const auto& outputState = getState();
- Region dirty(outputState.layerStackSpace.content);
- if (!repaintEverything) {
- dirty.andSelf(outputState.dirtyRegion);
- }
- return dirty;
+ return outputState.dirtyRegion.intersect(outputState.layerStackSpace.content);
}
-bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
- // The layerStackId's must match, and also the layer must not be internal
- // only when not on an internal output.
- const auto& outputState = getState();
- return layerStackId && (*layerStackId == outputState.layerStackId) &&
- (!internalOnly || outputState.layerStackInternal);
+bool Output::includesLayer(ui::LayerFilter filter) const {
+ return getState().layerFilter.includes(filter);
}
-bool Output::belongsInOutput(const sp<compositionengine::LayerFE>& layerFE) const {
+bool Output::includesLayer(const sp<LayerFE>& layerFE) const {
const auto* layerFEState = layerFE->getCompositionState();
- return layerFEState && belongsInOutput(layerFEState->layerStackId, layerFEState->internalOnly);
+ return layerFEState && includesLayer(layerFEState->outputFilter);
}
std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
@@ -496,8 +485,8 @@
layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry);
}
- // Only consider the layers on the given layer stack
- if (!belongsInOutput(layerFE)) {
+ // Only consider the layers on this output
+ if (!includesLayer(layerFE)) {
return;
}
@@ -908,7 +897,7 @@
void Output::beginFrame() {
auto& outputState = editState();
- const bool dirty = !getDirtyRegion(false).isEmpty();
+ const bool dirty = !getDirtyRegion().isEmpty();
const bool empty = getOutputLayerCount() == 0;
const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
@@ -960,14 +949,9 @@
}
if (getState().isEnabled) {
- // transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = getDirtyRegion(refreshArgs.repaintEverything);
- if (!dirtyRegion.isEmpty()) {
- base::unique_fd readyFence;
- // redraw the whole screen
+ if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) {
static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs));
-
- mRenderSurface->queueBuffer(std::move(readyFence));
+ mRenderSurface->queueBuffer(base::unique_fd());
}
}
@@ -1122,7 +1106,7 @@
// bounds its framebuffer cache but Skia RenderEngine has no current policy. The best fix is
// probably to encapsulate the output buffer into a structure that dispatches resource cleanup
// over to RenderEngine, in which case this flag can be removed from the drawLayers interface.
- const bool useFramebufferCache = outputState.layerStackInternal;
+ const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay;
status_t status =
renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex,
useFramebufferCache, std::move(fd), &readyFence);
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index ee30ad8..acc9216 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -28,9 +28,7 @@
dumpVal(out, "usesDeviceComposition", usesDeviceComposition);
dumpVal(out, "flipClientTarget", flipClientTarget);
dumpVal(out, "reusedClientComposition", reusedClientComposition);
-
- dumpVal(out, "layerStack", layerStackId);
- dumpVal(out, "layerStackInternal", layerStackInternal);
+ dumpVal(out, "layerFilter", layerFilter);
out.append("\n ");
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 72b16e0..f2978f9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -61,7 +61,6 @@
constexpr GpuVirtualDisplayId GPU_VIRTUAL_DISPLAY_ID{789u};
constexpr ui::Size DEFAULT_RESOLUTION{1920, 1080};
-constexpr uint32_t DEFAULT_LAYER_STACK = 42;
struct Layer {
Layer() {
@@ -161,13 +160,11 @@
EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
}
- DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
+ DisplayCreationArgs getDisplayCreationArgsForPhysicalDisplay() {
return DisplayCreationArgsBuilder()
.setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(ui::DisplayConnectionType::Internal)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(true)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.build();
}
@@ -177,7 +174,6 @@
.setId(GPU_VIRTUAL_DISPLAY_ID)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(false)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.build();
}
@@ -193,14 +189,13 @@
using Display = DisplayTestCommon::PartialMockDisplay;
std::shared_ptr<Display> mDisplay =
createPartialMockDisplay<Display>(mCompositionEngine,
- getDisplayCreationArgsForPhysicalHWCDisplay());
+ getDisplayCreationArgsForPhysicalDisplay());
};
struct FullDisplayImplTestCommon : public DisplayTestCommon {
using Display = DisplayTestCommon::FullImplDisplay;
std::shared_ptr<Display> mDisplay =
- createDisplay<Display>(mCompositionEngine,
- getDisplayCreationArgsForPhysicalHWCDisplay());
+ createDisplay<Display>(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay());
};
struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon {
@@ -218,8 +213,7 @@
LayerNoHWC2Layer mLayer3;
StrictMock<HWC2::mock::Layer> hwc2LayerUnknown;
std::shared_ptr<Display> mDisplay =
- createDisplay<Display>(mCompositionEngine,
- getDisplayCreationArgsForPhysicalHWCDisplay());
+ createDisplay<Display>(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay());
};
/*
@@ -232,7 +226,7 @@
TEST_F(DisplayCreationTest, createPhysicalInternalDisplay) {
auto display =
- impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalHWCDisplay());
+ impl::createDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay());
EXPECT_TRUE(display->isSecure());
EXPECT_FALSE(display->isVirtual());
EXPECT_EQ(DEFAULT_DISPLAY_ID, display->getId());
@@ -252,13 +246,11 @@
using DisplaySetConfigurationTest = PartialMockDisplayTestCommon;
-TEST_F(DisplaySetConfigurationTest, configuresInternalSecurePhysicalDisplay) {
+TEST_F(DisplaySetConfigurationTest, configuresPhysicalDisplay) {
mDisplay->setConfiguration(DisplayCreationArgsBuilder()
.setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(ui::DisplayConnectionType::Internal)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(true)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.setName(getDisplayNameFromCurrentTest())
.build());
@@ -266,28 +258,11 @@
EXPECT_EQ(DEFAULT_DISPLAY_ID, mDisplay->getId());
EXPECT_TRUE(mDisplay->isSecure());
EXPECT_FALSE(mDisplay->isVirtual());
- EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId);
- EXPECT_TRUE(mDisplay->getState().layerStackInternal);
EXPECT_FALSE(mDisplay->isValid());
-}
-TEST_F(DisplaySetConfigurationTest, configuresExternalInsecurePhysicalDisplay) {
- mDisplay->setConfiguration(DisplayCreationArgsBuilder()
- .setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(ui::DisplayConnectionType::External)
- .setPixels(DEFAULT_RESOLUTION)
- .setIsSecure(false)
- .setLayerStackId(DEFAULT_LAYER_STACK)
- .setPowerAdvisor(&mPowerAdvisor)
- .setName(getDisplayNameFromCurrentTest())
- .build());
-
- EXPECT_EQ(DEFAULT_DISPLAY_ID, mDisplay->getId());
- EXPECT_FALSE(mDisplay->isSecure());
- EXPECT_FALSE(mDisplay->isVirtual());
- EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId);
- EXPECT_FALSE(mDisplay->getState().layerStackInternal);
- EXPECT_FALSE(mDisplay->isValid());
+ const auto& filter = mDisplay->getState().layerFilter;
+ EXPECT_EQ(ui::INVALID_LAYER_STACK, filter.layerStack);
+ EXPECT_FALSE(filter.toInternalDisplay);
}
TEST_F(DisplaySetConfigurationTest, configuresHalVirtualDisplay) {
@@ -295,7 +270,6 @@
.setId(HAL_VIRTUAL_DISPLAY_ID)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(false)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.setName(getDisplayNameFromCurrentTest())
.build());
@@ -303,9 +277,11 @@
EXPECT_EQ(HAL_VIRTUAL_DISPLAY_ID, mDisplay->getId());
EXPECT_FALSE(mDisplay->isSecure());
EXPECT_TRUE(mDisplay->isVirtual());
- EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId);
- EXPECT_FALSE(mDisplay->getState().layerStackInternal);
EXPECT_FALSE(mDisplay->isValid());
+
+ const auto& filter = mDisplay->getState().layerFilter;
+ EXPECT_EQ(ui::INVALID_LAYER_STACK, filter.layerStack);
+ EXPECT_FALSE(filter.toInternalDisplay);
}
TEST_F(DisplaySetConfigurationTest, configuresGpuVirtualDisplay) {
@@ -313,7 +289,6 @@
.setId(GPU_VIRTUAL_DISPLAY_ID)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(false)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.setName(getDisplayNameFromCurrentTest())
.build());
@@ -321,9 +296,11 @@
EXPECT_EQ(GPU_VIRTUAL_DISPLAY_ID, mDisplay->getId());
EXPECT_FALSE(mDisplay->isSecure());
EXPECT_TRUE(mDisplay->isVirtual());
- EXPECT_EQ(DEFAULT_LAYER_STACK, mDisplay->getState().layerStackId);
- EXPECT_FALSE(mDisplay->getState().layerStackInternal);
EXPECT_FALSE(mDisplay->isValid());
+
+ const auto& filter = mDisplay->getState().layerFilter;
+ EXPECT_EQ(ui::INVALID_LAYER_STACK, filter.layerStack);
+ EXPECT_FALSE(filter.toInternalDisplay);
}
/*
@@ -902,10 +879,7 @@
mDisplay->editState().layerStackSpace.content = Rect(0, 0, 1, 1);
mDisplay->editState().dirtyRegion = Region::INVALID_REGION;
- CompositionRefreshArgs refreshArgs;
- refreshArgs.repaintEverything = false;
-
- mDisplay->finishFrame(refreshArgs);
+ mDisplay->finishFrame({});
}
TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) {
@@ -923,10 +897,7 @@
gpuDisplay->editState().layerStackSpace.content = Rect(0, 0, 1, 1);
gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION;
- CompositionRefreshArgs refreshArgs;
- refreshArgs.repaintEverything = false;
-
- gpuDisplay->finishFrame(refreshArgs);
+ gpuDisplay->finishFrame({});
}
TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) {
@@ -944,31 +915,7 @@
gpuDisplay->editState().layerStackSpace.content = Rect(0, 0, 1, 1);
gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1));
- CompositionRefreshArgs refreshArgs;
- refreshArgs.repaintEverything = false;
-
- gpuDisplay->finishFrame(refreshArgs);
-}
-
-TEST_F(DisplayFinishFrameTest, performsCompositionIfRepaintEverything) {
- auto args = getDisplayCreationArgsForGpuVirtualDisplay();
- std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args);
-
- mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
- gpuDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
-
- // We expect a single call to queueBuffer when composition is not skipped.
- EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(1);
-
- gpuDisplay->editState().isEnabled = true;
- gpuDisplay->editState().usesClientComposition = false;
- gpuDisplay->editState().layerStackSpace.content = Rect(0, 0, 1, 1);
- gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION;
-
- CompositionRefreshArgs refreshArgs;
- refreshArgs.repaintEverything = true;
-
- gpuDisplay->finishFrame(refreshArgs);
+ gpuDisplay->finishFrame({});
}
/*
@@ -998,10 +945,8 @@
Display>(mCompositionEngine,
DisplayCreationArgsBuilder()
.setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(ui::DisplayConnectionType::Internal)
.setPixels(DEFAULT_RESOLUTION)
.setIsSecure(true)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&mPowerAdvisor)
.build());
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index c3185e9..6c510eb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -403,17 +403,18 @@
}
/*
- * Output::setLayerStackFilter()
+ * Output::setLayerFilter()
*/
-TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
- const uint32_t layerStack = 123u;
- mOutput->setLayerStackFilter(layerStack, true);
+TEST_F(OutputTest, setLayerFilterSetsFilterAndDirtiesEntireOutput) {
+ constexpr ui::LayerFilter kFilter{ui::LayerStack{123u}, true};
+ mOutput->setLayerFilter(kFilter);
- EXPECT_TRUE(mOutput->getState().layerStackInternal);
- EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
+ const auto& state = mOutput->getState();
+ EXPECT_EQ(kFilter.layerStack, state.layerFilter.layerStack);
+ EXPECT_TRUE(state.layerFilter.toInternalDisplay);
- EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+ EXPECT_THAT(state.dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
}
/*
@@ -567,126 +568,100 @@
* Output::getDirtyRegion()
*/
-TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
+TEST_F(OutputTest, getDirtyRegion) {
const Rect viewport{100, 200};
mOutput->editState().layerStackSpace.content = viewport;
mOutput->editState().dirtyRegion.set(50, 300);
- {
- Region result = mOutput->getDirtyRegion(true);
-
- EXPECT_THAT(result, RegionEq(Region(viewport)));
- }
-}
-
-TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
- const Rect viewport{100, 200};
- mOutput->editState().layerStackSpace.content = viewport;
- mOutput->editState().dirtyRegion.set(50, 300);
-
- {
- Region result = mOutput->getDirtyRegion(false);
-
- // The dirtyRegion should be clipped to the display bounds.
- EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
- }
+ // The dirty region should be clipped to the display bounds.
+ EXPECT_THAT(mOutput->getDirtyRegion(), RegionEq(Region(Rect(50, 200))));
}
/*
- * Output::belongsInOutput()
+ * Output::includesLayer()
*/
-TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
- const uint32_t layerStack1 = 123u;
- const uint32_t layerStack2 = 456u;
+TEST_F(OutputTest, layerFiltering) {
+ const ui::LayerStack layerStack1{123u};
+ const ui::LayerStack layerStack2{456u};
- // If the output accepts layerStack1 and internal-only layers....
- mOutput->setLayerStackFilter(layerStack1, true);
+ // If the output is associated to layerStack1 and to an internal display...
+ mOutput->setLayerFilter({layerStack1, true});
- // A layer with no layerStack does not belong to it, internal-only or not.
- EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
- EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
+ // It excludes layers with no layer stack, internal-only or not.
+ EXPECT_FALSE(mOutput->includesLayer({ui::INVALID_LAYER_STACK, false}));
+ EXPECT_FALSE(mOutput->includesLayer({ui::INVALID_LAYER_STACK, true}));
- // Any layer with layerStack1 belongs to it, internal-only or not.
- EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
- EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
- EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
- EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
+ // It includes layers on layerStack1, internal-only or not.
+ EXPECT_TRUE(mOutput->includesLayer({layerStack1, false}));
+ EXPECT_TRUE(mOutput->includesLayer({layerStack1, true}));
+ EXPECT_FALSE(mOutput->includesLayer({layerStack2, true}));
+ EXPECT_FALSE(mOutput->includesLayer({layerStack2, false}));
- // If the output accepts layerStack21 but not internal-only layers...
- mOutput->setLayerStackFilter(layerStack1, false);
+ // If the output is associated to layerStack1 but not to an internal display...
+ mOutput->setLayerFilter({layerStack1, false});
- // Only non-internal layers with layerStack1 belong to it.
- EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
- EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
- EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
- EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
+ // It includes layers on layerStack1, unless they are internal-only.
+ EXPECT_TRUE(mOutput->includesLayer({layerStack1, false}));
+ EXPECT_FALSE(mOutput->includesLayer({layerStack1, true}));
+ EXPECT_FALSE(mOutput->includesLayer({layerStack2, true}));
+ EXPECT_FALSE(mOutput->includesLayer({layerStack2, false}));
}
-TEST_F(OutputTest, belongsInOutputHandlesLayerWithNoCompositionState) {
+TEST_F(OutputTest, layerFilteringWithoutCompositionState) {
NonInjectedLayer layer;
sp<LayerFE> layerFE(layer.layerFE);
- // If the layer has no composition state, it does not belong to any output.
+ // Layers without composition state are excluded.
EXPECT_CALL(*layer.layerFE, getCompositionState).WillOnce(Return(nullptr));
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
}
-TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
+TEST_F(OutputTest, layerFilteringWithCompositionState) {
NonInjectedLayer layer;
sp<LayerFE> layerFE(layer.layerFE);
- const uint32_t layerStack1 = 123u;
- const uint32_t layerStack2 = 456u;
+ const ui::LayerStack layerStack1{123u};
+ const ui::LayerStack layerStack2{456u};
- // If the output accepts layerStack1 and internal-only layers....
- mOutput->setLayerStackFilter(layerStack1, true);
+ // If the output is associated to layerStack1 and to an internal display...
+ mOutput->setLayerFilter({layerStack1, true});
- // A layer with no layerStack does not belong to it, internal-only or not.
- layer.layerFEState.layerStackId = std::nullopt;
- layer.layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ // It excludes layers with no layer stack, internal-only or not.
+ layer.layerFEState.outputFilter = {ui::INVALID_LAYER_STACK, false};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = std::nullopt;
- layer.layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {ui::INVALID_LAYER_STACK, true};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- // Any layer with layerStack1 belongs to it, internal-only or not.
- layer.layerFEState.layerStackId = layerStack1;
- layer.layerFEState.internalOnly = false;
- EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
+ // It includes layers on layerStack1, internal-only or not.
+ layer.layerFEState.outputFilter = {layerStack1, false};
+ EXPECT_TRUE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack1;
- layer.layerFEState.internalOnly = true;
- EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack1, true};
+ EXPECT_TRUE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack2;
- layer.layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack2, true};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack2;
- layer.layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack2, false};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- // If the output accepts layerStack1 but not internal-only layers...
- mOutput->setLayerStackFilter(layerStack1, false);
+ // If the output is associated to layerStack1 but not to an internal display...
+ mOutput->setLayerFilter({layerStack1, false});
- // Only non-internal layers with layerStack1 belong to it.
- layer.layerFEState.layerStackId = layerStack1;
- layer.layerFEState.internalOnly = false;
- EXPECT_TRUE(mOutput->belongsInOutput(layerFE));
+ // It includes layers on layerStack1, unless they are internal-only.
+ layer.layerFEState.outputFilter = {layerStack1, false};
+ EXPECT_TRUE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack1;
- layer.layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack1, true};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack2;
- layer.layerFEState.internalOnly = true;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack2, true};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
- layer.layerFEState.layerStackId = layerStack2;
- layer.layerFEState.internalOnly = false;
- EXPECT_FALSE(mOutput->belongsInOutput(layerFE));
+ layer.layerFEState.outputFilter = {layerStack2, false};
+ EXPECT_FALSE(mOutput->includesLayer(layerFE));
}
/*
@@ -1268,14 +1243,15 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_CONST_METHOD1(belongsInOutput, bool(const sp<compositionengine::LayerFE>&));
+ MOCK_METHOD(bool, includesLayer, (const sp<compositionengine::LayerFE>&),
+ (const, override));
MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
MOCK_METHOD2(ensureOutputLayer,
compositionengine::OutputLayer*(std::optional<size_t>, const sp<LayerFE>&));
};
OutputEnsureOutputLayerIfVisibleTest() {
- EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE)))
+ EXPECT_CALL(mOutput, includesLayer(sp<LayerFE>(mLayer.layerFE)))
.WillRepeatedly(Return(true));
EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
@@ -1326,8 +1302,8 @@
const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
Region(Rect(0, 0, 200, 100));
-TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
- EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerIncluded) {
+ EXPECT_CALL(mOutput, includesLayer(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
EXPECT_CALL(*mLayer.layerFE,
prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry));
@@ -1337,8 +1313,8 @@
}
TEST_F(OutputEnsureOutputLayerIfVisibleTest,
- skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
- EXPECT_CALL(mOutput, belongsInOutput(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
+ skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerIncluded) {
+ EXPECT_CALL(mOutput, includesLayer(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
ensureOutputLayerIfVisible();
}
@@ -2530,7 +2506,7 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
+ MOCK_METHOD(Region, getDirtyRegion, (), (const));
};
OutputBeginFrameTest() {
@@ -2542,8 +2518,7 @@
struct IfGetDirtyRegionExpectationState
: public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
[[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
- EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
- .WillOnce(Return(dirtyRegion));
+ EXPECT_CALL(getInstance()->mOutput, getDirtyRegion()).WillOnce(Return(dirtyRegion));
return nextState<AndIfGetOutputLayerCountExpectationState>();
}
};
@@ -2683,7 +2658,7 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
+ MOCK_METHOD(Region, getDirtyRegion, (), (const));
MOCK_METHOD2(composeSurfaces,
std::optional<base::unique_fd>(
const Region&, const compositionengine::CompositionRefreshArgs&));
@@ -2711,7 +2686,6 @@
TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
- mRefreshArgs.repaintEverything = true;
mOutput.mState.isEnabled = true;
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2719,7 +2693,6 @@
TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
- mRefreshArgs.repaintEverything = true;
mOutput.mState.isEnabled = false;
InSequence seq;
@@ -2729,13 +2702,12 @@
mOutput.devOptRepaintFlash(mRefreshArgs);
}
-TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
+TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfEnabled) {
mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
- mRefreshArgs.repaintEverything = true;
mOutput.mState.isEnabled = true;
InSequence seq;
- EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
+ EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kEmptyRegion));
EXPECT_CALL(mOutput, postFramebuffer());
EXPECT_CALL(mOutput, prepareFrame());
@@ -2744,11 +2716,10 @@
TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
- mRefreshArgs.repaintEverything = false;
mOutput.mState.isEnabled = true;
InSequence seq;
- EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
+ EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kNotEmptyRegion));
EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs)));
EXPECT_CALL(*mRenderSurface, queueBuffer(_));
EXPECT_CALL(mOutput, postFramebuffer());
@@ -3188,8 +3159,7 @@
r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
- const constexpr uint32_t kInternalLayerStack = 1234;
- mOutput.setLayerStackFilter(kInternalLayerStack, true);
+ mOutput.setLayerFilter({ui::LayerStack{1234u}, true});
EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4445eea..802a17d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -232,7 +232,7 @@
}
void DisplayDevice::setLayerStack(ui::LayerStack stack) {
- mCompositionDisplay->setLayerStackFilter(stack, isInternal());
+ mCompositionDisplay->setLayerFilter({stack, isInternal()});
if (mRefreshRateOverlay) {
mRefreshRateOverlay->setLayerStack(stack);
}
@@ -349,7 +349,7 @@
}
ui::LayerStack DisplayDevice::getLayerStack() const {
- return mCompositionDisplay->getState().layerStackId;
+ return mCompositionDisplay->getState().layerFilter.layerStack;
}
ui::Transform::RotationFlags DisplayDevice::getTransformHint() const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 7db87d9..43a6bd5 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -86,9 +86,7 @@
bool isVirtual() const { return !mConnectionType; }
bool isPrimary() const { return mIsPrimary; }
- bool isInternal() const {
- return !isVirtual() && mConnectionType == ui::DisplayConnectionType::Internal;
- }
+ bool isInternal() const { return mConnectionType == ui::DisplayConnectionType::Internal; }
// isSecure indicates whether this display can be trusted to display
// secure surfaces.
@@ -311,7 +309,7 @@
int32_t sequenceId = sNextSequenceId++;
std::optional<Physical> physical;
sp<IGraphicBufferProducer> surface;
- ui::LayerStack layerStack = ui::NO_LAYER_STACK;
+ ui::LayerStack layerStack;
uint32_t flags = 0;
Rect layerStackSpaceRect;
Rect orientedDisplaySpaceRect;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 87b0dbc..b872c85 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -107,7 +107,7 @@
mDrawingState.requestedCrop = mDrawingState.crop;
mDrawingState.z = 0;
mDrawingState.color.a = 1.0f;
- mDrawingState.layerStack = 0;
+ mDrawingState.layerStack = ui::DEFAULT_LAYER_STACK;
mDrawingState.sequence = 0;
mDrawingState.requested_legacy = mDrawingState.active_legacy;
mDrawingState.width = UINT32_MAX;
@@ -391,7 +391,6 @@
void Layer::prepareBasicGeometryCompositionState() {
const auto& drawingState{getDrawingState()};
- const uint32_t layerStack = getLayerStack();
const auto alpha = static_cast<float>(getAlpha());
const bool opaque = isOpaque(drawingState);
const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
@@ -403,9 +402,7 @@
}
auto* compositionState = editCompositionState();
- compositionState->layerStackId =
- (layerStack != ~0u) ? std::make_optional(layerStack) : std::nullopt;
- compositionState->internalOnly = getPrimaryDisplayOnly();
+ compositionState->outputFilter = getOutputFilter();
compositionState->isVisible = isVisible();
compositionState->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
compositionState->shadowRadius = mEffectiveShadowRadius;
@@ -728,14 +725,14 @@
mDrawingState.bufferlessSurfaceFramesTX.clear();
}
-uint32_t Layer::getTransactionFlags(uint32_t flags) {
- auto ret = mTransactionFlags & flags;
- mTransactionFlags &= ~flags;
- return ret;
+uint32_t Layer::clearTransactionFlags(uint32_t mask) {
+ const auto flags = mTransactionFlags & mask;
+ mTransactionFlags &= ~mask;
+ return flags;
}
-uint32_t Layer::setTransactionFlags(uint32_t flags) {
- return mTransactionFlags |= flags;
+void Layer::setTransactionFlags(uint32_t mask) {
+ mTransactionFlags |= mask;
}
bool Layer::setPosition(float x, float y) {
@@ -1005,7 +1002,7 @@
return true;
}
-bool Layer::setLayerStack(uint32_t layerStack) {
+bool Layer::setLayerStack(ui::LayerStack layerStack) {
if (mDrawingState.layerStack == layerStack) return false;
mDrawingState.sequence++;
mDrawingState.layerStack = layerStack;
@@ -1052,12 +1049,11 @@
return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE;
};
-uint32_t Layer::getLayerStack() const {
- auto p = mDrawingParent.promote();
- if (p == nullptr) {
- return getDrawingState().layerStack;
+ui::LayerStack Layer::getLayerStack() const {
+ if (const auto parent = mDrawingParent.promote()) {
+ return parent->getLayerStack();
}
- return p->getLayerStack();
+ return getDrawingState().layerStack;
}
bool Layer::setShadowRadius(float shadowRadius) {
@@ -1371,7 +1367,7 @@
info.mVisibleRegion = getVisibleRegion(display);
info.mSurfaceDamageRegion = surfaceDamageRegion;
- info.mLayerStack = getLayerStack();
+ info.mLayerStack = getLayerStack().id;
info.mX = ds.transform.tx();
info.mY = ds.transform.ty();
info.mZ = ds.z;
@@ -2031,6 +2027,7 @@
layerInfo->set_curr_frame(mCurrentFrameNumber);
layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
+ layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius);
layerInfo->set_corner_radius(getRoundedCornerState().radius);
layerInfo->set_background_blur_radius(getBackgroundBlurRadius());
layerInfo->set_is_trusted_overlay(isTrustedOverlay());
@@ -2087,7 +2084,7 @@
LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy,
[&]() { return layerInfo->mutable_transparent_region(); });
- layerInfo->set_layer_stack(getLayerStack());
+ layerInfo->set_layer_stack(getLayerStack().id);
layerInfo->set_z(state.z);
LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(),
@@ -2134,7 +2131,7 @@
if (traceFlags & SurfaceTracing::TRACE_INPUT) {
WindowInfo info;
if (useDrawing) {
- info = fillInputInfo({nullptr});
+ info = fillInputInfo(nullptr);
} else {
info = state.inputInfo;
}
@@ -2163,7 +2160,7 @@
return getCroppedBufferSize(getDrawingState());
}
-void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& toPhysicalDisplay) {
+void Layer::fillInputFrameInfo(WindowInfo& info, const ui::Transform& displayTransform) {
// Transform layer size to screen space and inset it by surface insets.
// If this is a portal window, set the touchableRegion to the layerBounds.
Rect layerBounds = info.portalToDisplayId == ADISPLAY_ID_NONE
@@ -2183,13 +2180,13 @@
return;
}
- ui::Transform layerToDisplay = getInputTransform();
- // Transform that takes window coordinates to unrotated display coordinates
- ui::Transform t = toPhysicalDisplay * layerToDisplay;
+ const ui::Transform layerTransform = getInputTransform();
+ // Transform that takes window coordinates to non-rotated display coordinates
+ ui::Transform t = displayTransform * layerTransform;
int32_t xSurfaceInset = info.surfaceInset;
int32_t ySurfaceInset = info.surfaceInset;
- // Bring screenBounds into unrotated space
- Rect screenBounds = toPhysicalDisplay.transform(Rect{mScreenBounds});
+ // Bring screenBounds into non-unrotated space
+ Rect screenBounds = displayTransform.transform(Rect{mScreenBounds});
const float xScale = t.getScaleX();
const float yScale = t.getScaleY();
@@ -2268,36 +2265,50 @@
}
}
-WindowInfo Layer::fillInputInfo(const sp<DisplayDevice>& display) {
+WindowInfo Layer::fillInputInfo(const DisplayDevice* display) {
if (!hasInputInfo()) {
mDrawingState.inputInfo.name = getName();
mDrawingState.inputInfo.ownerUid = mOwnerUid;
mDrawingState.inputInfo.ownerPid = mOwnerPid;
mDrawingState.inputInfo.inputFeatures = WindowInfo::Feature::NO_INPUT_CHANNEL;
mDrawingState.inputInfo.flags = WindowInfo::Flag::NOT_TOUCH_MODAL;
- mDrawingState.inputInfo.displayId = getLayerStack();
+ mDrawingState.inputInfo.displayId = getLayerStack().id;
}
WindowInfo info = mDrawingState.inputInfo;
info.id = sequence;
+ info.displayId = getLayerStack().id;
- if (info.displayId == ADISPLAY_ID_NONE) {
- info.displayId = getLayerStack();
- }
-
- // Transform that goes from "logical(rotated)" display to physical/unrotated display.
- // This is for when inputflinger operates in physical display-space.
- ui::Transform toPhysicalDisplay;
+ // Transform that maps from LayerStack space to display space, e.g. rotated to non-rotated.
+ // Used when InputFlinger operates in display space.
+ ui::Transform displayTransform;
if (display) {
- toPhysicalDisplay = display->getTransform();
- // getOrientation() without masking can contain more-significant bits (eg. ROT_INVALID).
- static constexpr uint32_t ALL_ROTATIONS_MASK =
- ui::Transform::ROT_90 | ui::Transform::ROT_180 | ui::Transform::ROT_270;
- info.displayOrientation = toPhysicalDisplay.getOrientation() & ALL_ROTATIONS_MASK;
- info.displayWidth = display->getWidth();
- info.displayHeight = display->getHeight();
+ // The physical orientation is set when the orientation of the display panel is different
+ // than the default orientation of the device. Other services like InputFlinger do not know
+ // about this, so we do not need to expose the physical orientation of the panel outside of
+ // SurfaceFlinger.
+ const ui::Rotation inversePhysicalOrientation =
+ ui::ROTATION_0 - display->getPhysicalOrientation();
+ auto width = display->getWidth();
+ auto height = display->getHeight();
+ if (inversePhysicalOrientation == ui::ROTATION_90 ||
+ inversePhysicalOrientation == ui::ROTATION_270) {
+ std::swap(width, height);
+ }
+ const ui::Transform undoPhysicalOrientation(ui::Transform::toRotationFlags(
+ inversePhysicalOrientation),
+ width, height);
+ displayTransform = undoPhysicalOrientation * display->getTransform();
+
+ // Send the inverse of the display orientation so that input can transform points back to
+ // the rotated display space.
+ const ui::Rotation inverseOrientation = ui::ROTATION_0 - display->getOrientation();
+ info.displayOrientation = ui::Transform::toRotationFlags(inverseOrientation);
+
+ info.displayWidth = width;
+ info.displayHeight = height;
}
- fillInputFrameInfo(info, toPhysicalDisplay);
+ fillInputFrameInfo(info, displayTransform);
// For compatibility reasons we let layers which can receive input
// receive input before they have actually submitted a buffer. Because
@@ -2313,15 +2324,11 @@
auto cropLayer = mDrawingState.touchableRegionCrop.promote();
if (info.replaceTouchableRegionWithCrop) {
- if (cropLayer == nullptr) {
- info.touchableRegion = Region(toPhysicalDisplay.transform(Rect{mScreenBounds}));
- } else {
- info.touchableRegion =
- Region(toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
- }
+ const Rect bounds(cropLayer ? cropLayer->mScreenBounds : mScreenBounds);
+ info.touchableRegion = Region(displayTransform.transform(bounds));
} else if (cropLayer != nullptr) {
info.touchableRegion = info.touchableRegion.intersect(
- toPhysicalDisplay.transform(Rect{cropLayer->mScreenBounds}));
+ displayTransform.transform(Rect{cropLayer->mScreenBounds}));
}
// Inherit the trusted state from the parent hierarchy, but don't clobber the trusted state
@@ -2332,9 +2339,8 @@
// If the layer is a clone, we need to crop the input region to cloned root to prevent
// touches from going outside the cloned area.
if (isClone()) {
- sp<Layer> clonedRoot = getClonedRoot();
- if (clonedRoot != nullptr) {
- Rect rect = toPhysicalDisplay.transform(Rect{clonedRoot->mScreenBounds});
+ if (const sp<Layer> clonedRoot = getClonedRoot()) {
+ const Rect rect = displayTransform.transform(Rect{clonedRoot->mScreenBounds});
info.touchableRegion = info.touchableRegion.intersect(rect);
}
}
@@ -2530,14 +2536,14 @@
}
}
-bool Layer::getPrimaryDisplayOnly() const {
+bool Layer::isInternalDisplayOverlay() const {
const State& s(mDrawingState);
if (s.flags & layer_state_t::eLayerSkipScreenshot) {
return true;
}
sp<Layer> parent = mDrawingParent.promote();
- return parent == nullptr ? false : parent->getPrimaryDisplayOnly();
+ return parent && parent->isInternalDisplayOverlay();
}
void Layer::setClonedChild(const sp<Layer>& clonedChild) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 41bdebd..4200be4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,12 +151,7 @@
Geometry requested_legacy;
int32_t z;
- // The identifier of the layer stack this layer belongs to. A layer can
- // only be associated to a single layer stack. A layer stack is a
- // z-ordered group of layers which can be associated to one or more
- // displays. Using the same layer stack on different displays is a way
- // to achieve mirroring.
- uint32_t layerStack;
+ ui::LayerStack layerStack;
uint32_t flags;
uint8_t reserved[2];
@@ -280,6 +275,8 @@
Rect bufferCrop;
Rect destinationFrame;
+
+ sp<IBinder> releaseBufferEndpoint;
};
/*
@@ -403,8 +400,8 @@
virtual bool setTransparentRegionHint(const Region& transparent);
virtual bool setTrustedOverlay(bool);
virtual bool setFlags(uint32_t flags, uint32_t mask);
- virtual bool setLayerStack(uint32_t layerStack);
- virtual uint32_t getLayerStack() const;
+ virtual bool setLayerStack(ui::LayerStack);
+ virtual ui::LayerStack getLayerStack() const;
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
virtual bool reparent(const sp<IBinder>& newParentHandle);
@@ -422,7 +419,8 @@
const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */,
std::optional<nsecs_t> /* dequeueTime */,
const FrameTimelineInfo& /*info*/,
- const sp<ITransactionCompletedListener>& /* releaseBufferListener */) {
+ const sp<ITransactionCompletedListener>& /* releaseBufferListener */,
+ const sp<IBinder>& /* releaseBufferEndpoint */) {
return false;
};
virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
@@ -642,13 +640,12 @@
bool isLegacyDataSpace() const;
uint32_t getTransactionFlags() const { return mTransactionFlags; }
- uint32_t getTransactionFlags(uint32_t flags);
- uint32_t setTransactionFlags(uint32_t flags);
- // Deprecated, please use compositionengine::Output::belongsInOutput()
- // instead.
- // TODO(lpique): Move the remaining callers (screencap) to the new function.
- bool belongsToDisplay(uint32_t layerStack) const { return getLayerStack() == layerStack; }
+ // Sets the masked bits.
+ void setTransactionFlags(uint32_t mask);
+
+ // Clears and returns the masked bits.
+ uint32_t clearTransactionFlags(uint32_t mask);
FloatRect getBounds(const Region& activeTransparentRegion) const;
FloatRect getBounds() const;
@@ -681,6 +678,14 @@
*/
bool isHiddenByPolicy() const;
+ // True if the layer should be skipped in screenshots, screen recordings,
+ // and mirroring to external or virtual displays.
+ bool isInternalDisplayOverlay() const;
+
+ ui::LayerFilter getOutputFilter() const {
+ return {getLayerStack(), isInternalDisplayOverlay()};
+ }
+
bool isRemovedFromCurrentState() const;
LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags, const DisplayDevice*);
@@ -697,8 +702,6 @@
gui::WindowInfo::Type getWindowType() const { return mWindowType; }
- bool getPrimaryDisplayOnly() const;
-
void updateMirrorInfo();
/*
@@ -848,7 +851,8 @@
bool getPremultipledAlpha() const;
void setInputInfo(const gui::WindowInfo& info);
- gui::WindowInfo fillInputInfo(const sp<DisplayDevice>& display);
+ gui::WindowInfo fillInputInfo(const DisplayDevice*);
+
/**
* Returns whether this layer has an explicitly set input-info.
*/
@@ -1069,8 +1073,8 @@
// hasInputInfo() or no-op if no such parent is found.
void fillTouchOcclusionMode(gui::WindowInfo& info);
- // Fills in the frame and transform info for the gui::WindowInfo
- void fillInputFrameInfo(gui::WindowInfo& info, const ui::Transform& toPhysicalDisplay);
+ // Fills in the frame and transform info for the gui::WindowInfo.
+ void fillInputFrameInfo(gui::WindowInfo&, const ui::Transform& displayTransform);
// Cached properties computed from drawing state
// Effective transform taking into account parent transforms and any parent scaling, which is
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index aee820a..f52e60d 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -45,8 +45,8 @@
const auto& lState = l->getDrawingState();
const auto& rState = r->getDrawingState();
- uint32_t ls = lState.layerStack;
- uint32_t rs = rState.layerStack;
+ const auto ls = lState.layerStack;
+ const auto rs = rState.layerStack;
if (ls != rs)
return (ls > rs) ? 1 : -1;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 2adfe14..0789e8d 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -281,7 +281,7 @@
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
-void RefreshRateOverlay::setLayerStack(uint32_t stack) {
+void RefreshRateOverlay::setLayerStack(ui::LayerStack stack) {
mLayer->setLayerStack(stack);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
@@ -292,7 +292,7 @@
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
std::nullopt /* dequeueTime */, FrameTimelineInfo{},
- nullptr /* releaseBufferListener */);
+ nullptr /* releaseBufferListener */, nullptr /* releaseBufferEndpoint */);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
@@ -306,7 +306,7 @@
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
std::nullopt /* dequeueTime */, FrameTimelineInfo{},
- nullptr /* releaseBufferListener */);
+ nullptr /* releaseBufferListener */, nullptr /* releaseBufferEndpoint */);
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index fd1e2df..63ae383 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -18,6 +18,7 @@
#include <math/vec4.h>
#include <renderengine/RenderEngine.h>
+#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Size.h>
#include <utils/StrongPointer.h>
@@ -41,7 +42,7 @@
public:
RefreshRateOverlay(SurfaceFlinger&, uint32_t lowFps, uint32_t highFps, bool showSpinner);
- void setLayerStack(uint32_t stack);
+ void setLayerStack(ui::LayerStack);
void setViewport(ui::Size);
void changeRefreshRate(const Fps&);
void onInvalidate();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index f808981..534efee 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -669,7 +669,7 @@
}
}
-void Scheduler::notifyTouchEvent() {
+void Scheduler::onTouchHint() {
if (mTouchTimer) {
mTouchTimer->reset();
@@ -878,7 +878,7 @@
void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
if (timeline.refreshRequired) {
- mSchedulerCallback.repaintEverythingForHWC();
+ mSchedulerCallback.scheduleRefresh(FrameHint::kNone);
}
std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
@@ -891,21 +891,21 @@
}
void Scheduler::onDisplayRefreshed(nsecs_t timestamp) {
- bool callRepaint = false;
- {
+ const bool refresh = [=] {
std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
- if (mLastVsyncPeriodChangeTimeline->refreshTimeNanos < timestamp) {
- mLastVsyncPeriodChangeTimeline->refreshRequired = false;
- } else {
- // We need to send another refresh as refreshTimeNanos is still in the future
- callRepaint = true;
+ if (timestamp < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) {
+ // We need to schedule another refresh as refreshTimeNanos is still in the future.
+ return true;
}
- }
- }
- if (callRepaint) {
- mSchedulerCallback.repaintEverythingForHWC();
+ mLastVsyncPeriodChangeTimeline->refreshRequired = false;
+ }
+ return false;
+ }();
+
+ if (refresh) {
+ mSchedulerCallback.scheduleRefresh(FrameHint::kNone);
}
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 4b6905b..420ba61 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -56,10 +56,13 @@
} // namespace frametimeline
struct ISchedulerCallback {
+ // Indicates frame activity, i.e. whether commit and/or composite is taking place.
+ enum class FrameHint { kNone, kActive };
+
+ virtual void scheduleRefresh(FrameHint) = 0;
virtual void setVsyncEnabled(bool) = 0;
virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
scheduler::RefreshRateConfigEvent) = 0;
- virtual void repaintEverythingForHWC() = 0;
virtual void kernelTimerChanged(bool expired) = 0;
virtual void triggerOnFrameRateOverridesChanged() = 0;
@@ -136,8 +139,8 @@
bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
void resetIdleTimer();
- // Function that resets the touch timer.
- void notifyTouchEvent();
+ // Indicates that touch interaction is taking place.
+ void onTouchHint();
void setDisplayPowerState(bool normal);
@@ -194,6 +197,8 @@
private:
friend class TestableScheduler;
+ using FrameHint = ISchedulerCallback::FrameHint;
+
// In order to make sure that the features don't override themselves, we need a state machine
// to keep track which feature requested the config change.
enum class ContentDetectionState { Off, On };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 99d9bb3..5d8d79b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -415,10 +415,7 @@
property_get("ro.build.type", value, "user");
mIsUserBuild = strcmp(value, "user") == 0;
- property_get("debug.sf.showupdates", value, "0");
- mDebugRegion = atoi(value);
-
- ALOGI_IF(mDebugRegion, "showupdates enabled");
+ mDebugFlashDelay = base::GetUintProperty("debug.sf.showupdates"s, 0u);
// DDMS debugging deprecated (b/120782499)
property_get("debug.sf.ddms", value, "0");
@@ -1066,8 +1063,8 @@
}
if (display->setDesiredActiveMode(info)) {
- // This will trigger HWC refresh without resetting the idle timer.
- repaintEverythingForHWC();
+ scheduleRefresh(FrameHint::kNone);
+
// Start receiving vsync samples now, so that we can detect a period
// switch.
mScheduler->resyncToHardwareVsync(true, info.mode->getVsyncPeriod());
@@ -1649,7 +1646,7 @@
Boost powerBoost = static_cast<Boost>(boostId);
if (powerBoost == Boost::INTERACTION) {
- mScheduler->notifyTouchEvent();
+ mScheduler->onTouchHint();
}
return NO_ERROR;
@@ -1666,16 +1663,26 @@
return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}
-void SurfaceFlinger::signalTransaction() {
- mScheduler->resetIdleTimer();
+void SurfaceFlinger::scheduleInvalidate(FrameHint hint) {
+ if (hint == FrameHint::kActive) {
+ mScheduler->resetIdleTimer();
+ }
mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
+void SurfaceFlinger::scheduleRefresh(FrameHint hint) {
+ mForceRefresh = true;
+ scheduleInvalidate(hint);
+}
+
+void SurfaceFlinger::scheduleRepaint() {
+ mGeometryDirty = true;
+ scheduleRefresh(FrameHint::kActive);
+}
+
void SurfaceFlinger::signalLayerUpdate() {
- mScheduler->resetIdleTimer();
- mPowerAdvisor.notifyDisplayUpdateImminent();
- mEventQueue->invalidate();
+ scheduleInvalidate(FrameHint::kActive);
}
void SurfaceFlinger::signalRefresh() {
@@ -1778,7 +1785,7 @@
void SurfaceFlinger::onComposerHalRefresh(hal::HWDisplayId) {
Mutex::Autolock lock(mStateLock);
- repaintEverythingForHWC();
+ scheduleRefresh(FrameHint::kNone);
}
void SurfaceFlinger::setVsyncEnabled(bool enabled) {
@@ -1945,7 +1952,7 @@
}
}
- bool refreshNeeded;
+ bool refreshNeeded = mForceRefresh.exchange(false);
{
mTracePostComposition = mTracing.flagIsSet(SurfaceTracing::TRACE_COMPOSITION) ||
mTracing.flagIsSet(SurfaceTracing::TRACE_SYNC) ||
@@ -1955,8 +1962,9 @@
mFrameTimeline->setSfWakeUp(vsyncId, frameStart, Fps::fromPeriodNsecs(stats.vsyncPeriod));
- refreshNeeded = handleMessageTransaction();
+ refreshNeeded |= flushAndCommitTransactions();
refreshNeeded |= handleMessageInvalidate();
+
if (tracePreComposition) {
if (mVisibleRegionsDirty) {
mTracing.notifyLocked("visibleRegionsDirty");
@@ -1978,7 +1986,6 @@
updateCursorAsync();
updateInputFlinger();
- refreshNeeded |= mRepaintEverything;
if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
// Signal a refresh if a transaction modified the window state,
// a new buffer was latched, or if HWC has requested a full
@@ -2000,25 +2007,23 @@
notifyRegionSamplingThread();
}
-bool SurfaceFlinger::handleMessageTransaction() {
+bool SurfaceFlinger::flushAndCommitTransactions() {
ATRACE_CALL();
- if (getTransactionFlags(eTransactionFlushNeeded)) {
+ if (clearTransactionFlags(eTransactionFlushNeeded)) {
flushTransactionQueues();
}
- uint32_t transactionFlags = peekTransactionFlags();
- bool runHandleTransaction =
- ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
- if (runHandleTransaction) {
- handleTransaction(eTransactionMask);
+ const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || mForceTraversal;
+ if (shouldCommit) {
+ commitTransactions();
}
if (transactionFlushNeeded()) {
setTransactionFlags(eTransactionFlushNeeded);
}
- return runHandleTransaction;
+ return shouldCommit;
}
void SurfaceFlinger::onMessageRefresh() {
@@ -2042,7 +2047,6 @@
refreshArgs.layersWithQueuedFrames.push_back(layerFE);
}
- refreshArgs.repaintEverything = mRepaintEverything.exchange(false);
refreshArgs.outputColorSetting = useColorManagement
? mDisplayColorSetting
: compositionengine::OutputColorSetting::kUnmanaged;
@@ -2050,7 +2054,7 @@
refreshArgs.forceOutputColorMode = mForceColorMode;
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
- refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty;
+ refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) || mVisibleRegionsDirty;
refreshArgs.blursAreExpensive = mBlursAreExpensive;
refreshArgs.internalDisplayRotationFlags = DisplayDevice::getPrimaryDisplayRotationFlags();
@@ -2059,11 +2063,11 @@
mDrawingState.colorMatrixChanged = false;
}
- refreshArgs.devOptForceClientComposition = mDebugDisableHWC || mDebugRegion;
+ refreshArgs.devOptForceClientComposition = mDebugDisableHWC;
- if (mDebugRegion != 0) {
- refreshArgs.devOptFlashDirtyRegionsDelay =
- std::chrono::milliseconds(mDebugRegion > 1 ? mDebugRegion : 0);
+ if (mDebugFlashDelay != 0) {
+ refreshArgs.devOptForceClientComposition = true;
+ refreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::milliseconds(mDebugFlashDelay);
}
const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(mExpectedPresentTime);
@@ -2072,8 +2076,6 @@
refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
refreshArgs.nextInvalidateTime = mEventQueue->nextExpectedInvalidate();
- mGeometryInvalid = false;
-
// Store the present time just before calling to the composition engine so we could notify
// the scheduler.
const auto presentTime = systemTime();
@@ -2295,7 +2297,7 @@
int32_t maxArea = 0;
mDrawingState.traverse([&, compositionDisplay = compositionDisplay](Layer* layer) {
const auto layerFe = layer->getCompositionEngineLayerFE();
- if (layer->isVisible() && compositionDisplay->belongsInOutput(layerFe)) {
+ if (layer->isVisible() && compositionDisplay->includesLayer(layerFe)) {
const Dataspace transfer =
static_cast<Dataspace>(layer->getDataSpace() & Dataspace::TRANSFER_MASK);
const bool isHdr = (transfer == Dataspace::TRANSFER_ST2084 ||
@@ -2426,8 +2428,8 @@
const auto& displayDevice = pair.second;
const auto display = displayDevice->getCompositionDisplay();
for (const auto& layer : mDrawingState.layersSortedByZ) {
- // only consider the layers on the given layer stack
- if (!display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+ // Only consider the layers on this display.
+ if (!display->includesLayer(layer->getOutputFilter())) {
continue;
}
@@ -2447,29 +2449,26 @@
}
}
-void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) {
+void SurfaceFlinger::commitTransactions() {
ATRACE_CALL();
- // here we keep a copy of the drawing state (that is the state that's
- // going to be overwritten by handleTransactionLocked()) outside of
- // mStateLock so that the side-effects of the State assignment
- // don't happen with mStateLock held (which can cause deadlocks).
+ // Keep a copy of the drawing state (that is going to be overwritten
+ // by commitTransactionsLocked) outside of mStateLock so that the side
+ // effects of the State assignment don't happen with mStateLock held,
+ // which can cause deadlocks.
State drawingState(mDrawingState);
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock lock(mStateLock);
mDebugInTransaction = systemTime();
// Here we're guaranteed that some transaction flags are set
- // so we can call handleTransactionLocked() unconditionally.
- // We call getTransactionFlags(), which will also clear the flags,
- // with mStateLock held to guarantee that mCurrentState won't change
- // until the transaction is committed.
+ // so we can call commitTransactionsLocked unconditionally.
+ // We clear the flags with mStateLock held to guarantee that
+ // mCurrentState won't change until the transaction is committed.
modulateVsync(&VsyncModulator::onTransactionCommit);
- transactionFlags = getTransactionFlags(eTransactionMask);
- handleTransactionLocked(transactionFlags);
+ commitTransactionsLocked(clearTransactionFlags(eTransactionMask));
mDebugInTransaction = 0;
- // here the transaction has been committed
}
void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
@@ -2732,14 +2731,12 @@
compositionengine::DisplayCreationArgsBuilder builder;
if (const auto& physical = state.physical) {
builder.setId(physical->id);
- builder.setConnectionType(physical->type);
} else {
builder.setId(acquireVirtualDisplay(resolution, pixelFormat));
}
builder.setPixels(resolution);
builder.setIsSecure(state.isSecure);
- builder.setLayerStackId(state.layerStack);
builder.setPowerAdvisor(&mPowerAdvisor);
builder.setName(state.displayName);
auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
@@ -2925,8 +2922,8 @@
mDrawingState.displays = mCurrentState.displays;
}
-void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) {
- // Commit display transactions
+void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) {
+ // Commit display transactions.
const bool displayTransactionNeeded = transactionFlags & eDisplayTransactionNeeded;
if (displayTransactionNeeded) {
processDisplayChangesLocked();
@@ -2940,18 +2937,9 @@
mSomeChildrenChanged = false;
}
- // Update transform hint
+ // 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
- // as changed).
- //
- // Walk through all the layers in currentLayers,
- // and update their transform hint.
- //
- // If a layer is visible only on a single display, then that
- // display is used to calculate the hint, otherwise we use the
- // default display.
+ // Layers and/or displays have changed, so update the transform hint for each layer.
//
// NOTE: we do this here, rather than when presenting the display so that
// the hint is set before we acquire a buffer from the surface texture.
@@ -2962,30 +2950,29 @@
// (soon to become the drawing state list).
//
sp<const DisplayDevice> hintDisplay;
- uint32_t currentlayerStack = 0;
- bool first = true;
+ ui::LayerStack layerStack;
+
mCurrentState.traverse([&](Layer* layer) REQUIRES(mStateLock) {
// NOTE: we rely on the fact that layers are sorted by
// layerStack first (so we don't have to traverse the list
// of displays for every layer).
- uint32_t layerStack = layer->getLayerStack();
- if (first || currentlayerStack != layerStack) {
- currentlayerStack = layerStack;
- // figure out if this layerstack is mirrored
- // (more than one display) if so, pick the default display,
- // if not, pick the only display it's on.
+ if (const auto filter = layer->getOutputFilter(); layerStack != filter.layerStack) {
+ layerStack = filter.layerStack;
hintDisplay = nullptr;
+
+ // Find the display that includes the layer.
for (const auto& [token, display] : mDisplays) {
- if (display->getCompositionDisplay()
- ->belongsInOutput(layer->getLayerStack(),
- layer->getPrimaryDisplayOnly())) {
- if (hintDisplay) {
- hintDisplay = nullptr;
- break;
- } else {
- hintDisplay = display;
- }
+ if (!display->getCompositionDisplay()->includesLayer(filter)) {
+ continue;
}
+
+ // Pick the primary display if another display mirrors the layer.
+ if (hintDisplay) {
+ hintDisplay = nullptr;
+ break;
+ }
+
+ hintDisplay = display;
}
}
@@ -2999,20 +2986,10 @@
hintDisplay = getDefaultDisplayDeviceLocked();
}
- // could be null if there is no display available at all to get
- // the transform hint from.
- if (hintDisplay) {
- layer->updateTransformHint(hintDisplay->getTransformHint());
- }
-
- first = false;
+ layer->updateTransformHint(hintDisplay->getTransformHint());
});
}
- /*
- * Perform our own transaction if needed
- */
-
if (mLayersAdded) {
mLayersAdded = false;
// Layers have been added.
@@ -3034,7 +3011,9 @@
});
}
- commitTransaction();
+ doCommitTransactions();
+ signalSynchronousTransactions(CountDownLatch::eSyncTransaction);
+ mAnimTransactionPending = false;
}
void SurfaceFlinger::updateInputFlinger() {
@@ -3069,9 +3048,12 @@
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
if (!layer->needsInputInfo()) return;
- sp<DisplayDevice> display = enablePerWindowInputRotation()
- ? ON_MAIN_THREAD(getDisplayWithInputByLayer(layer))
- : nullptr;
+
+ const DisplayDevice* display = nullptr;
+ if (enablePerWindowInputRotation()) {
+ display = ON_MAIN_THREAD(getDisplayWithInputByLayer(layer)).get();
+ }
+
// When calculating the screen bounds we ignore the transparent region since it may
// result in an unwanted offset.
windowInfos.push_back(layer->fillInputInfo(display));
@@ -3180,14 +3162,9 @@
mEventQueue->setDuration(config.sfWorkDuration);
}
-void SurfaceFlinger::commitTransaction() {
+void SurfaceFlinger::doCommitTransactions() {
ATRACE_CALL();
- commitTransactionLocked();
- signalSynchronousTransactions(CountDownLatch::eSyncTransaction);
- mAnimTransactionPending = false;
-}
-void SurfaceFlinger::commitTransactionLocked() {
if (!mLayersPendingRemoval.isEmpty()) {
// Notify removed layers now that they can't be drawn from
for (const auto& l : mLayersPendingRemoval) {
@@ -3231,11 +3208,10 @@
void SurfaceFlinger::commitOffscreenLayers() {
for (Layer* offscreenLayer : mOffscreenLayers) {
offscreenLayer->traverse(LayerVector::StateSet::Drawing, [](Layer* layer) {
- uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (!trFlags) return;
-
- layer->doTransaction(0);
- layer->commitChildList();
+ if (layer->clearTransactionFlags(eTransactionNeeded)) {
+ layer->doTransaction(0);
+ layer->commitChildList();
+ }
});
}
}
@@ -3243,7 +3219,7 @@
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) {
auto display = displayDevice->getCompositionDisplay();
- if (display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+ if (display->includesLayer(layer->getOutputFilter())) {
display->editState().dirtyRegion.orSelf(dirty);
}
}
@@ -3271,14 +3247,14 @@
// Display is now waiting on Layer 1's frame, which is behind layer 0's
// second frame. But layer 0's second frame could be waiting on display.
mDrawingState.traverse([&](Layer* layer) {
- uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
- if (trFlags || mForceTransactionDisplayChange) {
- const uint32_t flags = layer->doTransaction(0);
- if (flags & Layer::eVisibleRegion)
- mVisibleRegionsDirty = true;
- }
+ if (layer->clearTransactionFlags(eTransactionNeeded) || mForceTransactionDisplayChange) {
+ const uint32_t flags = layer->doTransaction(0);
+ if (flags & Layer::eVisibleRegion) {
+ mVisibleRegionsDirty = true;
+ }
+ }
- if (layer->hasReadyFrame()) {
+ if (layer->hasReadyFrame()) {
frameQueued = true;
if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.emplace(layer);
@@ -3286,7 +3262,7 @@
ATRACE_NAME("!layer->shouldPresentNow()");
layer->useEmptyDamage();
}
- } else {
+ } else {
layer->useEmptyDamage();
}
});
@@ -3339,10 +3315,6 @@
return !mLayersWithQueuedFrames.empty() && newDataLatched;
}
-void SurfaceFlinger::invalidateHwcGeometry() {
- mGeometryInvalid = true;
-}
-
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc,
const sp<IBinder>& parentHandle,
@@ -3389,23 +3361,23 @@
}));
}
-uint32_t SurfaceFlinger::peekTransactionFlags() {
+uint32_t SurfaceFlinger::getTransactionFlags() const {
return mTransactionFlags;
}
-uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) {
- return mTransactionFlags.fetch_and(~flags) & flags;
+uint32_t SurfaceFlinger::clearTransactionFlags(uint32_t mask) {
+ return mTransactionFlags.fetch_and(~mask) & mask;
}
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
- return setTransactionFlags(flags, TransactionSchedule::Late);
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask) {
+ return setTransactionFlags(mask, TransactionSchedule::Late);
}
-uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, TransactionSchedule schedule,
- const sp<IBinder>& token) {
- uint32_t old = mTransactionFlags.fetch_or(flags);
- modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, token);
- if ((old & flags) == 0) signalTransaction();
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule,
+ const sp<IBinder>& applyToken) {
+ const uint32_t old = mTransactionFlags.fetch_or(mask);
+ modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken);
+ if ((old & mask) == 0) scheduleInvalidate(FrameHint::kActive);
return old;
}
@@ -4205,7 +4177,7 @@
if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
s.cachedBuffer, frameNumber, dequeueBufferTimestamp, frameTimelineInfo,
- s.releaseBufferListener)) {
+ s.releaseBufferListener, s.releaseBufferEndpoint)) {
flags |= eTraversalNeeded;
}
} else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
@@ -4464,7 +4436,7 @@
d.what = DisplayState::eDisplayProjectionChanged |
DisplayState::eLayerStackChanged;
d.token = token;
- d.layerStack = 0;
+ d.layerStack = ui::DEFAULT_LAYER_STACK;
d.orientation = ui::ROTATION_0;
d.orientedDisplaySpaceRect.makeInvalid();
d.layerStackSpaceRect.makeInvalid();
@@ -4495,23 +4467,22 @@
}
sp<DisplayDevice> SurfaceFlinger::getDisplayWithInputByLayer(Layer* layer) const {
- sp<DisplayDevice> display;
- for (const auto& pair : mDisplays) {
- const auto& displayDevice = pair.second;
- if (!displayDevice->receivesInput() ||
- !displayDevice->getCompositionDisplay()
- ->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) {
+ const auto filter = layer->getOutputFilter();
+ sp<DisplayDevice> inputDisplay;
+
+ for (const auto& [_, display] : mDisplays) {
+ if (!display->receivesInput() || !display->getCompositionDisplay()->includesLayer(filter)) {
continue;
}
// Don't return immediately so that we can log duplicates.
- if (display) {
- ALOGE("Multiple display devices claim to accept input for the same layerstack: %d",
- layer->getLayerStack());
+ if (inputDisplay) {
+ ALOGE("Multiple displays claim to accept input for the same layer stack: %u",
+ filter.layerStack.id);
continue;
}
- display = displayDevice;
+ inputDisplay = display;
}
- return display;
+ return inputDisplay;
}
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
@@ -4556,7 +4527,7 @@
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
- repaintEverything();
+ scheduleRefresh(FrameHint::kActive);
} else if (mode == hal::PowerMode::OFF) {
// Turn off the display
if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
@@ -5148,7 +5119,7 @@
colorizer.bold(result);
result.append("h/w composer state:\n");
colorizer.reset(result);
- bool hwcDisabled = mDebugDisableHWC || mDebugRegion;
+ const bool hwcDisabled = mDebugDisableHWC || mDebugFlashDelay;
StringAppendF(&result, " h/w composer %s\n", hwcDisabled ? "disabled" : "enabled");
getHwComposer().dump(result);
@@ -5357,9 +5328,8 @@
status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
- status_t credentialCheck = CheckTransactCodeCredentials(code);
- if (credentialCheck != OK) {
- return credentialCheck;
+ if (const status_t error = CheckTransactCodeCredentials(code); error != OK) {
+ return error;
}
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
@@ -5376,47 +5346,43 @@
}
int n;
switch (code) {
- case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
- case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
+ case 1000: // Unused.
+ case 1001:
+ return NAME_NOT_FOUND;
+ case 1002: // Toggle flashing on surface damage.
+ if (const int delay = data.readInt32(); delay > 0) {
+ mDebugFlashDelay = delay;
+ } else {
+ mDebugFlashDelay = mDebugFlashDelay ? 0 : 1;
+ }
+ scheduleRepaint();
return NO_ERROR;
- case 1002: // SHOW_UPDATES
- n = data.readInt32();
- mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
- invalidateHwcGeometry();
- repaintEverything();
+ case 1004: // Force refresh ahead of next VSYNC.
+ scheduleRefresh(FrameHint::kActive);
return NO_ERROR;
- case 1004:{ // repaint everything
- repaintEverything();
+ case 1005: { // Force commit ahead of next VSYNC.
+ Mutex::Autolock lock(mStateLock);
+ setTransactionFlags(eTransactionNeeded | eDisplayTransactionNeeded |
+ eTraversalNeeded);
return NO_ERROR;
}
- case 1005:{ // force transaction
- Mutex::Autolock _l(mStateLock);
- setTransactionFlags(
- eTransactionNeeded|
- eDisplayTransactionNeeded|
- eTraversalNeeded);
- return NO_ERROR;
- }
- case 1006:{ // send empty update
+ case 1006: // Force refresh immediately.
signalRefresh();
return NO_ERROR;
- }
- case 1008: // toggle use of hw composer
- n = data.readInt32();
- mDebugDisableHWC = n != 0;
- invalidateHwcGeometry();
- repaintEverything();
+ case 1007: // Unused.
+ return NAME_NOT_FOUND;
+ case 1008: // Toggle forced GPU composition.
+ mDebugDisableHWC = data.readInt32() != 0;
+ scheduleRepaint();
return NO_ERROR;
- case 1009: // toggle use of transform hint
- n = data.readInt32();
- mDebugDisableTransformHint = n != 0;
- invalidateHwcGeometry();
- repaintEverything();
+ case 1009: // Toggle use of transform hint.
+ mDebugDisableTransformHint = data.readInt32() != 0;
+ scheduleRepaint();
return NO_ERROR;
- case 1010: // interrogate.
+ case 1010: // Interrogate.
reply->writeInt32(0);
reply->writeInt32(0);
- reply->writeInt32(mDebugRegion);
+ reply->writeInt32(mDebugFlashDelay);
reply->writeInt32(0);
reply->writeInt32(mDebugDisableHWC);
return NO_ERROR;
@@ -5471,12 +5437,15 @@
mClientColorMatrix = mat4();
}
+ // TODO(b/193487656): Restore once HWASan bug is fixed.
+#if 0
// Check that supplied matrix's last row is {0,0,0,1} so we can avoid
// the division by w in the fragment shader
float4 lastRow(transpose(mClientColorMatrix)[3]);
if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
ALOGE("The color transform's last row must be (0, 0, 0, 1)");
}
+#endif
updateColorMatrixLocked();
return NO_ERROR;
@@ -5530,8 +5499,7 @@
if (data.readInt32(&colorMode) == NO_ERROR) {
mForceColorMode = static_cast<ColorMode>(colorMode);
}
- invalidateHwcGeometry();
- repaintEverything();
+ scheduleRepaint();
return NO_ERROR;
}
// Deprecate, use 1030 to check whether the device is color managed.
@@ -5761,8 +5729,7 @@
if (error != OK) {
return error;
}
- invalidateHwcGeometry();
- repaintEverything();
+ scheduleRepaint();
return NO_ERROR;
}
}
@@ -5770,17 +5737,6 @@
return err;
}
-void SurfaceFlinger::repaintEverything() {
- mRepaintEverything = true;
- signalTransaction();
-}
-
-void SurfaceFlinger::repaintEverythingForHWC() {
- mRepaintEverything = true;
- mPowerAdvisor.notifyDisplayUpdateImminent();
- mEventQueue->invalidate();
-}
-
void SurfaceFlinger::kernelTimerChanged(bool expired) {
static bool updateOverlay =
property_get_bool("debug.sf.kernel_idle_timer_update_overlay", true);
@@ -6417,12 +6373,12 @@
// We loop through the first level of layers without traversing,
// as we need to determine which layers belong to the requested display.
for (const auto& layer : mDrawingState.layersSortedByZ) {
- if (!layer->belongsToDisplay(layerStack)) {
+ if (layer->getLayerStack() != layerStack) {
continue;
}
// relative layers are traversed in Layer::traverseInZOrder
layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (layer->getPrimaryDisplayOnly()) {
+ if (layer->isInternalDisplayOverlay()) {
return;
}
if (!layer->isVisible()) {
@@ -6793,7 +6749,7 @@
return NO_ERROR;
}
-int SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const {
+uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const {
Fps refreshRate(60.f);
if (const auto frameRateOverride = mScheduler->getFrameRateOverride(uid)) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 0ac6438..33bc17b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -285,8 +285,12 @@
template <typename F, typename T = std::invoke_result_t<F>>
[[nodiscard]] std::future<T> schedule(F&&);
- // force full composition on all displays
- void repaintEverything();
+ // Schedule commit of transactions on the main thread ahead of the next VSYNC.
+ void scheduleInvalidate(FrameHint);
+ // As above, but also force refresh regardless if transactions were committed.
+ void scheduleRefresh(FrameHint) override;
+ // As above, but also force dirty geometry to repaint.
+ void scheduleRepaint();
surfaceflinger::Factory& getFactory() { return mFactory; }
@@ -348,7 +352,6 @@
uint32_t permissions,
std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
REQUIRES(mStateLock);
- virtual void commitTransactionLocked();
// Used internally by computeLayerBounds() to gets the clip rectangle to use for the
// root layers on a particular display in layer-coordinate space. The
@@ -751,8 +754,6 @@
void setVsyncEnabled(bool) override;
// Initiates a refresh rate change to be applied on invalidate.
void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override;
- // Forces full composition on all displays without resetting the scheduler idle timer.
- void repaintEverythingForHWC() override;
// Called when kernel idle timer has expired. Used to update the refresh rate overlay.
void kernelTimerChanged(bool expired) override;
// Called when the frame rate override list changed to trigger an event.
@@ -771,8 +772,6 @@
* Message handling
*/
// Can only be called from the main thread or with mStateLock held
- void signalTransaction();
- // Can only be called from the main thread or with mStateLock held
void signalLayerUpdate();
void signalRefresh();
@@ -804,8 +803,12 @@
// incoming transactions
void onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTime);
- // Returns whether the transaction actually modified any state
- bool handleMessageTransaction();
+ // Returns whether transactions were committed.
+ bool flushAndCommitTransactions() EXCLUDES(mStateLock);
+
+ void commitTransactions() EXCLUDES(mStateLock);
+ void commitTransactionsLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
+ void doCommitTransactions() REQUIRES(mStateLock);
// Handle the REFRESH message queue event, sending the current frame down to RenderEngine and
// the Composer HAL for presentation
@@ -814,9 +817,6 @@
// Returns whether a new buffer has been latched (see handlePageFlip())
bool handleMessageInvalidate();
- void handleTransaction(uint32_t transactionFlags);
- void handleTransactionLocked(uint32_t transactionFlags) REQUIRES(mStateLock);
-
void updateInputFlinger();
void notifyWindowInfos();
void commitInputWindowCommands() REQUIRES(mStateLock);
@@ -848,18 +848,23 @@
void flushTransactionQueues();
// Returns true if there is at least one transaction that needs to be flushed
bool transactionFlushNeeded();
- uint32_t getTransactionFlags(uint32_t flags);
- uint32_t peekTransactionFlags();
- // Can only be called from the main thread or with mStateLock held
- uint32_t setTransactionFlags(uint32_t flags);
+
+ uint32_t getTransactionFlags() const;
+
+ // Sets the masked bits, and returns the old flags.
+ uint32_t setTransactionFlags(uint32_t mask);
+
+ // Clears and returns the masked bits.
+ uint32_t clearTransactionFlags(uint32_t mask);
+
// Indicate SF should call doTraversal on layers, but don't trigger a wakeup! We use this cases
// where there are still pending transactions but we know they won't be ready until a frame
// arrives from a different layer. So we need to ensure we performTransaction from invalidate
// but there is no need to try and wake up immediately to do it. Rather we rely on
// onFrameAvailable or another layer update to wake us up.
void setTraversalNeeded();
- uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule, const sp<IBinder>& = {});
- void commitTransaction() REQUIRES(mStateLock);
+ uint32_t setTransactionFlags(uint32_t mask, TransactionSchedule,
+ const sp<IBinder>& applyToken = {});
void commitOffscreenLayers();
bool transactionIsReadyToBeApplied(
const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime,
@@ -942,7 +947,7 @@
return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
}
- int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
+ uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
/*
* Display and layer stack management
@@ -1033,8 +1038,6 @@
/*
* Compositing
*/
- void invalidateHwcGeometry();
-
void postComposition();
void getCompositorTiming(CompositorTiming* compositorTiming);
void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
@@ -1251,7 +1254,8 @@
bool mLayersRemoved = false;
bool mLayersAdded = false;
- std::atomic<bool> mRepaintEverything = false;
+ std::atomic_bool mForceRefresh = false;
+ std::atomic_bool mGeometryDirty = false;
// constant members (no synchronization needed for access)
const nsecs_t mBootTime = systemTime();
@@ -1278,7 +1282,6 @@
bool mSomeDataspaceChanged = false;
bool mForceTransactionDisplayChange = false;
- bool mGeometryInvalid = false;
bool mAnimCompositionPending = false;
// Tracks layers that have pending frames which are candidates for being
@@ -1313,13 +1316,13 @@
std::optional<DisplayIdGenerator<HalVirtualDisplayId>> hal;
} mVirtualDisplayIdGenerators;
- // don't use a lock for these, we don't care
- int mDebugRegion = 0;
- bool mDebugDisableHWC = false;
- bool mDebugDisableTransformHint = false;
+ std::atomic_uint mDebugFlashDelay = 0;
+ std::atomic_bool mDebugDisableHWC = false;
+ std::atomic_bool mDebugDisableTransformHint = false;
+ std::atomic<nsecs_t> mDebugInTransaction = 0;
+ std::atomic_bool mForceFullDamage = false;
+
bool mLayerCachingEnabled = false;
- volatile nsecs_t mDebugInTransaction = 0;
- bool mForceFullDamage = false;
bool mPropagateBackpressureClientComposition = false;
sp<SurfaceInterceptor> mInterceptor;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 9be3abe..0782fef 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -323,11 +323,10 @@
}
void SurfaceInterceptor::addLayerStackLocked(Transaction* transaction, int32_t layerId,
- uint32_t layerStack)
-{
+ ui::LayerStack layerStack) {
SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
LayerStackChange* layerStackChange(change->mutable_layer_stack());
- layerStackChange->set_layer_stack(layerStack);
+ layerStackChange->set_layer_stack(layerStack.id);
}
void SurfaceInterceptor::addCropLocked(Transaction* transaction, int32_t layerId,
@@ -568,12 +567,11 @@
}
}
-void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction,
- int32_t sequenceId, uint32_t layerStack)
-{
+void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,
+ ui::LayerStack layerStack) {
DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
LayerStackChange* layerStackChange(dispChange->mutable_layer_stack());
- layerStackChange->set_layer_stack(layerStack);
+ layerStackChange->set_layer_stack(layerStack.id);
}
void SurfaceInterceptor::addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId,
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 7b331b9..970c3e5 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -160,7 +160,7 @@
void addTransparentRegionLocked(Transaction* transaction, int32_t layerId,
const Region& transRegion);
void addFlagsLocked(Transaction* transaction, int32_t layerId, uint8_t flags, uint8_t mask);
- void addLayerStackLocked(Transaction* transaction, int32_t layerId, uint32_t layerStack);
+ void addLayerStackLocked(Transaction* transaction, int32_t layerId, ui::LayerStack);
void addCropLocked(Transaction* transaction, int32_t layerId, const Rect& rect);
void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius);
void addBackgroundBlurRadiusLocked(Transaction* transaction, int32_t layerId,
@@ -183,8 +183,7 @@
DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId);
void addDisplaySurfaceLocked(Transaction* transaction, int32_t sequenceId,
const sp<const IGraphicBufferProducer>& surface);
- void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,
- uint32_t layerStack);
+ void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId, ui::LayerStack);
void addDisplayFlagsLocked(Transaction* transaction, int32_t sequenceId, uint32_t flags);
void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w,
uint32_t h);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index dddc677..9f4e7d2 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -130,6 +130,9 @@
repeated BlurRegion blur_regions = 54;
bool is_trusted_overlay = 55;
+
+ // Corner radius explicitly set on layer rather than inherited
+ float requested_corner_radius = 56;
}
message PositionProto {
@@ -228,4 +231,4 @@
int32 top = 8;
int32 right = 9;
int32 bottom = 10;
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index fa3f0e7..d33bc10 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -93,7 +93,7 @@
ASSERT_TRUE(mBGSurfaceControl->isValid());
Transaction t;
- t.setDisplayLayerStack(mDisplay, 0);
+ t.setDisplayLayerStack(mDisplay, ui::DEFAULT_LAYER_STACK);
ASSERT_EQ(NO_ERROR,
t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
}
diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp
index af00ec7..1361ded 100644
--- a/services/surfaceflinger/tests/EffectLayer_test.cpp
+++ b/services/surfaceflinger/tests/EffectLayer_test.cpp
@@ -33,7 +33,7 @@
mParentLayer = createColorLayer("Parent layer", Color::RED);
asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mParentLayer, INT32_MAX - 2).show(mParentLayer);
t.setFlags(mParentLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
});
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
index 9fa3d4c..8d7e175 100644
--- a/services/surfaceflinger/tests/IPC_test.cpp
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -159,7 +159,7 @@
{0, 0, static_cast<int32_t>(width),
static_cast<int32_t>(height)},
Color::RED);
- transaction->setLayerStack(mSurfaceControl, 0)
+ transaction->setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK)
.setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
.setBuffer(mSurfaceControl, gb)
.setAcquireFence(mSurfaceControl, fence)
@@ -232,7 +232,7 @@
mDisplayHeight = mode.resolution.getHeight();
Transaction setupTransaction;
- setupTransaction.setDisplayLayerStack(mPrimaryDisplay, 0);
+ setupTransaction.setDisplayLayerStack(mPrimaryDisplay, ui::DEFAULT_LAYER_STACK);
setupTransaction.apply();
}
@@ -310,7 +310,7 @@
Color::RED);
Transaction transaction;
- transaction.setLayerStack(sc, 0)
+ transaction.setLayerStack(sc, ui::DEFAULT_LAYER_STACK)
.setLayer(sc, std::numeric_limits<int32_t>::max() - 1)
.setBuffer(sc, gb)
.setAcquireFence(sc, fence)
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 0bc8fe7..6bd7920 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -266,7 +266,7 @@
sp<IBinder> mDisplay;
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
- uint32_t mDisplayLayerStack;
+ ui::LayerStack mDisplayLayerStack = ui::DEFAULT_LAYER_STACK;
Rect mDisplayRect = Rect::INVALID_RECT;
// leave room for ~256 layers
@@ -294,8 +294,6 @@
// vsyncs.
mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3;
- mDisplayLayerStack = 0;
-
mBlackBgSurface =
createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */,
PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect);
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index 43d957c..4076253 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -643,7 +643,8 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
- Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
+ const auto layerStack = ui::LayerStack::fromValue(mDisplayLayerStack.id + 1);
+ Transaction().setLayerStack(layer, layerStack).apply();
{
SCOPED_TRACE("non-existing layer stack");
getScreenCapture()->expectColor(mDisplayRect, Color::BLACK);
diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
index ee4d367..e1a7ecc 100644
--- a/services/surfaceflinger/tests/LayerUpdate_test.cpp
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -63,7 +63,7 @@
TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index d027865..3ec6da9 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -36,7 +36,7 @@
mParentLayer = createColorLayer("Parent layer", Color::RED);
mChildLayer = createColorLayer("Child layer", Color::GREEN, mParentLayer.get());
asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mParentLayer, INT32_MAX - 2).show(mParentLayer);
t.setCrop(mChildLayer, Rect(0, 0, 400, 400)).show(mChildLayer);
t.setPosition(mChildLayer, 50, 50);
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
index 08de01c..1ed6c65 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -52,7 +52,7 @@
mColorLayer = 0;
}
- void createDisplay(const ui::Size& layerStackSize, uint32_t layerStack) {
+ void createDisplay(const ui::Size& layerStackSize, ui::LayerStack layerStack) {
mVirtualDisplay =
SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/);
asTransaction([&](Transaction& t) {
@@ -63,7 +63,7 @@
});
}
- void createColorLayer(uint32_t layerStack) {
+ void createColorLayer(ui::LayerStack layerStack) {
mColorLayer =
createSurface(mClient, "ColorLayer", 0 /* buffer width */, 0 /* buffer height */,
PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect);
@@ -90,8 +90,9 @@
};
TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) {
- createDisplay(mMainDisplayState.layerStackSpaceRect, 1 /* layerStack */);
- createColorLayer(1 /* layerStack */);
+ constexpr ui::LayerStack kLayerStack{1u};
+ createDisplay(mMainDisplayState.layerStackSpaceRect, kLayerStack);
+ createColorLayer(kLayerStack);
asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
@@ -113,8 +114,8 @@
// Assumption here is that the new mirrored display has the same layer stack rect as the
// primary display that it is mirroring.
- createDisplay(mMainDisplayState.layerStackSpaceRect, 0 /* layerStack */);
- createColorLayer(0 /* layerStack */);
+ createDisplay(mMainDisplayState.layerStackSpaceRect, ui::DEFAULT_LAYER_STACK);
+ createColorLayer(ui::DEFAULT_LAYER_STACK);
asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); });
diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp
index fde6e6e..50a4092 100644
--- a/services/surfaceflinger/tests/RelativeZ_test.cpp
+++ b/services/surfaceflinger/tests/RelativeZ_test.cpp
@@ -43,7 +43,7 @@
mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
});
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index 579a26e..c4d42fa 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -99,10 +99,10 @@
}
static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
- const ReleaseCallbackId& expectedCallbackId) {
+ const ReleaseCallbackId& expectedReleaseBufferId) {
ReleaseCallbackId actualReleaseBufferId;
releaseCallback.getCallbackData(&actualReleaseBufferId);
- EXPECT_EQ(expectedCallbackId, actualReleaseBufferId);
+ EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId);
releaseCallback.verifyNoCallbacks();
}
static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
@@ -333,4 +333,60 @@
ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
}
+TEST_F(ReleaseBufferCallbackTest, DISABLED_Merge_Different_Processes) {
+ sp<TransactionCompletedListener> firstCompletedListener = new TransactionCompletedListener();
+ sp<TransactionCompletedListener> secondCompletedListener = new TransactionCompletedListener();
+
+ CallbackHelper callback1, callback2;
+
+ TransactionCompletedListener::setInstance(firstCompletedListener);
+
+ sp<SurfaceControl> layer = createBufferStateLayer();
+ ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
+
+ sp<GraphicBuffer> firstBuffer = getBuffer();
+ ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+
+ // Send initial buffer for the layer
+ submitBuffer(layer, firstBuffer, Fence::NO_FENCE, callback1, firstBufferCallbackId,
+ *releaseCallback);
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+
+ // Sent a second buffer to allow the first buffer to get released.
+ sp<GraphicBuffer> secondBuffer = getBuffer();
+ ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+
+ Transaction transaction1;
+ transaction1.setFrameNumber(layer, secondBufferCallbackId.framenumber);
+ transaction1.setBuffer(layer, secondBuffer, secondBufferCallbackId,
+ releaseCallback->getCallback());
+ transaction1.setAcquireFence(layer, Fence::NO_FENCE);
+ transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
+
+ // Set a different TransactionCompletedListener to mimic a second process
+ TransactionCompletedListener::setInstance(secondCompletedListener);
+
+ // Make sure the second "process" has a callback set up.
+ Transaction transaction2;
+ transaction2.addTransactionCompletedCallback(callback2.function, callback2.getContext());
+
+ // This merging order, merge transaction1 first then transaction2, seems to ensure the listener
+ // for transaction2 is ordered first. This makes sure the wrong process is added first to the
+ // layer's vector of listeners. With the bug, only the secondCompletedListener will get the
+ // release callback id, since it's ordered first. Then firstCompletedListener would fail to get
+ // the release callback id and not invoke the release callback.
+ Transaction().merge(std::move(transaction1)).merge(std::move(transaction2)).apply();
+
+ expected = ExpectedResult();
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED,
+ ExpectedResult::PreviousBuffer::RELEASED);
+ ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+ ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
+}
+
} // namespace android
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index ab2064e..95301b3 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -53,7 +53,7 @@
TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
asTransaction([&](Transaction& t) {
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl);
@@ -563,7 +563,7 @@
Transaction()
.show(redLayer)
.show(secureLayer)
- .setLayerStack(redLayer, 0)
+ .setLayerStack(redLayer, ui::DEFAULT_LAYER_STACK)
.setLayer(redLayer, INT32_MAX)
.apply();
@@ -655,7 +655,7 @@
Transaction()
.show(layer)
.hide(mFGSurfaceControl)
- .setLayerStack(layer, 0)
+ .setLayerStack(layer, ui::DEFAULT_LAYER_STACK)
.setLayer(layer, INT32_MAX)
.setColor(layer, {layerColor.r / 255, layerColor.g / 255, layerColor.b / 255})
.setCrop(layer, bounds)
@@ -702,7 +702,7 @@
.show(layer)
.show(childLayer)
.hide(mFGSurfaceControl)
- .setLayerStack(layer, 0)
+ .setLayerStack(layer, ui::DEFAULT_LAYER_STACK)
.setLayer(layer, INT32_MAX)
.setColor(layer, {layerColor.r / 255, layerColor.g / 255, layerColor.b / 255})
.setColor(childLayer, {childColor.r / 255, childColor.g / 255, childColor.b / 255})
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index a424059..ee16f40 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -283,7 +283,7 @@
ASSERT_TRUE(mFGSurfaceControl->isValid());
Transaction t;
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ASSERT_EQ(NO_ERROR,
t.setLayer(mBGSurfaceControl, INT_MAX - 3)
.show(mBGSurfaceControl)
@@ -380,7 +380,7 @@
}
void SurfaceInterceptorTest::layerStackUpdate(Transaction& t) {
- t.setLayerStack(mBGSurfaceControl, STACK_UPDATE);
+ t.setLayerStack(mBGSurfaceControl, ui::LayerStack::fromValue(STACK_UPDATE));
}
void SurfaceInterceptorTest::hiddenFlagUpdate(Transaction& t) {
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 89f6086..60cffb1 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -65,7 +65,7 @@
SurfaceComposerClient::Transaction t;
t.setDisplaySurface(vDisplay, producer);
- t.setDisplayLayerStack(vDisplay, 0);
+ t.setDisplayLayerStack(vDisplay, ui::DEFAULT_LAYER_STACK);
t.setDisplayProjection(vDisplay, displayState.orientation,
Rect(displayState.layerStackSpaceRect), Rect(resolution));
t.apply();
diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
index 89228d5..de116f2 100644
--- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp
+++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp
@@ -84,7 +84,7 @@
ISurfaceComposerClient::eFXSurfaceBufferState);
Transaction()
- .setLayerStack(surfaceControl, 0)
+ .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
.show(surfaceControl)
.setLayer(surfaceControl, INT32_MAX - 1)
.setInputWindowInfo(surfaceControl, windowInfo)
@@ -112,7 +112,7 @@
ISurfaceComposerClient::eFXSurfaceBufferState);
Transaction()
- .setLayerStack(surfaceControl, 0)
+ .setLayerStack(surfaceControl, ui::DEFAULT_LAYER_STACK)
.show(surfaceControl)
.setLayer(surfaceControl, INT32_MAX - 1)
.setInputWindowInfo(surfaceControl, windowInfo)
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index a9e935d..b3b4ec1 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -363,7 +363,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -426,7 +426,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -479,7 +479,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -534,7 +534,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -586,7 +586,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -651,7 +651,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -703,7 +703,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -750,7 +750,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -797,7 +797,7 @@
{
TransactionScope ts(*mFakeComposerClient);
- ts.setDisplayLayerStack(display, 0);
+ ts.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
ts.setLayer(surfaceControl, INT32_MAX - 2).show(surfaceControl);
}
@@ -1195,7 +1195,7 @@
fillSurfaceRGBA8(mFGSurfaceControl, RED);
Transaction t;
- t.setDisplayLayerStack(display, 0);
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
t.setLayer(mBGSurfaceControl, INT32_MAX - 2);
t.show(mBGSurfaceControl);
@@ -1342,7 +1342,7 @@
ALOGD("TransactionTest::SetLayerStack");
{
TransactionScope ts(*sFakeComposer);
- ts.setLayerStack(mFGSurfaceControl, 1);
+ ts.setLayerStack(mFGSurfaceControl, ui::LayerStack{1});
}
// Foreground layer should have disappeared.
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8bd6e62..200ecbd 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -70,10 +70,10 @@
"MessageQueueTest.cpp",
"SurfaceFlinger_CreateDisplayTest.cpp",
"SurfaceFlinger_DestroyDisplayTest.cpp",
+ "SurfaceFlinger_DisplayTransactionCommitTest.cpp",
"SurfaceFlinger_GetDisplayNativePrimariesTest.cpp",
- "SurfaceFlinger_HandleTransactionLockedTest.cpp",
- "SurfaceFlinger_NotifyPowerBoostTest.cpp",
"SurfaceFlinger_HotplugTest.cpp",
+ "SurfaceFlinger_NotifyPowerBoostTest.cpp",
"SurfaceFlinger_OnInitializeDisplaysTest.cpp",
"SurfaceFlinger_SetDisplayStateTest.cpp",
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp
index 6a7ec9b..6f85498 100644
--- a/services/surfaceflinger/tests/unittests/CachingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp
@@ -14,11 +14,6 @@
* limitations under the License.
*/
-// 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 "CachingTest"
@@ -42,7 +37,7 @@
sp<IBinder> binder = new BBinder();
// test getting invalid client_cache_id
client_cache_t id;
- uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+ int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
EXPECT_EQ(BufferQueue::INVALID_BUFFER_SLOT, slot);
}
@@ -51,7 +46,7 @@
client_cache_t id;
id.token = binder;
id.id = 0;
- uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+ int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);
client_cache_t idB;
@@ -72,31 +67,28 @@
std::vector<client_cache_t> ids;
uint32_t cacheId = 0;
// fill up cache
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
client_cache_t id;
id.token = binder;
id.id = cacheId;
ids.push_back(id);
- uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+ int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
cacheId++;
}
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(ids[i]);
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ int slot = mHwcSlotGenerator->getHwcCacheSlot(ids[static_cast<uint32_t>(i)]);
EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
}
- for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+ for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
client_cache_t id;
id.token = binder;
id.id = cacheId;
- uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+ int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
cacheId++;
}
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 98c1889..93a4ce2 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -82,7 +82,7 @@
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
constexpr int DEFAULT_TEXTURE_ID = 6000;
-constexpr int DEFAULT_LAYER_STACK = 7000;
+constexpr ui::LayerStack LAYER_STACK{7000u};
constexpr int DEFAULT_DISPLAY_MAX_LUMINANCE = 500;
@@ -157,7 +157,7 @@
// pain)
// mFlinger.mutableVisibleRegionsDirty() = true;
- mFlinger.mutableGeometryInvalid() = true;
+ mFlinger.mutableGeometryDirty() = true;
}
template <typename Case>
@@ -287,10 +287,8 @@
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
.setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(ui::DisplayConnectionType::Internal)
.setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
.setIsSecure(Derived::IS_SECURE)
- .setLayerStackId(DEFAULT_LAYER_STACK)
.setPowerAdvisor(&test->mPowerAdvisor)
.setName(std::string("Injected display for ") +
test_info->test_case_name() + "." + test_info->name())
@@ -309,7 +307,7 @@
.setPowerMode(Derived::INIT_POWER_MODE)
.inject();
Mock::VerifyAndClear(test->mNativeWindow);
- test->mDisplay->setLayerStack(DEFAULT_LAYER_STACK);
+ test->mDisplay->setLayerStack(LAYER_STACK);
}
template <typename Case>
@@ -834,7 +832,7 @@
template <typename L>
static void initLayerDrawingStateAndComputeBounds(CompositionTest* test, sp<L> layer) {
auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
- layerDrawingState.layerStack = DEFAULT_LAYER_STACK;
+ layerDrawingState.layerStack = LAYER_STACK;
layerDrawingState.width = 100;
layerDrawingState.height = 100;
layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 60b0f53..5a21e7b 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -139,20 +139,18 @@
EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64));
EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(AnyNumber());
- constexpr auto kConnectionType = ui::DisplayConnectionType::Internal;
- constexpr bool kIsPrimary = true;
-
auto compositionDisplay =
compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
compositionengine::DisplayCreationArgsBuilder()
.setId(DEFAULT_DISPLAY_ID)
- .setConnectionType(kConnectionType)
.setPixels({DEFAULT_DISPLAY_WIDTH,
DEFAULT_DISPLAY_HEIGHT})
.setPowerAdvisor(&mPowerAdvisor)
.build());
- auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay, kConnectionType,
+ constexpr bool kIsPrimary = true;
+ auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
+ ui::DisplayConnectionType::Internal,
DEFAULT_DISPLAY_HWC_DISPLAY_ID, kIsPrimary);
injector.setNativeWindow(mNativeWindow);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index de058a4..0f1cc67 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -267,11 +267,6 @@
.setPixels({WIDTH, HEIGHT})
.setPowerAdvisor(&test->mPowerAdvisor);
- const auto connectionType = CONNECTION_TYPE::value;
- if (connectionType) {
- ceDisplayArgs.setConnectionType(*connectionType);
- }
-
auto compositionDisplay =
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs.build());
@@ -279,7 +274,7 @@
auto injector =
TestableSurfaceFlinger::FakeDisplayDeviceInjector(test->mFlinger,
compositionDisplay,
- connectionType,
+ CONNECTION_TYPE::value,
HWC_DISPLAY_ID_OPT::value,
static_cast<bool>(PRIMARY));
@@ -388,7 +383,6 @@
auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder()
.setId(DisplayVariant::DISPLAY_ID::get())
- .setConnectionType(PhysicalDisplay::CONNECTION_TYPE)
.setPixels({DisplayVariant::WIDTH, DisplayVariant::HEIGHT})
.setIsSecure(static_cast<bool>(DisplayVariant::SECURE))
.setPowerAdvisor(&test->mPowerAdvisor)
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
similarity index 89%
rename from services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
rename to services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index 313ab03..6959ee3 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -22,8 +22,7 @@
namespace android {
namespace {
-class HandleTransactionLockedTest : public DisplayTransactionTest {
-public:
+struct DisplayTransactionCommitTest : DisplayTransactionTest {
template <typename Case>
void setupCommonPreconditions();
@@ -55,7 +54,7 @@
};
template <typename Case>
-void HandleTransactionLockedTest::setupCommonPreconditions() {
+void DisplayTransactionCommitTest::setupCommonPreconditions() {
// Wide color displays support is configured appropriately
Case::WideColorSupport::injectConfigChange(this);
@@ -68,7 +67,7 @@
}
template <typename Case, bool connected>
-void HandleTransactionLockedTest::expectHotplugReceived(mock::EventThread* eventThread) {
+void DisplayTransactionCommitTest::expectHotplugReceived(mock::EventThread* eventThread) {
const auto convert = [](auto physicalDisplayId) {
return std::make_optional(DisplayId{physicalDisplayId});
};
@@ -79,7 +78,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessing() {
+void DisplayTransactionCommitTest::setupCommonCallExpectationsForConnectProcessing() {
Case::Display::setupHwcHotplugCallExpectations(this);
Case::Display::setupFramebufferConsumerBufferQueueCallExpectations(this);
@@ -97,7 +96,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
+void DisplayTransactionCommitTest::setupCommonCallExpectationsForDisconnectProcessing() {
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
expectHotplugReceived<Case, false>(mEventThread);
@@ -105,7 +104,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) {
+void DisplayTransactionCommitTest::verifyDisplayIsConnected(const sp<IBinder>& displayToken) {
// The display device should have been set up in the list of displays.
ASSERT_TRUE(hasDisplayDevice(displayToken));
const auto& device = getDisplayDevice(displayToken);
@@ -137,7 +136,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::verifyPhysicalDisplayIsConnected() {
+void DisplayTransactionCommitTest::verifyPhysicalDisplayIsConnected() {
// HWComposer should have an entry for the display
EXPECT_TRUE(hasPhysicalHwcDisplay(Case::Display::HWC_DISPLAY_ID));
@@ -150,14 +149,14 @@
verifyDisplayIsConnected<Case>(displayToken);
}
-void HandleTransactionLockedTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
+void DisplayTransactionCommitTest::verifyDisplayIsNotConnected(const sp<IBinder>& displayToken) {
EXPECT_FALSE(hasDisplayDevice(displayToken));
EXPECT_FALSE(hasCurrentDisplayState(displayToken));
EXPECT_FALSE(hasDrawingDisplayState(displayToken));
}
template <typename Case>
-void HandleTransactionLockedTest::processesHotplugConnectCommon() {
+void DisplayTransactionCommitTest::processesHotplugConnectCommon() {
// --------------------------------------------------------------------
// Preconditions
@@ -174,7 +173,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -191,7 +190,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::ignoresHotplugConnectCommon() {
+void DisplayTransactionCommitTest::ignoresHotplugConnectCommon() {
// --------------------------------------------------------------------
// Preconditions
@@ -203,7 +202,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -213,7 +212,7 @@
}
template <typename Case>
-void HandleTransactionLockedTest::processesHotplugDisconnectCommon() {
+void DisplayTransactionCommitTest::processesHotplugDisconnectCommon() {
// --------------------------------------------------------------------
// Preconditions
@@ -238,7 +237,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -255,18 +254,18 @@
verifyDisplayIsNotConnected(existing.token());
}
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectPrimaryDisplay) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugConnectPrimaryDisplay) {
processesHotplugConnectCommon<SimplePrimaryDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectExternalDisplay) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugConnectExternalDisplay) {
// Inject a primary display.
PrimaryDisplayVariant::injectHwcDisplay(this);
processesHotplugConnectCommon<SimpleExternalDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected) {
+TEST_F(DisplayTransactionCommitTest, ignoresHotplugConnectIfPrimaryAndExternalAlreadyConnected) {
// Inject both a primary and external display.
PrimaryDisplayVariant::injectHwcDisplay(this);
ExternalDisplayVariant::injectHwcDisplay(this);
@@ -281,16 +280,16 @@
ignoresHotplugConnectCommon<SimpleTertiaryDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectPrimaryDisplay) {
EXPECT_EXIT(processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>(),
testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
}
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectExternalDisplay) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectExternalDisplay) {
processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processesHotplugConnectThenDisconnectPrimary) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugConnectThenDisconnectPrimary) {
EXPECT_EXIT(
[this] {
using Case = SimplePrimaryDisplayCase;
@@ -320,7 +319,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -336,7 +335,7 @@
testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
}
-TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectThenConnectPrimary) {
+TEST_F(DisplayTransactionCommitTest, processesHotplugDisconnectThenConnectPrimary) {
EXPECT_EXIT(
[this] {
using Case = SimplePrimaryDisplayCase;
@@ -365,7 +364,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -393,7 +392,7 @@
testing::KilledBySignal(SIGABRT), "Primary display cannot be disconnected.");
}
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAdded) {
+TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayAdded) {
using Case = HwcVirtualDisplayCase;
// --------------------------------------------------------------------
@@ -444,7 +443,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -464,7 +463,7 @@
mFlinger.mutableDrawingState().displays.removeItem(displayToken);
}
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayAddedWithNoSurface) {
+TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayAddedWithNoSurface) {
using Case = HwcVirtualDisplayCase;
// --------------------------------------------------------------------
@@ -490,7 +489,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -504,7 +503,7 @@
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), draw.isVirtual());
}
-TEST_F(HandleTransactionLockedTest, processesVirtualDisplayRemoval) {
+TEST_F(DisplayTransactionCommitTest, processesVirtualDisplayRemoval) {
using Case = HwcVirtualDisplayCase;
// --------------------------------------------------------------------
@@ -522,7 +521,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -531,11 +530,11 @@
verifyDisplayIsNotConnected(existing.token());
}
-TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayLayerStackChanges) {
using Case = NonHwcVirtualDisplayCase;
- constexpr uint32_t oldLayerStack = 0u;
- constexpr uint32_t newLayerStack = 123u;
+ constexpr ui::LayerStack oldLayerStack = ui::DEFAULT_LAYER_STACK;
+ constexpr ui::LayerStack newLayerStack{123u};
// --------------------------------------------------------------------
// Preconditions
@@ -551,7 +550,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -559,7 +558,7 @@
EXPECT_EQ(newLayerStack, display.mutableDisplayDevice()->getLayerStack());
}
-TEST_F(HandleTransactionLockedTest, processesDisplayTransformChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayTransformChanges) {
using Case = NonHwcVirtualDisplayCase;
constexpr ui::Rotation oldTransform = ui::ROTATION_0;
@@ -579,7 +578,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -587,7 +586,7 @@
EXPECT_EQ(newTransform, display.mutableDisplayDevice()->getOrientation());
}
-TEST_F(HandleTransactionLockedTest, processesDisplayLayerStackRectChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayLayerStackRectChanges) {
using Case = NonHwcVirtualDisplayCase;
const Rect oldLayerStackRect(0, 0, 0, 0);
@@ -607,7 +606,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -615,7 +614,7 @@
EXPECT_EQ(newLayerStackRect, display.mutableDisplayDevice()->getLayerStackSpaceRect());
}
-TEST_F(HandleTransactionLockedTest, processesDisplayRectChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayRectChanges) {
using Case = NonHwcVirtualDisplayCase;
const Rect oldDisplayRect(0, 0);
@@ -635,7 +634,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
// --------------------------------------------------------------------
// Postconditions
@@ -643,7 +642,7 @@
EXPECT_EQ(newDisplayRect, display.mutableDisplayDevice()->getOrientedDisplaySpaceRect());
}
-TEST_F(HandleTransactionLockedTest, processesDisplayWidthChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayWidthChanges) {
using Case = NonHwcVirtualDisplayCase;
constexpr int oldWidth = 0;
@@ -685,10 +684,10 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
}
-TEST_F(HandleTransactionLockedTest, processesDisplayHeightChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplayHeightChanges) {
using Case = NonHwcVirtualDisplayCase;
constexpr int oldWidth = 0;
@@ -730,10 +729,10 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
}
-TEST_F(HandleTransactionLockedTest, processesDisplaySizeDisplayRectAndLayerStackRectChanges) {
+TEST_F(DisplayTransactionCommitTest, processesDisplaySizeDisplayRectAndLayerStackRectChanges) {
using Case = NonHwcVirtualDisplayCase;
constexpr uint32_t kOldWidth = 567;
@@ -780,7 +779,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.handleTransactionLocked(eDisplayTransactionNeeded);
+ mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
EXPECT_EQ(display.mutableDisplayDevice()->getBounds(), kNewSize);
EXPECT_EQ(display.mutableDisplayDevice()->getWidth(), kNewWidth);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
index ef8b149..bafa910 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
@@ -63,15 +63,11 @@
// The primary display should have a current state
ASSERT_TRUE(hasCurrentDisplayState(primaryDisplay.token()));
const auto& primaryDisplayState = getCurrentDisplayState(primaryDisplay.token());
- // The layer stack state should be set to zero
- EXPECT_EQ(0u, primaryDisplayState.layerStack);
- // The orientation state should be set to zero
+
+ // The primary display state should be reset
+ EXPECT_EQ(ui::DEFAULT_LAYER_STACK, primaryDisplayState.layerStack);
EXPECT_EQ(ui::ROTATION_0, primaryDisplayState.orientation);
-
- // The orientedDisplaySpaceRect state should be set to INVALID
EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.orientedDisplaySpaceRect);
-
- // The layerStackSpaceRect state should be set to INVALID
EXPECT_EQ(Rect::INVALID_RECT, primaryDisplayState.layerStackSpaceRect);
// The width and height should both be zero
@@ -99,4 +95,4 @@
}
} // namespace
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
index fc40818..7d9e22b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp
@@ -25,6 +25,8 @@
namespace android {
namespace {
+constexpr ui::LayerStack LAYER_STACK{456u};
+
class SetDisplayStateLockedTest : public DisplayTransactionTest {};
TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingWithUnknownDisplay) {
@@ -38,7 +40,7 @@
DisplayState state;
state.what = DisplayState::eLayerStackChanged;
state.token = displayToken;
- state.layerStack = 456;
+ state.layerStack = LAYER_STACK;
// --------------------------------------------------------------------
// Invocation
@@ -167,13 +169,13 @@
display.inject();
// The display has a layer stack set
- display.mutableCurrentDisplayState().layerStack = 456u;
+ display.mutableCurrentDisplayState().layerStack = LAYER_STACK;
// The incoming request sets the same layer stack
DisplayState state;
state.what = DisplayState::eLayerStackChanged;
state.token = display.token();
- state.layerStack = 456u;
+ state.layerStack = LAYER_STACK;
// --------------------------------------------------------------------
// Invocation
@@ -187,7 +189,7 @@
EXPECT_EQ(0u, flags);
// The current display state is unchanged
- EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
+ EXPECT_EQ(LAYER_STACK, display.getCurrentDisplayState().layerStack);
}
TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStackChanged) {
@@ -201,13 +203,13 @@
display.inject();
// The display has a layer stack set
- display.mutableCurrentDisplayState().layerStack = 654u;
+ display.mutableCurrentDisplayState().layerStack = ui::LayerStack{LAYER_STACK.id + 1};
// The incoming request sets a different layer stack
DisplayState state;
state.what = DisplayState::eLayerStackChanged;
state.token = display.token();
- state.layerStack = 456u;
+ state.layerStack = LAYER_STACK;
// --------------------------------------------------------------------
// Invocation
@@ -221,7 +223,7 @@
EXPECT_EQ(eDisplayTransactionNeeded, flags);
// The desired display state has been set to the new value.
- EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack);
+ EXPECT_EQ(LAYER_STACK, display.getCurrentDisplayState().layerStack);
}
TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfFlagsNotChanged) {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e036f4d..d8352ed 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -316,9 +316,9 @@
dispSurface, producer);
}
- auto handleTransactionLocked(uint32_t transactionFlags) {
- Mutex::Autolock _l(mFlinger->mStateLock);
- return mFlinger->handleTransactionLocked(transactionFlags);
+ auto commitTransactionsLocked(uint32_t transactionFlags) {
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ return mFlinger->commitTransactionsLocked(transactionFlags);
}
void onComposerHalHotplug(hal::HWDisplayId hwcDisplayId, hal::Connection connection) {
@@ -326,7 +326,7 @@
}
auto setDisplayStateLocked(const DisplayState& s) {
- Mutex::Autolock _l(mFlinger->mStateLock);
+ Mutex::Autolock lock(mFlinger->mStateLock);
return mFlinger->setDisplayStateLocked(s);
}
@@ -426,7 +426,7 @@
auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDrawingState() { return mFlinger->mDrawingState; }
auto& mutableEventQueue() { return mFlinger->mEventQueue; }
- auto& mutableGeometryInvalid() { return mFlinger->mGeometryInvalid; }
+ auto& mutableGeometryDirty() { return mFlinger->mGeometryDirty; }
auto& mutableInterceptor() { return mFlinger->mInterceptor; }
auto& mutableMainThreadId() { return mFlinger->mMainThreadId; }
auto& mutablePendingHotplugEvents() { return mFlinger->mPendingHotplugEvents; }
@@ -762,9 +762,9 @@
};
private:
+ void scheduleRefresh(FrameHint) override {}
void setVsyncEnabled(bool) override {}
void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {}
- void repaintEverythingForHWC() override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() {}
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index 2845d0a..a749ece 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -119,7 +119,7 @@
FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache,
frameNumber, dequeueTime, FrameTimelineInfo{},
- nullptr /* releaseBufferCallback */);
+ nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint*/);
commitTransaction(layer.get());
bool computeVisisbleRegions;
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 7bf224d..2a7921f 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -119,7 +119,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
acquireFence->signalForTest(12);
commitTransaction(layer.get());
@@ -147,7 +148,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -160,7 +162,8 @@
mRenderEngine, false);
nsecs_t start = systemTime();
layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
nsecs_t end = systemTime();
acquireFence2->signalForTest(12);
@@ -200,7 +203,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
acquireFence->signalForTest(12);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -228,7 +232,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -260,7 +265,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -298,7 +304,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -309,7 +316,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
acquireFence2->signalForTest(12);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -339,7 +347,8 @@
1, 0),
mRenderEngine, false);
layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -353,7 +362,7 @@
auto dropStartTime1 = systemTime();
layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
{/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0},
- nullptr /* releaseBufferCallback */);
+ nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint */);
auto dropEndTime1 = systemTime();
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -367,7 +376,8 @@
mRenderEngine, false);
auto dropStartTime2 = systemTime();
layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+ {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
auto dropEndTime2 = systemTime();
acquireFence3->signalForTest(12);
@@ -411,7 +421,8 @@
mRenderEngine, false);
layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0},
- nullptr /* releaseBufferCallback */);
+ nullptr /* releaseBufferCallback */,
+ nullptr /* releaseBufferEndpoint */);
layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
/*inputEventId*/ 0},
10);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index ab19886..291559f 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -23,20 +23,20 @@
namespace android::mock {
struct SchedulerCallback final : ISchedulerCallback {
+ MOCK_METHOD(void, scheduleRefresh, (FrameHint), (override));
MOCK_METHOD1(setVsyncEnabled, void(bool));
MOCK_METHOD2(changeRefreshRate,
void(const scheduler::RefreshRateConfigs::RefreshRate&,
scheduler::RefreshRateConfigEvent));
- MOCK_METHOD0(repaintEverythingForHWC, void());
MOCK_METHOD1(kernelTimerChanged, void(bool));
MOCK_METHOD0(triggerOnFrameRateOverridesChanged, void());
};
struct NoOpSchedulerCallback final : ISchedulerCallback {
+ void scheduleRefresh(FrameHint) override {}
void setVsyncEnabled(bool) override {}
void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
scheduler::RefreshRateConfigEvent) override {}
- void repaintEverythingForHWC() override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() {}
};