Merge "Update transactions.proto to sync with layer_state_t"
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 0389e57..6f579ca 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -209,13 +209,13 @@
/**
* The time in nanoseconds which the frame at given index is expected to be presented.
*/
-int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
+int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos(
const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33);
/**
* The time in nanoseconds which the frame at given index needs to be ready by.
*/
-int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline(
+int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33);
__END_DECLS
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 509ee0e..4c83a14 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -216,6 +216,61 @@
*/
void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
+/*
+ * Set the socket tag and owning UID for traffic statistics on the specified
+ * socket.
+ *
+ * Subsequent calls always replace any existing parameters. The socket tag and
+ * uid (if set) are kept when the socket is sent to another process using binder
+ * IPCs or other mechanisms such as UNIX socket fd passing. Any app can accept
+ * blame for future traffic performed on a socket originally created by another
+ * app by calling this method with its own UID (or calling
+ * android_tag_socket(int sockfd, int tag)). However, only apps holding the
+ * android.Manifest.permission#UPDATE_DEVICE_STATS permission may assign blame
+ * to another UIDs. If unset (default) the socket tag is 0, and the uid is the
+ * socket creator's uid.
+ *
+ * Returns 0 on success, or a negative POSIX error code (see errno.h) on
+ * failure.
+ *
+ * Available since API level 33.
+ */
+int android_tag_socket_with_uid(int sockfd, int tag, uid_t uid) __INTRODUCED_IN(33);
+
+/*
+ * Set the socket tag for traffic statistics on the specified socket.
+ *
+ * This function tags the socket with the caller's UID (accepting blame for
+ * future traffic performed on this socket) even if the socket was originally
+ * opened by another UID or was previously tagged by another UID. Subsequent
+ * calls always replace any existing parameters. The socket tag is kept when the
+ * socket is sent to another process using binder IPCs or other mechanisms such
+ * as UNIX socket fd passing.
+ *
+ * Returns 0 on success, or a negative POSIX error code (see errno.h) on
+ * failure.
+ *
+ * Available since API level 33.
+ */
+int android_tag_socket(int sockfd, int tag) __INTRODUCED_IN(33);
+
+/*
+ * Untag a network socket.
+ *
+ * Future traffic on this socket will no longer be associated with any
+ * previously configured tag and uid. If the socket was created by another UID
+ * or was previously tagged by another UID, calling this function will clear the
+ * statistics parameters, and thus the UID blamed for traffic on the socket will
+ * be the UID that originally created the socket, even if the socket was
+ * subsequently tagged by a different UID.
+ *
+ * Returns 0 on success, or a negative POSIX error code (see errno.h) on
+ * failure.
+ *
+ * Available since API level 33.
+ */
+int android_untag_socket(int sockfd) __INTRODUCED_IN(33);
+
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
diff --git a/include/ftl/concat.h b/include/ftl/concat.h
new file mode 100644
index 0000000..ded48f7
--- /dev/null
+++ b/include/ftl/concat.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <ftl/details/concat.h>
+
+namespace android::ftl {
+
+// Lightweight (not allocating nor sprintf-based) concatenation.
+//
+// std::string_view name = "Volume";
+// ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB");
+//
+// assert(string.str() == "Vol: -3 dB");
+// assert(string.c_str()[string.size()] == '\0');
+//
+template <std::size_t, typename... Ts>
+struct Concat;
+
+template <std::size_t N, typename T, typename... Ts>
+struct Concat<N, T, Ts...> : Concat<N + details::StaticString<T>::N, Ts...> {
+ explicit constexpr Concat(T v, Ts... args) { append(v, args...); }
+
+ protected:
+ constexpr Concat() = default;
+
+ constexpr void append(T v, Ts... args) {
+ using Str = details::StaticString<T>;
+ const Str str(v);
+
+ // TODO: Replace with constexpr std::copy in C++20.
+ for (auto it = str.view.begin(); it != str.view.end();) {
+ *this->end_++ = *it++;
+ }
+
+ using Base = Concat<N + Str::N, Ts...>;
+ this->Base::append(args...);
+ }
+};
+
+template <std::size_t N>
+struct Concat<N> {
+ static constexpr std::size_t max_size() { return N; }
+ constexpr std::size_t size() const { return end_ - buffer_; }
+
+ constexpr const char* c_str() const { return buffer_; }
+
+ constexpr std::string_view str() const {
+ // TODO: Replace with {buffer_, end_} in C++20.
+ return {buffer_, size()};
+ }
+
+ protected:
+ constexpr Concat() : end_(buffer_) {}
+ constexpr void append() { *end_ = '\0'; }
+
+ char buffer_[N + 1];
+ char* end_;
+};
+
+// Deduction guide.
+template <typename... Ts>
+Concat(Ts&&...) -> Concat<0, Ts...>;
+
+template <std::size_t N>
+constexpr auto truncated(std::string_view v) {
+ return details::Truncated<N>{v};
+}
+
+} // namespace android::ftl
diff --git a/include/ftl/details/concat.h b/include/ftl/details/concat.h
new file mode 100644
index 0000000..8ce949e
--- /dev/null
+++ b/include/ftl/details/concat.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <string_view>
+
+#include <ftl/string.h>
+
+namespace android::ftl::details {
+
+template <typename T, typename = void>
+struct StaticString;
+
+template <typename T>
+struct StaticString<T, std::enable_if_t<std::is_integral_v<T>>> {
+ static constexpr std::size_t N = to_chars_length_v<T>;
+
+ explicit StaticString(T v) : view(to_chars(buffer, v)) {}
+
+ to_chars_buffer_t<T> buffer;
+ const std::string_view view;
+};
+
+template <std::size_t M>
+struct StaticString<const char (&)[M], void> {
+ static constexpr std::size_t N = M - 1;
+
+ explicit constexpr StaticString(const char (&str)[M]) : view(str, N) {}
+
+ const std::string_view view;
+};
+
+template <std::size_t N>
+struct Truncated {
+ std::string_view view;
+};
+
+template <std::size_t M>
+struct StaticString<Truncated<M>, void> {
+ static constexpr std::size_t N = M;
+
+ explicit constexpr StaticString(Truncated<M> str) : view(str.view.substr(0, N)) {}
+
+ const std::string_view view;
+};
+
+} // namespace android::ftl::details
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index c903998..2c471c6 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -163,6 +163,15 @@
const T get() const { return mT; }
/**
+ * Release the underlying resource.
+ */
+ [[nodiscard]] T release() {
+ T a = mT;
+ mT = DEFAULT;
+ return a;
+ }
+
+ /**
* This allows the value in this class to be set from beneath it. If you call this method and
* then change the value of T*, you must take ownership of the value you are replacing and add
* ownership to the object that is put in here.
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 58fa13a..357b454 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -752,6 +752,29 @@
ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
}
+static void addOne(int* to) {
+ if (!to) return;
+ ++(*to);
+}
+struct FakeResource : public ndk::impl::ScopedAResource<int*, addOne, nullptr> {
+ explicit FakeResource(int* a) : ScopedAResource(a) {}
+};
+
+TEST(NdkBinder_ScopedAResource, GetDelete) {
+ int deleteCount = 0;
+ { FakeResource resource(&deleteCount); }
+ EXPECT_EQ(deleteCount, 1);
+}
+
+TEST(NdkBinder_ScopedAResource, Release) {
+ int deleteCount = 0;
+ {
+ FakeResource resource(&deleteCount);
+ (void)resource.release();
+ }
+ EXPECT_EQ(deleteCount, 0);
+}
+
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index ca68b99..c2639e7 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1517,10 +1517,11 @@
auto keepAlive = sp<BBinder>::make();
auto setRpcClientDebugStatus = binder->setRpcClientDebug(std::move(socket), keepAlive);
- if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+ if (!android::base::GetBoolProperty("ro.debuggable", false) ||
+ android::base::GetProperty("ro.build.type", "") == "user") {
ASSERT_EQ(INVALID_OPERATION, setRpcClientDebugStatus)
- << "setRpcClientDebug should return INVALID_OPERATION on non-debuggable builds, "
- "but get "
+ << "setRpcClientDebug should return INVALID_OPERATION on non-debuggable or user "
+ "builds, but get "
<< statusToString(setRpcClientDebugStatus);
GTEST_SKIP();
}
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index 5a80ad0..bc2eb23 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -16,6 +16,7 @@
srcs: [
"Flags_test.cpp",
"cast_test.cpp",
+ "concat_test.cpp",
"enum_test.cpp",
"future_test.cpp",
"small_map_test.cpp",
diff --git a/libs/ftl/concat_test.cpp b/libs/ftl/concat_test.cpp
new file mode 100644
index 0000000..8ecb1b2
--- /dev/null
+++ b/libs/ftl/concat_test.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ftl/concat.h>
+#include <gtest/gtest.h>
+
+namespace android::test {
+
+// Keep in sync with example usage in header file.
+TEST(Concat, Example) {
+ std::string_view name = "Volume";
+ ftl::Concat string(ftl::truncated<3>(name), ": ", -3, " dB");
+
+ EXPECT_EQ(string.str(), "Vol: -3 dB");
+ EXPECT_EQ(string.c_str()[string.size()], '\0');
+}
+
+namespace {
+
+static_assert(ftl::Concat{"foo"}.str() == "foo");
+static_assert(ftl::Concat{ftl::truncated<3>("foobar")}.str() == "foo");
+
+constexpr ftl::Concat kConcat{"po", "trz", "ebie"};
+
+static_assert(kConcat.size() == 9);
+static_assert(kConcat.max_size() == 9);
+static_assert(kConcat.str() == "potrzebie");
+static_assert(kConcat.str() == std::string_view(kConcat.c_str()));
+
+constexpr auto concat() {
+ return ftl::Concat{ftl::truncated<1>("v???"), ftl::truncated<2>("ee??"),
+ ftl::truncated<3>("ble?"), ftl::truncated<4>("fetz"),
+ ftl::truncated<90>("er")};
+}
+
+static_assert(concat().size() == 12);
+static_assert(concat().max_size() == 100);
+static_assert(concat().str() == "veeblefetzer");
+static_assert(concat().str() == std::string_view(concat().c_str()));
+
+} // namespace
+} // namespace android::test
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a931709..0227043 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -428,6 +428,94 @@
return static_cast<status_t>(reply.readInt32());
}
+ // TODO(b/213909104) : Add unit tests to verify surface flinger boot time APIs
+ status_t getBootDisplayModeSupport(bool* outSupport) const override {
+ Parcel data, reply;
+ status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (error != NO_ERROR) {
+ ALOGE("getBootDisplayModeSupport: failed to write interface token: %d", error);
+ return error;
+ }
+ error = remote()->transact(BnSurfaceComposer::GET_BOOT_DISPLAY_MODE_SUPPORT, data, &reply);
+ if (error != NO_ERROR) {
+ ALOGE("getBootDisplayModeSupport: failed to transact: %d", error);
+ return error;
+ }
+ bool support;
+ error = reply.readBool(&support);
+ if (error != NO_ERROR) {
+ ALOGE("getBootDisplayModeSupport: failed to read support: %d", error);
+ return error;
+ }
+ *outSupport = support;
+ return NO_ERROR;
+ }
+
+ status_t setBootDisplayMode(const sp<IBinder>& display,
+ ui::DisplayModeId displayModeId) override {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = data.writeInt32(displayModeId);
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to writeIint32: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::SET_BOOT_DISPLAY_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to transact: %d", result);
+ }
+ return result;
+ }
+
+ status_t clearBootDisplayMode(const sp<IBinder>& display) override {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("clearBootDisplayMode failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("clearBootDisplayMode failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::CLEAR_BOOT_DISPLAY_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("clearBootDisplayMode failed to transact: %d", result);
+ }
+ return result;
+ }
+
+ status_t getPreferredBootDisplayMode(const sp<IBinder>& display,
+ ui::DisplayModeId* displayModeId) override {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getPreferredBootDisplayMode failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getPreferredBootDisplayMode failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_PREFERRED_BOOT_DISPLAY_MODE, data,
+ &reply);
+ if (result == NO_ERROR) {
+ reply.writeInt32(*displayModeId);
+ }
+ return result;
+ }
+
void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -1521,6 +1609,56 @@
result = reply->writeInt32(result);
return result;
}
+ case GET_BOOT_DISPLAY_MODE_SUPPORT: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ bool support = false;
+ status_t result = getBootDisplayModeSupport(&support);
+ if (result == NO_ERROR) {
+ reply->writeBool(support);
+ }
+ return result;
+ }
+ case SET_BOOT_DISPLAY_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ ui::DisplayModeId displayModeId;
+ result = data.readInt32(&displayModeId);
+ if (result != NO_ERROR) {
+ ALOGE("setBootDisplayMode failed to readInt32: %d", result);
+ return result;
+ }
+ return setBootDisplayMode(display, displayModeId);
+ }
+ case CLEAR_BOOT_DISPLAY_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("clearBootDisplayMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ return clearBootDisplayMode(display);
+ }
+ case GET_PREFERRED_BOOT_DISPLAY_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getPreferredBootDisplayMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ ui::DisplayModeId displayModeId;
+ result = getPreferredBootDisplayMode(display, &displayModeId);
+ if (result == NO_ERROR) {
+ reply->writeInt32(displayModeId);
+ }
+ return result;
+ }
case SET_AUTO_LOW_LATENCY_MODE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = nullptr;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6a4ddae..b4f6cd5 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2075,6 +2075,25 @@
return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
}
+status_t SurfaceComposerClient::getBootDisplayModeSupport(bool* support) {
+ return ComposerService::getComposerService()->getBootDisplayModeSupport(support);
+}
+
+status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display,
+ ui::DisplayModeId displayModeId) {
+ return ComposerService::getComposerService()->setBootDisplayMode(display, displayModeId);
+}
+
+status_t SurfaceComposerClient::clearBootDisplayMode(const sp<IBinder>& display) {
+ return ComposerService::getComposerService()->clearBootDisplayMode(display);
+}
+
+status_t SurfaceComposerClient::getPreferredBootDisplayMode(const sp<IBinder>& display,
+ ui::DisplayModeId* displayModeId) {
+ return ComposerService::getComposerService()->getPreferredBootDisplayMode(display,
+ displayModeId);
+}
+
void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
ComposerService::getComposerService()->setAutoLowLatencyMode(display, on);
}
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 69dce9d..f37580c 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -224,6 +224,35 @@
ui::ColorMode colorMode) = 0;
/**
+ * Sets the user-preferred display mode that a device should boot in.
+ */
+ virtual status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId) = 0;
+
+ /**
+ * Clears the user-preferred display mode. The device should now boot in system preferred
+ * display mode.
+ */
+ virtual status_t clearBootDisplayMode(const sp<IBinder>& display) = 0;
+
+ /**
+ * Gets the display mode in which the device boots if there is no user-preferred display mode.
+ */
+ virtual status_t getPreferredBootDisplayMode(const sp<IBinder>& display,
+ ui::DisplayModeId*) = 0;
+
+ /**
+ * Gets whether boot time display mode operations are supported on the device.
+ *
+ * outSupport
+ * An output parameter for whether boot time display mode operations are supported.
+ *
+ * Returns NO_ERROR upon success. Otherwise,
+ * NAME_NOT_FOUND if the display is invalid, or
+ * BAD_VALUE if the output parameter is invalid.
+ */
+ virtual status_t getBootDisplayModeSupport(bool* outSupport) const = 0;
+
+ /**
* Switches Auto Low Latency Mode on/off on the connected display, if it is
* available. This should only be called if the display supports Auto Low
* Latency Mode as reported in #getDynamicDisplayInfo.
@@ -645,6 +674,10 @@
REMOVE_WINDOW_INFOS_LISTENER,
GET_PRIMARY_PHYSICAL_DISPLAY_ID,
GET_DISPLAY_DECORATION_SUPPORT,
+ GET_BOOT_DISPLAY_MODE_SUPPORT,
+ SET_BOOT_DISPLAY_MODE,
+ CLEAR_BOOT_DISPLAY_MODE,
+ GET_PREFERRED_BOOT_DISPLAY_MODE,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 62758af..c192323 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -167,6 +167,15 @@
static status_t setActiveColorMode(const sp<IBinder>& display,
ui::ColorMode colorMode);
+ // Gets if boot display mode operations are supported on a device
+ static status_t getBootDisplayModeSupport(bool* support);
+ // Sets the user-preferred display mode that a device should boot in
+ static status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId);
+ // Clears the user-preferred display mode
+ static status_t clearBootDisplayMode(const sp<IBinder>& display);
+ // Gets the display mode in which the device boots if there is no user-preferred display mode
+ static status_t getPreferredBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId*);
+
// Switches on/off Auto Low Latency Mode on the connected display. This should only be
// called if the connected display supports Auto Low Latency Mode as reported by
// #getAutoLowLatencyModeSupport
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index d5e089a..999874b 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -755,6 +755,15 @@
}
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
ColorMode /*colorMode*/) override { return NO_ERROR; }
+ status_t getBootDisplayModeSupport(bool* /*outSupport*/) const override { return NO_ERROR; }
+ status_t setBootDisplayMode(const sp<IBinder>& /*display*/, ui::DisplayModeId /*id*/) override {
+ return NO_ERROR;
+ }
+ status_t clearBootDisplayMode(const sp<IBinder>& /*display*/) override { return NO_ERROR; }
+ status_t getPreferredBootDisplayMode(const sp<IBinder>& /*display*/,
+ ui::DisplayModeId* /*id*/) override {
+ return NO_ERROR;
+ }
void setAutoLowLatencyMode(const sp<IBinder>& /*display*/, bool /*on*/) override {}
void setGameContentType(const sp<IBinder>& /*display*/, bool /*on*/) override {}
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index fc9680b..84daea0 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -556,13 +556,13 @@
const AChoreographerFrameCallbackData* data, size_t index) {
return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index);
}
-int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime(
+int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos(
const AChoreographerFrameCallbackData* data, size_t index) {
- return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(data, index);
+ return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos(data, index);
}
-int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline(
+int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
const AChoreographerFrameCallbackData* data, size_t index) {
- return AChoreographerFrameCallbackData_getFrameTimelineDeadline(data, index);
+ return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index);
}
int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) {
@@ -653,7 +653,7 @@
LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
return frameCallbackData->frameTimelines[index].id;
}
-int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(
+int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos(
const AChoreographerFrameCallbackData* data, size_t index) {
const ChoreographerFrameCallbackDataImpl* frameCallbackData =
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
@@ -662,7 +662,7 @@
LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds");
return frameCallbackData->frameTimelines[index].expectedPresentTime;
}
-int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline(
+int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(
const AChoreographerFrameCallbackData* data, size_t index) {
const ChoreographerFrameCallbackDataImpl* frameCallbackData =
AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data);
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index 4aa7e69..0a1fcbe 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -67,9 +67,9 @@
const AChoreographerFrameCallbackData* data);
int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId(
const AChoreographerFrameCallbackData* data, size_t index);
-int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime(
+int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos(
const AChoreographerFrameCallbackData* data, size_t index);
-int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline(
+int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos(
const AChoreographerFrameCallbackData* data, size_t index);
} // namespace android
diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt
index 4dbfde8..b1b6498 100644
--- a/libs/nativedisplay/libnativedisplay.map.txt
+++ b/libs/nativedisplay/libnativedisplay.map.txt
@@ -12,8 +12,8 @@
AChoreographerFrameCallbackData_getFrameTimelinesLength; # apex # introduced=33
AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex; # apex # introduced=33
AChoreographerFrameCallbackData_getFrameTimelineVsyncId; # apex # introduced=33
- AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime; # apex # introduced=33
- AChoreographerFrameCallbackData_getFrameTimelineDeadline; # apex # introduced=33
+ AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos; # apex # introduced=33
+ AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos; # apex # introduced=33
AChoreographer_create; # apex # introduced=30
AChoreographer_destroy; # apex # introduced=30
AChoreographer_getFd; # apex # introduced=30
@@ -40,8 +40,8 @@
android::AChoreographerFrameCallbackData_routeGetFrameTimelinesLength*;
android::AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex*;
android::AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId*;
- android::AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime*;
- android::AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline*;
+ android::AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos*;
+ android::AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos*;
android::AChoreographer_signalRefreshRateCallbacks*;
android::AChoreographer_getFrameInterval*;
android::ADisplay_acquirePhysicalDisplays*;
diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp
index eabff58..84771c0 100644
--- a/libs/renderengine/ExternalTexture.cpp
+++ b/libs/renderengine/ExternalTexture.cpp
@@ -14,30 +14,32 @@
* limitations under the License.
*/
-#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <ui/GraphicBuffer.h>
#include "log/log_main.h"
-namespace android::renderengine {
+namespace android::renderengine::impl {
-ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine,
- uint32_t usage)
+ExternalTexture::ExternalTexture(const sp<GraphicBuffer>& buffer,
+ renderengine::RenderEngine& renderEngine, uint32_t usage)
: mBuffer(buffer), mRenderEngine(renderEngine) {
LOG_ALWAYS_FATAL_IF(buffer == nullptr,
"Attempted to bind a null buffer to an external texture!");
// GLESRenderEngine has a separate texture cache for output buffers,
- if (usage == Usage::WRITEABLE &&
- (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES ||
- mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) {
+ if (usage == WRITEABLE &&
+ (mRenderEngine.getRenderEngineType() ==
+ renderengine::RenderEngine::RenderEngineType::GLES ||
+ mRenderEngine.getRenderEngineType() ==
+ renderengine::RenderEngine::RenderEngineType::THREADED)) {
return;
}
- mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE);
+ mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & WRITEABLE);
}
ExternalTexture::~ExternalTexture() {
mRenderEngine.unmapExternalTextureBuffer(mBuffer);
}
-} // namespace android::renderengine
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp
index 6c8f8e8..ead97cf 100644
--- a/libs/renderengine/benchmark/RenderEngineBench.cpp
+++ b/libs/renderengine/benchmark/RenderEngineBench.cpp
@@ -22,6 +22,7 @@
#include <renderengine/ExternalTexture.h>
#include <renderengine/LayerSettings.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <mutex>
@@ -115,15 +116,15 @@
uint32_t height,
uint64_t extraUsageFlags = 0,
std::string name = "output") {
- return std::make_shared<ExternalTexture>(new GraphicBuffer(width, height,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE |
- extraUsageFlags,
- std::move(name)),
- re,
- ExternalTexture::Usage::READABLE |
- ExternalTexture::Usage::WRITEABLE);
+ return std::make_shared<
+ impl::ExternalTexture>(new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE |
+ extraUsageFlags,
+ std::move(name)),
+ re,
+ impl::ExternalTexture::Usage::READABLE |
+ impl::ExternalTexture::Usage::WRITEABLE);
}
static std::shared_ptr<ExternalTexture> copyBuffer(RenderEngine& re,
diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h
index 07f0833..621a209 100644
--- a/libs/renderengine/include/renderengine/ExternalTexture.h
+++ b/libs/renderengine/include/renderengine/ExternalTexture.h
@@ -33,28 +33,22 @@
*/
class ExternalTexture {
public:
- // Usage specifies the rendering intent for the buffer.
- enum Usage : uint32_t {
- // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
- // hint to load the buffer into a separate cache
- READABLE = 1 << 0,
+ ExternalTexture() = default;
+ virtual ~ExternalTexture() = default;
- // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
- // external texture
- WRITEABLE = 1 << 1,
- };
- // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
- // usage hint of type Usage.
- ExternalTexture(const sp<GraphicBuffer>& buffer, RenderEngine& renderEngine, uint32_t usage);
-
- ~ExternalTexture();
+ virtual bool hasSameBuffer(const ExternalTexture& other) const = 0;
+ virtual uint32_t getWidth() const = 0;
+ virtual uint32_t getHeight() const = 0;
+ virtual uint64_t getId() const = 0;
+ virtual PixelFormat getPixelFormat() const = 0;
+ virtual uint64_t getUsage() const = 0;
// Retrieves the buffer that is bound to this texture.
- const sp<GraphicBuffer>& getBuffer() const { return mBuffer; }
+ virtual const sp<GraphicBuffer>& getBuffer() const = 0;
-private:
- sp<GraphicBuffer> mBuffer;
- RenderEngine& mRenderEngine;
+ Rect getBounds() const {
+ return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())};
+ }
DISALLOW_COPY_AND_ASSIGN(ExternalTexture);
};
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index d646756..faa84fc 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -76,6 +76,7 @@
namespace impl {
class RenderEngine;
+class ExternalTexture;
}
enum class Protection {
@@ -228,7 +229,7 @@
// avoid any thread synchronization that may be required by directly calling postRenderCleanup.
virtual bool canSkipPostRenderCleanup() const = 0;
- friend class ExternalTexture;
+ friend class impl::ExternalTexture;
friend class threaded::RenderEngineThreaded;
friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
const RenderEngineType mRenderEngineType;
diff --git a/libs/renderengine/include/renderengine/impl/ExternalTexture.h b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
new file mode 100644
index 0000000..c0e24f0
--- /dev/null
+++ b/libs/renderengine/include/renderengine/impl/ExternalTexture.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <renderengine/ExternalTexture.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android::renderengine::impl {
+
+class RenderEngine;
+
+class ExternalTexture : public android::renderengine::ExternalTexture {
+public:
+ // Usage specifies the rendering intent for the buffer.
+ enum Usage : uint32_t {
+ // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a
+ // hint to load the buffer into a separate cache
+ READABLE = 1 << 0,
+
+ // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an
+ // external texture
+ WRITEABLE = 1 << 1,
+ };
+
+ // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given
+ // usage hint of type Usage.
+ ExternalTexture(const sp<GraphicBuffer>& buffer,
+ android::renderengine::RenderEngine& renderEngine, uint32_t usage);
+ ~ExternalTexture();
+ const sp<GraphicBuffer>& getBuffer() const override { return mBuffer; };
+ uint32_t getWidth() const override { return getBuffer()->getWidth(); }
+ uint32_t getHeight() const override { return getBuffer()->getHeight(); }
+ uint64_t getId() const override { return getBuffer()->getId(); }
+ PixelFormat getPixelFormat() const override { return getBuffer()->getPixelFormat(); }
+ uint64_t getUsage() const override { return getBuffer()->getUsage(); }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getBuffer() == other.getBuffer();
+ }
+
+private:
+ sp<GraphicBuffer> mBuffer;
+ android::renderengine::RenderEngine& mRenderEngine;
+};
+
+} // namespace android::renderengine::impl
diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
new file mode 100644
index 0000000..974e0fd
--- /dev/null
+++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <renderengine/ExternalTexture.h>
+
+namespace android {
+namespace renderengine {
+namespace mock {
+
+class FakeExternalTexture : public renderengine::ExternalTexture {
+ const sp<GraphicBuffer> mNullBuffer = nullptr;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint64_t mId;
+ PixelFormat mPixelFormat;
+ uint64_t mUsage;
+
+public:
+ FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
+ uint64_t usage)
+ : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
+ const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getId() == other.getId();
+ }
+ uint32_t getWidth() const override { return mWidth; }
+ uint32_t getHeight() const override { return mHeight; }
+ uint64_t getId() const override { return mId; }
+ PixelFormat getPixelFormat() const override { return mPixelFormat; }
+ uint64_t getUsage() const override { return mUsage; }
+ ~FakeExternalTexture() = default;
+};
+
+} // namespace mock
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index b18a872..a3a1969 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -19,6 +19,7 @@
#include "android-base/unique_fd.h"
#include "renderengine/DisplaySettings.h"
#include "renderengine/LayerSettings.h"
+#include "renderengine/impl/ExternalTexture.h"
#include "ui/GraphicBuffer.h"
#include "ui/GraphicTypes.h"
#include "ui/PixelFormat.h"
@@ -365,8 +366,8 @@
1, usage, "primeShaderCache_dst");
const auto dstTexture =
- std::make_shared<ExternalTexture>(dstBuffer, *renderengine,
- ExternalTexture::Usage::WRITEABLE);
+ std::make_shared<impl::ExternalTexture>(dstBuffer, *renderengine,
+ impl::ExternalTexture::Usage::WRITEABLE);
// This buffer will be the source for the call to drawImageLayers. Draw
// something to it as a placeholder for what an app draws. We should draw
// something, but the details are not important. Make use of the shadow layer drawing step
@@ -375,10 +376,10 @@
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
1, usage, "drawImageLayer_src");
- const auto srcTexture =
- std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
- ExternalTexture::Usage::READABLE |
- ExternalTexture::Usage::WRITEABLE);
+ const auto srcTexture = std::make_shared<
+ impl::ExternalTexture>(srcBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE |
+ impl::ExternalTexture::Usage::WRITEABLE);
drawHolePunchLayer(renderengine, display, dstTexture);
drawSolidLayers(renderengine, display, dstTexture);
@@ -398,8 +399,8 @@
new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888,
1, usageExternal, "primeShaderCache_external");
const auto externalTexture =
- std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
- ExternalTexture::Usage::READABLE);
+ std::make_shared<impl::ExternalTexture>(externalBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE);
std::vector<const std::shared_ptr<ExternalTexture>> textures =
{srcTexture, externalTexture};
@@ -412,8 +413,8 @@
status_t error = f16ExternalBuffer->initCheck();
if (!error) {
const auto f16ExternalTexture =
- std::make_shared<ExternalTexture>(f16ExternalBuffer, *renderengine,
- ExternalTexture::Usage::READABLE);
+ std::make_shared<impl::ExternalTexture>(f16ExternalBuffer, *renderengine,
+ impl::ExternalTexture::Usage::READABLE);
textures.push_back(f16ExternalTexture);
}
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index eb2b2dc..2a25b0b 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -26,6 +26,7 @@
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <sync/sync.h>
#include <system/graphics-base-v1.0.h>
#include <tonemap/tonemap.h>
@@ -178,7 +179,7 @@
public:
std::shared_ptr<renderengine::ExternalTexture> allocateDefaultBuffer() {
return std::make_shared<
- renderengine::
+ renderengine::impl::
ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH,
DEFAULT_DISPLAY_HEIGHT,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
@@ -188,15 +189,16 @@
GRALLOC_USAGE_HW_TEXTURE,
"output"),
*mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
// Allocates a 1x1 buffer to fill with a solid color
std::shared_ptr<renderengine::ExternalTexture> allocateSourceBuffer(uint32_t width,
uint32_t height) {
return std::make_shared<
- renderengine::
+ renderengine::impl::
ExternalTexture>(new GraphicBuffer(width, height,
HAL_PIXEL_FORMAT_RGBA_8888, 1,
GRALLOC_USAGE_SW_READ_OFTEN |
@@ -204,8 +206,9 @@
GRALLOC_USAGE_HW_TEXTURE,
"input"),
*mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width,
@@ -2439,16 +2442,17 @@
};
auto buf = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE,
- "input"),
- *mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "input"),
+ *mRE,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
ASSERT_EQ(0, buf->getBuffer()->initCheck());
{
@@ -2472,16 +2476,17 @@
}
mBuffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC_USAGE_SW_READ_OFTEN |
- GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_TEXTURE,
- "output"),
- *mRE,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
+ GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "output"),
+ *mRE,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
ASSERT_EQ(0, mBuffer->getBuffer()->initCheck());
const renderengine::LayerSettings layer{
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index db7e12b..9685189 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -17,6 +17,7 @@
#include <cutils/properties.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include "../threaded/RenderEngineThreaded.h"
@@ -174,9 +175,10 @@
renderengine::DisplaySettings settings;
std::vector<renderengine::LayerSettings> layers;
std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), *mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
base::unique_fd bufferFence;
diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS
index ac300d0..0ff65bf 100644
--- a/services/gpuservice/OWNERS
+++ b/services/gpuservice/OWNERS
@@ -1,2 +1,6 @@
chrisforbes@google.com
lpy@google.com
+alecmouri@google.com
+lfy@google.com
+paulthomson@google.com
+pbaiget@google.com
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 3e6d49f..26ac269 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -189,7 +189,6 @@
"Scheduler/MessageQueue.cpp",
"Scheduler/RefreshRateConfigs.cpp",
"Scheduler/Scheduler.cpp",
- "Scheduler/SchedulerUtils.cpp",
"Scheduler/Timer.cpp",
"Scheduler/VSyncDispatchTimerQueue.cpp",
"Scheduler/VSyncPredictor.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d61a4cb..649138a 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -164,7 +164,7 @@
const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
((isSecure() || isProtected()) && !targetSettings.isSecure);
const bool bufferCanBeUsedAsHwTexture =
- mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
+ mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
compositionengine::LayerFE::LayerSettings& layer = *result;
if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
@@ -201,7 +201,7 @@
}
layer.source.buffer.maxLuminanceNits = maxLuminance;
layer.frameNumber = mCurrentFrameNumber;
- layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0;
+ layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
const bool useFiltering =
targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
@@ -436,7 +436,7 @@
void BufferLayer::gatherBufferInfo() {
mBufferInfo.mPixelFormat =
- !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format;
+ !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat();
mBufferInfo.mFrameLatencyNeeded = true;
}
@@ -533,10 +533,10 @@
}
if (oldBufferInfo.mBuffer != nullptr) {
- uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
- if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) ||
- bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) {
+ uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
+ if (bufWidth != oldBufferInfo.mBuffer->getWidth() ||
+ bufHeight != oldBufferInfo.mBuffer->getHeight()) {
recomputeVisibleRegions = true;
}
}
@@ -558,7 +558,7 @@
bool BufferLayer::isProtected() const {
return (mBufferInfo.mBuffer != nullptr) &&
- (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED);
+ (mBufferInfo.mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
}
// As documented in libhardware header, formats in the range
@@ -638,8 +638,8 @@
return Rect::INVALID_RECT;
}
- uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+ uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
// Undo any transformations on the buffer and return the result.
if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -670,8 +670,8 @@
return parentBounds;
}
- uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+ uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
// Undo any transformations on the buffer and return the result.
if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -713,7 +713,7 @@
return mBufferInfo.mCrop;
} else if (mBufferInfo.mBuffer != nullptr) {
// otherwise we use the whole buffer
- return mBufferInfo.mBuffer->getBuffer()->getBounds();
+ return mBufferInfo.mBuffer->getBounds();
} else {
// if we don't have a buffer yet, we use an empty/invalid crop
return Rect();
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index c79fa11..9ae45fc 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -41,6 +41,7 @@
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/Trace.h>
@@ -208,8 +209,9 @@
if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr ||
mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) {
mImages[item->mSlot] = std::make_shared<
- renderengine::ExternalTexture>(item->mGraphicBuffer, mRE,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(item->mGraphicBuffer, mRE,
+ renderengine::impl::ExternalTexture::
+ Usage::READABLE);
}
}
@@ -462,8 +464,9 @@
if (oldImage == nullptr || oldImage->getBuffer() == nullptr ||
oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) {
mImages[item.mSlot] = std::make_shared<
- renderengine::ExternalTexture>(item.mGraphicBuffer, mRE,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(item.mGraphicBuffer, mRE,
+ renderengine::impl::ExternalTexture::
+ Usage::READABLE);
}
}
}
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2fac880..6cecd89 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -295,8 +295,8 @@
return assignTransform(&mDrawingState.transform, t);
}
- uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth();
- uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->getHeight();
+ uint32_t bufferWidth = mDrawingState.buffer->getWidth();
+ uint32_t bufferHeight = mDrawingState.buffer->getHeight();
// Undo any transformations on the buffer.
if (mDrawingState.bufferTransform & ui::Transform::ROT_90) {
std::swap(bufferWidth, bufferHeight);
@@ -368,46 +368,13 @@
return true;
}
-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,
+bool BufferStateLayer::setBuffer(std::shared_ptr<renderengine::ExternalTexture>& buffer,
+ const BufferData& bufferData, nsecs_t postTime,
nsecs_t desiredPresentTime, bool isAutoTimestamp,
std::optional<nsecs_t> dequeueTime,
const FrameTimelineInfo& info) {
ATRACE_CALL();
- const std::shared_ptr<renderengine::ExternalTexture>& buffer =
- getBufferFromBufferData(bufferData);
if (!buffer) {
return false;
}
@@ -419,8 +386,9 @@
if (mDrawingState.buffer) {
mReleasePreviousBuffer = true;
- if (mDrawingState.buffer != mBufferInfo.mBuffer ||
- mDrawingState.frameNumber != mBufferInfo.mFrameNumber) {
+ if (!mBufferInfo.mBuffer ||
+ (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) ||
+ mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) {
// If mDrawingState has a buffer, and we are about to update again
// before swapping to drawing state, then the first buffer will be
// dropped and we should decrement the pending buffer count and
@@ -448,7 +416,7 @@
mDrawingState.frameNumber = frameNumber;
mDrawingState.releaseBufferListener = bufferData.releaseBufferListener;
- mDrawingState.buffer = buffer;
+ mDrawingState.buffer = std::move(buffer);
mDrawingState.clientCacheId = bufferData.cachedBuffer;
mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged)
@@ -485,7 +453,7 @@
setFrameTimelineVsyncForBufferTransaction(info, postTime);
if (buffer && dequeueTime && *dequeueTime != 0) {
- const uint64_t bufferId = buffer->getBuffer()->getId();
+ const uint64_t bufferId = buffer->getId();
mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime,
FrameTracer::FrameEvent::DEQUEUE);
@@ -493,8 +461,8 @@
FrameTracer::FrameEvent::QUEUE);
}
- mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
- mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
+ mDrawingState.width = mDrawingState.buffer->getWidth();
+ mDrawingState.height = mDrawingState.buffer->getHeight();
mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint;
return true;
}
@@ -599,8 +567,8 @@
return Rect::INVALID_RECT;
}
- uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth();
- uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight();
+ uint32_t bufWidth = mBufferInfo.mBuffer->getWidth();
+ uint32_t bufHeight = mBufferInfo.mBuffer->getHeight();
// Undo any transformations on the buffer and return the result.
if (mBufferInfo.mTransform & ui::Transform::ROT_90) {
@@ -709,7 +677,7 @@
}
const int32_t layerId = getSequence();
- const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId();
+ const uint64_t bufferId = mDrawingState.buffer->getId();
const uint64_t frameNumber = mDrawingState.frameNumber;
const auto acquireFence = std::make_shared<FenceTime>(mDrawingState.acquireFence);
mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence);
@@ -749,7 +717,7 @@
return BAD_VALUE;
}
- if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) {
+ if (!mBufferInfo.mBuffer || !s.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) {
decrementPendingBufferCount();
}
@@ -874,10 +842,10 @@
Rect BufferStateLayer::computeBufferCrop(const State& s) {
if (s.buffer && !s.bufferCrop.isEmpty()) {
Rect bufferCrop;
- s.buffer->getBuffer()->getBounds().intersect(s.bufferCrop, &bufferCrop);
+ s.buffer->getBounds().intersect(s.bufferCrop, &bufferCrop);
return bufferCrop;
} else if (s.buffer) {
- return s.buffer->getBuffer()->getBounds();
+ return s.buffer->getBounds();
} else {
return s.bufferCrop;
}
@@ -898,8 +866,8 @@
return false;
}
- int32_t bufferWidth = s.buffer->getBuffer()->width;
- int32_t bufferHeight = s.buffer->getBuffer()->height;
+ int32_t bufferWidth = static_cast<int32_t>(s.buffer->getWidth());
+ int32_t bufferHeight = static_cast<int32_t>(s.buffer->getHeight());
// Undo any transformations on the buffer and return the result.
if (s.bufferTransform & ui::Transform::ROT_90) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index eea700c..2f613d7 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -57,7 +57,8 @@
bool setTransform(uint32_t transform) override;
bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
bool setCrop(const Rect& crop) override;
- bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
+ bool setBuffer(std::shared_ptr<renderengine::ExternalTexture>& /* buffer */,
+ 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;
@@ -136,9 +137,6 @@
bool bufferNeedsFiltering() const override;
- std::shared_ptr<renderengine::ExternalTexture> getBufferFromBufferData(
- const BufferData& bufferData);
-
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp
index e7b8995..3c7b9d9 100644
--- a/services/surfaceflinger/ClientCache.cpp
+++ b/services/surfaceflinger/ClientCache.cpp
@@ -22,6 +22,7 @@
#include <cinttypes>
#include <android-base/stringprintf.h>
+#include <renderengine/impl/ExternalTexture.h>
#include "ClientCache.h"
@@ -109,8 +110,9 @@
"Attempted to build the ClientCache before a RenderEngine instance was "
"ready!");
processBuffers[id].buffer = std::make_shared<
- renderengine::ExternalTexture>(buffer, *mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(buffer, *mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE);
return true;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index a19d23f..12c2c8e 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -28,6 +28,7 @@
#include <log/log.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <system/window.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
@@ -182,9 +183,10 @@
mTexture = texture;
} else {
mTexture = std::make_shared<
- renderengine::ExternalTexture>(GraphicBuffer::from(buffer),
- mCompositionEngine.getRenderEngine(),
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture>(GraphicBuffer::from(buffer),
+ mCompositionEngine.getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
mTextureCache.push_back(mTexture);
if (mTextureCache.size() > mMaxTextureCacheSize) {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
index 497c433..54ecb56 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
@@ -20,6 +20,7 @@
#define LOG_TAG "Planner"
#include <compositionengine/impl/planner/TexturePool.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <utils/Log.h>
namespace android::compositionengine::impl::planner {
@@ -82,16 +83,19 @@
std::shared_ptr<renderengine::ExternalTexture> TexturePool::genTexture() {
LOG_ALWAYS_FATAL_IF(!mSize.isValid(), "Attempted to generate texture with invalid size");
return std::make_shared<
- renderengine::ExternalTexture>(sp<GraphicBuffer>::
- make(mSize.getWidth(), mSize.getHeight(),
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GraphicBuffer::USAGE_HW_RENDER |
- GraphicBuffer::USAGE_HW_COMPOSER |
- GraphicBuffer::USAGE_HW_TEXTURE,
- "Planner"),
- mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(sp<GraphicBuffer>::
+ make(static_cast<uint32_t>(mSize.getWidth()),
+ static_cast<uint32_t>(mSize.getHeight()),
+ HAL_PIXEL_FORMAT_RGBA_8888, 1U,
+ static_cast<uint64_t>(
+ GraphicBuffer::USAGE_HW_RENDER |
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_HW_TEXTURE),
+ "Planner"),
+ mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
}
void TexturePool::setEnabled(bool enabled) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index dc5c5c8..bd3022b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -106,6 +106,9 @@
status_t(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline*));
+ MOCK_METHOD2(setBootDisplayMode, status_t(PhysicalDisplayId, hal::HWConfigId));
+ MOCK_METHOD1(clearBootDisplayMode, status_t(PhysicalDisplayId));
+ MOCK_METHOD1(getPreferredBootDisplayMode, hal::HWConfigId(PhysicalDisplayId));
MOCK_METHOD2(setAutoLowLatencyMode, status_t(PhysicalDisplayId, bool));
MOCK_METHOD2(getSupportedContentTypes,
status_t(PhysicalDisplayId, std::vector<hal::ContentType>*));
@@ -124,6 +127,7 @@
(const, override));
MOCK_METHOD(std::optional<hal::HWDisplayId>, fromPhysicalDisplayId, (PhysicalDisplayId),
(const, override));
+ MOCK_METHOD(bool, getBootDisplayModeSupport, (), (override));
};
} // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index f34b621..132ac02 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -24,6 +24,7 @@
#include <gtest/gtest.h>
#include <log/log.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/PixelFormat.h>
#include "MockHWC2.h"
@@ -815,10 +816,11 @@
auto& overrideInfo = mOutputLayer.editState().overrideInfo;
overrideInfo.buffer = std::make_shared<
- renderengine::ExternalTexture>(kOverrideBuffer, mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::
- WRITEABLE);
+ renderengine::impl::ExternalTexture>(kOverrideBuffer, mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE |
+ renderengine::impl::ExternalTexture::
+ Usage::WRITEABLE);
overrideInfo.acquireFence = kOverrideFence;
overrideInfo.displayFrame = kOverrideDisplayFrame;
overrideInfo.dataspace = kOverrideDataspace;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index f7c7533..b13e13c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -26,6 +26,8 @@
#include <compositionengine/mock/RenderSurface.h>
#include <ftl/future.h>
#include <gtest/gtest.h>
+#include <renderengine/ExternalTexture.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -37,7 +39,6 @@
#include "MockHWC2.h"
#include "RegionMatcher.h"
#include "TestUtils.h"
-#include "renderengine/ExternalTexture.h"
namespace android::compositionengine {
namespace {
@@ -273,9 +274,10 @@
// Inject some layers
InjectedLayer layer;
layer.outputLayerState.overrideInfo.buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), renderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
injectOutputLayer(layer);
// inject a null layer to check for null exceptions
injectNullOutputLayer();
@@ -967,9 +969,10 @@
mOutput->planComposition();
std::shared_ptr<renderengine::ExternalTexture> buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), renderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
layer1.outputLayerState.overrideInfo.buffer = buffer;
layer2.outputLayerState.overrideInfo.buffer = buffer;
layer1.outputLayerState.overrideInfo.peekThroughLayer = layer3.outputLayer;
@@ -3088,9 +3091,10 @@
mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
StrictMock<OutputPartialMock> mOutput;
std::shared_ptr<renderengine::ExternalTexture> mOutputBuffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
std::optional<base::unique_fd> mReadyFence;
};
@@ -3324,9 +3328,10 @@
.WillRepeatedly(Return());
const auto otherOutputBuffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
.WillOnce(Return(mOutputBuffer))
.WillOnce(Return(otherOutputBuffer));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 7c8e41b..e5f9ebf 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -27,6 +27,7 @@
#include <compositionengine/mock/OutputLayer.h>
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/GraphicBuffer.h>
@@ -251,9 +252,10 @@
TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) {
const auto buffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE |
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::
+ ExternalTexture>(new GraphicBuffer(), mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::READABLE |
+ renderengine::impl::ExternalTexture::Usage::WRITEABLE);
mSurface.mutableTextureForTest() = buffer;
impl::OutputCompositionState state;
@@ -269,8 +271,8 @@
}
TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) {
- const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
- mRenderEngine, false);
+ const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+ mRenderEngine, false);
mSurface.mutableTextureForTest() = buffer;
impl::OutputCompositionState state;
@@ -288,8 +290,8 @@
}
TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) {
- const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
- mRenderEngine, false);
+ const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+ mRenderEngine, false);
mSurface.mutableTextureForTest() = buffer;
impl::OutputCompositionState state;
@@ -327,8 +329,8 @@
}
TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) {
- const auto buffer = std::make_shared<renderengine::ExternalTexture>(new GraphicBuffer(),
- mRenderEngine, false);
+ const auto buffer = std::make_shared<renderengine::impl::ExternalTexture>(new GraphicBuffer(),
+ mRenderEngine, false);
mSurface.mutableTextureForTest() = buffer;
impl::OutputCompositionState state;
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index d5a117a..4ae921d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -22,6 +22,7 @@
#include <gmock/gmock-actions.h>
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/GraphicTypes.h>
#include <utils/Errors.h>
@@ -702,9 +703,11 @@
std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
clientCompList3.push_back({});
- clientCompList3[0].source.buffer.buffer = std::make_shared<
- renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
- renderengine::ExternalTexture::READABLE);
+ clientCompList3[0].source.buffer.buffer =
+ std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
@@ -901,9 +904,11 @@
std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
clientCompList3.push_back({});
- clientCompList3[0].source.buffer.buffer = std::make_shared<
- renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
- renderengine::ExternalTexture::READABLE);
+ clientCompList3[0].source.buffer.buffer =
+ std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
EXPECT_CALL(*layerFE1,
prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 35d051e..58dc244 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -23,6 +23,7 @@
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/LayerSettings.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <chrono>
@@ -639,9 +640,10 @@
LayerFE::LayerSettings{},
};
clientCompositionList[0].source.buffer.buffer = std::make_shared<
- renderengine::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer,
- mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer,
+ mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE);
EXPECT_CALL(*mTestLayers[2]->layerFE, prepareClientCompositionList(_))
.WillOnce(Return(clientCompositionList));
@@ -711,9 +713,10 @@
LayerFE::LayerSettings{},
};
clientCompositionList[0].source.buffer.buffer = std::make_shared<
- renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
- mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
+ mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE);
EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
.WillOnce(Return(clientCompositionList));
@@ -781,9 +784,10 @@
LayerFE::LayerSettings{},
};
clientCompositionList[0].source.buffer.buffer = std::make_shared<
- renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
- mRenderEngine,
- renderengine::ExternalTexture::Usage::READABLE);
+ renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
+ mRenderEngine,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE);
EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_))
.WillOnce(Return(clientCompositionList));
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 3c578bc..1448e56 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -237,6 +237,7 @@
case OptionalFeature::RefreshRateSwitching:
case OptionalFeature::ExpectedPresentTime:
case OptionalFeature::DisplayBrightnessCommand:
+ case OptionalFeature::BootDisplayConfig:
return true;
}
}
@@ -1009,6 +1010,38 @@
return V2_4::Error::UNSUPPORTED;
}
+Error AidlComposer::setBootDisplayConfig(Display display, Config config) {
+ const auto status = mAidlComposerClient->setBootDisplayConfig(translate<int64_t>(display),
+ translate<int32_t>(config));
+ if (!status.isOk()) {
+ ALOGE("setBootDisplayConfig failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ return Error::NONE;
+}
+
+Error AidlComposer::clearBootDisplayConfig(Display display) {
+ const auto status = mAidlComposerClient->clearBootDisplayConfig(translate<int64_t>(display));
+ if (!status.isOk()) {
+ ALOGE("clearBootDisplayConfig failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ return Error::NONE;
+}
+
+Error AidlComposer::getPreferredBootDisplayConfig(Display display, Config* config) {
+ int32_t displayConfig;
+ const auto status =
+ mAidlComposerClient->getPreferredBootDisplayConfig(translate<int64_t>(display),
+ &displayConfig);
+ if (!status.isOk()) {
+ ALOGE("getPreferredBootDisplayConfig failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ *config = translate<uint32_t>(displayConfig);
+ return Error::NONE;
+}
+
Error AidlComposer::getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
float* whitePointNits) {
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index cdd16e2..6770017 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -213,6 +213,9 @@
Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) override;
+ Error setBootDisplayConfig(Display displayId, Config) override;
+ Error clearBootDisplayConfig(Display displayId) override;
+ Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
private:
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index bb4b784..22f424f 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -81,6 +81,7 @@
ExpectedPresentTime,
// Whether setDisplayBrightness is able to be applied as part of a display command.
DisplayBrightnessCommand,
+ BootDisplayConfig,
};
virtual bool isSupported(OptionalFeature) const = 0;
@@ -248,6 +249,7 @@
const std::vector<uint8_t>& value) = 0;
virtual V2_4::Error getLayerGenericMetadataKeys(
std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) = 0;
+
virtual Error getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
float* outWhitePointNits) = 0;
@@ -256,6 +258,9 @@
virtual Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) = 0;
virtual Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) = 0;
+ virtual Error setBootDisplayConfig(Display displayId, Config) = 0;
+ virtual Error clearBootDisplayConfig(Display displayId) = 0;
+ virtual Error getPreferredBootDisplayConfig(Display displayId, Config*) = 0;
};
} // namespace android::Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 34f2e76..05e3aef 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -539,6 +539,21 @@
});
}
+Error Display::setBootDisplayConfig(hal::HWConfigId configId) {
+ auto intError = mComposer.setBootDisplayConfig(mId, configId);
+ return static_cast<Error>(intError);
+}
+
+Error Display::clearBootDisplayConfig() {
+ auto intError = mComposer.clearBootDisplayConfig(mId);
+ return static_cast<Error>(intError);
+}
+
+Error Display::getPreferredBootDisplayConfig(hal::HWConfigId* configId) const {
+ auto intError = mComposer.getPreferredBootDisplayConfig(mId, configId);
+ return static_cast<Error>(intError);
+}
+
Error Display::setAutoLowLatencyMode(bool on) {
auto intError = mComposer.setAutoLowLatencyMode(mId, on);
return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 01a482d..57eb128 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -149,6 +149,11 @@
[[clang::warn_unused_result]] virtual hal::Error setActiveConfigWithConstraints(
hal::HWConfigId configId, const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setBootDisplayConfig(
+ hal::HWConfigId configId) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error clearBootDisplayConfig() = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getPreferredBootDisplayConfig(
+ hal::HWConfigId* configId) const = 0;
[[clang::warn_unused_result]] virtual hal::Error setAutoLowLatencyMode(bool on) = 0;
[[clang::warn_unused_result]] virtual hal::Error getSupportedContentTypes(
std::vector<hal::ContentType>*) const = 0;
@@ -218,6 +223,9 @@
hal::Error setActiveConfigWithConstraints(hal::HWConfigId configId,
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
+ hal::Error setBootDisplayConfig(hal::HWConfigId configId) override;
+ hal::Error clearBootDisplayConfig() override;
+ hal::Error getPreferredBootDisplayConfig(hal::HWConfigId* configId) const override;
hal::Error setAutoLowLatencyMode(bool on) override;
hal::Error getSupportedContentTypes(
std::vector<hal::ContentType>* outSupportedContentTypes) const override;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 057db46..44e4597 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -801,6 +801,52 @@
});
}
+bool HWComposer::getBootDisplayModeSupport() {
+ return mComposer->isSupported(Hwc2::Composer::OptionalFeature::BootDisplayConfig);
+}
+
+status_t HWComposer::setBootDisplayMode(PhysicalDisplayId displayId,
+ hal::HWConfigId displayModeId) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->setBootDisplayConfig(displayModeId);
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
+status_t HWComposer::clearBootDisplayMode(PhysicalDisplayId displayId) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->clearBootDisplayConfig();
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
+hal::HWConfigId HWComposer::getPreferredBootDisplayMode(PhysicalDisplayId displayId) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ hal::HWConfigId displayModeId = -1;
+ const auto error =
+ mDisplayData[displayId].hwcDisplay->getPreferredBootDisplayConfig(&displayModeId);
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return displayModeId;
+}
+
status_t HWComposer::setAutoLowLatencyMode(PhysicalDisplayId displayId, bool on) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto error = mDisplayData[displayId].hwcDisplay->setAutoLowLatencyMode(on);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 4fae06d..9e57602 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -255,6 +255,12 @@
virtual std::optional<PhysicalDisplayId> toPhysicalDisplayId(hal::HWDisplayId) const = 0;
virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(PhysicalDisplayId) const = 0;
+
+ // Composer 3.0
+ virtual bool getBootDisplayModeSupport() = 0;
+ virtual status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) = 0;
+ virtual status_t clearBootDisplayMode(PhysicalDisplayId) = 0;
+ virtual hal::HWConfigId getPreferredBootDisplayMode(PhysicalDisplayId) = 0;
};
namespace impl {
@@ -381,6 +387,12 @@
const std::unordered_map<std::string, bool>& getSupportedLayerGenericMetadata() const override;
+ // Composer 3.0
+ bool getBootDisplayModeSupport() override;
+ status_t setBootDisplayMode(PhysicalDisplayId, hal::HWConfigId) override;
+ status_t clearBootDisplayMode(PhysicalDisplayId) override;
+ hal::HWConfigId getPreferredBootDisplayMode(PhysicalDisplayId) override;
+
// for debugging ----------------------------------------------------------
void dump(std::string& out) const override;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index 0ab1cfb..d3acecb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -162,6 +162,7 @@
return mClient_2_4 != nullptr;
case OptionalFeature::ExpectedPresentTime:
case OptionalFeature::DisplayBrightnessCommand:
+ case OptionalFeature::BootDisplayConfig:
return false;
}
}
@@ -1216,6 +1217,18 @@
return error;
}
+Error HidlComposer::setBootDisplayConfig(Display /*displayId*/, Config) {
+ return Error::UNSUPPORTED;
+}
+
+Error HidlComposer::clearBootDisplayConfig(Display /*displayId*/) {
+ return Error::UNSUPPORTED;
+}
+
+Error HidlComposer::getPreferredBootDisplayConfig(Display /*displayId*/, Config*) {
+ return Error::UNSUPPORTED;
+}
+
Error HidlComposer::getClientTargetProperty(
Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty,
float* outWhitePointNits) {
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index 8282d8a..c8c7800 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -323,6 +323,9 @@
Error setLayerWhitePointNits(Display display, Layer layer, float whitePointNits) override;
Error setLayerBlockingRegion(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& blocking) override;
+ Error setBootDisplayConfig(Display displayId, Config) override;
+ Error clearBootDisplayConfig(Display displayId) override;
+ Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 31cdf0b..0d2618a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -416,8 +416,10 @@
// 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 BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
- bool /*isAutoTimestamp*/, std::optional<nsecs_t> /* dequeueTime */,
+ virtual bool setBuffer(std::shared_ptr<renderengine::ExternalTexture>& /* buffer */,
+ const BufferData& /* bufferData */, nsecs_t /* postTime */,
+ nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
+ std::optional<nsecs_t> /* dequeueTime */,
const FrameTimelineInfo& /*info*/) {
return false;
};
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index da8c3e0..ff30348 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -31,6 +31,7 @@
#include <cutils/properties.h>
#include <ftl/future.h>
#include <gui/SyncScreenCaptureListener.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <ui/DisplayStatInfo.h>
#include <utils/Trace.h>
@@ -351,8 +352,9 @@
LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d",
bufferStatus);
buffer = std::make_shared<
- renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(),
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ renderengine::impl::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
}
auto captureScreenResultFuture =
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 74a2ca7..0efc28b 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -33,7 +33,6 @@
#include "../Layer.h"
#include "LayerInfo.h"
-#include "SchedulerUtils.h"
namespace android::scheduler {
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 2d88a4f..8a3b0b9 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -29,7 +29,6 @@
#include "LayerHistory.h"
#include "RefreshRateConfigs.h"
-#include "SchedulerUtils.h"
namespace android {
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 71d5631..42dc539 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -618,7 +618,7 @@
const auto [refreshRate, score] = *i;
ALOGV("%s scores %.2f", refreshRate->getName().c_str(), score);
- ATRACE_INT(refreshRate->getName().c_str(), round<int>(score * 100));
+ ATRACE_INT(refreshRate->getName().c_str(), static_cast<int>(std::round(score * 100)));
if (score > max * (1 + kEpsilon)) {
max = score;
@@ -714,20 +714,19 @@
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();
+ [this] {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ if (const auto callbacks = getIdleTimerCallbacks()) {
+ callbacks->onReset();
+ }
},
- [getCallback] {
- if (const auto callback = getCallback()) callback->onExpired();
+ [this] {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ if (const auto callbacks = getIdleTimerCallbacks()) {
+ callbacks->onExpired();
+ }
});
}
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 4bbdab6..de5afb7 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -30,7 +30,6 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "Scheduler/OneShotTimer.h"
-#include "Scheduler/SchedulerUtils.h"
#include "Scheduler/StrongTyping.h"
namespace android::scheduler {
@@ -348,16 +347,24 @@
bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; }
- void setIdleTimerCallbacks(std::function<void()> platformTimerReset,
- std::function<void()> platformTimerExpired,
- std::function<void()> kernelTimerReset,
- std::function<void()> kernelTimerExpired) {
+ struct IdleTimerCallbacks {
+ struct Callbacks {
+ std::function<void()> onReset;
+ std::function<void()> onExpired;
+ };
+
+ Callbacks platform;
+ Callbacks kernel;
+ };
+
+ void setIdleTimerCallbacks(IdleTimerCallbacks callbacks) EXCLUDES(mIdleTimerCallbacksMutex) {
std::scoped_lock lock(mIdleTimerCallbacksMutex);
- mIdleTimerCallbacks.emplace();
- mIdleTimerCallbacks->platform.onReset = std::move(platformTimerReset);
- mIdleTimerCallbacks->platform.onExpired = std::move(platformTimerExpired);
- mIdleTimerCallbacks->kernel.onReset = std::move(kernelTimerReset);
- mIdleTimerCallbacks->kernel.onExpired = std::move(kernelTimerExpired);
+ mIdleTimerCallbacks = std::move(callbacks);
+ }
+
+ void clearIdleTimerCallbacks() EXCLUDES(mIdleTimerCallbacksMutex) {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ mIdleTimerCallbacks.reset();
}
void startIdleTimer() {
@@ -380,7 +387,7 @@
return;
}
mIdleTimer->reset();
- };
+ }
void dump(std::string& result) const EXCLUDES(mLock);
@@ -448,6 +455,13 @@
void initializeIdleTimer();
+ std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const
+ REQUIRES(mIdleTimerCallbacksMutex) {
+ if (!mIdleTimerCallbacks) return {};
+ return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel
+ : mIdleTimerCallbacks->platform;
+ }
+
// The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
@@ -492,21 +506,11 @@
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;
- };
-
+ // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
std::mutex mIdleTimerCallbacksMutex;
std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex);
+ // Used to detect (lack of) frame activity.
+ std::optional<scheduler::OneShotTimer> mIdleTimer;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index 23ebb06..f1ad755 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -25,7 +25,6 @@
#include <scheduler/Fps.h>
-#include "Scheduler/SchedulerUtils.h"
#include "TimeStats/TimeStats.h"
namespace android::scheduler {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index cbe4552..d4b3917 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -44,7 +44,6 @@
#include "EventThread.h"
#include "InjectVSyncSource.h"
#include "OneShotTimer.h"
-#include "SchedulerUtils.h"
#include "SurfaceFlingerProperties.h"
#include "VSyncPredictor.h"
#include "VSyncReactor.h"
@@ -62,6 +61,15 @@
Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
: impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
+Scheduler::~Scheduler() {
+ // Stop timers and wait for their threads to exit.
+ mDisplayPowerTimer.reset();
+ mTouchTimer.reset();
+
+ // Stop idle timer and clear callbacks, as the RefreshRateConfigs may outlive the Scheduler.
+ setRefreshRateConfigs(nullptr);
+}
+
void Scheduler::startTimers() {
using namespace sysprop;
using namespace std::string_literals;
@@ -84,11 +92,32 @@
}
}
-Scheduler::~Scheduler() {
- // Ensure the OneShotTimer threads are joined before we start destroying state.
- mDisplayPowerTimer.reset();
- mTouchTimer.reset();
- mRefreshRateConfigs.reset();
+void Scheduler::setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs) {
+ {
+ // The current RefreshRateConfigs instance may outlive this call, so unbind its idle timer.
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (mRefreshRateConfigs) {
+ mRefreshRateConfigs->stopIdleTimer();
+ mRefreshRateConfigs->clearIdleTimerCallbacks();
+ }
+ }
+ {
+ // Clear state that depends on the current instance.
+ std::scoped_lock lock(mPolicyLock);
+ mPolicy = {};
+ }
+
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs = std::move(configs);
+ if (!mRefreshRateConfigs) return;
+
+ mRefreshRateConfigs->setIdleTimerCallbacks(
+ {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); },
+ .onExpired = [this] { idleTimerCallback(TimerState::Expired); }},
+ .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); },
+ .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}});
+
+ mRefreshRateConfigs->startIdleTimer();
}
void Scheduler::run() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 818f1ed..2f3d952 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -17,6 +17,7 @@
#pragma once
#include <atomic>
+#include <cstdint>
#include <functional>
#include <future>
#include <memory>
@@ -38,9 +39,37 @@
#include "MessageQueue.h"
#include "OneShotTimer.h"
#include "RefreshRateConfigs.h"
-#include "SchedulerUtils.h"
#include "VsyncSchedule.h"
+namespace android::scheduler {
+
+// Opaque handle to scheduler connection.
+struct ConnectionHandle {
+ using Id = std::uintptr_t;
+ static constexpr Id INVALID_ID = static_cast<Id>(-1);
+
+ Id id = INVALID_ID;
+
+ explicit operator bool() const { return id != INVALID_ID; }
+};
+
+inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) {
+ return lhs.id == rhs.id;
+}
+
+} // namespace android::scheduler
+
+namespace std {
+
+template <>
+struct hash<android::scheduler::ConnectionHandle> {
+ size_t operator()(android::scheduler::ConnectionHandle handle) const {
+ return hash<android::scheduler::ConnectionHandle::Id>()(handle.id);
+ }
+};
+
+} // namespace std
+
namespace android {
class FenceTime;
@@ -74,11 +103,15 @@
public:
Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags);
- ~Scheduler();
+ virtual ~Scheduler();
+
+ void startTimers();
+ void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs>)
+ EXCLUDES(mRefreshRateConfigsLock);
+
+ void run();
void createVsyncSchedule(FeatureFlags);
- void startTimers();
- void run();
using Impl::initVsync;
using Impl::setInjector;
@@ -198,36 +231,6 @@
std::optional<Fps> getFrameRateOverride(uid_t uid) const
EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock);
- void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> refreshRateConfigs)
- EXCLUDES(mRefreshRateConfigsLock) {
- // We need to stop the idle timer on the previous RefreshRateConfigs instance
- // and cleanup the scheduler's state before we switch to the other RefreshRateConfigs.
- {
- std::scoped_lock lock(mRefreshRateConfigsLock);
- if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer();
- }
- {
- std::scoped_lock lock(mPolicyLock);
- mPolicy = {};
- }
- {
- 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);
- });
- mRefreshRateConfigs->startIdleTimer();
- }
- }
-
nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
std::scoped_lock lock(mRefreshRateConfigsLock);
return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp b/services/surfaceflinger/Scheduler/SchedulerUtils.cpp
deleted file mode 100644
index e8e0444..0000000
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SchedulerUtils.h"
-
-#include <cinttypes>
-#include <numeric>
-#include <unordered_map>
-#include <vector>
-
-namespace android {
-namespace scheduler {
-
-int64_t calculate_median(std::vector<int64_t>* v) {
- if (!v || v->empty()) {
- return 0;
- }
-
- size_t n = v->size() / 2;
- nth_element(v->begin(), v->begin() + static_cast<long>(n), v->end());
- return v->at(n);
-}
-
-} // namespace scheduler
-} // namespace android
-
diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h
deleted file mode 100644
index 04a4cd1..0000000
--- a/services/surfaceflinger/Scheduler/SchedulerUtils.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <utils/Timers.h>
-#include <cinttypes>
-#include <numeric>
-#include <unordered_map>
-#include <vector>
-
-namespace android::scheduler {
-
-// Opaque handle to scheduler connection.
-struct ConnectionHandle {
- using Id = std::uintptr_t;
- static constexpr Id INVALID_ID = static_cast<Id>(-1);
-
- Id id = INVALID_ID;
-
- explicit operator bool() const { return id != INVALID_ID; }
-};
-
-inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) {
- return lhs.id == rhs.id;
-}
-
-// Calculates the statistical mean (average) in the data structure (array, vector). The
-// function does not modify the contents of the array.
-template <typename T>
-auto calculate_mean(const T& v) {
- using V = typename T::value_type;
- V sum = std::accumulate(v.begin(), v.end(), static_cast<V>(0));
- return sum / static_cast<V>(v.size());
-}
-
-// Calculates the statistical median in the vector. Return 0 if the vector is empty. The
-// function modifies the vector contents.
-int64_t calculate_median(std::vector<int64_t>* v);
-
-// Calculates the statistical mode in the vector. Return 0 if the vector is empty.
-template <typename T>
-auto calculate_mode(const T& v) {
- if (v.empty()) {
- return 0;
- }
-
- // Create a map with all the counts for the indivicual values in the vector.
- std::unordered_map<int64_t, int> counts;
- for (int64_t value : v) {
- counts[value]++;
- }
-
- // Sort the map, and return the number with the highest count. If two numbers have
- // the same count, first one is returned.
- using ValueType = const decltype(counts)::value_type&;
- const auto compareCounts = [](ValueType l, ValueType r) { return l.second <= r.second; };
- return static_cast<int>(std::max_element(counts.begin(), counts.end(), compareCounts)->first);
-}
-
-template <class T, size_t N>
-constexpr size_t arrayLen(T (&)[N]) {
- return N;
-}
-
-static constexpr size_t max64print = std::numeric_limits<nsecs_t>::digits10 + 1;
-
-template <typename T>
-static inline T round(float f) {
- return static_cast<T>(std::round(f));
-}
-
-} // namespace android::scheduler
-
-namespace std {
-
-template <>
-struct hash<android::scheduler::ConnectionHandle> {
- size_t operator()(android::scheduler::ConnectionHandle handle) const {
- return hash<android::scheduler::ConnectionHandle::Id>()(handle.id);
- }
-};
-
-} // namespace std
diff --git a/services/surfaceflinger/Scheduler/Timer.cpp b/services/surfaceflinger/Scheduler/Timer.cpp
index 68f9321..38e277c 100644
--- a/services/surfaceflinger/Scheduler/Timer.cpp
+++ b/services/surfaceflinger/Scheduler/Timer.cpp
@@ -25,16 +25,14 @@
#include <sys/timerfd.h>
#include <sys/unistd.h>
-#include <android-base/stringprintf.h>
+#include <ftl/concat.h>
#include <ftl/enum.h>
#include <log/log.h>
#include <utils/Trace.h>
-#include "SchedulerUtils.h"
#include "Timer.h"
namespace android::scheduler {
-using base::StringAppendF;
static constexpr size_t kReadPipe = 0;
static constexpr size_t kWritePipe = 1;
@@ -180,9 +178,6 @@
}
uint64_t iteration = 0;
- char const traceNamePrefix[] = "TimerIteration #";
- static constexpr size_t maxlen = arrayLen(traceNamePrefix) + max64print;
- std::array<char, maxlen> str_buffer;
while (true) {
setDebugState(DebugState::Waiting);
@@ -191,9 +186,8 @@
setDebugState(DebugState::Running);
if (ATRACE_ENABLED()) {
- snprintf(str_buffer.data(), str_buffer.size(), "%s%" PRIu64, traceNamePrefix,
- iteration++);
- ATRACE_NAME(str_buffer.data());
+ ftl::Concat trace("TimerIteration #", iteration++);
+ ATRACE_NAME(trace.c_str());
}
if (nfds == -1) {
@@ -237,7 +231,9 @@
void Timer::dump(std::string& result) const {
std::lock_guard lock(mMutex);
- StringAppendF(&result, "\t\tDebugState: %s\n", ftl::enum_string(mDebugState).c_str());
+ result.append("\t\tDebugState: ");
+ result.append(ftl::enum_string(mDebugState));
+ result.push_back('\n');
}
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index b805bf6..c0646ad 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -15,15 +15,19 @@
*/
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <android-base/stringprintf.h>
-#include <utils/Trace.h>
+
#include <vector>
+#include <android-base/stringprintf.h>
+#include <ftl/concat.h>
+#include <utils/Trace.h>
+
#include "TimeKeeper.h"
#include "VSyncDispatchTimerQueue.h"
#include "VSyncTracker.h"
namespace android::scheduler {
+
using base::StringAppendF;
namespace {
@@ -222,16 +226,6 @@
rearmTimerSkippingUpdateFor(now, mCallbacks.end());
}
-void VSyncDispatchTimerQueue::TraceBuffer::note(std::string_view name, nsecs_t alarmIn,
- nsecs_t vsFor) {
- if (ATRACE_ENABLED()) {
- snprintf(str_buffer.data(), str_buffer.size(), "%.4s%s%" PRId64 "%s%" PRId64,
- name.substr(0, kMaxNamePrint).data(), kTraceNamePrefix, alarmIn,
- kTraceNameSeparator, vsFor);
- }
- ATRACE_NAME(str_buffer.data());
-}
-
void VSyncDispatchTimerQueue::rearmTimerSkippingUpdateFor(
nsecs_t now, CallbackMap::iterator const& skipUpdateIt) {
std::optional<nsecs_t> min;
@@ -247,16 +241,18 @@
callback->update(mTracker, now);
}
auto const wakeupTime = *callback->wakeupTime();
- if (!min || (min && *min > wakeupTime)) {
+ if (!min || *min > wakeupTime) {
nextWakeupName = callback->name();
min = wakeupTime;
targetVsync = callback->targetVsync();
}
}
- if (min && (min < mIntendedWakeupTime)) {
- if (targetVsync && nextWakeupName) {
- mTraceBuffer.note(*nextWakeupName, *min - now, *targetVsync - now);
+ if (min && min < mIntendedWakeupTime) {
+ if (ATRACE_ENABLED() && nextWakeupName && targetVsync) {
+ ftl::Concat trace(ftl::truncated<5>(*nextWakeupName), " alarm in ", ns2us(*min - now),
+ "us; VSYNC in ", ns2us(*targetVsync - now), "us");
+ ATRACE_NAME(trace.c_str());
}
setTimer(*min, now);
} else {
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
index 26237b6..76e1caf 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h
@@ -17,7 +17,6 @@
#pragma once
#include <android-base/thread_annotations.h>
-#include <array>
#include <functional>
#include <memory>
#include <mutex>
@@ -25,7 +24,6 @@
#include <string_view>
#include <unordered_map>
-#include "SchedulerUtils.h"
#include "VSyncDispatch.h"
namespace android::scheduler {
@@ -153,17 +151,6 @@
CallbackMap mCallbacks GUARDED_BY(mMutex);
nsecs_t mIntendedWakeupTime GUARDED_BY(mMutex) = kInvalidTime;
- struct TraceBuffer {
- static constexpr char const kTraceNamePrefix[] = "-alarm in:";
- static constexpr char const kTraceNameSeparator[] = " for vs:";
- static constexpr size_t kMaxNamePrint = 4;
- static constexpr size_t kNumTsPrinted = 2;
- static constexpr size_t maxlen = kMaxNamePrint + arrayLen(kTraceNamePrefix) +
- arrayLen(kTraceNameSeparator) - 1 + (kNumTsPrinted * max64print);
- std::array<char, maxlen> str_buffer;
- void note(std::string_view name, nsecs_t in, nsecs_t vs);
- } mTraceBuffer GUARDED_BY(mMutex);
-
// For debugging purposes
nsecs_t mLastTimerCallback GUARDED_BY(mMutex) = kInvalidTime;
nsecs_t mLastTimerSchedule GUARDED_BY(mMutex) = kInvalidTime;
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index e9bd92a..61d2fb7 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -18,24 +18,27 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wextra"
+#undef LOG_TAG
+#define LOG_TAG "VSyncPredictor"
+
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-#include "VSyncPredictor.h"
+
+#include <algorithm>
+#include <chrono>
+#include <sstream>
+
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <utils/Log.h>
#include <utils/Trace.h>
-#include <algorithm>
-#include <chrono>
-#include <sstream>
-#include "RefreshRateConfigs.h"
-#undef LOG_TAG
-#define LOG_TAG "VSyncPredictor"
+#include "RefreshRateConfigs.h"
+#include "VSyncPredictor.h"
namespace android::scheduler {
+
using base::StringAppendF;
static auto constexpr kMaxPercent = 100u;
@@ -121,7 +124,8 @@
mTimestamps[mLastTimestampIndex] = timestamp;
}
- if (mTimestamps.size() < kMinimumSamplesForPrediction) {
+ const size_t numSamples = mTimestamps.size();
+ if (numSamples < kMinimumSamplesForPrediction) {
mRateMap[mIdealPeriod] = {mIdealPeriod, 0};
return true;
}
@@ -141,36 +145,44 @@
//
// intercept = mean(Y) - slope * mean(X)
//
- std::vector<nsecs_t> vsyncTS(mTimestamps.size());
- std::vector<nsecs_t> ordinals(mTimestamps.size());
+ std::vector<nsecs_t> vsyncTS(numSamples);
+ std::vector<nsecs_t> ordinals(numSamples);
- // normalizing to the oldest timestamp cuts down on error in calculating the intercept.
- auto const oldest_ts = *std::min_element(mTimestamps.begin(), mTimestamps.end());
+ // Normalizing to the oldest timestamp cuts down on error in calculating the intercept.
+ const auto oldestTS = *std::min_element(mTimestamps.begin(), mTimestamps.end());
auto it = mRateMap.find(mIdealPeriod);
auto const currentPeriod = it->second.slope;
- // TODO (b/144707443): its important that there's some precision in the mean of the ordinals
- // for the intercept calculation, so scale the ordinals by 1000 to continue
- // fixed point calculation. Explore expanding
- // scheduler::utils::calculate_mean to have a fixed point fractional part.
- static constexpr int64_t kScalingFactor = 1000;
- for (auto i = 0u; i < mTimestamps.size(); i++) {
+ // The mean of the ordinals must be precise for the intercept calculation, so scale them up for
+ // fixed-point arithmetic.
+ constexpr int64_t kScalingFactor = 1000;
+
+ nsecs_t meanTS = 0;
+ nsecs_t meanOrdinal = 0;
+
+ for (size_t i = 0; i < numSamples; i++) {
traceInt64If("VSP-ts", mTimestamps[i]);
- vsyncTS[i] = mTimestamps[i] - oldest_ts;
- ordinals[i] = ((vsyncTS[i] + (currentPeriod / 2)) / currentPeriod) * kScalingFactor;
+ const auto timestamp = mTimestamps[i] - oldestTS;
+ vsyncTS[i] = timestamp;
+ meanTS += timestamp;
+
+ const auto ordinal = (vsyncTS[i] + currentPeriod / 2) / currentPeriod * kScalingFactor;
+ ordinals[i] = ordinal;
+ meanOrdinal += ordinal;
}
- auto meanTS = scheduler::calculate_mean(vsyncTS);
- auto meanOrdinal = scheduler::calculate_mean(ordinals);
- for (size_t i = 0; i < vsyncTS.size(); i++) {
+ meanTS /= numSamples;
+ meanOrdinal /= numSamples;
+
+ for (size_t i = 0; i < numSamples; i++) {
vsyncTS[i] -= meanTS;
ordinals[i] -= meanOrdinal;
}
- auto top = 0ll;
- auto bottom = 0ll;
- for (size_t i = 0; i < vsyncTS.size(); i++) {
+ nsecs_t top = 0;
+ nsecs_t bottom = 0;
+ for (size_t i = 0; i < numSamples; i++) {
top += vsyncTS[i] * ordinals[i];
bottom += ordinals[i] * ordinals[i];
}
@@ -365,4 +377,4 @@
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 40e6944..cfaf7d6 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -16,11 +16,12 @@
#pragma once
-#include <android-base/thread_annotations.h>
#include <mutex>
#include <unordered_map>
#include <vector>
-#include "SchedulerUtils.h"
+
+#include <android-base/thread_annotations.h>
+
#include "VSyncTracker.h"
namespace android::scheduler {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3d6bcb7..3fad6de 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,7 @@
#include <private/gui/SyncFeatures.h>
#include <processgroup/processgroup.h>
#include <renderengine/RenderEngine.h>
+#include <renderengine/impl/ExternalTexture.h>
#include <sys/types.h>
#include <ui/ColorSpace.h>
#include <ui/DataspaceUtils.h>
@@ -384,7 +385,7 @@
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
mPowerAdvisor(*this),
- mWindowInfosListenerInvoker(new WindowInfosListenerInvoker(this)) {
+ mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}
@@ -1426,6 +1427,52 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getBootDisplayModeSupport(bool* outSupport) const {
+ auto future = mScheduler->schedule([=]() MAIN_THREAD mutable -> status_t {
+ *outSupport = getHwComposer().getBootDisplayModeSupport();
+ return NO_ERROR;
+ });
+ return future.get();
+}
+
+status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) {
+ auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ return getHwComposer().setBootDisplayMode(*displayId, id);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return BAD_VALUE;
+ }
+ });
+ return future.get();
+}
+
+status_t SurfaceFlinger::clearBootDisplayMode(const sp<IBinder>& displayToken) {
+ auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ return getHwComposer().clearBootDisplayMode(*displayId);
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return BAD_VALUE;
+ }
+ });
+ return future.get();
+}
+
+status_t SurfaceFlinger::getPreferredBootDisplayMode(const sp<IBinder>& displayToken,
+ ui::DisplayModeId* id) {
+ auto future = mScheduler->schedule([=]() MAIN_THREAD mutable -> status_t {
+ if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
+ *id = getHwComposer().getPreferredBootDisplayMode(*displayId);
+ return NO_ERROR;
+ } else {
+ ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
+ return BAD_VALUE;
+ }
+ });
+ return future.get();
+}
+
void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
const char* const whence = __func__;
static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD {
@@ -1605,7 +1652,7 @@
status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea,
const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) {
- if (!listener || samplingArea == Rect::INVALID_RECT) {
+ if (!listener || samplingArea == Rect::INVALID_RECT || samplingArea.isEmpty()) {
return BAD_VALUE;
}
@@ -4475,10 +4522,13 @@
}
}
- if (what & layer_state_t::eBufferChanged &&
- layer->setBuffer(*s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
- dequeueBufferTimestamp, frameTimelineInfo)) {
- flags |= eTraversalNeeded;
+ if (what & layer_state_t::eBufferChanged) {
+ std::shared_ptr<renderengine::ExternalTexture> buffer =
+ getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName());
+ if (layer->setBuffer(buffer, *s.bufferData, postTime, desiredPresentTime, isAutoTimestamp,
+ dequeueBufferTimestamp, frameTimelineInfo)) {
+ flags |= eTraversalNeeded;
+ }
} else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime);
}
@@ -5404,6 +5454,10 @@
case SET_DESIRED_DISPLAY_MODE_SPECS:
case GET_DESIRED_DISPLAY_MODE_SPECS:
case SET_ACTIVE_COLOR_MODE:
+ case GET_BOOT_DISPLAY_MODE_SUPPORT:
+ case SET_BOOT_DISPLAY_MODE:
+ case CLEAR_BOOT_DISPLAY_MODE:
+ case GET_PREFERRED_BOOT_DISPLAY_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
case SET_AUTO_LOW_LATENCY_MODE:
case GET_GAME_CONTENT_TYPE_SUPPORT:
@@ -6440,9 +6494,10 @@
const status_t bufferStatus = buffer->initCheck();
LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d",
bufferStatus);
- const auto texture = std::make_shared<
- renderengine::ExternalTexture>(buffer, getRenderEngine(),
- renderengine::ExternalTexture::Usage::WRITEABLE);
+ const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared<
+ renderengine::impl::ExternalTexture>(buffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::Usage::
+ WRITEABLE);
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture,
false /* regionSampling */, grayscale, captureListener);
}
@@ -6519,7 +6574,7 @@
captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure());
});
- const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED;
+ const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
// We allow the system server to take screenshots of secure layers for
// use in situations like the Screen-rotation animation and place
@@ -7130,6 +7185,36 @@
return NO_ERROR;
}
+std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextureFromBufferData(
+ const BufferData& bufferData, const char* layerName) const {
+ bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged);
+ bool bufferSizeExceedsLimit = false;
+ std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
+ if (cacheIdChanged && bufferData.buffer != nullptr) {
+ bufferSizeExceedsLimit = 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 = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(),
+ bufferData.buffer->getHeight());
+ if (!bufferSizeExceedsLimit) {
+ buffer = std::make_shared<
+ renderengine::impl::ExternalTexture>(bufferData.buffer, getRenderEngine(),
+ renderengine::impl::ExternalTexture::
+ Usage::READABLE);
+ }
+ }
+ ALOGE_IF(bufferSizeExceedsLimit,
+ "Attempted to create an ExternalTexture for layer %s that exceeds render target size "
+ "limit.",
+ layerName);
+ return buffer;
+}
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 61cfb4e..7349238 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -326,6 +326,9 @@
virtual void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState&)
REQUIRES(mStateLock);
+ virtual std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
+ const BufferData& bufferData, const char* layerName) const;
+
// Returns true if any display matches a `bool(const DisplayDevice&)` predicate.
template <typename Predicate>
bool hasDisplay(Predicate p) const REQUIRES(mStateLock) {
@@ -531,6 +534,11 @@
status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
ui::DisplayPrimaries&) override;
status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+ status_t getBootDisplayModeSupport(bool* outSupport) const override;
+ status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) override;
+ status_t clearBootDisplayMode(const sp<IBinder>& displayToken) override;
+ status_t getPreferredBootDisplayMode(const sp<IBinder>& displayToken,
+ ui::DisplayModeId* id) override;
void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) override;
void setGameContentType(const sp<IBinder>& displayToken, bool on) override;
void setPowerMode(const sp<IBinder>& displayToken, int mode) override;
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index b93d127..72434e9 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -25,24 +25,21 @@
using gui::IWindowInfosListener;
using gui::WindowInfo;
-struct WindowInfosReportedListener : gui::BnWindowInfosReportedListener {
- explicit WindowInfosReportedListener(std::function<void()> listenerCb)
- : mListenerCb(listenerCb) {}
+struct WindowInfosListenerInvoker::WindowInfosReportedListener
+ : gui::BnWindowInfosReportedListener {
+ explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {}
binder::Status onWindowInfosReported() override {
- if (mListenerCb != nullptr) {
- mListenerCb();
- }
+ mInvoker.windowInfosReported();
return binder::Status::ok();
}
- std::function<void()> mListenerCb;
+ WindowInfosListenerInvoker& mInvoker;
};
-WindowInfosListenerInvoker::WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf) : mSf(sf) {
- mWindowInfosReportedListener =
- new WindowInfosReportedListener([&]() { windowInfosReported(); });
-}
+WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger)
+ : mFlinger(flinger),
+ mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {}
void WindowInfosListenerInvoker::addWindowInfosListener(
const sp<IWindowInfosListener>& windowInfosListener) {
@@ -91,8 +88,8 @@
void WindowInfosListenerInvoker::windowInfosReported() {
mCallbacksPending--;
if (mCallbacksPending == 0) {
- mSf->windowInfosReported();
+ mFlinger.windowInfosReported();
}
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index 4e08393..2eabf48 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -31,7 +31,8 @@
class WindowInfosListenerInvoker : public IBinder::DeathRecipient {
public:
- WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf);
+ explicit WindowInfosListenerInvoker(SurfaceFlinger&);
+
void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
@@ -42,13 +43,15 @@
void binderDied(const wp<IBinder>& who) override;
private:
+ struct WindowInfosReportedListener;
void windowInfosReported();
- const sp<SurfaceFlinger> mSf;
+ SurfaceFlinger& mFlinger;
std::mutex mListenersMutex;
std::unordered_map<wp<IBinder>, const sp<gui::IWindowInfosListener>, WpHash>
mWindowInfosListeners GUARDED_BY(mListenersMutex);
sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener;
std::atomic<size_t> mCallbacksPending{0};
};
-} // namespace android
\ No newline at end of file
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index bba880e..c053d43 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -82,7 +82,6 @@
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
"SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
"SchedulerTest.cpp",
- "SchedulerUtilsTest.cpp",
"SetFrameRateTest.cpp",
"RefreshRateConfigsTest.cpp",
"RefreshRateSelectionTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 6c96d5f..3716f59 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -30,6 +30,7 @@
#include <gui/IProducerListener.h>
#include <gui/LayerMetadata.h>
#include <log/log.h>
+#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/Framebuffer.h>
#include <renderengine/mock/Image.h>
#include <renderengine/mock/RenderEngine.h>
@@ -143,11 +144,10 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
- constexpr scheduler::ISchedulerCallback* kCallback = nullptr;
- constexpr bool kHasMultipleConfigs = true;
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
- std::move(eventThread), std::move(sfEventThread), kCallback,
- kHasMultipleConfigs);
+ std::move(eventThread), std::move(sfEventThread),
+ TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+ TestableSurfaceFlinger::kTwoDisplayModes);
}
void setupForceGeometryDirty() {
@@ -234,15 +234,13 @@
CaptureArgs::UNSET_UID, visitor);
};
- // TODO: Eliminate expensive/real allocation if possible.
const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
- mCaptureScreenBuffer = std::make_shared<
- renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(),
- renderArea->getReqHeight(),
- HAL_PIXEL_FORMAT_RGBA_8888, 1, usage,
- "screenshot"),
- *mRenderEngine, true);
+ mCaptureScreenBuffer =
+ std::make_shared<renderengine::mock::FakeExternalTexture>(renderArea->getReqWidth(),
+ renderArea->getReqHeight(),
+ HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ usage);
auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer,
forSystem, regionSampling);
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index 5a0033e..40a9b1a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -44,8 +44,8 @@
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
- .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120})
- .setActiveMode(kDisplayModeId60)
+ .setDisplayModes({kDisplayMode60, kDisplayMode90, kDisplayMode120},
+ kDisplayModeId60)
.inject();
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index c318e28..2425862 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -77,7 +77,8 @@
mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController),
std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker),
std::unique_ptr<EventThread>(mEventThread),
- std::unique_ptr<EventThread>(mSFEventThread), &mSchedulerCallback);
+ std::unique_ptr<EventThread>(mSFEventThread),
+ TestableSurfaceFlinger::SchedulerCallbackImpl::kMock);
}
void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 69ac26e..45eceff 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -48,7 +48,6 @@
#include "mock/DisplayHardware/MockPowerAdvisor.h"
#include "mock/MockEventThread.h"
#include "mock/MockNativeWindowSurface.h"
-#include "mock/MockSchedulerCallback.h"
#include "mock/MockSurfaceInterceptor.h"
#include "mock/MockVsyncController.h"
#include "mock/system/window/MockNativeWindow.h"
@@ -121,7 +120,6 @@
mock::VsyncController* mVsyncController = new mock::VsyncController;
mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
- scheduler::mock::SchedulerCallback mSchedulerCallback;
mock::EventThread* mEventThread = new mock::EventThread;
mock::EventThread* mSFEventThread = new mock::EventThread;
diff --git a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp
deleted file mode 100644
index 5f6a715..0000000
--- a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#undef LOG_TAG
-#define LOG_TAG "SchedulerUnittests"
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <array>
-
-#include "Scheduler/SchedulerUtils.h"
-
-namespace android {
-namespace scheduler {
-
-class SchedulerUtilsTest : public testing::Test {
-public:
- SchedulerUtilsTest() = default;
- ~SchedulerUtilsTest() override = default;
-};
-
-namespace {
-TEST_F(SchedulerUtilsTest, calculate_mean) {
- std::array<int64_t, 30> testArray{};
- // Calling the function on empty array returns 0.
- EXPECT_EQ(0, calculate_mean(testArray));
-
- testArray[0] = 33;
- EXPECT_EQ(1, calculate_mean(testArray));
- testArray[1] = 33;
- testArray[2] = 33;
- EXPECT_EQ(3, calculate_mean(testArray));
- testArray[3] = 42;
- EXPECT_EQ(4, calculate_mean(testArray));
- testArray[4] = 33;
- EXPECT_EQ(5, calculate_mean(testArray));
- testArray[5] = 42;
- EXPECT_EQ(7, calculate_mean(testArray));
- for (int i = 6; i < 30; i++) {
- testArray[i] = 33;
- }
- EXPECT_EQ(33, calculate_mean(testArray));
-}
-
-TEST_F(SchedulerUtilsTest, calculate_median) {
- std::vector<int64_t> testVector;
- // Calling the function on empty vector returns 0.
- EXPECT_EQ(0, calculate_median(&testVector));
-
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(33);
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_median(&testVector));
- testVector.push_back(42);
- EXPECT_EQ(42, calculate_median(&testVector));
- testVector.push_back(60);
- EXPECT_EQ(42, calculate_median(&testVector));
- testVector.push_back(60);
- EXPECT_EQ(42, calculate_median(&testVector));
- testVector.push_back(33);
- EXPECT_EQ(42, calculate_median(&testVector));
- testVector.push_back(33);
- EXPECT_EQ(42, calculate_median(&testVector));
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_median(&testVector));
-}
-
-TEST_F(SchedulerUtilsTest, calculate_mode) {
- std::vector<int64_t> testVector;
- // Calling the function on empty vector returns 0.
- EXPECT_EQ(0, calculate_mode(testVector));
-
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(33);
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(33);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(60);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(60);
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(33);
- // 5 occurences of 33.
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- // 5 occurences of 33, 5 occurences of 42. We choose the first one.
- EXPECT_EQ(33, calculate_mode(testVector));
- testVector.push_back(42);
- // 5 occurences of 33, 6 occurences of 42.
- EXPECT_EQ(42, calculate_mode(testVector));
- testVector.push_back(42);
- // 5 occurences of 33, 7 occurences of 42.
- EXPECT_EQ(42, calculate_mode(testVector));
-}
-
-} // namespace
-} // namespace scheduler
-} // namespace android
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index fe5f9e0..2b69f13 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -164,8 +164,9 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
- std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr,
- /*hasMultipleModes*/ true);
+ std::move(eventThread), std::move(sfEventThread),
+ TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+ TestableSurfaceFlinger::kTwoDisplayModes);
}
namespace {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 56a0506..3205952 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -42,13 +42,18 @@
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
- mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
- .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120,
- kDisplayMode90DifferentResolution})
- .setActiveMode(kDisplayModeId60)
- .inject();
+ {
+ DisplayModes modes = {kDisplayMode60, kDisplayMode90, kDisplayMode120,
+ kDisplayMode90DifferentResolution};
+ const DisplayModeId activeModeId = kDisplayModeId60;
+ auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
- setupScheduler();
+ mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
+ .setDisplayModes(modes, activeModeId, std::move(configs))
+ .inject();
+ }
+
+ setupScheduler(mDisplay->holdRefreshRateConfigs());
// isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
// will call setActiveConfig instead of setActiveConfigWithConstraints.
@@ -57,7 +62,7 @@
}
protected:
- void setupScheduler();
+ void setupScheduler(std::shared_ptr<scheduler::RefreshRateConfigs>);
void testChangeRefreshRate(bool isDisplayActive, bool isRefreshRequired);
sp<DisplayDevice> mDisplay;
@@ -108,7 +113,8 @@
.build();
};
-void DisplayModeSwitchingTest::setupScheduler() {
+void DisplayModeSwitchingTest::setupScheduler(
+ std::shared_ptr<scheduler::RefreshRateConfigs> configs) {
auto eventThread = std::make_unique<mock::EventThread>();
mAppEventThread = eventThread.get();
auto sfEventThread = std::make_unique<mock::EventThread>();
@@ -132,8 +138,9 @@
Return(TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
- std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr,
- /*hasMultipleModes*/ true);
+ std::move(eventThread), std::move(sfEventThread),
+ TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp,
+ std::move(configs));
}
TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRequired) {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index b57feff..7948e60 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -61,7 +61,7 @@
struct EventThreadBaseSupportedVariant {
static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) {
// The callback should not be notified to toggle VSYNC.
- EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0);
+ EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(_)).Times(0);
// The event thread should not be notified.
EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0);
@@ -88,7 +88,7 @@
struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant {
static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) {
// The callback should be notified to enable VSYNC.
- EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1);
+ EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(true)).Times(1);
// The event thread should be notified that the screen was acquired.
EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1);
@@ -96,7 +96,7 @@
static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) {
// The callback should be notified to disable VSYNC.
- EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1);
+ EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(false)).Times(1);
// The event thread should not be notified that the screen was released.
EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1);
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 361d629..d292e08 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,6 +16,9 @@
#pragma once
+#include <algorithm>
+#include <variant>
+
#include <compositionengine/Display.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
@@ -24,7 +27,6 @@
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/mock/DisplaySurface.h>
#include <gui/ScreenCaptureResults.h>
-#include <algorithm>
#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
@@ -45,6 +47,7 @@
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
+#include "mock/MockSchedulerCallback.h"
namespace android {
@@ -170,7 +173,7 @@
} // namespace surfaceflinger::test
-class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback {
+class TestableSurfaceFlinger {
public:
using HotplugEvent = SurfaceFlinger::HotplugEvent;
@@ -193,42 +196,64 @@
mFlinger->mCompositionEngine->setTimeStats(timeStats);
}
- // The ISchedulerCallback argument can be nullptr for a no-op implementation.
+ enum class SchedulerCallbackImpl { kNoOp, kMock };
+
+ static constexpr struct OneDisplayMode {
+ } kOneDisplayMode;
+
+ static constexpr struct TwoDisplayModes {
+ } kTwoDisplayModes;
+
+ using RefreshRateConfigsPtr = std::shared_ptr<scheduler::RefreshRateConfigs>;
+
+ using DisplayModesVariant =
+ std::variant<OneDisplayMode, TwoDisplayModes, RefreshRateConfigsPtr>;
+
void setupScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController,
std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
- scheduler::ISchedulerCallback* callback = nullptr,
- bool hasMultipleModes = false) {
- DisplayModes modes{DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(16'666'667)
- .setGroup(0)
- .build()};
+ SchedulerCallbackImpl callbackImpl = SchedulerCallbackImpl::kNoOp,
+ DisplayModesVariant modesVariant = kOneDisplayMode) {
+ RefreshRateConfigsPtr configs;
+ if (std::holds_alternative<RefreshRateConfigsPtr>(modesVariant)) {
+ configs = std::move(std::get<RefreshRateConfigsPtr>(modesVariant));
+ } else {
+ DisplayModes modes = {DisplayMode::Builder(0)
+ .setId(DisplayModeId(0))
+ .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+ .setVsyncPeriod(16'666'667)
+ .setGroup(0)
+ .build()};
- if (hasMultipleModes) {
- modes.emplace_back(DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setVsyncPeriod(11'111'111)
- .setGroup(0)
- .build());
+ if (std::holds_alternative<TwoDisplayModes>(modesVariant)) {
+ modes.emplace_back(DisplayMode::Builder(1)
+ .setId(DisplayModeId(1))
+ .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+ .setVsyncPeriod(11'111'111)
+ .setGroup(0)
+ .build());
+ }
+
+ configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, DisplayModeId(0));
}
- const auto currMode = DisplayModeId(0);
- mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
- const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ const auto currFps = configs->getCurrentRefreshRate().getFps();
mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
mFlinger->mVsyncConfiguration->getCurrentConfigs());
mFlinger->mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
- /*powerMode=*/hal::PowerMode::OFF);
+ hal::PowerMode::OFF);
+
+ using Callback = scheduler::ISchedulerCallback;
+ Callback& callback = callbackImpl == SchedulerCallbackImpl::kNoOp
+ ? static_cast<Callback&>(mNoOpSchedulerCallback)
+ : static_cast<Callback&>(mSchedulerCallback);
mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
- std::move(vsyncTracker), mRefreshRateConfigs,
- *(callback ?: this));
+ std::move(vsyncTracker), std::move(configs),
+ callback);
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
@@ -237,7 +262,8 @@
void resetScheduler(scheduler::Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); }
- scheduler::TestableScheduler& mutableScheduler() const { return *mScheduler; }
+ scheduler::TestableScheduler& mutableScheduler() { return *mScheduler; }
+ scheduler::mock::SchedulerCallback& mockSchedulerCallback() { return mSchedulerCallback; }
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
@@ -662,23 +688,6 @@
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
-
- mCreationArgs.activeModeId = DisplayModeId(0);
- DisplayModePtr activeMode =
- DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
- .setId(mCreationArgs.activeModeId)
- .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
- .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
- .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
- .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
- .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
- .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
- .setGroup(0)
- .build();
-
- DisplayModes modes{activeMode};
- mCreationArgs.supportedModes = modes;
- mCreationArgs.refreshRateConfigs = flinger.mRefreshRateConfigs;
}
sp<IBinder> token() const { return mDisplayToken; }
@@ -701,13 +710,16 @@
auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
- auto& setActiveMode(DisplayModeId mode) {
- mCreationArgs.activeModeId = mode;
- return *this;
- }
-
- auto& setSupportedModes(DisplayModes mode) {
- mCreationArgs.supportedModes = mode;
+ // If `configs` is nullptr, the injector creates RefreshRateConfigs from the `modes`.
+ // Otherwise, it uses `configs`, which the caller must create using the same `modes`.
+ //
+ // TODO(b/182939859): Once `modes` can be retrieved from RefreshRateConfigs, remove
+ // the `configs` parameter in favor of an alternative setRefreshRateConfigs API.
+ auto& setDisplayModes(DisplayModes modes, DisplayModeId activeModeId,
+ std::shared_ptr<scheduler::RefreshRateConfigs> configs = nullptr) {
+ mCreationArgs.supportedModes = std::move(modes);
+ mCreationArgs.activeModeId = activeModeId;
+ mCreationArgs.refreshRateConfigs = std::move(configs);
return *this;
}
@@ -749,39 +761,58 @@
}
sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS {
- const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
+ auto& modes = mCreationArgs.supportedModes;
+ auto& activeModeId = mCreationArgs.activeModeId;
+
+ if (!mCreationArgs.refreshRateConfigs) {
+ if (modes.empty()) {
+ activeModeId = DisplayModeId(0);
+ modes.emplace_back(
+ DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+ .setId(activeModeId)
+ .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+ .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+ .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+ .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+ .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setGroup(0)
+ .build());
+ }
+
+ mCreationArgs.refreshRateConfigs =
+ std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId);
+ }
DisplayDeviceState state;
if (const auto type = mCreationArgs.connectionType) {
+ const auto displayId = mCreationArgs.compositionDisplay->getDisplayId();
LOG_ALWAYS_FATAL_IF(!displayId);
const auto physicalId = PhysicalDisplayId::tryCast(*displayId);
LOG_ALWAYS_FATAL_IF(!physicalId);
LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
- const DisplayModePtr activeModePtr =
- *std::find_if(mCreationArgs.supportedModes.begin(),
- mCreationArgs.supportedModes.end(), [&](DisplayModePtr mode) {
- return mode->getId() == mCreationArgs.activeModeId;
- });
+ const auto it = std::find_if(modes.begin(), modes.end(),
+ [&activeModeId](const DisplayModePtr& mode) {
+ return mode->getId() == activeModeId;
+ });
+ LOG_ALWAYS_FATAL_IF(it == modes.end());
+
state.physical = {.id = *physicalId,
.type = *type,
.hwcDisplayId = *mHwcDisplayId,
.deviceProductInfo = {},
- .supportedModes = mCreationArgs.supportedModes,
- .activeMode = activeModePtr};
+ .supportedModes = modes,
+ .activeMode = *it};
}
state.isSecure = mCreationArgs.isSecure;
- mCreationArgs.refreshRateConfigs =
- std::make_shared<scheduler::RefreshRateConfigs>(mCreationArgs.supportedModes,
- mCreationArgs.activeModeId);
-
- sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
- if (!device->isVirtual()) {
- device->setActiveMode(mCreationArgs.activeModeId);
+ sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs);
+ if (!display->isVirtual()) {
+ display->setActiveMode(activeModeId);
}
- mFlinger.mutableDisplays().emplace(mDisplayToken, device);
+ mFlinger.mutableDisplays().emplace(mDisplayToken, display);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -789,7 +820,7 @@
mFlinger.mutablePhysicalDisplayTokens()[physical->id] = mDisplayToken;
}
- return device;
+ return display;
}
private:
@@ -800,16 +831,12 @@
};
private:
- void scheduleComposite(FrameHint) override {}
- void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
- void kernelTimerChanged(bool) override {}
- void triggerOnFrameRateOverridesChanged() {}
-
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
+
+ scheduler::mock::SchedulerCallback mSchedulerCallback;
+ scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback;
scheduler::TestableScheduler* mScheduler = nullptr;
- std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index deeb785..5364630 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -22,6 +22,7 @@
#include <gui/SurfaceComposerClient.h>
#include <log/log.h>
#include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <utils/String8.h>
@@ -101,9 +102,8 @@
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
- const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
int32_t layerId = layer->getSequence();
- uint64_t bufferId = buffer->getId();
+ uint64_t bufferId = 42;
uint64_t frameNumber = 5;
nsecs_t dequeueTime = 10;
nsecs_t postTime = 20;
@@ -115,13 +115,16 @@
traceTimestamp(layerId, bufferId, frameNumber, postTime,
FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
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{});
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, bufferId,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, 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 704340d..5bb4c92 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -22,6 +22,7 @@
#include <gui/SurfaceComposerClient.h>
#include <log/log.h>
#include <renderengine/ExternalTexture.h>
+#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <utils/String8.h>
@@ -114,14 +115,17 @@
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence->signalForTest(12);
@@ -145,14 +149,17 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -160,14 +167,17 @@
sp<Fence> fence2(new Fence());
auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
- const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
nsecs_t start = systemTime();
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 2ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
nsecs_t end = systemTime();
acquireFence2->signalForTest(12);
@@ -203,14 +213,17 @@
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence->signalForTest(12);
@@ -234,14 +247,17 @@
sp<BufferStateLayer> layer = createBufferStateLayer();
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -269,14 +285,17 @@
sp<Fence> fence(new Fence());
auto acquireFence = fenceFactory.createFenceTimeForTest(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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 3, /*inputEventId*/ 0});
EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -310,27 +329,33 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture1, 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 = 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
acquireFence2->signalForTest(12);
@@ -356,14 +381,17 @@
sp<Fence> fence1(new Fence());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture1 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -371,14 +399,17 @@
sp<Fence> fence2(new Fence());
auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
- const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
auto dropStartTime1 = systemTime();
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture2 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
auto dropEndTime1 = systemTime();
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -387,14 +418,17 @@
sp<Fence> fence3(new Fence());
auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
- const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0);
auto dropStartTime2 = systemTime();
- 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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture3 = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture3, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 2, /*inputEventId*/ 0});
auto dropEndTime2 = systemTime();
acquireFence3->signalForTest(12);
@@ -432,14 +466,17 @@
std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> bufferlessSurfaceFrames;
for (int i = 0; i < 10; i += 2) {
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,
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0ULL /*usage*/);
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
{/*vsyncId*/ 1, /*inputEventId*/ 0});
layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
/*inputEventId*/ 0},
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index ecdadf7..4273401 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -135,6 +135,10 @@
V2_4::Error(Display, Config, const IComposerClient::VsyncPeriodChangeConstraints&,
VsyncPeriodChangeTimeline*));
MOCK_METHOD2(setAutoLowLatencyMode, V2_4::Error(Display, bool));
+ MOCK_METHOD2(getBootDisplayConfigSupport, Error(Display, bool*));
+ MOCK_METHOD2(setBootDisplayConfig, Error(Display, Config));
+ MOCK_METHOD1(clearBootDisplayConfig, Error(Display));
+ MOCK_METHOD2(getPreferredBootDisplayConfig, Error(Display, Config*));
MOCK_METHOD2(getSupportedContentTypes,
V2_4::Error(Display, std::vector<IComposerClient::ContentType>*));
MOCK_METHOD2(setContentType, V2_4::Error(Display, IComposerClient::ContentType));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 7ac0c78..9015944 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -86,6 +86,9 @@
(hal::HWConfigId, const hal::VsyncPeriodChangeConstraints &,
hal::VsyncPeriodChangeTimeline *),
(override));
+ MOCK_METHOD(hal::Error, setBootDisplayConfig, (hal::HWConfigId), (override));
+ MOCK_METHOD(hal::Error, clearBootDisplayConfig, (), (override));
+ MOCK_METHOD(hal::Error, getPreferredBootDisplayConfig, (hal::HWConfigId *), (const, override));
MOCK_METHOD(hal::Error, setAutoLowLatencyMode, (bool), (override));
MOCK_METHOD(hal::Error, getSupportedContentTypes, (std::vector<hal::ContentType> *),
(const, override));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index 849e308..c90b8ed 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -35,7 +35,7 @@
void setVsyncEnabled(bool) override {}
void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
void kernelTimerChanged(bool) override {}
- void triggerOnFrameRateOverridesChanged() {}
+ void triggerOnFrameRateOverridesChanged() override {}
};
} // namespace android::scheduler::mock