Merge "Remove unused private Choreographer apis."
diff --git a/libs/binder/ParcelValTypes.h b/libs/binder/ParcelValTypes.h
index 666d22a..80736c8 100644
--- a/libs/binder/ParcelValTypes.h
+++ b/libs/binder/ParcelValTypes.h
@@ -27,18 +27,32 @@
VAL_PARCELABLE = 4,
VAL_SHORT = 5,
VAL_LONG = 6,
+ VAL_FLOAT = 7,
VAL_DOUBLE = 8,
VAL_BOOLEAN = 9,
+ VAL_CHARSEQUENCE = 10,
+ VAL_LIST = 11,
+ VAL_SPARSEARRAY = 12,
VAL_BYTEARRAY = 13,
VAL_STRINGARRAY = 14,
VAL_IBINDER = 15,
+ VAL_PARCELABLEARRAY = 16,
+ VAL_OBJECTARRAY = 17,
VAL_INTARRAY = 18,
VAL_LONGARRAY = 19,
VAL_BYTE = 20,
VAL_SERIALIZABLE = 21,
+ VAL_SPARSEBOOLEANARRAY = 22,
VAL_BOOLEANARRAY = 23,
+ VAL_CHARSEQUENCEARRAY = 24,
VAL_PERSISTABLEBUNDLE = 25,
+ VAL_SIZE = 26,
+ VAL_SIZEF = 27,
VAL_DOUBLEARRAY = 28,
+ VAL_CHAR = 29,
+ VAL_SHORTARRAY = 30,
+ VAL_CHARARRAY = 31,
+ VAL_FLOATARRAY = 32,
};
} // namespace binder
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index ba2920e..44b588b 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "RpcServer"
+#include <inttypes.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -38,6 +39,8 @@
namespace android {
+constexpr size_t kSessionIdBytes = 32;
+
using base::ScopeGuard;
using base::unique_fd;
@@ -289,13 +292,19 @@
std::vector<uint8_t> sessionId;
if (status == OK) {
if (header.sessionIdSize > 0) {
- sessionId.resize(header.sessionIdSize);
- status = client->interruptableReadFully(server->mShutdownTrigger.get(),
- sessionId.data(), sessionId.size(), {});
- if (status != OK) {
- ALOGE("Failed to read session ID for client connecting to RPC server: %s",
- statusToString(status).c_str());
- // still need to cleanup before we can return
+ if (header.sessionIdSize == kSessionIdBytes) {
+ sessionId.resize(header.sessionIdSize);
+ status = client->interruptableReadFully(server->mShutdownTrigger.get(),
+ sessionId.data(), sessionId.size(), {});
+ if (status != OK) {
+ ALOGE("Failed to read session ID for client connecting to RPC server: %s",
+ statusToString(status).c_str());
+ // still need to cleanup before we can return
+ }
+ } else {
+ ALOGE("Malformed session ID. Expecting session ID of size %zu but got %" PRIu16,
+ kSessionIdBytes, header.sessionIdSize);
+ status = BAD_VALUE;
}
}
}
@@ -353,8 +362,7 @@
// Uniquely identify session at the application layer. Even if a
// client/server use the same certificates, if they create multiple
// sessions, we still want to distinguish between them.
- constexpr size_t kSessionIdSize = 32;
- sessionId.resize(kSessionIdSize);
+ sessionId.resize(kSessionIdBytes);
size_t tries = 0;
do {
// don't block if there is some entropy issue
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 86cc91c..ef62f20 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -183,6 +183,10 @@
status_t RpcState::flushExcessBinderRefs(const sp<RpcSession>& session, uint64_t address,
const sp<IBinder>& binder) {
+ // We can flush all references when the binder is destroyed. No need to send
+ // extra reference counting packets now.
+ if (binder->remoteBinder()) return OK;
+
std::unique_lock<std::mutex> _l(mNodeMutex);
if (mTerminated) return DEAD_OBJECT;
@@ -192,20 +196,19 @@
LOG_ALWAYS_FATAL_IF(it->second.binder != binder,
"Caller of flushExcessBinderRefs using inconsistent arguments");
- // if this is a local binder, then we want to get rid of all refcounts
- // (tell the other process it can drop the binder when it wants to - we
- // have a local sp<>, so we will drop it when we want to as well). if
- // this is a remote binder, then we need to hold onto one refcount until
- // it is dropped in BpBinder::onLastStrongRef
- size_t targetRecd = binder->localBinder() ? 0 : 1;
+ LOG_ALWAYS_FATAL_IF(it->second.timesSent <= 0, "Local binder must have been sent %p",
+ binder.get());
- // We have timesRecd RPC refcounts, but we only need to hold on to one
- // when we keep the object. All additional dec strongs are sent
- // immediately, we wait to send the last one in BpBinder::onLastDecStrong.
- if (it->second.timesRecd != targetRecd) {
+ // For a local binder, we only need to know that we sent it. Now that we
+ // have an sp<> for this call, we don't need anything more. If the other
+ // process is done with this binder, it needs to know we received the
+ // refcount associated with this call, so we can acknowledge that we
+ // received it. Once (or if) it has no other refcounts, it would reply with
+ // its own decStrong so that it could be removed from this session.
+ if (it->second.timesRecd != 0) {
_l.unlock();
- return session->sendDecStrongToTarget(address, targetRecd);
+ return session->sendDecStrongToTarget(address, 0);
}
return OK;
@@ -882,12 +885,6 @@
}
}
- // Binder refs are flushed for oneway calls only after all calls which are
- // built up are executed. Otherwise, they fill up the binder buffer.
- if (addr != 0 && replyStatus == OK && !oneway) {
- replyStatus = flushExcessBinderRefs(session, addr, target);
- }
-
if (oneway) {
if (replyStatus != OK) {
ALOGW("Oneway call failed with error: %d", replyStatus);
@@ -947,6 +944,12 @@
return OK;
}
+ // Binder refs are flushed for oneway calls only after all calls which are
+ // built up are executed. Otherwise, they fill up the binder buffer.
+ if (addr != 0 && replyStatus == OK) {
+ replyStatus = flushExcessBinderRefs(session, addr, target);
+ }
+
LOG_ALWAYS_FATAL_IF(std::numeric_limits<int32_t>::max() - sizeof(RpcWireHeader) -
sizeof(RpcWireReply) <
reply.dataSize(),
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 43533c5..782328d 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -289,7 +289,7 @@
/**
* Built-in transaction for all binder objects. This sends a transaction that will immediately
* return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
- * sanity check.
+ * consistency check.
*
* Available since API level 29.
*
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 6bf6e92..f8718aa 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -96,7 +96,7 @@
auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
CHECK_NE(cert.get(), nullptr);
- auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
+ auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(OK);
auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
}
diff --git a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
index cbf11bf..094addd 100644
--- a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
+++ b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
@@ -80,7 +80,11 @@
// A RpcCertificateVerifier that does not verify anything.
class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
public:
- status_t verify(const SSL*, uint8_t*) override { return OK; }
+ RpcCertificateVerifierNoOp(status_t status) : mStatus(status) {}
+ status_t verify(const SSL*, uint8_t*) override { return mStatus; }
+
+private:
+ status_t mStatus;
};
} // namespace android
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index be55eba..c0f0a12 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -19,12 +19,19 @@
srcs: [
"main.cpp",
],
+ // Not using libbinder_tls_shared_deps to use deterministic boringssl libraries.
static_libs: [
"libbase",
"libcutils",
"liblog",
+ "libbinder_tls_static",
+ "libbinder_tls_test_utils",
+ "libssl_fuzz_unsafe",
+ "libcrypto_fuzz_unsafe",
],
-
+ cflags: [
+ "-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE" // for RAND_reset_for_fuzzing
+ ],
target: {
android: {
shared_libs: [
@@ -39,4 +46,8 @@
],
},
},
+ data: [
+ "server.crt",
+ "server.key",
+ ],
}
diff --git a/libs/binder/tests/rpc_fuzzer/create_certs.sh b/libs/binder/tests/rpc_fuzzer/create_certs.sh
new file mode 100755
index 0000000..4ae4cb1
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/create_certs.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# As explained in
+# https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca
+
+openssl genrsa -des3 -passout pass:xxxx -out server.pass.key 2048
+openssl rsa -passin pass:xxxx -in server.pass.key -out server.key
+rm -f server.pass.key
+
+openssl req \
+ -subj "/" \
+ -new -key server.key -out server.csr
+
+openssl x509 -req -sha256 -days 99999 -in server.csr -signkey server.key -out server.crt
+rm -f server.csr
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index c848798..518849a 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
-#include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
+#include <binder/RpcTransport.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
#include <fuzzer/FuzzedDataProvider.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
#include <sys/resource.h>
#include <sys/un.h>
@@ -51,13 +58,66 @@
}
};
+int passwordCallback(char* buf, int size, int /*rwflag*/, void* /*u*/) {
+ constexpr const char pass[] = "xxxx"; // See create_certs.sh
+ if (size <= 0) return 0;
+ int numCopy = std::min<int>(size, sizeof(pass));
+ (void)memcpy(buf, pass, numCopy);
+ return numCopy;
+}
+
+struct ServerAuth {
+ bssl::UniquePtr<EVP_PKEY> pkey;
+ bssl::UniquePtr<X509> cert;
+};
+
+// Use pre-configured keys because runtime generated keys / certificates are not
+// deterministic, and the algorithm is time consuming.
+ServerAuth readServerKeyAndCert() {
+ ServerAuth ret;
+
+ auto keyPath = android::base::GetExecutableDirectory() + "/data/server.key";
+ bssl::UniquePtr<BIO> keyBio(BIO_new_file(keyPath.c_str(), "r"));
+ ret.pkey.reset(PEM_read_bio_PrivateKey(keyBio.get(), nullptr, passwordCallback, nullptr));
+ CHECK_NE(ret.pkey.get(), nullptr);
+
+ auto certPath = android::base::GetExecutableDirectory() + "/data/server.crt";
+ bssl::UniquePtr<BIO> certBio(BIO_new_file(certPath.c_str(), "r"));
+ ret.cert.reset(PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
+ CHECK_NE(ret.cert.get(), nullptr);
+
+ return ret;
+}
+
+std::unique_ptr<RpcAuth> createServerRpcAuth() {
+ static auto sAuth = readServerKeyAndCert();
+
+ CHECK(EVP_PKEY_up_ref(sAuth.pkey.get()));
+ bssl::UniquePtr<EVP_PKEY> pkey(sAuth.pkey.get());
+ CHECK(X509_up_ref(sAuth.cert.get()));
+ bssl::UniquePtr<X509> cert(sAuth.cert.get());
+
+ return std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
+}
+
+std::unique_ptr<RpcTransportCtxFactory> makeTransportCtxFactory(FuzzedDataProvider* provider) {
+ bool isTls = provider->ConsumeBool();
+ if (!isTls) {
+ return RpcTransportCtxFactoryRaw::make();
+ }
+ status_t verifyStatus = provider->ConsumeIntegral<status_t>();
+ auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(verifyStatus);
+ return RpcTransportCtxFactoryTls::make(verifier, createServerRpcAuth());
+}
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > 50000) return 0;
FuzzedDataProvider provider(data, size);
+ RAND_reset_for_fuzzing();
unlink(kSock.c_str());
- sp<RpcServer> server = RpcServer::make();
+ sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
server->setRootObject(sp<SomeBinder>::make());
server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
diff --git a/libs/binder/tests/rpc_fuzzer/server.crt b/libs/binder/tests/rpc_fuzzer/server.crt
new file mode 100644
index 0000000..9142474
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICiTCCAXECFG1ggXE36l2WXeG6YTnaRVB7EmgQMA0GCSqGSIb3DQEBCwUAMAAw
+IBcNMjEwOTI5MDEzOTEzWhgPMjI5NTA3MTQwMTM5MTNaMAAwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDE3KnhPMwINpP5aIHIo/3GTlROZOK5AmkEsWmP
+w8smSWo2hJ7M0sOhruvOz82WORj48K8C0W72yFN+e9g32qoNMJFP/s6j1RWmaAKZ
+eSQUq6ixyaGhFLBOoukVykfTnY4qn4RbX5HzgpAPR1gv5ELvMXXPrxvtpIcVIrhm
+/dBQIa3iHZS6kypNbmRx/nhDVU8FK9s9WU5VLpbuNxv+m4X4Y1M/VZNatUMx5I0o
+ystV4JTqzjRZRPR4sxtMhu8/A11JsBVLeu8ZM/0IGCjmLOF4hy5a5YDv8MOJtdG2
+LI7ibZNtyrZiKwwhJc3tElzeIFit4T5Xjx69y/EMS4Hwhf3zAgMBAAEwDQYJKoZI
+hvcNAQELBQADggEBAD3gRbUybW7P2CihMyskTgS9HoIT9c02JWjtueWQIiQkyqTB
+6QdUQTHM5weil6TiW8NfpQQUIvrh66Pkph65shvFqxUsjdW25b4RbfUldFihfs1n
+kTa+e+hZONnVuzLvezIs2b8dygH9GA5y2OiLxwrMUcyaoCHGwKF7iOE0SJhfx0kY
+JDs4O+gAVjEsBSc24pm9aHBxgRCiEm1I4+RZf6PRBIz1ZadGBFsCZ+Gj6wyLP2Wq
+kjjMiV6o8pEjJjM+Oi4GfxvNewMCd2hMZYuJYpYC3cc7fPIpx8luidqKJdve8c6m
+KQ+dJ6ZQxEi0Zc9Jzre7NNoVcpIdc8SbkEM/DDo=
+-----END CERTIFICATE-----
diff --git a/libs/binder/tests/rpc_fuzzer/server.key b/libs/binder/tests/rpc_fuzzer/server.key
new file mode 100644
index 0000000..743470e
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAxNyp4TzMCDaT+WiByKP9xk5UTmTiuQJpBLFpj8PLJklqNoSe
+zNLDoa7rzs/NljkY+PCvAtFu9shTfnvYN9qqDTCRT/7Oo9UVpmgCmXkkFKuoscmh
+oRSwTqLpFcpH052OKp+EW1+R84KQD0dYL+RC7zF1z68b7aSHFSK4Zv3QUCGt4h2U
+upMqTW5kcf54Q1VPBSvbPVlOVS6W7jcb/puF+GNTP1WTWrVDMeSNKMrLVeCU6s40
+WUT0eLMbTIbvPwNdSbAVS3rvGTP9CBgo5izheIcuWuWA7/DDibXRtiyO4m2Tbcq2
+YisMISXN7RJc3iBYreE+V48evcvxDEuB8IX98wIDAQABAoIBACcI5jp+NqrOP6st
+uMZTFifzMi5VPMuYmcBPeXIDTc3qsr/ari5JAHeX2rQoakiGS9hYySsS4iDW+g9T
+eT0iA6QX5Ehrawf7YY6cgx9xcOEUZJ/ULlNlacw961/huzpPvHfhJ3qCycryMaSF
+7guZBFivgv/KZgxKGmrrdosdeufYXL3eHWZIrvcN4cDVgxslZg0o3Y5kCW3/KmDO
+QwvBlqgja93yImmkFA5BA/hQUsWuMBiR0xAd4b1NSBVCGTAYuCm6Up+6tIxeBSu5
+MVnNXbAIyVkbAS+gaR4uut6ObzFwUyGKDMaMpJ0LHLbusZy0svevu6Hjx+eH0ePC
+rj1xmDECgYEA4WR+1m3Tej0botG68+pZ8yLBgomSBAqpINCFkMEGQ2sQ1CqMMkHq
+8LAQNotU56W/0/H3eQemE3qBSKt1BUffpCvCHWkL9DRyDNhiq9U2PvV2Lx0Bv77e
+ET5MSDECUjlIsDqnv2qbq/m23BiP7AM8c9s6HjD0PqptyHjLlWHK86kCgYEA35hW
+AZEqMzsTNVQ8lXQtbqCyv8lls1SJbvIf3b5KItw9CwqpLr+UXssXh713j+yMW+WN
+3nv5+VaggkNBa9fHdqQEYT0L52OnLNjsfTlVhP5g2lOIa5VQYb/wqF1TaiZ27SGU
+lmLqiyArZgTnc3yo1wuIRPAbYbbm6CVnz7bm5jsCgYEAqfov7WZF5hnPjaq9YtWJ
+oGLFrLwy8flYMvcOw2vOXWmQ93Be6kfr9jfRAlFxZoEJeb0w9IVgKbBpb3Ree+0I
+K7cUXTmrWi9zE1zcjNnuXuyehElL2F8I+dgRjx/msDujJcQWXbT4UWmxDas4XrTS
+Ek1yNvKUP+4nfNgcMDvf4oECgYEAjgfYajpqEgzukKunqFAaI/HUWdt2zMlgW6dV
+8qdTtH0uEXt+KIHtn6FmmwURk8zxA9b3nWInUeljIBvUzMpOm+BoH9SFYUB+CxDo
+eEsZNdfYchcpyx0X6F/iYTCXMhCo7syr9DN1RVbz+mQXGdcP8ToUH6Zd3l4uozxP
+izRly80CgYEAqz7fCgQH74BwHoroSNdD3Cn6KNVx+oPuwRmzO4xMSOGyd/dNB2NA
+uzzuCTbrzC0jCXpqR0Bh9gYMjxyRZbifPX/YuFHyCIKK4+SQfeC4ZEwmSJVGWeh7
+3NksFJPCH4K3KbLNputByWJWOgKUdy70e/xOi83acBAVyRs+7H9LocE=
+-----END RSA PRIVATE KEY-----
diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
index 6f054d2..8ea948c 100644
--- a/libs/binder/tests/unit_fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -30,16 +30,28 @@
"-Wall",
"-Werror",
],
- shared_libs: [
- "libbinder",
- "libutils",
- "libbase",
- ],
target: {
+ android: {
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
darwin: {
enabled: false,
- }
- }
+ },
+ },
}
cc_fuzz {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 379b090..14ec948 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -456,10 +456,10 @@
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
+ const bool sizeHasChanged = mRequestedSize != mSize;
+ mSize = mRequestedSize;
+ const bool updateDestinationFrame = sizeHasChanged || !mLastBufferInfo.hasBuffer;
Rect crop = computeCrop(bufferItem);
- const bool updateDestinationFrame =
- bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE ||
- !mLastBufferInfo.hasBuffer;
mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
bufferItem.mScalingMode, crop);
@@ -468,12 +468,12 @@
std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4);
- t->setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback);
+ sp<Fence> fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE;
+ t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId,
+ releaseBufferCallback);
t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace));
t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata);
t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage);
- t->setAcquireFence(mSurfaceControl,
- bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
mSurfaceControlsWithPendingCallback.push(mSurfaceControl);
@@ -486,7 +486,6 @@
if (!bufferItem.mIsAutoTimestamp) {
t->setDesiredPresentTime(bufferItem.mTimestamp);
}
- t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
if (!mNextFrameTimelineInfoQueue.empty()) {
t->setFrameTimelineInfo(mNextFrameTimelineInfoQueue.front());
@@ -572,7 +571,6 @@
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
- mSize = mRequestedSize;
// Only reject buffers if scaling mode is freeze.
return false;
}
@@ -586,7 +584,6 @@
}
ui::Size bufferSize(bufWidth, bufHeight);
if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
- mSize = mRequestedSize;
return false;
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index a419a63..cf61209 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -64,12 +64,10 @@
frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS),
fixedTransformHint(ui::Transform::ROT_INVALID),
- frameNumber(0),
autoRefresh(false),
isTrustedOverlay(false),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
- releaseBufferListener(nullptr),
dropInputMode(gui::DropInputMode::NONE) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -104,20 +102,6 @@
SAFE_PARCEL(output.writeBool, transformToDisplayInverse);
SAFE_PARCEL(output.write, orientedDisplaySpaceRect);
- if (buffer) {
- SAFE_PARCEL(output.writeBool, true);
- SAFE_PARCEL(output.write, *buffer);
- } else {
- SAFE_PARCEL(output.writeBool, false);
- }
-
- if (acquireFence) {
- SAFE_PARCEL(output.writeBool, true);
- SAFE_PARCEL(output.write, *acquireFence);
- } else {
- SAFE_PARCEL(output.writeBool, false);
- }
-
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dataspace));
SAFE_PARCEL(output.write, hdrMetadata);
SAFE_PARCEL(output.write, surfaceDamageRegion);
@@ -133,8 +117,6 @@
SAFE_PARCEL(output.write, colorTransform.asArray(), 16 * sizeof(float));
SAFE_PARCEL(output.writeFloat, cornerRadius);
SAFE_PARCEL(output.writeUint32, backgroundBlurRadius);
- SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote());
- SAFE_PARCEL(output.writeUint64, cachedBuffer.id);
SAFE_PARCEL(output.writeParcelable, metadata);
SAFE_PARCEL(output.writeFloat, bgColorAlpha);
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(bgColorDataspace));
@@ -151,9 +133,7 @@
SAFE_PARCEL(output.writeByte, frameRateCompatibility);
SAFE_PARCEL(output.writeByte, changeFrameRateStrategy);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
- SAFE_PARCEL(output.writeUint64, frameNumber);
SAFE_PARCEL(output.writeBool, autoRefresh);
- SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener));
SAFE_PARCEL(output.writeUint32, blurRegions.size());
for (auto region : blurRegions) {
@@ -174,8 +154,8 @@
SAFE_PARCEL(output.write, destinationFrame);
SAFE_PARCEL(output.writeBool, isTrustedOverlay);
- SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode));
+ SAFE_PARCEL(bufferData.write, output);
return NO_ERROR;
}
@@ -217,19 +197,6 @@
SAFE_PARCEL(input.readBool, &transformToDisplayInverse);
SAFE_PARCEL(input.read, orientedDisplaySpaceRect);
- bool tmpBool = false;
- SAFE_PARCEL(input.readBool, &tmpBool);
- if (tmpBool) {
- buffer = new GraphicBuffer();
- SAFE_PARCEL(input.read, *buffer);
- }
-
- SAFE_PARCEL(input.readBool, &tmpBool);
- if (tmpBool) {
- acquireFence = new Fence();
- SAFE_PARCEL(input.read, *acquireFence);
- }
-
uint32_t tmpUint32 = 0;
SAFE_PARCEL(input.readUint32, &tmpUint32);
dataspace = static_cast<ui::Dataspace>(tmpUint32);
@@ -237,6 +204,8 @@
SAFE_PARCEL(input.read, hdrMetadata);
SAFE_PARCEL(input.read, surfaceDamageRegion);
SAFE_PARCEL(input.readInt32, &api);
+
+ bool tmpBool = false;
SAFE_PARCEL(input.readBool, &tmpBool);
if (tmpBool) {
sidebandStream = NativeHandle::create(input.readNativeHandle(), true);
@@ -245,10 +214,6 @@
SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float));
SAFE_PARCEL(input.readFloat, &cornerRadius);
SAFE_PARCEL(input.readUint32, &backgroundBlurRadius);
- sp<IBinder> tmpBinder;
- SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
- cachedBuffer.token = tmpBinder;
- SAFE_PARCEL(input.readUint64, &cachedBuffer.id);
SAFE_PARCEL(input.readParcelable, &metadata);
SAFE_PARCEL(input.readFloat, &bgColorAlpha);
@@ -273,15 +238,8 @@
SAFE_PARCEL(input.readByte, &changeFrameRateStrategy);
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
- SAFE_PARCEL(input.readUint64, &frameNumber);
SAFE_PARCEL(input.readBool, &autoRefresh);
- tmpBinder = nullptr;
- SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
- if (tmpBinder) {
- releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
- }
-
uint32_t numRegions = 0;
SAFE_PARCEL(input.readUint32, &numRegions);
blurRegions.clear();
@@ -305,11 +263,10 @@
SAFE_PARCEL(input.read, destinationFrame);
SAFE_PARCEL(input.readBool, &isTrustedOverlay);
- SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
-
uint32_t mode;
SAFE_PARCEL(input.readUint32, &mode);
dropInputMode = static_cast<gui::DropInputMode>(mode);
+ SAFE_PARCEL(bufferData.read, input);
return NO_ERROR;
}
@@ -460,12 +417,7 @@
}
if (other.what & eBufferChanged) {
what |= eBufferChanged;
- buffer = other.buffer;
- releaseBufferEndpoint = other.releaseBufferEndpoint;
- }
- if (other.what & eAcquireFenceChanged) {
- what |= eAcquireFenceChanged;
- acquireFence = other.acquireFence;
+ bufferData = other.bufferData;
}
if (other.what & eDataspaceChanged) {
what |= eDataspaceChanged;
@@ -498,10 +450,6 @@
what |= eInputInfoChanged;
windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle);
}
- if (other.what & eCachedBufferChanged) {
- what |= eCachedBufferChanged;
- cachedBuffer = other.cachedBuffer;
- }
if (other.what & eBackgroundColorChanged) {
what |= eBackgroundColorChanged;
color = other.color;
@@ -530,10 +478,6 @@
what |= eFixedTransformHintChanged;
fixedTransformHint = other.fixedTransformHint;
}
- if (other.what & eFrameNumberChanged) {
- what |= eFrameNumberChanged;
- frameNumber = other.frameNumber;
- }
if (other.what & eAutoRefreshChanged) {
what |= eAutoRefreshChanged;
autoRefresh = other.autoRefresh;
@@ -542,13 +486,6 @@
what |= eTrustedOverlayChanged;
isTrustedOverlay = other.isTrustedOverlay;
}
- if (other.what & eReleaseBufferListenerChanged) {
- if (releaseBufferListener) {
- ALOGW("Overriding releaseBufferListener");
- }
- what |= eReleaseBufferListenerChanged;
- releaseBufferListener = other.releaseBufferListener;
- }
if (other.what & eStretchChanged) {
what |= eStretchChanged;
stretchEffect = other.stretchEffect;
@@ -576,11 +513,11 @@
}
bool layer_state_t::hasBufferChanges() const {
- return (what & layer_state_t::eBufferChanged) || (what & layer_state_t::eCachedBufferChanged);
+ return what & layer_state_t::eBufferChanged;
}
bool layer_state_t::hasValidBuffer() const {
- return buffer || cachedBuffer.isValid();
+ return bufferData.buffer || bufferData.cachedBuffer.isValid();
}
status_t layer_state_t::matrix22_t::write(Parcel& output) const {
@@ -741,4 +678,66 @@
return NO_ERROR;
}
+status_t BufferData::write(Parcel& output) const {
+ SAFE_PARCEL(output.writeInt32, flags.get());
+
+ if (buffer) {
+ SAFE_PARCEL(output.writeBool, true);
+ SAFE_PARCEL(output.write, *buffer);
+ } else {
+ SAFE_PARCEL(output.writeBool, false);
+ }
+
+ if (acquireFence) {
+ SAFE_PARCEL(output.writeBool, true);
+ SAFE_PARCEL(output.write, *acquireFence);
+ } else {
+ SAFE_PARCEL(output.writeBool, false);
+ }
+
+ SAFE_PARCEL(output.writeUint64, frameNumber);
+ SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener));
+ SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
+
+ SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote());
+ SAFE_PARCEL(output.writeUint64, cachedBuffer.id);
+
+ return NO_ERROR;
+}
+
+status_t BufferData::read(const Parcel& input) {
+ int32_t tmpInt32;
+ SAFE_PARCEL(input.readInt32, &tmpInt32);
+ flags = Flags<BufferDataChange>(tmpInt32);
+
+ bool tmpBool = false;
+ SAFE_PARCEL(input.readBool, &tmpBool);
+ if (tmpBool) {
+ buffer = new GraphicBuffer();
+ SAFE_PARCEL(input.read, *buffer);
+ }
+
+ SAFE_PARCEL(input.readBool, &tmpBool);
+ if (tmpBool) {
+ acquireFence = new Fence();
+ SAFE_PARCEL(input.read, *acquireFence);
+ }
+
+ SAFE_PARCEL(input.readUint64, &frameNumber);
+
+ sp<IBinder> tmpBinder = nullptr;
+ SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
+ if (tmpBinder) {
+ releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
+ }
+ SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
+
+ tmpBinder = nullptr;
+ SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder);
+ cachedBuffer.token = tmpBinder;
+ SAFE_PARCEL(input.readUint64, &cachedBuffer.id);
+
+ return NO_ERROR;
+}
+
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index bbd3cca..aca59b6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -805,7 +805,7 @@
layer_state_t* s = &(mComposerStates[handle].state);
if (!(s->what & layer_state_t::eBufferChanged)) {
continue;
- } else if (s->what & layer_state_t::eCachedBufferChanged) {
+ } else if (s->bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged)) {
// If eBufferChanged and eCachedBufferChanged are both trued then that means
// we already cached the buffer in a previous call to cacheBuffers, perhaps
// from writeToParcel on a Transaction that was merged in to this one.
@@ -814,23 +814,22 @@
// Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste
// time trying to cache them.
- if (!s->buffer) {
+ if (!s->bufferData.buffer) {
continue;
}
uint64_t cacheId = 0;
- status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId);
+ status_t ret = BufferCache::getInstance().getCacheId(s->bufferData.buffer, &cacheId);
if (ret == NO_ERROR) {
// Cache-hit. Strip the buffer and send only the id.
- s->what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged);
- s->buffer = nullptr;
+ s->bufferData.buffer = nullptr;
} else {
// Cache-miss. Include the buffer and send the new cacheId.
- cacheId = BufferCache::getInstance().cache(s->buffer);
+ cacheId = BufferCache::getInstance().cache(s->bufferData.buffer);
}
- s->what |= layer_state_t::eCachedBufferChanged;
- s->cachedBuffer.token = BufferCache::getInstance().getToken();
- s->cachedBuffer.id = cacheId;
+ s->bufferData.flags |= BufferData::BufferDataChange::cachedBufferChanged;
+ s->bufferData.cachedBuffer.token = BufferCache::getInstance().getToken();
+ s->bufferData.cachedBuffer.id = cacheId;
// If we have more buffers than the size of the cache, we should stop caching so we don't
// evict other buffers in this transaction
@@ -1289,22 +1288,33 @@
}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer(
- const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer, const ReleaseCallbackId& id,
- ReleaseBufferCallback callback) {
+ const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+ const std::optional<sp<Fence>>& fence, const std::optional<uint64_t>& frameNumber,
+ const ReleaseCallbackId& id, ReleaseBufferCallback callback) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
removeReleaseBufferCallback(s);
- s->what |= layer_state_t::eBufferChanged;
- s->buffer = buffer;
- s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ if (frameNumber) {
+ bufferData.frameNumber = *frameNumber;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ }
+ if (fence) {
+ bufferData.acquireFence = *fence;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ }
+ bufferData.releaseBufferEndpoint =
+ IInterface::asBinder(TransactionCompletedListener::getIInstance());
if (mIsAutoTimestamp) {
mDesiredPresentTime = systemTime();
}
- setReleaseBufferCallback(s, id, callback);
-
+ setReleaseBufferCallback(&bufferData, id, callback);
+ s->what |= layer_state_t::eBufferChanged;
+ s->bufferData = bufferData;
registerSurfaceControlForCallback(sc);
mContainsBuffer = true;
@@ -1312,51 +1322,33 @@
}
void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) {
- if (!s->releaseBufferListener) {
+ if (!(s->what & layer_state_t::eBufferChanged)) {
return;
}
- s->what &= ~static_cast<uint64_t>(layer_state_t::eReleaseBufferListenerChanged);
- s->releaseBufferListener = nullptr;
auto listener = TransactionCompletedListener::getInstance();
- listener->removeReleaseBufferCallback(s->releaseCallbackId);
- s->releaseCallbackId = ReleaseCallbackId::INVALID_ID;
+ listener->removeReleaseBufferCallback(s->bufferData.releaseCallbackId);
}
-void SurfaceComposerClient::Transaction::setReleaseBufferCallback(layer_state_t* s,
+void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData,
const ReleaseCallbackId& id,
ReleaseBufferCallback callback) {
if (!callback) {
return;
}
- if (!s->buffer) {
+ if (!bufferData->buffer) {
ALOGW("Transaction::setReleaseBufferCallback"
"ignored trying to set a callback on a null buffer.");
return;
}
- s->what |= layer_state_t::eReleaseBufferListenerChanged;
- s->releaseBufferListener = TransactionCompletedListener::getIInstance();
- s->releaseCallbackId = id;
+ bufferData->releaseBufferListener = TransactionCompletedListener::getIInstance();
+ bufferData->releaseCallbackId = id;
auto listener = TransactionCompletedListener::getInstance();
listener->setReleaseBufferCallback(id, callback);
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence(
- const sp<SurfaceControl>& sc, const sp<Fence>& fence) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eAcquireFenceChanged;
- s->acquireFence = fence;
-
- registerSurfaceControlForCallback(sc);
- return *this;
-}
-
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace(
const sp<SurfaceControl>& sc, ui::Dataspace dataspace) {
layer_state_t* s = getLayerState(sc);
@@ -1506,20 +1498,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameNumber(
- const sp<SurfaceControl>& sc, uint64_t frameNumber) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
-
- s->what |= layer_state_t::eFrameNumberChanged;
- s->frameNumber = frameNumber;
-
- return *this;
-}
-
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
const sp<SurfaceControl>& sc, const WindowInfo& info) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b27102b..1f5d289 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -58,6 +58,44 @@
bool isValid() const { return token != nullptr; }
};
+struct BufferData {
+ enum class BufferDataChange : uint32_t {
+ fenceChanged = 0x01,
+ frameNumberChanged = 0x02,
+ cachedBufferChanged = 0x04,
+ };
+
+ sp<GraphicBuffer> buffer;
+ sp<Fence> acquireFence;
+
+ // Used by BlastBufferQueue to forward the framenumber generated by the
+ // graphics producer.
+ uint64_t frameNumber = 0;
+
+ // Listens to when the buffer is safe to be released. This is used for blast
+ // layers only. The callback includes a release fence as well as the graphic
+ // buffer id to identify the buffer.
+ sp<ITransactionCompletedListener> releaseBufferListener = nullptr;
+
+ // Keeps track of the release callback id associated with the listener. This
+ // is not sent to the server since the id can be reconstructed there. This
+ // is used to remove the old callback from the client process map if it is
+ // overwritten by another setBuffer call.
+ ReleaseCallbackId releaseCallbackId = ReleaseCallbackId::INVALID_ID;
+
+ // 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;
+
+ Flags<BufferDataChange> flags;
+
+ client_cache_t cachedBuffer;
+
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+};
+
/*
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
@@ -82,7 +120,7 @@
eTransparentRegionChanged = 0x00000020,
eFlagsChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
- eReleaseBufferListenerChanged = 0x00000400,
+ /* unused 0x00000400, */
eShadowRadiusChanged = 0x00000800,
eLayerCreated = 0x00001000,
eBufferCropChanged = 0x00002000,
@@ -94,7 +132,7 @@
eTransformToDisplayInverseChanged = 0x00080000,
eCropChanged = 0x00100000,
eBufferChanged = 0x00200000,
- eAcquireFenceChanged = 0x00400000,
+ /* unused 0x00400000, */
eDataspaceChanged = 0x00800000,
eHdrMetadataChanged = 0x01000000,
eSurfaceDamageRegionChanged = 0x02000000,
@@ -105,7 +143,7 @@
eInputInfoChanged = 0x40000000,
eCornerRadiusChanged = 0x80000000,
eDestinationFrameChanged = 0x1'00000000,
- eCachedBufferChanged = 0x2'00000000,
+ /* unused = 0x2'00000000, */
eBackgroundColorChanged = 0x4'00000000,
eMetadataChanged = 0x8'00000000,
eColorSpaceAgnosticChanged = 0x10'00000000,
@@ -114,7 +152,7 @@
eBackgroundBlurRadiusChanged = 0x80'00000000,
eProducerDisconnect = 0x100'00000000,
eFixedTransformHintChanged = 0x200'00000000,
- eFrameNumberChanged = 0x400'00000000,
+ /* unused 0x400'00000000, */
eBlurRegionsChanged = 0x800'00000000,
eAutoRefreshChanged = 0x1000'00000000,
eStretchChanged = 0x2000'00000000,
@@ -169,8 +207,7 @@
bool transformToDisplayInverse;
Rect crop;
Rect orientedDisplaySpaceRect;
- sp<GraphicBuffer> buffer;
- sp<Fence> acquireFence;
+ BufferData bufferData;
ui::Dataspace dataspace;
HdrMetadata hdrMetadata;
Region surfaceDamageRegion;
@@ -181,8 +218,6 @@
sp<gui::WindowInfoHandle> windowInfoHandle = new gui::WindowInfoHandle();
- client_cache_t cachedBuffer;
-
LayerMetadata metadata;
// The following refer to the alpha, and dataspace, respectively of
@@ -216,10 +251,6 @@
// otherwise the value will be a valid ui::Rotation.
ui::Transform::RotationFlags fixedTransformHint;
- // Used by BlastBufferQueue to forward the framenumber generated by the
- // graphics producer.
- uint64_t frameNumber;
-
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
// in shared buffer mode.
@@ -235,22 +266,6 @@
Rect bufferCrop;
Rect destinationFrame;
- // Listens to when the buffer is safe to be released. This is used for blast
- // layers only. The callback includes a release fence as well as the graphic
- // buffer id to identify the buffer.
- sp<ITransactionCompletedListener> releaseBufferListener;
-
- // Keeps track of the release callback id associated with the listener. This
- // is not sent to the server since the id can be reconstructed there. This
- // 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;
-
// Force inputflinger to drop all input events for the layer and its children.
gui::DropInputMode dropInputMode;
};
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 403ca0a..82249a3 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -399,8 +399,7 @@
void cacheBuffers();
void registerSurfaceControlForCallback(const sp<SurfaceControl>& sc);
- void setReleaseBufferCallback(layer_state_t*, const ReleaseCallbackId&,
- ReleaseBufferCallback);
+ void setReleaseBufferCallback(BufferData*, const ReleaseCallbackId&, ReleaseBufferCallback);
void removeReleaseBufferCallback(layer_state_t*);
public:
@@ -473,10 +472,10 @@
Transaction& setTransformToDisplayInverse(const sp<SurfaceControl>& sc,
bool transformToDisplayInverse);
Transaction& setBuffer(const sp<SurfaceControl>& sc, const sp<GraphicBuffer>& buffer,
+ const std::optional<sp<Fence>>& fence = std::nullopt,
+ const std::optional<uint64_t>& frameNumber = std::nullopt,
const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID,
ReleaseBufferCallback callback = nullptr);
- Transaction& setCachedBuffer(const sp<SurfaceControl>& sc, int32_t bufferId);
- Transaction& setAcquireFence(const sp<SurfaceControl>& sc, const sp<Fence>& fence);
Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace);
Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata);
Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc,
@@ -501,8 +500,6 @@
// ONLY FOR BLAST ADAPTER
Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc);
- // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
- Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const gui::WindowInfo& info);
Transaction& setFocusedWindow(const gui::FocusRequest& request);
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 26d902d..b474086 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -672,6 +672,83 @@
/*border*/ 0, /*outsideRegion*/ true));
}
+// b/196339769 verify we can can update the requested size while the in FREEZE scaling mode and
+// scale the buffer properly when the mode changes to SCALE_TO_WINDOW
+TEST_F(BLASTBufferQueueTest, ScalingModeChanges) {
+ uint8_t r = 255;
+ uint8_t g = 0;
+ uint8_t b = 0;
+
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight / 4);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 4,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ uint32_t* bufData;
+ buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+ fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ adapter.waitForCallbacks();
+ }
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(r, g, b,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 4}));
+
+ // update the size to half the display and dequeue a buffer quarter of the display.
+ adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight / 2);
+
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 8,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ uint32_t* bufData;
+ buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+ g = 255;
+ fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
+ 0, Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ adapter.waitForCallbacks();
+ }
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+ // verify we still scale the buffer to the new size (half the screen height)
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(r, g, b,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
+}
+
class TestProducerListener : public BnProducerListener {
public:
sp<IGraphicBufferProducer> mIgbp;
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 6af6195..2b6833e 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -34,19 +34,19 @@
BlurFilter::BlurFilter() {
SkString blurString(R"(
- uniform shader input;
+ uniform shader child;
uniform float2 in_blurOffset;
uniform float2 in_maxSizeXY;
half4 main(float2 xy) {
- half4 c = input.eval(xy);
- c += input.eval(float2(clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ half4 c = child.eval(xy);
+ c += child.eval(float2(clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
clamp( in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
- c += input.eval(float2(clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ c += child.eval(float2(clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
clamp(-in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
- c += input.eval(float2(clamp(-in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ c += child.eval(float2(clamp(-in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
clamp( in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
- c += input.eval(float2(clamp(-in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ c += child.eval(float2(clamp(-in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
clamp(-in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
return half4(c.rgb * 0.2, 1.0);
@@ -101,7 +101,7 @@
// start by downscaling and doing the first blur pass
SkSamplingOptions linear(SkFilterMode::kLinear, SkMipmapMode::kNone);
SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
- blurBuilder.child("input") =
+ blurBuilder.child("child") =
input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear, blurMatrix);
blurBuilder.uniform("in_blurOffset") = SkV2{stepX * kInputScale, stepY * kInputScale};
blurBuilder.uniform("in_maxSizeXY") =
@@ -112,7 +112,7 @@
// And now we'll build our chain of scaled blur stages
for (auto i = 1; i < numberOfPasses; i++) {
const float stepScale = (float)i * kInputScale;
- blurBuilder.child("input") =
+ blurBuilder.child("child") =
tmpBlur->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear);
blurBuilder.uniform("in_blurOffset") = SkV2{stepX * stepScale, stepY * stepScale};
blurBuilder.uniform("in_maxSizeXY") =
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index dc5fe17..73dadef 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -389,9 +389,9 @@
static void generateEffectiveOOTF(bool undoPremultipliedAlpha, SkString& shader) {
shader.append(R"(
- uniform shader input;
+ uniform shader child;
half4 main(float2 xy) {
- float4 c = float4(input.eval(xy));
+ float4 c = float4(child.eval(xy));
)");
if (undoPremultipliedAlpha) {
shader.append(R"(
@@ -451,7 +451,7 @@
ATRACE_CALL();
SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
- effectBuilder.child("input") = shader;
+ effectBuilder.child("child") = shader;
if (linearEffect.inputDataspace == linearEffect.outputDataspace) {
effectBuilder.uniform("in_rgbToXyz") = mat4();
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c351676..db1a1cc 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -614,6 +614,8 @@
Return<void> SensorDevice::onDynamicSensorsConnected(
const hidl_vec<SensorInfo> &dynamicSensorsAdded) {
+ std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+
// Allocate a sensor_t structure for each dynamic sensor added and insert
// it into the dictionary of connected dynamic sensors keyed by handle.
for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
@@ -629,6 +631,8 @@
std::make_pair(sensor->handle, sensor));
}
+ mDynamicSensorsCv.notify_all();
+
return Return<void>();
}
@@ -1174,8 +1178,20 @@
dst->dynamic_sensor_meta.connected = dyn.connected;
dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
if (dyn.connected) {
+ std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+ // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
+ // can be received out of order from this event due to a bug in the HIDL spec that
+ // marks it as oneway.
auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
- CHECK(it != mConnectedDynamicSensors.end());
+ if (it == mConnectedDynamicSensors.end()) {
+ mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT,
+ [&, dyn]{
+ return mConnectedDynamicSensors.find(dyn.sensorHandle)
+ != mConnectedDynamicSensors.end();
+ });
+ it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+ CHECK(it != mConnectedDynamicSensors.end());
+ }
dst->dynamic_sensor_meta.sensor = it->second;
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 75da7bb..bc8d20f 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -139,6 +139,14 @@
Vector<sensor_t> mSensorList;
std::unordered_map<int32_t, sensor_t*> mConnectedDynamicSensors;
+ // A bug in the Sensors HIDL spec which marks onDynamicSensorsConnected as oneway causes dynamic
+ // meta events and onDynamicSensorsConnected to be received out of order. This mutex + CV are
+ // used to block meta event processing until onDynamicSensorsConnected is received to simplify
+ // HAL implementations.
+ std::mutex mDynamicSensorsMutex;
+ std::condition_variable mDynamicSensorsCv;
+ static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
+
static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
mutable Mutex mLock; // protect mActivationCount[].batchParams
// fixed-size array after construction
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d805294..ef05fe2 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -620,14 +620,6 @@
return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
}
-uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
- if (hasFrameUpdate()) {
- return getFrameNumber(expectedPresentTime);
- } else {
- return mCurrentFrameNumber;
- }
-}
-
Rect BufferLayer::getBufferSize(const State& s) const {
// If we have a sideband stream, or we are scaling the buffer then return the layer size since
// we cannot determine the buffer size.
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 760c8b9..2da73f8 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -164,8 +164,6 @@
void updateCloneBufferInfo() override;
uint64_t mPreviousFrameNumber = 0;
- uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const override;
-
void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
// Transform hint provided to the producer. This must be accessed holding
@@ -189,8 +187,6 @@
private:
virtual bool fenceHasSignaled() const = 0;
virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0;
- virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0;
-
// Latch sideband stream and returns true if the dirty region should be updated.
virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index d51db88..8bbe438 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -161,39 +161,6 @@
return mQueueItems[0].item.mTimestamp <= expectedPresentTime;
}
-uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const {
- Mutex::Autolock lock(mQueueItemLock);
- uint64_t frameNumber = mQueueItems[0].item.mFrameNumber;
-
- // The head of the queue will be dropped if there are signaled and timely frames behind it
- if (isRemovedFromCurrentState()) {
- expectedPresentTime = 0;
- }
-
- for (size_t i = 1; i < mQueueItems.size(); i++) {
- const bool fenceSignaled =
- mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
- if (!fenceSignaled) {
- break;
- }
-
- // We don't drop frames without explicit timestamps
- if (mQueueItems[i].item.mIsAutoTimestamp) {
- break;
- }
-
- const nsecs_t desiredPresent = mQueueItems[i].item.mTimestamp;
- if (desiredPresent < expectedPresentTime - BufferQueueConsumer::MAX_REASONABLE_NSEC ||
- desiredPresent > expectedPresentTime) {
- break;
- }
-
- frameNumber = mQueueItems[i].item.mFrameNumber;
- }
-
- return frameNumber;
-}
-
bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
// We need to update the sideband stream if the layer has both a buffer and a sideband stream.
editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get();
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index b3b7948..be2902b 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -89,7 +89,6 @@
};
private:
- uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
bool latchSidebandStream(bool& recomputeVisibleRegions) override;
void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 7466c06..ed45cab 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -214,7 +214,7 @@
JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
}
- mFlinger->getTransactionCallbackInvoker().finalizePendingCallbackHandles(
+ mFlinger->getTransactionCallbackInvoker().addCallbackHandles(
mDrawingState.callbackHandles, jankData);
mDrawingState.callbackHandles = {};
@@ -406,15 +406,55 @@
return true;
}
-bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- const sp<Fence>& acquireFence, nsecs_t postTime,
+std::shared_ptr<renderengine::ExternalTexture> BufferStateLayer::getBufferFromBufferData(
+ const BufferData& bufferData) {
+ bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
+ bool bufferSizeExceedsLimit = false;
+ std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
+ if (cacheIdChanged && bufferData.buffer != nullptr) {
+ bufferSizeExceedsLimit =
+ mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+ bufferData.buffer->getHeight());
+ if (!bufferSizeExceedsLimit) {
+ ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer);
+ buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+ }
+ } else if (cacheIdChanged) {
+ buffer = ClientCache::getInstance().get(bufferData.cachedBuffer);
+ } else if (bufferData.buffer != nullptr) {
+ bufferSizeExceedsLimit =
+ mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+ bufferData.buffer->getHeight());
+ if (!bufferSizeExceedsLimit) {
+ buffer = std::make_shared<
+ renderengine::ExternalTexture>(bufferData.buffer, mFlinger->getRenderEngine(),
+ renderengine::ExternalTexture::Usage::READABLE);
+ }
+ }
+ ALOGE_IF(bufferSizeExceedsLimit,
+ "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
+ "limit.",
+ getDebugName());
+ return buffer;
+}
+
+bool BufferStateLayer::setBuffer(const BufferData& bufferData, 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>& releaseBufferListener,
- const sp<IBinder>& releaseBufferEndpoint) {
+ std::optional<nsecs_t> dequeueTime,
+ const FrameTimelineInfo& info) {
ATRACE_CALL();
+ const std::shared_ptr<renderengine::ExternalTexture>& buffer =
+ getBufferFromBufferData(bufferData);
+ if (!buffer) {
+ return false;
+ }
+
+ const bool frameNumberChanged =
+ bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
+ const uint64_t frameNumber =
+ frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1;
+
if (mDrawingState.buffer) {
mReleasePreviousBuffer = true;
if (mDrawingState.buffer != mBufferInfo.mBuffer ||
@@ -438,9 +478,17 @@
}
mDrawingState.frameNumber = frameNumber;
- mDrawingState.releaseBufferListener = releaseBufferListener;
+ mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
mDrawingState.buffer = buffer;
- mDrawingState.clientCacheId = clientCacheId;
+ mDrawingState.clientCacheId = bufferData.cachedBuffer;
+
+ mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
+ ? bufferData.acquireFence
+ : Fence::NO_FENCE;
+ mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(mDrawingState.acquireFence);
+ // The acquire fences of BufferStateLayers have already signaled before they are set
+ mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
+
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
@@ -462,7 +510,7 @@
mFlinger->mScheduler->recordLayerHistory(this, presentTime,
LayerHistory::LayerUpdateType::Buffer);
- addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
+ addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
setFrameTimelineVsyncForBufferTransaction(info, postTime);
@@ -477,20 +525,7 @@
mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
- mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint;
-
- return true;
-}
-
-bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
- mDrawingState.acquireFence = fence;
- mDrawingState.acquireFenceTime = std::make_unique<FenceTime>(fence);
-
- // The acquire fences of BufferStateLayers have already signaled before they are set
- mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime();
-
- mDrawingState.modified = true;
- setTransactionFlags(eTransactionNeeded);
+ mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
return true;
}
@@ -564,10 +599,6 @@
handle->acquireTime = mCallbackHandleAcquireTime;
handle->frameNumber = mDrawingState.frameNumber;
- // Notify the transaction completed thread that there is a pending latched callback
- // handle
- mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle);
-
// Store so latched time and release fence can be set
mDrawingState.callbackHandles.push_back(handle);
@@ -659,36 +690,6 @@
return BufferLayer::onPreComposition(refreshStartTime);
}
-uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {
- return mDrawingState.frameNumber;
-}
-
-/**
- * This is the frameNumber used for deferred transaction signalling. We need to use this because
- * of cases where we defer a transaction for a surface to itself. In the BLAST world this
- * may not make a huge amount of sense (Why not just merge the Buffer transaction with the
- * deferred transaction?) but this is an important legacy use case, for example moving
- * a window at the same time it draws makes use of this kind of technique. So anyway
- * imagine we have something like this:
- *
- * Transaction { // containing
- * Buffer -> frameNumber = 2
- * DeferTransactionUntil -> frameNumber = 2
- * Random other stuff
- * }
- * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber).
- * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we
- * haven't swapped mDrawingState to mDrawingState yet we will think the sync point
- * is not ready. So we will return false from applyPendingState and not swap
- * current state to drawing state. But because we don't swap current state
- * to drawing state the number will never update and we will be stuck. This way
- * we can see we need to return the frame number for the buffer we are about
- * to apply.
- */
-uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const {
- return mDrawingState.frameNumber;
-}
-
void BufferStateLayer::setAutoRefresh(bool autoRefresh) {
if (!mAutoRefresh.exchange(autoRefresh)) {
mFlinger->signalLayerUpdate();
@@ -765,7 +766,7 @@
std::deque<sp<CallbackHandle>> remainingHandles;
mFlinger->getTransactionCallbackInvoker()
- .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
+ .addOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
mDrawingState.callbackHandles = remainingHandles;
mDrawingStateModified = false;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 124e91a..87b68ea 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -55,13 +55,9 @@
bool setTransform(uint32_t transform) override;
bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
bool setCrop(const Rect& crop) override;
- bool setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
- 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,
- const sp<IBinder>& releaseBufferEndpoint) override;
- bool setAcquireFence(const sp<Fence>& fence) override;
+ bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
+ bool isAutoTimestamp, std::optional<nsecs_t> dequeueTime,
+ const FrameTimelineInfo& info) override;
bool setDataspace(ui::Dataspace dataspace) override;
bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
@@ -105,7 +101,6 @@
protected:
void gatherBufferInfo() override;
- uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const;
void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
ui::Transform getInputTransform() const override;
Rect getInputBounds() const override;
@@ -122,8 +117,6 @@
status_t addReleaseFence(const sp<CallbackHandle>& ch, const sp<Fence>& releaseFence);
- uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override;
-
bool latchSidebandStream(bool& recomputeVisibleRegions) override;
bool hasFrameUpdate() const override;
@@ -143,6 +136,9 @@
bool bufferNeedsFiltering() const override;
+ std::shared_ptr<renderengine::ExternalTexture> getBufferFromBufferData(
+ const BufferData& bufferData);
+
sp<Fence> mPreviousReleaseFence;
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8c281d5..f29ebde 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -416,17 +416,11 @@
// Used only to set BufferStateLayer state
virtual bool setTransform(uint32_t /*transform*/) { return false; };
virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
- virtual bool setBuffer(const std::shared_ptr<renderengine::ExternalTexture>& /*buffer*/,
- 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>& /* releaseBufferListener */,
- const sp<IBinder>& /* releaseBufferEndpoint */) {
+ virtual bool setBuffer(const BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
+ bool /*isAutoTimestamp*/, std::optional<nsecs_t> /* dequeueTime */,
+ const FrameTimelineInfo& /*info*/) {
return false;
};
- virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; };
@@ -527,8 +521,6 @@
virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
- virtual uint64_t getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { return 0; }
-
/*
* called after composition.
* returns true if the layer latched a new buffer this frame.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 3f6bd6f..c9f00a0 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -22,6 +22,7 @@
#pragma clang diagnostic ignored "-Wextra"
#include "RefreshRateConfigs.h"
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <utils/Trace.h>
#include <chrono>
@@ -714,9 +715,31 @@
RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
Config config)
: mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
+ initializeIdleTimer();
updateDisplayModes(modes, currentModeId);
}
+void RefreshRateConfigs::initializeIdleTimer() {
+ if (mConfig.idleTimerTimeoutMs > 0) {
+ const auto getCallback = [this]() -> std::optional<IdleTimerCallbacks::Callbacks> {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ if (!mIdleTimerCallbacks.has_value()) return {};
+ return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel
+ : mIdleTimerCallbacks->platform;
+ };
+
+ mIdleTimer.emplace(
+ "IdleTimer", std::chrono::milliseconds(mConfig.idleTimerTimeoutMs),
+ [getCallback] {
+ if (const auto callback = getCallback()) callback->onReset();
+ },
+ [getCallback] {
+ if (const auto callback = getCallback()) callback->onExpired();
+ });
+ mIdleTimer->start();
+ }
+}
+
void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,
DisplayModeId currentModeId) {
std::lock_guard lock(mLock);
@@ -990,6 +1013,9 @@
base::StringAppendF(&result, "Supports Frame Rate Override: %s\n",
mSupportsFrameRateOverride ? "yes" : "no");
+ base::StringAppendF(&result, "Idle timer: (%s) %s\n",
+ mConfig.supportKernelIdleTimer ? "kernel" : "platform",
+ mIdleTimer ? mIdleTimer->dump().c_str() : "off");
result.append("\n");
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index ffaa029..3abf83d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -27,6 +27,7 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "Fps.h"
+#include "Scheduler/OneShotTimer.h"
#include "Scheduler/SchedulerUtils.h"
#include "Scheduler/Seamlessness.h"
#include "Scheduler/StrongTyping.h"
@@ -305,11 +306,19 @@
// or heuristic, such that refresh rates higher than this value will not be voted for. 0 if
// no threshold is set.
int frameRateMultipleThreshold = 0;
+
+ // The Idle Timer timeout. 0 timeout means no idle timer.
+ int32_t idleTimerTimeoutMs = 0;
+
+ // Whether to use idle timer callbacks that support the kernel timer.
+ bool supportKernelIdleTimer = false;
};
- RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
+ RefreshRateConfigs(const DisplayModes&, DisplayModeId,
Config config = {.enableFrameRateOverride = false,
- .frameRateMultipleThreshold = 0});
+ .frameRateMultipleThreshold = 0,
+ .idleTimerTimeoutMs = 0,
+ .supportKernelIdleTimer = false});
// Returns whether switching modes (refresh rate or resolution) is possible.
// TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
@@ -349,6 +358,30 @@
Fps displayFrameRate, bool touch) const
EXCLUDES(mLock);
+ bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; }
+
+ void setIdleTimerCallbacks(std::function<void()> platformTimerReset,
+ std::function<void()> platformTimerExpired,
+ std::function<void()> kernelTimerReset,
+ std::function<void()> kernelTimerExpired) {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ mIdleTimerCallbacks.emplace();
+ mIdleTimerCallbacks->platform.onReset = platformTimerReset;
+ mIdleTimerCallbacks->platform.onExpired = platformTimerExpired;
+ mIdleTimerCallbacks->kernel.onReset = kernelTimerReset;
+ mIdleTimerCallbacks->kernel.onExpired = kernelTimerExpired;
+ }
+
+ void resetIdleTimer(bool kernelOnly) {
+ if (!mIdleTimer) {
+ return;
+ }
+ if (kernelOnly && !mConfig.supportKernelIdleTimer) {
+ return;
+ }
+ mIdleTimer->reset();
+ };
+
void dump(std::string& result) const EXCLUDES(mLock);
RefreshRateConfigs(const RefreshRateConfigs&) = delete;
@@ -414,6 +447,8 @@
void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
+ void initializeIdleTimer();
+
// The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
@@ -457,6 +492,22 @@
};
mutable std::optional<GetBestRefreshRateInvocation> lastBestRefreshRateInvocation
GUARDED_BY(mLock);
+
+ // Timer that records time between requests for next vsync.
+ std::optional<scheduler::OneShotTimer> mIdleTimer;
+
+ struct IdleTimerCallbacks {
+ struct Callbacks {
+ std::function<void()> onReset;
+ std::function<void()> onExpired;
+ };
+
+ Callbacks platform;
+ Callbacks kernel;
+ };
+
+ std::mutex mIdleTimerCallbacksMutex;
+ std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex);
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index c64ccd1..12e741b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -120,28 +120,15 @@
Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& callback)
: Scheduler(configs, callback,
- {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
- .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
+ {.useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}
Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& callback, Options options)
- : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
+ : Scheduler(createVsyncSchedule(configs->supportsKernelIdleTimer()), configs, callback,
createLayerHistory(), options) {
using namespace sysprop;
- const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
-
- if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {
- const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback
- : &Scheduler::idleTimerCallback;
- mIdleTimer.emplace(
- "IdleTimer", std::chrono::milliseconds(millis),
- [this, callback] { std::invoke(callback, this, TimerState::Reset); },
- [this, callback] { std::invoke(callback, this, TimerState::Expired); });
- mIdleTimer->start();
- }
-
if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
// Touch events are coming to SF every 100ms, so the timer needs to be higher than that
mTouchTimer.emplace(
@@ -168,11 +155,11 @@
mVsyncSchedule(std::move(schedule)),
mLayerHistory(std::move(layerHistory)),
mSchedulerCallback(schedulerCallback),
- mRefreshRateConfigs(configs),
mPredictedVsyncTracer(
base::GetBoolProperty("debug.sf.show_predicted_vsync", false)
? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch)
: nullptr) {
+ setRefreshRateConfigs(configs);
mSchedulerCallback.setVsyncEnabled(false);
}
@@ -180,7 +167,7 @@
// Ensure the OneShotTimer threads are joined before we start destroying state.
mDisplayPowerTimer.reset();
mTouchTimer.reset();
- mIdleTimer.reset();
+ mRefreshRateConfigs.reset();
}
Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
@@ -672,18 +659,16 @@
}
void Scheduler::resetIdleTimer() {
- if (mIdleTimer) {
- mIdleTimer->reset();
- }
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ false);
}
void Scheduler::onTouchHint() {
if (mTouchTimer) {
mTouchTimer->reset();
- if (mOptions.supportKernelTimer && mIdleTimer) {
- mIdleTimer->reset();
- }
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ true);
}
}
@@ -755,7 +740,6 @@
void Scheduler::dump(std::string& result) const {
using base::StringAppendF;
- StringAppendF(&result, "+ Idle timer: %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Touch timer: %s\n",
mTouchTimer ? mTouchTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Content detection: %s %s\n\n",
@@ -867,7 +851,7 @@
}
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
- const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
+ const bool idle = mFeatures.idleTimer == TimerState::Expired;
return refreshRateConfigs
->getBestRefreshRate(mFeatures.contentRequirements,
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 420ba61..3f3debe 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -136,7 +136,6 @@
// Detects content using layer history, and selects a matching refresh rate.
void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock);
- bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
void resetIdleTimer();
// Indicates that touch interaction is taking place.
@@ -187,6 +186,15 @@
EXCLUDES(mRefreshRateConfigsLock) {
std::scoped_lock lock(mRefreshRateConfigsLock);
mRefreshRateConfigs = std::move(refreshRateConfigs);
+ mRefreshRateConfigs->setIdleTimerCallbacks(
+ [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Reset); },
+ [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Expired); },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Reset);
+ },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Expired);
+ });
}
nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
@@ -206,8 +214,6 @@
enum class TouchState { Inactive, Active };
struct Options {
- // Whether to use idle timer callbacks that support the kernel timer.
- bool supportKernelTimer;
// Whether to use content detection at all.
bool useContentDetection;
};
@@ -293,8 +299,6 @@
// Used to choose refresh rate if content detection is enabled.
std::unique_ptr<LayerHistory> mLayerHistory;
- // Timer that records time between requests for next vsync.
- std::optional<scheduler::OneShotTimer> mIdleTimer;
// Timer used to monitor touch events.
std::optional<scheduler::OneShotTimer> mTouchTimer;
// Timer used to monitor display power mode.
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 7b5d462..ee973f7 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -42,6 +42,7 @@
: mClock(std::move(clock)),
mTracker(tracker),
mPendingLimit(pendingFenceLimit),
+ // TODO(adyabr): change mSupportKernelIdleTimer when the active display changes
mSupportKernelIdleTimer(supportKernelIdleTimer) {}
VSyncReactor::~VSyncReactor() = default;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4345b84..e90af3a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -277,6 +277,40 @@
ROTATE_SURFACE_FLINGER = 0x2,
};
+struct IdleTimerConfig {
+ int32_t timeoutMs;
+ bool supportKernelIdleTimer;
+};
+
+IdleTimerConfig getIdleTimerConfiguration(DisplayId displayId) {
+ // TODO(adyabr): use ro.surface_flinger.* namespace
+
+ const auto displayIdleTimerMsKey = [displayId] {
+ std::stringstream ss;
+ ss << "debug.sf.set_idle_timer_ms_" << displayId.value;
+ return ss.str();
+ }();
+
+ const auto displaySupportKernelIdleTimerKey = [displayId] {
+ std::stringstream ss;
+ ss << "debug.sf.support_kernel_idle_timer_" << displayId.value;
+ return ss.str();
+ }();
+
+ const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
+ const auto displaySupportKernelIdleTimer =
+ base::GetBoolProperty(displaySupportKernelIdleTimerKey, false);
+
+ if (displayIdleTimerMs > 0) {
+ return {displayIdleTimerMs, displaySupportKernelIdleTimer};
+ }
+
+ const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
+ const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
+
+ return {millis, sysprop::support_kernel_idle_timer(false)};
+}
+
} // namespace anonymous
// ---------------------------------------------------------------------------
@@ -462,9 +496,6 @@
useFrameRateApi = use_frame_rate_api(true);
- mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false);
- base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
-
mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
// Debug property overrides ro. property
@@ -2152,10 +2183,11 @@
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
+ // Send on commit callbacks
+ mTransactionCallbackInvoker.sendCallbacks();
+
bool refreshNeeded = handlePageFlip();
- // Send on commit callbacks
- mTransactionCallbackInvoker.sendCallbacks();
if (mVisibleRegionsDirty) {
computeLayerBounds();
@@ -2346,6 +2378,7 @@
mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);
mTransactionCallbackInvoker.sendCallbacks();
+ mTransactionCallbackInvoker.clearCompletedTransactions();
if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&
mPreviousPresentFences[0].fenceTime->isValid()) {
@@ -2653,10 +2686,14 @@
creationArgs.connectionType = physical->type;
creationArgs.supportedModes = physical->supportedModes;
creationArgs.activeModeId = physical->activeMode->getId();
+ const auto [idleTimerTimeoutMs, supportKernelIdleTimer] =
+ getIdleTimerConfiguration(compositionDisplay->getId());
scheduler::RefreshRateConfigs::Config config =
{.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
.frameRateMultipleThreshold =
- base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
+ base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0),
+ .idleTimerTimeoutMs = idleTimerTimeoutMs,
+ .supportKernelIdleTimer = supportKernelIdleTimer};
creationArgs.refreshRateConfigs =
std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
creationArgs.activeModeId, config);
@@ -3564,9 +3601,10 @@
for (const ComposerState& state : states) {
const layer_state_t& s = state.state;
- const bool acquireFenceChanged = (s.what & layer_state_t::eAcquireFenceChanged);
- if (acquireFenceChanged && s.acquireFence && !enableLatchUnsignaled &&
- s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
+ const bool acquireFenceChanged =
+ s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged);
+ if (acquireFenceChanged && s.bufferData.acquireFence && !enableLatchUnsignaled &&
+ s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) {
ATRACE_NAME("fence unsignaled");
return false;
}
@@ -3729,8 +3767,7 @@
// that listeners with SurfaceControls will start registration during setClientStateLocked
// below.
for (const auto& listener : listenerCallbacks) {
- mTransactionCallbackInvoker.startRegistration(listener);
- mTransactionCallbackInvoker.endRegistration(listener);
+ mTransactionCallbackInvoker.addEmptyTransaction(listener);
}
std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces;
@@ -3748,10 +3785,6 @@
}
}
- for (const auto& listenerCallback : listenerCallbacksWithSurfaces) {
- mTransactionCallbackInvoker.endRegistration(listenerCallback);
- }
-
// If the state doesn't require a traversal and there are callbacks, send them now
if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) {
mTransactionCallbackInvoker.sendCallbacks();
@@ -3881,14 +3914,12 @@
ListenerCallbacks onCommitCallbacks = listener.filter(CallbackId::Type::ON_COMMIT);
if (!onCommitCallbacks.callbackIds.empty()) {
- mTransactionCallbackInvoker.startRegistration(onCommitCallbacks);
filteredListeners.push_back(onCommitCallbacks);
outListenerCallbacks.insert(onCommitCallbacks);
}
ListenerCallbacks onCompleteCallbacks = listener.filter(CallbackId::Type::ON_COMPLETE);
if (!onCompleteCallbacks.callbackIds.empty()) {
- mTransactionCallbackInvoker.startRegistration(onCompleteCallbacks);
filteredListeners.push_back(onCompleteCallbacks);
outListenerCallbacks.insert(onCompleteCallbacks);
}
@@ -4063,9 +4094,6 @@
if (what & layer_state_t::eCropChanged) {
if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
}
- if (what & layer_state_t::eAcquireFenceChanged) {
- if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded;
- }
if (what & layer_state_t::eDataspaceChanged) {
if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded;
}
@@ -4192,43 +4220,11 @@
callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface));
}
}
- bool bufferChanged = what & layer_state_t::eBufferChanged;
- bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged;
- bool bufferSizeExceedsLimit = false;
- std::shared_ptr<renderengine::ExternalTexture> buffer;
- if (bufferChanged && cacheIdChanged && s.buffer != nullptr) {
- bufferSizeExceedsLimit =
- exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight());
- if (!bufferSizeExceedsLimit) {
- ClientCache::getInstance().add(s.cachedBuffer, s.buffer);
- buffer = ClientCache::getInstance().get(s.cachedBuffer);
- }
- } else if (cacheIdChanged) {
- buffer = ClientCache::getInstance().get(s.cachedBuffer);
- } else if (bufferChanged && s.buffer != nullptr) {
- bufferSizeExceedsLimit =
- exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight());
- if (!bufferSizeExceedsLimit) {
- buffer = std::make_shared<
- renderengine::ExternalTexture>(s.buffer, getRenderEngine(),
- renderengine::ExternalTexture::Usage::READABLE);
- }
- }
- ALOGE_IF(bufferSizeExceedsLimit,
- "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
- "limit.",
- layer->getDebugName());
- if (buffer) {
- const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged;
- const uint64_t frameNumber = frameNumberChanged
- ? s.frameNumber
- : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1;
- if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
- s.cachedBuffer, frameNumber, dequeueBufferTimestamp, frameTimelineInfo,
- s.releaseBufferListener, s.releaseBufferEndpoint)) {
- flags |= eTraversalNeeded;
- }
+ if (what & layer_state_t::eBufferChanged &&
+ layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
+ dequeueBufferTimestamp, frameTimelineInfo)) {
+ flags |= eTraversalNeeded;
} else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime);
}
@@ -5846,16 +5842,18 @@
void SurfaceFlinger::toggleKernelIdleTimer() {
using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
- // If the support for kernel idle timer is disabled in SF code, don't do anything.
- if (!mSupportKernelIdleTimer) {
- return;
- }
const auto display = getDefaultDisplayDeviceLocked();
if (!display) {
ALOGW("%s: default display is null", __func__);
return;
}
+ // If the support for kernel idle timer is disabled for the active display,
+ // don't do anything.
+ if (!display->refreshRateConfigs().supportsKernelIdleTimer()) {
+ return;
+ }
+
const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
switch (action) {
case KernelIdleTimerAction::TurnOff:
@@ -6978,6 +6976,10 @@
mScheduler->setRefreshRateConfigs(activeDisplay->holdRefreshRateConfigs());
onActiveDisplaySizeChanged(activeDisplay);
mActiveDisplayTransformHint = activeDisplay->getTransformHint();
+
+ // Update the kernel timer for the current active display, since the policy
+ // for this display might have changed when it was not the active display.
+ toggleKernelIdleTimer();
}
status_t SurfaceFlinger::addWindowInfosListener(
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6c046fc..1217d63 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -363,6 +363,10 @@
return static_cast<bool>(findDisplay(p));
}
+ bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const {
+ return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
+ }
+
private:
friend class BufferLayer;
friend class BufferQueueLayer;
@@ -759,8 +763,6 @@
// Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
// make calls to sys prop each time.
bool mKernelIdleTimerEnabled = false;
- // Keeps track of whether the kernel timer is supported on the SF side.
- bool mSupportKernelIdleTimer = false;
// Show spinner with refresh rate overlay
bool mRefreshRateOverlaySpinner = false;
@@ -939,10 +941,6 @@
void readPersistentProperties();
- bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const {
- return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
- }
-
uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
/*
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index 6af69f0..4b12a26 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -49,121 +49,25 @@
return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT;
}
-TransactionCallbackInvoker::~TransactionCallbackInvoker() {
- {
- std::lock_guard lock(mMutex);
- for (const auto& [listener, transactionStats] : mCompletedTransactions) {
- listener->unlinkToDeath(mDeathRecipient);
- }
- }
-}
-
-status_t TransactionCallbackInvoker::startRegistration(const ListenerCallbacks& listenerCallbacks) {
- std::lock_guard lock(mMutex);
-
- auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
+void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) {
auto& [listener, callbackIds] = listenerCallbacks;
-
- if (inserted) {
- if (mCompletedTransactions.count(listener) == 0) {
- status_t err = listener->linkToDeath(mDeathRecipient);
- if (err != NO_ERROR) {
- ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
- return err;
- }
- }
- auto& transactionStatsDeque = mCompletedTransactions[listener];
- transactionStatsDeque.emplace_back(callbackIds);
- }
-
- return NO_ERROR;
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+ transactionStatsDeque.emplace_back(callbackIds);
}
-status_t TransactionCallbackInvoker::endRegistration(const ListenerCallbacks& listenerCallbacks) {
- std::lock_guard lock(mMutex);
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- if (itr == mRegisteringTransactions.end()) {
- ALOGE("cannot end a registration that does not exist");
- return BAD_VALUE;
- }
-
- mRegisteringTransactions.erase(itr);
-
- return NO_ERROR;
-}
-
-bool TransactionCallbackInvoker::isRegisteringTransaction(
- const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
- ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- return itr != mRegisteringTransactions.end();
-}
-
-status_t TransactionCallbackInvoker::registerPendingCallbackHandle(
- const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
-
- // If we can't find the transaction stats something has gone wrong. The client should call
- // startRegistration before trying to register a pending callback handle.
- TransactionStats* transactionStats;
- status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
- if (err != NO_ERROR) {
- ALOGE("cannot find transaction stats");
- return err;
- }
-
- mPendingTransactions[handle->listener][handle->callbackIds]++;
- return NO_ERROR;
-}
-
-status_t TransactionCallbackInvoker::finalizeCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) {
- auto listener = mPendingTransactions.find(handle->listener);
- if (listener != mPendingTransactions.end()) {
- auto& pendingCallbacks = listener->second;
- auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
-
- if (pendingCallback != pendingCallbacks.end()) {
- auto& pendingCount = pendingCallback->second;
-
- // Decrease the pending count for this listener
- if (--pendingCount == 0) {
- pendingCallbacks.erase(pendingCallback);
- }
- } else {
- ALOGW("there are more latched callbacks than there were registered callbacks");
- }
- if (listener->second.size() == 0) {
- mPendingTransactions.erase(listener);
- }
- } else {
- ALOGW("cannot find listener in mPendingTransactions");
- }
-
- status_t err = addCallbackHandle(handle, jankData);
- if (err != NO_ERROR) {
- ALOGE("could not add callback handle");
- return err;
- }
- return NO_ERROR;
-}
-
-status_t TransactionCallbackInvoker::finalizeOnCommitCallbackHandles(
+status_t TransactionCallbackInvoker::addOnCommitCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles,
std::deque<sp<CallbackHandle>>& outRemainingHandles) {
if (handles.empty()) {
return NO_ERROR;
}
- std::lock_guard lock(mMutex);
const std::vector<JankData>& jankData = std::vector<JankData>();
for (const auto& handle : handles) {
if (!containsOnCommitCallbacks(handle->callbackIds)) {
outRemainingHandles.push_back(handle);
continue;
}
- status_t err = finalizeCallbackHandle(handle, jankData);
+ status_t err = addCallbackHandle(handle, jankData);
if (err != NO_ERROR) {
return err;
}
@@ -172,14 +76,13 @@
return NO_ERROR;
}
-status_t TransactionCallbackInvoker::finalizePendingCallbackHandles(
+status_t TransactionCallbackInvoker::addCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
if (handles.empty()) {
return NO_ERROR;
}
- std::lock_guard lock(mMutex);
for (const auto& handle : handles) {
- status_t err = finalizeCallbackHandle(handle, jankData);
+ status_t err = addCallbackHandle(handle, jankData);
if (err != NO_ERROR) {
return err;
}
@@ -190,8 +93,6 @@
status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle(
const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
-
return addCallbackHandle(handle, std::vector<JankData>());
}
@@ -208,9 +109,8 @@
return NO_ERROR;
}
}
-
- ALOGE("could not find transaction stats");
- return BAD_VALUE;
+ *outTransactionStats = &transactionStatsDeque.emplace_back(callbackIds);
+ return NO_ERROR;
}
status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle,
@@ -244,13 +144,10 @@
}
void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) {
- std::lock_guard<std::mutex> lock(mMutex);
mPresentFence = presentFence;
}
void TransactionCallbackInvoker::sendCallbacks() {
- std::lock_guard lock(mMutex);
-
// For each listener
auto completedTransactionsItr = mCompletedTransactions.begin();
while (completedTransactionsItr != mCompletedTransactions.end()) {
@@ -263,27 +160,9 @@
while (transactionStatsItr != transactionStatsDeque.end()) {
auto& transactionStats = *transactionStatsItr;
- // If this transaction is still registering, it is not safe to send a callback
- // because there could be surface controls that haven't been added to
- // transaction stats or mPendingTransactions.
- if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
- break;
- }
-
- // If we are still waiting on the callback handles for this transaction, stop
- // here because all transaction callbacks for the same listener must come in order
- auto pendingTransactions = mPendingTransactions.find(listener);
- if (pendingTransactions != mPendingTransactions.end() &&
- pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
- break;
- }
-
// If the transaction has been latched
if (transactionStats.latchTime >= 0 &&
!containsOnCommitCallbacks(transactionStats.callbackIds)) {
- if (!mPresentFence) {
- break;
- }
transactionStats.presentFence = mPresentFence;
}
@@ -303,20 +182,9 @@
// we get pointers that compare unequal in the SF process.
interface_cast<ITransactionCompletedListener>(listenerStats.listener)
->onTransactionCompleted(listenerStats);
- if (transactionStatsDeque.empty()) {
- listener->unlinkToDeath(mDeathRecipient);
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
- } else {
- completedTransactionsItr++;
- }
- } else {
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
}
- } else {
- completedTransactionsItr++;
}
+ completedTransactionsItr++;
}
if (mPresentFence) {
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 6f4d812..71ca6e5 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -56,79 +56,38 @@
class TransactionCallbackInvoker {
public:
- ~TransactionCallbackInvoker();
-
- // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
- // to be included in the callback. This functions should be call before attempting to register
- // any callback handles.
- status_t startRegistration(const ListenerCallbacks& listenerCallbacks);
- // Ends the registration. After this is called, no more CallbackHandles will be registered.
- // It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
- status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
-
- // Informs the TransactionCallbackInvoker that there is a Transaction with a CallbackHandle
- // that needs to be latched and presented this frame. This function should be called once the
- // layer has received the CallbackHandle so the TransactionCallbackInvoker knows not to send
- // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
- // presented.
- status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
- // Notifies the TransactionCallbackInvoker that a pending CallbackHandle has been presented.
- status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
+ status_t addCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
const std::vector<JankData>& jankData);
- status_t finalizeOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
+ status_t addOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
std::deque<sp<CallbackHandle>>& outRemainingHandles);
// Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
// presented this frame.
status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
+ void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks);
void addPresentFence(const sp<Fence>& presentFence);
void sendCallbacks();
-
-private:
-
- bool isRegisteringTransaction(const sp<IBinder>& transactionListener,
- const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
-
- status_t findTransactionStats(const sp<IBinder>& listener,
- const std::vector<CallbackId>& callbackIds,
- TransactionStats** outTransactionStats) REQUIRES(mMutex);
+ void clearCompletedTransactions() {
+ mCompletedTransactions.clear();
+ }
status_t addCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) REQUIRES(mMutex);
+ const std::vector<JankData>& jankData);
- status_t finalizeCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) REQUIRES(mMutex);
- class CallbackDeathRecipient : public IBinder::DeathRecipient {
- public:
- // This function is a no-op. isBinderAlive needs a linked DeathRecipient to work.
- // Death recipients needs a binderDied function.
- //
- // (isBinderAlive checks if BpBinder's mAlive is 0. mAlive is only set to 0 in sendObituary.
- // sendObituary is only called if linkToDeath was called with a DeathRecipient.)
- void binderDied(const wp<IBinder>& /*who*/) override {}
- };
- sp<CallbackDeathRecipient> mDeathRecipient =
- new CallbackDeathRecipient();
+private:
+ status_t findTransactionStats(const sp<IBinder>& listener,
+ const std::vector<CallbackId>& callbackIds,
+ TransactionStats** outTransactionStats);
- std::mutex mMutex;
- std::condition_variable_any mConditionVariable;
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> mRegisteringTransactions
- GUARDED_BY(mMutex);
-
- std::unordered_map<
- sp<IBinder>,
- std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
- IListenerHash>
- mPendingTransactions GUARDED_BY(mMutex);
std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
- mCompletedTransactions GUARDED_BY(mMutex);
+ mCompletedTransactions;
- sp<Fence> mPresentFence GUARDED_BY(mMutex);
+ sp<Fence> mPresentFence;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
index 8d7e175..94e1e0c 100644
--- a/services/surfaceflinger/tests/IPC_test.cpp
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -161,8 +161,7 @@
Color::RED);
transaction->setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK)
.setLayer(mSurfaceControl, std::numeric_limits<int32_t>::max())
- .setBuffer(mSurfaceControl, gb)
- .setAcquireFence(mSurfaceControl, fence)
+ .setBuffer(mSurfaceControl, gb, fence)
.show(mSurfaceControl)
.addTransactionCompletedCallback(mCallbackHelper.function,
mCallbackHelper.getContext());
@@ -312,8 +311,7 @@
Transaction transaction;
transaction.setLayerStack(sc, ui::DEFAULT_LAYER_STACK)
.setLayer(sc, std::numeric_limits<int32_t>::max() - 1)
- .setBuffer(sc, gb)
- .setAcquireFence(sc, fence)
+ .setBuffer(sc, gb, fence)
.show(sc)
.addTransactionCompletedCallback(helper1.function, helper1.getContext());
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 965aac3..e8759e5 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -66,8 +66,7 @@
return err;
}
- transaction.setBuffer(layer, buffer);
- transaction.setAcquireFence(layer, fence);
+ transaction.setBuffer(layer, buffer, fence);
}
if (setBackgroundColor) {
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index c8eeac6..0e2bc3d 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -1353,7 +1353,7 @@
return;
}
- Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+ Transaction().setBuffer(layer, buffer, fence).apply();
status_t status = fence->wait(1000);
ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
@@ -1375,7 +1375,7 @@
sp<Fence> fence = Fence::NO_FENCE;
- Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+ Transaction().setBuffer(layer, buffer, fence).apply();
auto shot = getScreenCapture();
shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index c4d42fa..3847a51 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -85,9 +85,7 @@
sp<Fence> fence, CallbackHelper& callback, const ReleaseCallbackId& id,
ReleaseBufferCallbackHelper& releaseCallback) {
Transaction t;
- t.setFrameNumber(layer, id.framenumber);
- t.setBuffer(layer, buffer, id, releaseCallback.getCallback());
- t.setAcquireFence(layer, fence);
+ t.setBuffer(layer, buffer, fence, id.framenumber, id, releaseCallback.getCallback());
t.addTransactionCompletedCallback(callback.function, callback.getContext());
t.apply();
}
@@ -302,8 +300,8 @@
nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count();
Transaction t;
- t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback());
- t.setAcquireFence(layer, Fence::NO_FENCE);
+ t.setBuffer(layer, firstBuffer, std::nullopt, std::nullopt, firstBufferCallbackId,
+ releaseCallback->getCallback());
t.addTransactionCompletedCallback(transactionCallback.function,
transactionCallback.getContext());
t.setDesiredPresentTime(time);
@@ -318,8 +316,8 @@
// Dropping frames in transaction queue emits a callback
sp<GraphicBuffer> secondBuffer = getBuffer();
ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
- t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback());
- t.setAcquireFence(layer, Fence::NO_FENCE);
+ t.setBuffer(layer, secondBuffer, std::nullopt, std::nullopt, secondBufferCallbackId,
+ releaseCallback->getCallback());
t.addTransactionCompletedCallback(transactionCallback.function,
transactionCallback.getContext());
t.setDesiredPresentTime(time);
@@ -361,10 +359,8 @@
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.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber,
+ secondBufferCallbackId, releaseCallback->getCallback());
transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
// Set a different TransactionCompletedListener to mimic a second process
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index 35033ea..e388a6f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -21,7 +21,6 @@
#include <gtest/gtest.h>
#include <gui/LayerMetadata.h>
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "EffectLayer.h"
#include "Layer.h"
@@ -60,7 +59,6 @@
static constexpr int32_t PRIORITY_UNSET = -1;
void setupScheduler();
- sp<BufferQueueLayer> createBufferQueueLayer();
sp<BufferStateLayer> createBufferStateLayer();
sp<EffectLayer> createEffectLayer();
@@ -90,12 +88,6 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-sp<BufferQueueLayer> RefreshRateSelectionTest::createBufferQueueLayer() {
- sp<Client> client;
- LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
- LAYER_FLAGS, LayerMetadata());
- return new BufferQueueLayer(args);
-}
sp<BufferStateLayer> RefreshRateSelectionTest::createBufferStateLayer() {
sp<Client> client;
@@ -149,46 +141,6 @@
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(RefreshRateSelectionTest, testPriorityOnBufferQueueLayers) {
- mParent = createBufferQueueLayer();
- mChild = createBufferQueueLayer();
- setParent(mChild.get(), mParent.get());
- mGrandChild = createBufferQueueLayer();
- setParent(mGrandChild.get(), mChild.get());
-
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mGrandChild->getFrameRateSelectionPriority());
-
- // Child has its own priority.
- mGrandChild->setFrameRateSelectionPriority(1);
- commitTransaction(mGrandChild.get());
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-
- // Child inherits from his parent.
- mChild->setFrameRateSelectionPriority(1);
- commitTransaction(mChild.get());
- mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mGrandChild.get());
-
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-
- // Grandchild inherits from his grand parent.
- mParent->setFrameRateSelectionPriority(1);
- commitTransaction(mParent.get());
- mChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mChild.get());
- mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mGrandChild.get());
- ASSERT_EQ(1, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-}
-
TEST_F(RefreshRateSelectionTest, testPriorityOnBufferStateLayers) {
mParent = createBufferStateLayer();
mChild = createBufferStateLayer();
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index a4e9d20..84fa1e2 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -24,7 +24,6 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "EffectLayer.h"
#include "Layer.h"
@@ -65,17 +64,6 @@
static constexpr uint32_t LAYER_FLAGS = 0;
};
-class BufferQueueLayerFactory : public LayerFactory {
-public:
- std::string name() override { return "BufferQueueLayer"; }
- sp<Layer> createLayer(TestableSurfaceFlinger& flinger) override {
- sp<Client> client;
- LayerCreationArgs args(flinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
- LAYER_FLAGS, LayerMetadata());
- return new BufferQueueLayer(args);
- }
-};
-
class BufferStateLayerFactory : public LayerFactory {
public:
std::string name() override { return "BufferStateLayer"; }
@@ -417,8 +405,7 @@
}
INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest,
- testing::Values(std::make_shared<BufferQueueLayerFactory>(),
- std::make_shared<BufferStateLayerFactory>(),
+ testing::Values(std::make_shared<BufferStateLayerFactory>(),
std::make_shared<EffectLayerFactory>()),
PrintToStringParamName);
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index a99dabe..1d21bd4 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -44,7 +44,7 @@
ISchedulerCallback& callback)
: Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr},
refreshRateConfigs, callback, createLayerHistory(),
- {.supportKernelTimer = false, .useContentDetection = true}) {}
+ {.useContentDetection = true}) {}
// Used to inject mock event thread.
ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index a749ece..bd6a780 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -46,6 +46,7 @@
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
setupScheduler();
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+ mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
}
~TransactionFrameTracerTest() {
@@ -92,21 +93,17 @@
}
TestableSurfaceFlinger mFlinger;
- renderengine::mock::RenderEngine mRenderEngine;
+ renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
FenceToFenceTimeMap fenceFactory;
- client_cache_t mClientCache;
void BLASTTransactionSendsFrameTracerEvents() {
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
- const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
int32_t layerId = layer->getSequence();
- uint64_t bufferId = buffer->getBuffer()->getId();
+ uint64_t bufferId = buffer->getId();
uint64_t frameNumber = 5;
nsecs_t dequeueTime = 10;
nsecs_t postTime = 20;
@@ -117,9 +114,14 @@
EXPECT_CALL(*mFlinger.getFrameTracer(),
traceTimestamp(layerId, bufferId, frameNumber, postTime,
FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
- layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache,
- frameNumber, dequeueTime, FrameTimelineInfo{},
- nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint*/);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = frameNumber;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, postTime, /*desiredPresentTime*/ 30, false, dequeueTime,
+ FrameTimelineInfo{});
commitTransaction(layer.get());
bool computeVisisbleRegions;
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 2a7921f..2b5b7b5 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -46,6 +46,7 @@
ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
setupScheduler();
mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
+ mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
}
~TransactionSurfaceFrameTest() {
@@ -92,10 +93,9 @@
}
TestableSurfaceFlinger mFlinger;
- renderengine::mock::RenderEngine mRenderEngine;
+ renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
FenceToFenceTimeMap fenceFactory;
- client_cache_t mClientCache;
void PresentedSurfaceFrameForBufferlessTransaction() {
sp<BufferStateLayer> layer = createBufferStateLayer();
@@ -114,13 +114,15 @@
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
- const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence->signalForTest(12);
commitTransaction(layer.get());
@@ -143,27 +145,30 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- const auto buffer1 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer1;
+ bufferData.acquireFence = fence1;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
sp<Fence> fence2(new Fence());
auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
- const auto buffer2 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
+ const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
nsecs_t start = systemTime();
- layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ bufferData.buffer = buffer2;
+ bufferData.acquireFence = fence2;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
nsecs_t end = systemTime();
acquireFence2->signalForTest(12);
@@ -198,13 +203,15 @@
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
- const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence->signalForTest(12);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -227,13 +234,15 @@
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
- const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -260,13 +269,15 @@
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
- const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 3, /*inputEventId*/ 0});
EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -299,25 +310,28 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- const auto buffer1 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer1;
+ bufferData.acquireFence = fence1;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
sp<Fence> fence2(new Fence());
auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
- const auto buffer2 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ bufferData.buffer = buffer2;
+ bufferData.acquireFence = fence2;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence2->signalForTest(12);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -342,27 +356,30 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- const auto buffer1 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
- layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer1;
+ bufferData.acquireFence = fence1;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX;
sp<Fence> fence2(new Fence());
auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
- const auto buffer2 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
+ const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
auto dropStartTime1 = systemTime();
- layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0},
- nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint */);
+ bufferData.buffer = buffer2;
+ bufferData.acquireFence = fence2;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
auto dropEndTime1 = systemTime();
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -370,14 +387,15 @@
sp<Fence> fence3(new Fence());
auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
- const auto buffer3 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888,
- 1, 0),
- mRenderEngine, false);
+ const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
auto dropStartTime2 = systemTime();
- layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ bufferData.buffer = buffer3;
+ bufferData.acquireFence = fence3;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 2, /*inputEventId*/ 0});
auto dropEndTime2 = systemTime();
acquireFence3->signalForTest(12);
@@ -413,16 +431,16 @@
uint32_t surfaceFramesPendingClassification = 0;
std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> bufferlessSurfaceFrames;
for (int i = 0; i < 10; i += 2) {
- sp<Fence> fence1(new Fence());
- const auto buffer1 = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(1, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- 0),
- mRenderEngine, false);
- layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0},
- nullptr /* releaseBufferCallback */,
- nullptr /* releaseBufferEndpoint */);
+ sp<Fence> fence(new Fence());
+ const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
+ BufferData bufferData;
+ bufferData.buffer = buffer;
+ bufferData.acquireFence = fence;
+ bufferData.frameNumber = 1;
+ bufferData.flags |= BufferData::BufferDataChange::fenceChanged;
+ bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged;
+ layer->setBuffer(bufferData, 10, 20, false, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
/*inputEventId*/ 0},
10);