Merge "Fuzzer for libbinder(_ndk)/libhwbinder"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d9c9e4a..302d491 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1057,7 +1057,7 @@
std::string path(title);
path.append(" - ").append(String8(service).c_str());
size_t bytes_written = 0;
- status_t status = dumpsys.startDumpThread(service, /* dumpPid = */ true, args);
+ status_t status = dumpsys.startDumpThread(service, args);
if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
std::chrono::duration<double> elapsed_seconds;
@@ -1129,7 +1129,7 @@
path.append("_HIGH");
}
path.append(kProtoExt);
- status_t status = dumpsys.startDumpThread(service, /* dumpPid = */ false, args);
+ status_t status = dumpsys.startDumpThread(service, args);
if (status == OK) {
status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
bool dumpTerminated = (status == OK);
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index 68b3907..9f65425 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -201,7 +201,13 @@
if (i == optind) {
services.add(String16(argv[i]));
} else {
- args.add(String16(argv[i]));
+ const String16 arg(argv[i]);
+ args.add(arg);
+ // For backward compatible, if the proto argument is passed to the service, the
+ // dump request is also considered to use proto.
+ if (!asProto && !arg.compare(String16(PriorityDumper::PROTO_ARG))) {
+ asProto = true;
+ }
}
}
}
@@ -236,13 +242,11 @@
return 0;
}
- const bool dumpPid = !asProto;
-
for (size_t i = 0; i < N; i++) {
const String16& serviceName = services[i];
if (IsSkipped(skippedServices, serviceName)) continue;
- if (startDumpThread(serviceName, dumpPid, args) == OK) {
+ if (startDumpThread(serviceName, args) == OK) {
bool addSeparator = (N > 1);
if (addSeparator) {
writeDumpHeader(STDOUT_FILENO, serviceName, priorityFlags);
@@ -309,7 +313,7 @@
}
}
-status_t Dumpsys::startDumpThread(const String16& serviceName, bool dumpPid, const Vector<String16>& args) {
+status_t Dumpsys::startDumpThread(const String16& serviceName, const Vector<String16>& args) {
sp<IBinder> service = sm_->checkService(serviceName);
if (service == nullptr) {
aerr << "Can't find service: " << serviceName << endl;
@@ -329,20 +333,7 @@
// dump blocks until completion, so spawn a thread..
activeThread_ = std::thread([=, remote_end{std::move(remote_end)}]() mutable {
- if (dumpPid) {
- pid_t pid;
- status_t status = service->getDebugPid(&pid);
- if (status == OK) {
- std::ostringstream pidinfo;
- pidinfo << "Pid: " << pid << std::endl;
- WriteStringToFd(pidinfo.str(), remote_end.get());
- } else {
- aerr << "Error getting pid status_t (" << status << "): "
- << serviceName << endl;
- }
- }
-
- status_t err = service->dump(remote_end.get(), args);
+ int err = service->dump(remote_end.get(), args);
// It'd be nice to be able to close the remote end of the socketpair before the dump
// call returns, to terminate our reads if the other end closes their copy of the
@@ -350,8 +341,8 @@
// way to do this, though.
remote_end.reset();
- if (err != OK) {
- aerr << "Error dumping service info status_t (" << err << "): "
+ if (err != 0) {
+ aerr << "Error dumping service info: (" << strerror(err) << ") "
<< serviceName << endl;
}
});
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 8d1291a..c48a1e9 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -56,13 +56,12 @@
* the output to a pipe. Thread must be stopped by a subsequent callto {@code
* stopDumpThread}.
* @param serviceName
- * @param dumpPid whether to include a header with service PID information
* @param args list of arguments to pass to service dump method.
* @return {@code OK} thread is started successfully.
* {@code NAME_NOT_FOUND} service could not be found.
* {@code != OK} error
*/
- status_t startDumpThread(const String16& serviceName, bool dumpPid, const Vector<String16>& args);
+ status_t startDumpThread(const String16& serviceName, const Vector<String16>& args);
/**
* Writes a section header to a file descriptor.
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index d0b167e..cbac839 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -188,6 +188,22 @@
EXPECT_THAT(status, Eq(0));
}
+ void CallSingleService(const String16& serviceName, Vector<String16>& args, int priorityFlags,
+ bool supportsProto, std::chrono::duration<double>& elapsedDuration,
+ size_t& bytesWritten) {
+ CaptureStdout();
+ CaptureStderr();
+ dump_.setServiceArgs(args, supportsProto, priorityFlags);
+ status_t status = dump_.startDumpThread(serviceName, args);
+ EXPECT_THAT(status, Eq(0));
+ status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false,
+ elapsedDuration, bytesWritten);
+ EXPECT_THAT(status, Eq(0));
+ dump_.stopDumpThread(/* dumpCompleted = */ true);
+ stdout_ = GetCapturedStdout();
+ stderr_ = GetCapturedStderr();
+ }
+
void AssertRunningServices(const std::vector<std::string>& services) {
std::string expected;
if (services.size() > 1) {
@@ -199,13 +215,16 @@
EXPECT_THAT(stdout_, HasSubstr(expected));
}
+ void AssertOutput(const std::string& expected) {
+ EXPECT_THAT(stdout_, StrEq(expected));
+ }
+
void AssertOutputContains(const std::string& expected) {
EXPECT_THAT(stdout_, HasSubstr(expected));
}
void AssertDumped(const std::string& service, const std::string& dump) {
- EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n"));
- EXPECT_THAT(stdout_, HasSubstr(dump));
+ EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
}
@@ -213,8 +232,7 @@
const char16_t* priorityType) {
std::string priority = String8(priorityType).c_str();
EXPECT_THAT(stdout_,
- HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n"));
- EXPECT_THAT(stdout_, HasSubstr(dump));
+ HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump));
EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
}
@@ -295,8 +313,7 @@
CallMain({"Valet"});
- AssertOutputContains("Pid: " + std::to_string(getpid()));
- AssertOutputContains("Here's your car");
+ AssertOutput("Here's your car");
}
// Tests 'dumpsys -t 1 service_name' on a service that times out after 2s
@@ -331,7 +348,7 @@
CallMain({"SERVICE", "Y", "U", "NO", "HANDLE", "ARGS"});
- AssertOutputContains("I DO!");
+ AssertOutput("I DO!");
}
// Tests dumpsys passes the -a flag when called on all services
@@ -522,6 +539,23 @@
AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH);
}
+TEST_F(DumpsysTest, GetBytesWritten) {
+ const char* serviceName = "service2";
+ const char* dumpContents = "dump1";
+ ExpectDump(serviceName, dumpContents);
+
+ String16 service(serviceName);
+ Vector<String16> args;
+ std::chrono::duration<double> elapsedDuration;
+ size_t bytesWritten;
+
+ CallSingleService(service, args, IServiceManager::DUMP_FLAG_PRIORITY_ALL,
+ /* as_proto = */ false, elapsedDuration, bytesWritten);
+
+ AssertOutput(dumpContents);
+ EXPECT_THAT(bytesWritten, Eq(strlen(dumpContents)));
+}
+
TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) {
std::chrono::duration<double> elapsedDuration;
size_t bytesWritten;
@@ -529,4 +563,4 @@
dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500),
/* as_proto = */ false, elapsedDuration, bytesWritten);
EXPECT_THAT(status, Eq(INVALID_OPERATION));
-}
+}
\ No newline at end of file
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index dd51898..4026f29 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -832,7 +832,7 @@
};
LOG(DEBUG) << "Copying " << from << " to " << to;
- return android_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, true);
+ return logwrap_fork_execvp(ARRAY_SIZE(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
}
binder::Status InstalldNativeService::snapshotAppData(
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index dd4c55d..f39f066 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -827,11 +827,14 @@
drawMesh(mesh);
// The middle part of the layer can turn off blending.
- const Rect middleRect(bounds.left, bounds.top + radius, bounds.right, bounds.bottom - radius);
- setScissor(middleRect);
- mState.cornerRadius = 0.0;
- disableBlending();
- drawMesh(mesh);
+ if (topRect.bottom < bottomRect.top) {
+ const Rect middleRect(bounds.left, bounds.top + radius, bounds.right,
+ bounds.bottom - radius);
+ setScissor(middleRect);
+ mState.cornerRadius = 0.0;
+ disableBlending();
+ drawMesh(mesh);
+ }
disableScissor();
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 693e48e..48a68af 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -72,15 +72,13 @@
"libarect",
],
header_libs: [
+ "bionic_libc_platform_headers",
"gl_headers",
"libsystem_headers",
"libhardware_headers",
"libnativebase_headers",
],
export_header_lib_headers: ["gl_headers"],
-
- // we need to access the private Bionic header <bionic_tls.h>
- include_dirs: ["bionic/libc/private"],
}
//##############################################################################
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 63a0e14..86fec21 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -46,7 +46,7 @@
#define MAX_NUMBER_OF_GL_EXTENSIONS 256
-#include <bionic_tls.h> /* special private C library header */
+#include <bionic/tls.h> /* special private C library header */
// ----------------------------------------------------------------------------
namespace android {
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index 19c8b37..8bfe517 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -28,9 +28,11 @@
],
include_dirs: [
- "bionic/libc/private",
"frameworks/native/opengl/libs",
"frameworks/native/opengl/libs/EGL",
],
+ header_libs: [
+ "bionic_libc_platform_headers",
+ ],
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 3830b07..48d1471 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -17,9 +17,12 @@
#pragma once
#include <cstdint>
+#include <iterator>
#include <optional>
#include <string>
+#include <type_traits>
#include <unordered_map>
+#include <utility>
#include <compositionengine/LayerFE.h>
#include <renderengine/LayerSettings.h>
@@ -55,10 +58,67 @@
*/
class Output {
public:
- using OutputLayers = std::vector<std::unique_ptr<compositionengine::OutputLayer>>;
using ReleasedLayers = std::vector<wp<LayerFE>>;
using UniqueFELayerStateMap = std::unordered_map<LayerFE*, LayerFECompositionState*>;
+ // A helper class for enumerating the output layers using a C++11 ranged-based for loop
+ template <typename T>
+ class OutputLayersEnumerator {
+ public:
+ // TODO(lpique): Consider turning this into a C++20 view when possible.
+ template <bool IsConstIter>
+ class IteratorImpl {
+ public:
+ // Required definitions to be considered an iterator
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = decltype(std::declval<T>().getOutputLayerOrderedByZByIndex(0));
+ using difference_type = std::ptrdiff_t;
+ using pointer = std::conditional_t<IsConstIter, const value_type*, value_type*>;
+ using reference = std::conditional_t<IsConstIter, const value_type&, value_type&>;
+
+ IteratorImpl() = default;
+ IteratorImpl(const T* output, size_t index) : mOutput(output), mIndex(index) {}
+
+ value_type operator*() const {
+ return mOutput->getOutputLayerOrderedByZByIndex(mIndex);
+ }
+ value_type operator->() const {
+ return mOutput->getOutputLayerOrderedByZByIndex(mIndex);
+ }
+
+ bool operator==(const IteratorImpl& other) const {
+ return mOutput == other.mOutput && mIndex == other.mIndex;
+ }
+ bool operator!=(const IteratorImpl& other) const { return !operator==(other); }
+
+ IteratorImpl& operator++() {
+ ++mIndex;
+ return *this;
+ }
+ IteratorImpl operator++(int) {
+ auto prev = *this;
+ ++mIndex;
+ return prev;
+ }
+
+ private:
+ const T* mOutput{nullptr};
+ size_t mIndex{0};
+ };
+
+ using iterator = IteratorImpl<false>;
+ using const_iterator = IteratorImpl<true>;
+
+ explicit OutputLayersEnumerator(const T& output) : mOutput(output) {}
+ auto begin() const { return iterator(&mOutput, 0); }
+ auto end() const { return iterator(&mOutput, mOutput.getOutputLayerCount()); }
+ auto cbegin() const { return const_iterator(&mOutput, 0); }
+ auto cend() const { return const_iterator(&mOutput, mOutput.getOutputLayerCount()); }
+
+ private:
+ const T& mOutput;
+ };
+
struct FrameFences {
sp<Fence> presentFence{Fence::NO_FENCE};
sp<Fence> clientTargetAcquireFence{Fence::NO_FENCE};
@@ -152,28 +212,32 @@
virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;
// Determines if a layer belongs to the output.
- virtual bool belongsInOutput(const compositionengine::Layer*) const = 0;
+ virtual bool belongsInOutput(const Layer*) const = 0;
// Returns a pointer to the output layer corresponding to the given layer on
// this output, or nullptr if the layer does not have one
virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0;
- // Creates an OutputLayer instance for this output
- virtual std::unique_ptr<OutputLayer> createOutputLayer(const std::shared_ptr<Layer>&,
- const sp<LayerFE>&) const = 0;
+ // Immediately clears all layers from the output.
+ virtual void clearOutputLayers() = 0;
- // Sets the new ordered set of output layers for this output
- virtual void setOutputLayersOrderedByZ(OutputLayers&&) = 0;
+ // For tests use only. Creates and appends an OutputLayer into the output.
+ virtual OutputLayer* injectOutputLayerForTest(const std::shared_ptr<Layer>&,
+ const sp<LayerFE>&) = 0;
- // Gets the ordered set of output layers for this output
- virtual const OutputLayers& getOutputLayersOrderedByZ() const = 0;
+ // Gets the count of output layers managed by this output
+ virtual size_t getOutputLayerCount() const = 0;
+
+ // Gets an output layer in Z order given its index
+ virtual OutputLayer* getOutputLayerOrderedByZByIndex(size_t) const = 0;
+
+ // A helper function for enumerating all the output layers in Z order using
+ // a C++11 range-based for loop.
+ auto getOutputLayersOrderedByZ() const { return OutputLayersEnumerator(*this); }
// Sets the new set of layers being released this frame
virtual void setReleasedLayers(ReleasedLayers&&) = 0;
- // Takes (moves) the set of layers being released this frame.
- virtual ReleasedLayers takeReleasedLayers() = 0;
-
// Prepare the output, updating the OutputLayers used in the output
virtual void prepare(const CompositionRefreshArgs&, LayerFESet&) = 0;
@@ -187,12 +251,10 @@
virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
- virtual void rebuildLayerStacks(const compositionengine::CompositionRefreshArgs&,
- LayerFESet&) = 0;
+ virtual void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) = 0;
virtual void collectVisibleLayers(const CompositionRefreshArgs&, CoverageState&) = 0;
- virtual std::unique_ptr<OutputLayer> getOutputLayerIfVisible(
- std::shared_ptr<compositionengine::Layer>, CoverageState&) = 0;
- virtual void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) = 0;
+ virtual void ensureOutputLayerIfVisible(std::shared_ptr<Layer>, CoverageState&) = 0;
+ virtual void setReleasedLayers(const CompositionRefreshArgs&) = 0;
virtual void updateAndWriteCompositionState(const CompositionRefreshArgs&) = 0;
virtual void setColorTransform(const CompositionRefreshArgs&) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 45a604f..4acaab9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -41,8 +41,6 @@
// compositionengine::Output overrides
void dump(std::string&) const override;
- std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const override;
using compositionengine::impl::Output::setReleasedLayers;
void setReleasedLayers(const CompositionRefreshArgs&) override;
void setColorTransform(const CompositionRefreshArgs&) override;
@@ -72,6 +70,10 @@
virtual void applyDisplayRequests(const DisplayRequests&);
virtual void applyLayerRequestsToLayers(const LayerRequests&);
+ // Internal
+ std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;
+
private:
const bool mIsVirtual;
std::optional<DisplayId> mId;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 2766572..ba6f72f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -60,13 +60,8 @@
compositionengine::OutputLayer* getOutputLayerForLayer(
compositionengine::Layer*) const override;
- std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
- const std::shared_ptr<Layer>&, const sp<LayerFE>&) const override;
- void setOutputLayersOrderedByZ(OutputLayers&&) override;
- const OutputLayers& getOutputLayersOrderedByZ() const override;
void setReleasedLayers(ReleasedLayers&&) override;
- ReleasedLayers takeReleasedLayers() override;
void prepare(const CompositionRefreshArgs&, LayerFESet&) override;
void present(const CompositionRefreshArgs&) override;
@@ -74,9 +69,8 @@
void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override;
void collectVisibleLayers(const CompositionRefreshArgs&,
compositionengine::Output::CoverageState&) override;
- std::unique_ptr<compositionengine::OutputLayer> getOutputLayerIfVisible(
- std::shared_ptr<compositionengine::Layer>,
- compositionengine::Output::CoverageState&) override;
+ void ensureOutputLayerIfVisible(std::shared_ptr<compositionengine::Layer>,
+ compositionengine::Output::CoverageState&) override;
void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override;
void updateLayerStateFromFE(const CompositionRefreshArgs&) const override;
@@ -95,9 +89,9 @@
void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
protected:
- virtual const CompositionEngine& getCompositionEngine() const = 0;
- std::unique_ptr<compositionengine::OutputLayer> takeOutputLayerForLayer(
- compositionengine::Layer*);
+ std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) const;
+ std::optional<size_t> findCurrentOutputLayerForLayer(compositionengine::Layer*) const;
void chooseCompositionStrategy() override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
@@ -109,7 +103,14 @@
void dumpBase(std::string&) const;
// Implemented by the final implementation for the final state it uses.
- virtual void dumpState(std::string&) const = 0;
+ virtual compositionengine::OutputLayer* ensureOutputLayer(
+ std::optional<size_t>, const std::shared_ptr<compositionengine::Layer>&,
+ const sp<LayerFE>&) = 0;
+ virtual compositionengine::OutputLayer* injectOutputLayerForTest(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&) = 0;
+ virtual void finalizePendingOutputLayers() = 0;
+ virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0;
+ virtual void dumpState(std::string& out) const = 0;
private:
void dirtyEntireOutput();
@@ -122,7 +123,6 @@
std::unique_ptr<compositionengine::DisplayColorProfile> mDisplayColorProfile;
std::unique_ptr<compositionengine::RenderSurface> mRenderSurface;
- OutputLayers mOutputLayersOrderedByZ;
ReleasedLayers mReleasedLayers;
};
@@ -141,6 +141,8 @@
using OutputCompositionState = std::remove_const_t<
std::remove_reference_t<decltype(std::declval<BaseOutput>().getState())>>;
+ using OutputLayer = std::remove_pointer_t<decltype(
+ std::declval<BaseOutput>().getOutputLayerOrderedByZByIndex(0))>;
#pragma clang diagnostic pop
@@ -151,16 +153,72 @@
private:
// compositionengine::Output overrides
const OutputCompositionState& getState() const override { return mState; }
+
OutputCompositionState& editState() override { return mState; }
+ size_t getOutputLayerCount() const override {
+ return mCurrentOutputLayersOrderedByZ.size();
+ }
+
+ OutputLayer* getOutputLayerOrderedByZByIndex(size_t index) const override {
+ if (index >= mCurrentOutputLayersOrderedByZ.size()) {
+ return nullptr;
+ }
+ return mCurrentOutputLayersOrderedByZ[index].get();
+ }
+
// compositionengine::impl::Output overrides
const CompositionEngine& getCompositionEngine() const override {
return mCompositionEngine;
};
+
+ OutputLayer* ensureOutputLayer(std::optional<size_t> prevIndex,
+ const std::shared_ptr<compositionengine::Layer>& layer,
+ const sp<LayerFE>& layerFE) {
+ auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size())
+ ? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex])
+ : BaseOutput::createOutputLayer(layer, layerFE);
+ auto result = outputLayer.get();
+ mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
+ return result;
+ }
+
+ void finalizePendingOutputLayers() override {
+ // The pending layers are added in reverse order. Reverse them to
+ // get the back-to-front ordered list of layers.
+ std::reverse(mPendingOutputLayersOrderedByZ.begin(),
+ mPendingOutputLayersOrderedByZ.end());
+
+ mCurrentOutputLayersOrderedByZ = std::move(mPendingOutputLayersOrderedByZ);
+ }
+
void dumpState(std::string& out) const override { mState.dump(out); }
+ OutputLayer* injectOutputLayerForTest(
+ const std::shared_ptr<compositionengine::Layer>& layer,
+ const sp<LayerFE>& layerFE) override {
+ auto outputLayer = BaseOutput::createOutputLayer(layer, layerFE);
+ auto result = outputLayer.get();
+ mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
+ return result;
+ }
+
+ // Note: This is declared as a private virtual non-override so it can be
+ // an override implementation in the unit tests, but otherwise is not an
+ // accessible override for the normal implementation.
+ virtual void injectOutputLayerForTest(std::unique_ptr<OutputLayer> outputLayer) {
+ mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer));
+ }
+
+ void clearOutputLayers() override {
+ mCurrentOutputLayersOrderedByZ.clear();
+ mPendingOutputLayersOrderedByZ.clear();
+ }
+
const CompositionEngine& mCompositionEngine;
OutputCompositionState mState;
+ std::vector<std::unique_ptr<OutputLayer>> mCurrentOutputLayersOrderedByZ;
+ std::vector<std::unique_ptr<OutputLayer>> mPendingOutputLayersOrderedByZ;
};
return std::make_shared<Output>(compositionEngine, std::forward<Args>(args)...);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 286a20f..dd211f1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -64,20 +64,14 @@
MOCK_CONST_METHOD1(getOutputLayerForLayer,
compositionengine::OutputLayer*(compositionengine::Layer*));
- MOCK_CONST_METHOD2(createOutputLayer,
- std::unique_ptr<compositionengine::OutputLayer>(
- const std::shared_ptr<compositionengine::Layer>&,
- const sp<compositionengine::LayerFE>&));
- MOCK_METHOD2(getOrCreateOutputLayer,
- std::unique_ptr<compositionengine::OutputLayer>(
- std::shared_ptr<compositionengine::Layer>,
- sp<compositionengine::LayerFE>));
-
- MOCK_METHOD1(setOutputLayersOrderedByZ, void(OutputLayers&&));
- MOCK_CONST_METHOD0(getOutputLayersOrderedByZ, OutputLayers&());
+ MOCK_METHOD0(clearOutputLayers, void());
+ MOCK_METHOD2(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
+ const sp<compositionengine::LayerFE>&));
+ MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
+ MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
MOCK_METHOD1(setReleasedLayers, void(ReleasedLayers&&));
- MOCK_METHOD0(takeReleasedLayers, ReleasedLayers());
MOCK_METHOD2(prepare, void(const compositionengine::CompositionRefreshArgs&, LayerFESet&));
MOCK_METHOD1(present, void(const compositionengine::CompositionRefreshArgs&));
@@ -87,10 +81,9 @@
MOCK_METHOD2(collectVisibleLayers,
void(const compositionengine::CompositionRefreshArgs&,
compositionengine::Output::CoverageState&));
- MOCK_METHOD2(getOutputLayerIfVisible,
- std::unique_ptr<compositionengine::OutputLayer>(
- std::shared_ptr<compositionengine::Layer>,
- compositionengine::Output::CoverageState&));
+ MOCK_METHOD2(ensureOutputLayerIfVisible,
+ void(std::shared_ptr<compositionengine::Layer>,
+ compositionengine::Output::CoverageState&));
MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
MOCK_CONST_METHOD1(updateLayerStateFromFE, void(const CompositionRefreshArgs&));
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index abf73ad..295c289 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -101,7 +101,7 @@
uniqueVisibleLayers;
for (const auto& output : args.outputs) {
- for (auto& layer : output->getOutputLayersOrderedByZ()) {
+ for (auto* layer : output->getOutputLayersOrderedByZ()) {
if (layer->isHardwareCursor()) {
// Latch the cursor composition state from each front-end layer.
layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState());
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 87df858..405ad42 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -132,7 +132,7 @@
std::unique_ptr<compositionengine::OutputLayer> Display::createOutputLayer(
const std::shared_ptr<compositionengine::Layer>& layer,
const sp<compositionengine::LayerFE>& layerFE) const {
- auto result = Output::createOutputLayer(layer, layerFE);
+ auto result = impl::createOutputLayer(*this, layer, layerFE);
if (result && mId) {
auto& hwc = getCompositionEngine().getHwComposer();
@@ -167,7 +167,7 @@
// Any non-null entries in the current list of layers are layers that are no
// longer going to be visible
- for (auto& layer : getOutputLayersOrderedByZ()) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
if (!layer) {
continue;
}
@@ -230,14 +230,14 @@
}
bool Display::anyLayersRequireClientComposition() const {
- const auto& layers = getOutputLayersOrderedByZ();
- return std::any_of(layers.cbegin(), layers.cend(),
+ const auto layers = getOutputLayersOrderedByZ();
+ return std::any_of(layers.begin(), layers.end(),
[](const auto& layer) { return layer->requiresClientComposition(); });
}
bool Display::allLayersRequireClientComposition() const {
- const auto& layers = getOutputLayersOrderedByZ();
- return std::all_of(layers.cbegin(), layers.cend(),
+ const auto layers = getOutputLayersOrderedByZ();
+ return std::all_of(layers.begin(), layers.end(),
[](const auto& layer) { return layer->requiresClientComposition(); });
}
@@ -246,7 +246,7 @@
return;
}
- for (auto& layer : getOutputLayersOrderedByZ()) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
auto hwcLayer = layer->getHwcLayer();
if (!hwcLayer) {
continue;
@@ -267,7 +267,7 @@
}
void Display::applyLayerRequestsToLayers(const LayerRequests& layerRequests) {
- for (auto& layer : getOutputLayersOrderedByZ()) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
layer->prepareForDeviceLayerRequests();
auto hwcLayer = layer->getHwcLayer();
@@ -295,7 +295,7 @@
result.presentFence = hwc.getPresentFence(*mId);
// TODO(b/121291683): Change HWComposer call to return entire map
- for (const auto& layer : getOutputLayersOrderedByZ()) {
+ for (const auto* layer : getOutputLayersOrderedByZ()) {
auto hwcLayer = layer->getHwcLayer();
if (!hwcLayer) {
continue;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index c511306..c3e5cfd 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -186,8 +186,8 @@
out.append(" No render surface!\n");
}
- android::base::StringAppendF(&out, "\n %zu Layers\b", mOutputLayersOrderedByZ.size());
- for (const auto& outputLayer : mOutputLayersOrderedByZ) {
+ android::base::StringAppendF(&out, "\n %zu Layers\n", getOutputLayerCount());
+ for (const auto* outputLayer : getOutputLayersOrderedByZ()) {
if (!outputLayer) {
continue;
}
@@ -253,49 +253,32 @@
return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly);
}
-compositionengine::OutputLayer* Output::getOutputLayerForLayer(
- compositionengine::Layer* layer) const {
- for (const auto& outputLayer : mOutputLayersOrderedByZ) {
- if (outputLayer && &outputLayer->getLayer() == layer) {
- return outputLayer.get();
- }
- }
- return nullptr;
-}
-
-std::unique_ptr<compositionengine::OutputLayer> Output::takeOutputLayerForLayer(
- compositionengine::Layer* layer) {
- // Removes the outputLayer from mOutputLayersorderedByZ and transfers ownership to the caller.
- for (auto& outputLayer : mOutputLayersOrderedByZ) {
- if (outputLayer && &outputLayer->getLayer() == layer) {
- return std::move(outputLayer);
- }
- }
- return nullptr;
-}
-
std::unique_ptr<compositionengine::OutputLayer> Output::createOutputLayer(
- const std::shared_ptr<compositionengine::Layer>& layer,
- const sp<compositionengine::LayerFE>& layerFE) const {
+ const std::shared_ptr<compositionengine::Layer>& layer, const sp<LayerFE>& layerFE) const {
return impl::createOutputLayer(*this, layer, layerFE);
}
-void Output::setOutputLayersOrderedByZ(OutputLayers&& layers) {
- mOutputLayersOrderedByZ = std::move(layers);
+compositionengine::OutputLayer* Output::getOutputLayerForLayer(
+ compositionengine::Layer* layer) const {
+ auto index = findCurrentOutputLayerForLayer(layer);
+ return index ? getOutputLayerOrderedByZByIndex(*index) : nullptr;
}
-const Output::OutputLayers& Output::getOutputLayersOrderedByZ() const {
- return mOutputLayersOrderedByZ;
+std::optional<size_t> Output::findCurrentOutputLayerForLayer(
+ compositionengine::Layer* layer) const {
+ for (size_t i = 0; i < getOutputLayerCount(); i++) {
+ auto outputLayer = getOutputLayerOrderedByZByIndex(i);
+ if (outputLayer && &outputLayer->getLayer() == layer) {
+ return i;
+ }
+ }
+ return std::nullopt;
}
void Output::setReleasedLayers(Output::ReleasedLayers&& layers) {
mReleasedLayers = std::move(layers);
}
-Output::ReleasedLayers Output::takeReleasedLayers() {
- return std::move(mReleasedLayers);
-}
-
void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArgs,
LayerFESet& geomSnapshots) {
ATRACE_CALL();
@@ -345,47 +328,34 @@
void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArgs& refreshArgs,
compositionengine::Output::CoverageState& coverage) {
- // We build up a list of all layers that are going to be visible in the new
- // frame.
- compositionengine::Output::OutputLayers newLayersSortedByZ;
-
// Evaluate the layers from front to back to determine what is visible. This
// also incrementally calculates the coverage information for each layer as
// well as the entire output.
for (auto& layer : reversed(refreshArgs.layers)) {
- // Incrementally process the coverage for each layer, obtaining an
- // optional outputLayer if the layer is visible.
- auto outputLayer = getOutputLayerIfVisible(layer, coverage);
- if (outputLayer) {
- newLayersSortedByZ.emplace_back(std::move(outputLayer));
- }
+ // Incrementally process the coverage for each layer
+ ensureOutputLayerIfVisible(layer, coverage);
// TODO(b/121291683): Stop early if the output is completely covered and
// no more layers could even be visible underneath the ones on top.
}
- // Since we walked the layers in reverse order, we need to reverse
- // newLayersSortedByZ to get the back-to-front ordered list of layers.
- std::reverse(newLayersSortedByZ.begin(), newLayersSortedByZ.end());
+ setReleasedLayers(refreshArgs);
+
+ finalizePendingOutputLayers();
// Generate a simple Z-order values to each visible output layer
uint32_t zOrder = 0;
- for (auto& outputLayer : newLayersSortedByZ) {
+ for (auto* outputLayer : getOutputLayersOrderedByZ()) {
outputLayer->editState().z = zOrder++;
}
-
- setReleasedLayers(refreshArgs);
-
- mOutputLayersOrderedByZ = std::move(newLayersSortedByZ);
}
-std::unique_ptr<compositionengine::OutputLayer> Output::getOutputLayerIfVisible(
- std::shared_ptr<compositionengine::Layer> layer,
- compositionengine::Output::CoverageState& coverage) {
+void Output::ensureOutputLayerIfVisible(std::shared_ptr<compositionengine::Layer> layer,
+ compositionengine::Output::CoverageState& coverage) {
// Note: Converts a wp<LayerFE> to a sp<LayerFE>
auto layerFE = layer->getLayerFE();
if (layerFE == nullptr) {
- return nullptr;
+ return;
}
// Ensure we have a snapshot of the basic geometry layer state. Limit the
@@ -402,7 +372,7 @@
// Only consider the layers on the given layer stack
if (!belongsInOutput(layer.get())) {
- return nullptr;
+ return;
}
/*
@@ -436,7 +406,7 @@
// handle hidden surfaces by setting the visible region to empty
if (CC_UNLIKELY(!layerFEState.isVisible)) {
- return nullptr;
+ return;
}
const ui::Transform& tr = layerFEState.geomLayerTransform;
@@ -447,7 +417,7 @@
visibleRegion.set(Rect(tr.transform(layerFEState.geomLayerBounds)));
if (visibleRegion.isEmpty()) {
- return nullptr;
+ return;
}
// Remove the transparent area from the visible region
@@ -483,12 +453,14 @@
visibleRegion.subtractSelf(coverage.aboveOpaqueLayers);
if (visibleRegion.isEmpty()) {
- return nullptr;
+ return;
}
// Get coverage information for the layer as previously displayed,
// also taking over ownership from mOutputLayersorderedByZ.
- auto prevOutputLayer = takeOutputLayerForLayer(layer.get());
+ auto prevOutputLayerIndex = findCurrentOutputLayerForLayer(layer.get());
+ auto prevOutputLayer =
+ prevOutputLayerIndex ? getOutputLayerOrderedByZByIndex(*prevOutputLayerIndex) : nullptr;
// Get coverage information for the layer as previously displayed
// TODO(b/121291683): Define kEmptyRegion as a constant in Region.h
@@ -540,13 +512,12 @@
Region drawRegion(outputState.transform.transform(visibleNonTransparentRegion));
drawRegion.andSelf(outputState.bounds);
if (drawRegion.isEmpty()) {
- return nullptr;
+ return;
}
// The layer is visible. Either reuse the existing outputLayer if we have
// one, or create a new one if we do not.
- std::unique_ptr<compositionengine::OutputLayer> result =
- prevOutputLayer ? std::move(prevOutputLayer) : createOutputLayer(layer, layerFE);
+ auto result = ensureOutputLayer(prevOutputLayerIndex, layer, layerFE);
// Store the layer coverage information into the layer state as some of it
// is useful later.
@@ -556,8 +527,6 @@
outputLayerState.coveredRegion = coveredRegion;
outputLayerState.outputSpaceVisibleRegion = outputState.transform.transform(
outputLayerState.visibleRegion.intersect(outputState.viewport));
-
- return result;
}
void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) {
@@ -565,7 +534,7 @@
}
void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
- for (auto& layer : mOutputLayersOrderedByZ) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(),
args.updatingGeometryThisFrame
? LayerFE::StateSubset::GeometryAndContent
@@ -578,7 +547,7 @@
ATRACE_CALL();
ALOGV(__FUNCTION__);
- for (auto& layer : mOutputLayersOrderedByZ) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
if (refreshArgs.devOptForceClientComposition) {
layer->editState().forceClientComposition = true;
}
@@ -608,7 +577,7 @@
ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB;
*outHdrDataSpace = ui::Dataspace::UNKNOWN;
- for (const auto& layer : mOutputLayersOrderedByZ) {
+ for (const auto* layer : getOutputLayersOrderedByZ()) {
switch (layer->getLayer().getFEState().dataspace) {
case ui::Dataspace::V0_SCRGB:
case ui::Dataspace::V0_SCRGB_LINEAR:
@@ -702,7 +671,7 @@
void Output::beginFrame() {
auto& outputState = editState();
const bool dirty = !getDirtyRegion(false).isEmpty();
- const bool empty = mOutputLayersOrderedByZ.empty();
+ const bool empty = getOutputLayerCount() == 0;
const bool wasEmpty = !outputState.lastCompositionHadVisibleLayers;
// If nothing has changed (!dirty), don't recompose.
@@ -832,11 +801,10 @@
// least one layer has protected content, we need to use a secure back
// buffer.
if (outputState.isSecure && supportsProtectedContent) {
- bool needsProtected =
- std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(),
- [](auto& layer) {
- return layer->getLayer().getFEState().hasProtectedContent;
- });
+ auto layers = getOutputLayersOrderedByZ();
+ bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
+ return layer->getLayer().getFEState().hasProtectedContent;
+ });
if (needsProtected != renderEngine.isProtected()) {
renderEngine.useProtectedContext(needsProtected);
}
@@ -888,7 +856,7 @@
// Used when a layer clears part of the buffer.
Region dummyRegion;
- for (auto& layer : mOutputLayersOrderedByZ) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
const auto& layerState = layer->getState();
const auto& layerFEState = layer->getLayer().getFEState();
auto& layerFE = layer->getLayerFE();
@@ -979,7 +947,7 @@
mRenderSurface->onPresentDisplayCompleted();
- for (auto& layer : mOutputLayersOrderedByZ) {
+ for (auto* layer : getOutputLayersOrderedByZ()) {
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
@@ -1006,7 +974,7 @@
}
// We've got a list of layers needing fences, that are disjoint with
- // mOutputLayersOrderedByZ. The best we can do is to
+ // OutputLayersOrderedByZ. The best we can do is to
// supply them with the present fence.
for (auto& weakLayer : mReleasedLayers) {
if (auto layer = weakLayer.promote(); layer != nullptr) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 8401f08..4d71d43 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -48,17 +48,33 @@
constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
struct DisplayTest : public testing::Test {
+ class Display : public impl::Display {
+ public:
+ explicit Display(const compositionengine::DisplayCreationArgs& args)
+ : impl::Display(args) {}
+
+ using impl::Display::injectOutputLayerForTest;
+ virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
+ };
+
+ static std::shared_ptr<Display> createDisplay(
+ const compositionengine::CompositionEngine& compositionEngine,
+ compositionengine::DisplayCreationArgs&& args) {
+ return impl::createDisplayTemplated<Display>(compositionEngine, args);
+ }
+
DisplayTest() {
EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
EXPECT_CALL(*mLayer1, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer1));
EXPECT_CALL(*mLayer2, getHwcLayer()).WillRepeatedly(Return(&mHWC2Layer2));
EXPECT_CALL(*mLayer3, getHwcLayer()).WillRepeatedly(Return(nullptr));
- std::vector<std::unique_ptr<OutputLayer>> layers;
- layers.emplace_back(mLayer1);
- layers.emplace_back(mLayer2);
- layers.emplace_back(mLayer3);
- mDisplay->setOutputLayersOrderedByZ(std::move(layers));
+ mDisplay->injectOutputLayerForTest(
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer1));
+ mDisplay->injectOutputLayerForTest(
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer2));
+ mDisplay->injectOutputLayerForTest(
+ std::unique_ptr<compositionengine::OutputLayer>(mLayer3));
}
StrictMock<android::mock::HWComposer> mHwComposer;
@@ -71,12 +87,11 @@
mock::OutputLayer* mLayer1 = new StrictMock<mock::OutputLayer>();
mock::OutputLayer* mLayer2 = new StrictMock<mock::OutputLayer>();
mock::OutputLayer* mLayer3 = new StrictMock<mock::OutputLayer>();
- std::shared_ptr<impl::Display> mDisplay =
- impl::createDisplay(mCompositionEngine,
- DisplayCreationArgsBuilder()
- .setDisplayId(DEFAULT_DISPLAY_ID)
- .setPowerAdvisor(&mPowerAdvisor)
- .build());
+ std::shared_ptr<Display> mDisplay = createDisplay(mCompositionEngine,
+ DisplayCreationArgsBuilder()
+ .setDisplayId(DEFAULT_DISPLAY_ID)
+ .setPowerAdvisor(&mPowerAdvisor)
+ .build());
};
/*
@@ -376,7 +391,20 @@
};
// These need implementations though are not expected to be called.
+ MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
+ MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
+ compositionengine::OutputLayer*(size_t));
+ MOCK_METHOD3(ensureOutputLayer,
+ compositionengine::OutputLayer*(
+ std::optional<size_t>,
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD0(finalizePendingOutputLayers, void());
+ MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
+ MOCK_METHOD2(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
const compositionengine::CompositionEngine& mCompositionEngine;
impl::OutputCompositionState mState;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 635d77b..95ae888 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -50,6 +50,17 @@
const mat4 kNonIdentityQuarter = mat4() * 0.25;
struct OutputTest : public testing::Test {
+ class Output : public impl::Output {
+ public:
+ using impl::Output::injectOutputLayerForTest;
+ virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
+ };
+
+ static std::shared_ptr<Output> createOutput(
+ const compositionengine::CompositionEngine& compositionEngine) {
+ return impl::createOutputTemplated<Output>(compositionEngine);
+ }
+
OutputTest() {
mOutput->setDisplayColorProfileForTest(
std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
@@ -63,7 +74,7 @@
StrictMock<mock::CompositionEngine> mCompositionEngine;
mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
- std::shared_ptr<impl::Output> mOutput = impl::createOutput(mCompositionEngine);
+ std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
};
const Rect OutputTest::kDefaultDisplaySize{100, 200};
@@ -449,11 +460,9 @@
mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
- Output::OutputLayers outputLayers;
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
- outputLayers.emplace_back(nullptr);
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
- mOutput->setOutputLayersOrderedByZ(std::move(outputLayers));
+ mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
+ mOutput->injectOutputLayerForTest(nullptr);
+ mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
StrictMock<mock::Layer> layer;
StrictMock<mock::Layer> otherLayer;
@@ -488,8 +497,21 @@
OutputCompositionState& editState() override { return mState; }
// These need implementations though are not expected to be called.
+ MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
+ MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
+ compositionengine::OutputLayer*(size_t));
+ MOCK_METHOD3(ensureOutputLayer,
+ compositionengine::OutputLayer*(
+ std::optional<size_t>,
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD0(finalizePendingOutputLayers, void());
+ MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+ MOCK_METHOD2(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
impl::OutputCompositionState mState;
};
@@ -566,8 +588,21 @@
OutputCompositionState& editState() override { return mState; }
// These need implementations though are not expected to be called.
+ MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
+ MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
+ compositionengine::OutputLayer*(size_t));
+ MOCK_METHOD3(ensureOutputLayer,
+ compositionengine::OutputLayer*(
+ std::optional<size_t>,
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD0(finalizePendingOutputLayers, void());
+ MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+ MOCK_METHOD2(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
impl::OutputCompositionState mState;
};
@@ -577,11 +612,6 @@
std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
- Output::OutputLayers outputLayers;
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(mOutputLayer1));
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(mOutputLayer2));
- mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
-
mOutput.editState().frame = kDefaultOutputFrame;
mOutput.editState().viewport = kDefaultOutputViewport;
mOutput.editState().scissor = kDefaultOutputScissor;
@@ -594,6 +624,11 @@
mOutput.editState().usesClientComposition = true;
mOutput.editState().usesDeviceComposition = false;
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
+ .WillRepeatedly(Return(&mOutputLayer1));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
+ .WillRepeatedly(Return(&mOutputLayer2));
EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
}
@@ -602,8 +637,8 @@
StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
- mock::OutputLayer* mOutputLayer1 = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* mOutputLayer2 = new StrictMock<mock::OutputLayer>();
+ StrictMock<mock::OutputLayer> mOutputLayer1;
+ StrictMock<mock::OutputLayer> mOutputLayer2;
StrictMock<OutputPartialMock> mOutput;
sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
};
@@ -671,8 +706,21 @@
OutputCompositionState& editState() override { return mState; }
// These need implementations though are not expected to be called.
+ MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
+ MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
+ compositionengine::OutputLayer*(size_t));
+ MOCK_METHOD3(ensureOutputLayer,
+ compositionengine::OutputLayer*(
+ std::optional<size_t>,
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD0(finalizePendingOutputLayers, void());
+ MOCK_METHOD0(clearOutputLayers, void());
MOCK_CONST_METHOD1(dumpState, void(std::string&));
MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
+ MOCK_METHOD2(injectOutputLayerForTest,
+ compositionengine::OutputLayer*(
+ const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
+ MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
impl::OutputCompositionState mState;
};
@@ -695,8 +743,8 @@
// one layer on the left covering the left side of the output, and one layer
// on the right covering that side of the output.
- mock::OutputLayer* leftOutputLayer = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* rightOutputLayer = new StrictMock<mock::OutputLayer>();
+ StrictMock<mock::OutputLayer> leftOutputLayer;
+ StrictMock<mock::OutputLayer> rightOutputLayer;
StrictMock<mock::Layer> leftLayer;
StrictMock<mock::LayerFE> leftLayerFE;
@@ -725,26 +773,27 @@
renderengine::LayerSettings rightLayerRESettings;
rightLayerRESettings.source.solidColor = rightLayerColor;
- EXPECT_CALL(*leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
- EXPECT_CALL(*leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
- EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
- EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
- EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
+ EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
+ EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
+ EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
+ EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
- EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
- EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
- EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
- EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
- EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
+ EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
+ EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
+ EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
+ EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
- Output::OutputLayers outputLayers;
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(leftOutputLayer));
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(rightOutputLayer));
- mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
+ .WillRepeatedly(Return(&leftOutputLayer));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
+ .WillRepeatedly(Return(&rightOutputLayer));
const Rect kPortraitFrame(0, 0, 1000, 2000);
const Rect kPortraitViewport(0, 0, 2000, 1000);
@@ -773,7 +822,7 @@
// Layers whose visible region does not intersect with the viewport will be
// skipped when generating client composition request state.
- mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
+ StrictMock<mock::OutputLayer> outputLayer;
StrictMock<mock::Layer> layer;
StrictMock<mock::LayerFE> layerFE;
@@ -784,17 +833,16 @@
LayerFECompositionState layerFEState;
layerFEState.isOpaque = true;
- EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
- EXPECT_CALL(*outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
- EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
- EXPECT_CALL(*outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
- EXPECT_CALL(*outputLayer, needsFiltering()).WillRepeatedly(Return(false));
+ EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
+ EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
+ EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
+ EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
+ EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
- Output::OutputLayers outputLayers;
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer));
- mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
const Rect kPortraitFrame(0, 0, 1000, 2000);
const Rect kPortraitViewport(0, 0, 2000, 1000);
@@ -824,8 +872,8 @@
// set to do so. The first layer is skipped as the frame buffer is already
// expected to be clear.
- mock::OutputLayer* leftOutputLayer = new StrictMock<mock::OutputLayer>();
- mock::OutputLayer* rightOutputLayer = new StrictMock<mock::OutputLayer>();
+ StrictMock<mock::OutputLayer> leftOutputLayer;
+ StrictMock<mock::OutputLayer> rightOutputLayer;
StrictMock<mock::Layer> leftLayer;
StrictMock<mock::LayerFE> leftLayerFE;
@@ -851,25 +899,26 @@
rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
rightLayerRESettings.source.solidColor = rightLayerColor;
- EXPECT_CALL(*leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
- EXPECT_CALL(*leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
- EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
- EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
+ EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
+ EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
+ EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
+ EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
- EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
- EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
- EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
- EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
- EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
+ EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
+ EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
+ EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
+ EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
+ EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
- Output::OutputLayers outputLayers;
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(leftOutputLayer));
- outputLayers.emplace_back(std::unique_ptr<OutputLayer>(rightOutputLayer));
- mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
+ .WillRepeatedly(Return(&leftOutputLayer));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
+ .WillRepeatedly(Return(&rightOutputLayer));
const Rect kPortraitFrame(0, 0, 1000, 2000);
const Rect kPortraitViewport(0, 0, 2000, 1000);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e3cf84a..cd68e45 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1509,8 +1509,7 @@
// any HWC layers are destroyed through that interface before it becomes
// invalid.
for (const auto& [token, displayDevice] : mDisplays) {
- displayDevice->getCompositionDisplay()->setOutputLayersOrderedByZ(
- compositionengine::Output::OutputLayers());
+ displayDevice->getCompositionDisplay()->clearOutputLayers();
}
// This DisplayDevice will no longer be relevant once resetDisplayState() is
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f29e2dd..b6fa2a6 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -812,14 +812,10 @@
EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _))
.WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE)));
- std::vector<std::unique_ptr<compositionengine::OutputLayer>> outputLayers;
- outputLayers.emplace_back(test->mDisplay->getCompositionDisplay()
- ->createOutputLayer(layer->getCompositionLayer(), layer));
-
- outputLayers.back()->editState().visibleRegion = Region(Rect(0, 0, 100, 100));
- outputLayers.back()->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100));
-
- test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers));
+ auto outputLayer = test->mDisplay->getCompositionDisplay()
+ ->injectOutputLayerForTest(layer->getCompositionLayer(), layer);
+ outputLayer->editState().visibleRegion = Region(Rect(0, 0, 100, 100));
+ outputLayer->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100));
Mock::VerifyAndClear(test->mComposer);
@@ -830,8 +826,7 @@
EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER))
.WillOnce(Return(Error::NONE));
- test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(
- std::vector<std::unique_ptr<compositionengine::OutputLayer>>());
+ test->mDisplay->getCompositionDisplay()->clearOutputLayers();
test->mFlinger.mutableDrawingState().layersSortedByZ.clear();
}
};