Revert^2 "Added surfaceflinger_fuzzer"
b1e4314856cded61f5db5864d0598d1c68ba79b7
Change-Id: I67191c6efd915fa498978f67f4b0ddd154da2b03
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
new file mode 100644
index 0000000..7eebd9b
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ */
+
+cc_defaults {
+ name: "surfaceflinger_fuzz_defaults",
+ include_dirs: [
+ "frameworks/native/services/surfaceflinger/tests/unittests",
+ ],
+ static_libs: [
+ "android.hardware.graphics.composer@2.1-resources",
+ "libgmock",
+ "libgui_mocks",
+ "libgmock_ndk",
+ "libgmock_main",
+ "libgtest_ndk_c++",
+ "libgmock_main_ndk",
+ "librenderengine_mocks",
+ "perfetto_trace_protos",
+ "libcompositionengine_mocks",
+ "perfetto_trace_protos",
+ ],
+ shared_libs: [
+ "libprotoutil",
+ "libstatssocket",
+ "libstatspull",
+ "libtimestats",
+ "libtimestats_proto",
+ "libprotobuf-cpp-full",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ ],
+ srcs: [
+ ":libsurfaceflinger_sources",
+ ":libsurfaceflinger_mock_sources",
+ ],
+ defaults: [
+ "libsurfaceflinger_defaults",
+ ],
+ header_libs: [
+ "libui_fuzzableDataspaces_headers",
+ "libsurfaceflinger_headers",
+ "libui_headers",
+ ],
+ cflags: [
+ "-Wno-unused-result",
+ "-Wno-conversion",
+ "-Wno-sign-compare",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "surfaceflinger_fuzzer",
+ defaults: [
+ "surfaceflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "surfaceflinger_fuzzer.cpp",
+ ],
+}
diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md
new file mode 100644
index 0000000..7b244fc
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/README.md
@@ -0,0 +1,24 @@
+# Fuzzers for SurfaceFlinger
+## Table of contents
++ [SurfaceFlinger](#SurfaceFlinger)
+
+# <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger
+
+SurfaceFlinger supports the following data sources:
+1. Pixel Formats (parameter name: `defaultCompositionPixelFormat`)
+2. Data Spaces (parameter name: `defaultCompositionDataspace`)
+3. Rotations (parameter name: `internalDisplayOrientation`)
+3. Surface composer tags (parameter name: `onTransact`)
+
+You can find the possible values in the fuzzer's source code.
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) surfaceflinger_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/surfaceflinger_fuzzer/surfaceflinger_fuzzer
+```
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
new file mode 100644
index 0000000..4f89cd9
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -0,0 +1,294 @@
+/*
+ * 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 <FuzzableDataspaces.h>
+#include <binder/IServiceManager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <ui/DisplayStatInfo.h>
+#include "surfaceflinger_fuzzers_utils.h"
+
+namespace android::fuzz {
+
+static constexpr LatchUnsignaledConfig kLatchUnsignaledConfig[] = {
+ LatchUnsignaledConfig::Always,
+ LatchUnsignaledConfig::Auto,
+ LatchUnsignaledConfig::Disabled,
+};
+
+static constexpr ui::PixelFormat kPixelFormats[] = {ui::PixelFormat::RGBA_8888,
+ ui::PixelFormat::RGBX_8888,
+ ui::PixelFormat::RGB_888,
+ ui::PixelFormat::RGB_565,
+ ui::PixelFormat::BGRA_8888,
+ ui::PixelFormat::YCBCR_422_SP,
+ ui::PixelFormat::YCRCB_420_SP,
+ ui::PixelFormat::YCBCR_422_I,
+ ui::PixelFormat::RGBA_FP16,
+ ui::PixelFormat::RAW16,
+ ui::PixelFormat::BLOB,
+ ui::PixelFormat::IMPLEMENTATION_DEFINED,
+ ui::PixelFormat::YCBCR_420_888,
+ ui::PixelFormat::RAW_OPAQUE,
+ ui::PixelFormat::RAW10,
+ ui::PixelFormat::RAW12,
+ ui::PixelFormat::RGBA_1010102,
+ ui::PixelFormat::Y8,
+ ui::PixelFormat::Y16,
+ ui::PixelFormat::YV12,
+ ui::PixelFormat::DEPTH_16,
+ ui::PixelFormat::DEPTH_24,
+ ui::PixelFormat::DEPTH_24_STENCIL_8,
+ ui::PixelFormat::DEPTH_32F,
+ ui::PixelFormat::DEPTH_32F_STENCIL_8,
+ ui::PixelFormat::STENCIL_8,
+ ui::PixelFormat::YCBCR_P010,
+ ui::PixelFormat::HSV_888};
+
+static constexpr ui::Rotation kRotations[] = {ui::Rotation::Rotation0, ui::Rotation::Rotation90,
+ ui::Rotation::Rotation180, ui::Rotation::Rotation270};
+
+static constexpr BnSurfaceComposer::ISurfaceComposerTag kSurfaceComposerTags[]{
+ BnSurfaceComposer::BOOT_FINISHED,
+ BnSurfaceComposer::CREATE_CONNECTION,
+ BnSurfaceComposer::GET_STATIC_DISPLAY_INFO,
+ BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
+ BnSurfaceComposer::CREATE_DISPLAY,
+ BnSurfaceComposer::DESTROY_DISPLAY,
+ BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN,
+ BnSurfaceComposer::SET_TRANSACTION_STATE,
+ BnSurfaceComposer::AUTHENTICATE_SURFACE,
+ BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
+ BnSurfaceComposer::GET_DISPLAY_MODES,
+ BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE,
+ BnSurfaceComposer::GET_DISPLAY_STATE,
+ BnSurfaceComposer::CAPTURE_DISPLAY,
+ BnSurfaceComposer::CAPTURE_LAYERS,
+ BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS,
+ BnSurfaceComposer::GET_ANIMATION_FRAME_STATS,
+ BnSurfaceComposer::SET_POWER_MODE,
+ BnSurfaceComposer::GET_DISPLAY_STATS,
+ BnSurfaceComposer::GET_HDR_CAPABILITIES,
+ BnSurfaceComposer::GET_DISPLAY_COLOR_MODES,
+ BnSurfaceComposer::GET_ACTIVE_COLOR_MODE,
+ BnSurfaceComposer::SET_ACTIVE_COLOR_MODE,
+ BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS,
+ BnSurfaceComposer::INJECT_VSYNC,
+ BnSurfaceComposer::GET_LAYER_DEBUG_INFO,
+ BnSurfaceComposer::GET_COMPOSITION_PREFERENCE,
+ BnSurfaceComposer::GET_COLOR_MANAGEMENT,
+ BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
+ BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
+ BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE,
+ BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT,
+ BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY,
+ BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES,
+ BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS,
+ BnSurfaceComposer::ADD_REGION_SAMPLING_LISTENER,
+ BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER,
+ BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS,
+ BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS,
+ BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT,
+ BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS,
+ BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID,
+ BnSurfaceComposer::NOTIFY_POWER_BOOST,
+ BnSurfaceComposer::SET_GLOBAL_SHADOW_SETTINGS,
+ BnSurfaceComposer::GET_AUTO_LOW_LATENCY_MODE_SUPPORT,
+ BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE,
+ BnSurfaceComposer::GET_GAME_CONTENT_TYPE_SUPPORT,
+ BnSurfaceComposer::SET_GAME_CONTENT_TYPE,
+ BnSurfaceComposer::SET_FRAME_RATE,
+ BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
+ BnSurfaceComposer::SET_FRAME_TIMELINE_INFO,
+ BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER,
+ BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY,
+ BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT,
+ BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO,
+ BnSurfaceComposer::ADD_FPS_LISTENER,
+ BnSurfaceComposer::REMOVE_FPS_LISTENER,
+ BnSurfaceComposer::OVERRIDE_HDR_TYPES,
+ BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER,
+ BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER,
+ BnSurfaceComposer::ON_PULL_ATOM,
+ BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER,
+ BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
+ BnSurfaceComposer::ADD_WINDOW_INFOS_LISTENER,
+ BnSurfaceComposer::REMOVE_WINDOW_INFOS_LISTENER,
+};
+
+static constexpr uint32_t kMinCode = 1000;
+static constexpr uint32_t kMaxCode = 1050;
+
+class SurfaceFlingerFuzzer {
+public:
+ SurfaceFlingerFuzzer(const uint8_t *data, size_t size) : mFdp(data, size) {
+ mFlinger = mTestableFlinger.flinger();
+ };
+ void process(const uint8_t *data, size_t size);
+
+private:
+ void setUp();
+ void invokeFlinger();
+ void setTransactionState();
+ void setInternalDisplayPrimaries();
+ void setDisplayStateLocked();
+ void onTransact(const uint8_t *data, size_t size);
+
+ FuzzedDataProvider mFdp;
+ TestableSurfaceFlinger mTestableFlinger;
+ sp<SurfaceFlinger> mFlinger = nullptr;
+};
+
+void SurfaceFlingerFuzzer::invokeFlinger() {
+ mFlinger->setSchedFifo(mFdp.ConsumeBool());
+ mFlinger->setSchedAttr(mFdp.ConsumeBool());
+ mFlinger->getServiceName();
+ mFlinger->hasSyncFramework = mFdp.ConsumeBool();
+ mFlinger->dispSyncPresentTimeOffset = mFdp.ConsumeIntegral<int64_t>();
+ mFlinger->useHwcForRgbToYuv = mFdp.ConsumeBool();
+ mFlinger->maxFrameBufferAcquiredBuffers = mFdp.ConsumeIntegral<int64_t>();
+ mFlinger->maxGraphicsWidth = mFdp.ConsumeIntegral<uint32_t>();
+ mFlinger->maxGraphicsHeight = mFdp.ConsumeIntegral<uint32_t>();
+ mFlinger->hasWideColorDisplay = mFdp.ConsumeBool();
+ mFlinger->internalDisplayOrientation = mFdp.PickValueInArray(kRotations);
+ mFlinger->useContextPriority = mFdp.ConsumeBool();
+
+ mFlinger->defaultCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+ mFlinger->defaultCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+ mFlinger->wideColorGamutCompositionDataspace = mFdp.PickValueInArray(kDataspaces);
+ mFlinger->wideColorGamutCompositionPixelFormat = mFdp.PickValueInArray(kPixelFormats);
+
+ mFlinger->enableLatchUnsignaledConfig = mFdp.PickValueInArray(kLatchUnsignaledConfig);
+
+ mFlinger->scheduleComposite(mFdp.ConsumeBool()
+ ? scheduler::ISchedulerCallback::FrameHint::kActive
+ : scheduler::ISchedulerCallback::FrameHint::kNone);
+
+ mFlinger->scheduleRepaint();
+ mFlinger->scheduleSample();
+
+ uint32_t texture = mFlinger->getNewTexture();
+ mFlinger->deleteTextureAsync(texture);
+
+ sp<IBinder> handle = defaultServiceManager()->checkService(
+ String16(mFdp.ConsumeRandomLengthString().c_str()));
+ mFlinger->fromHandle(handle);
+ mFlinger->windowInfosReported();
+ mFlinger->disableExpensiveRendering();
+}
+
+void SurfaceFlingerFuzzer::setInternalDisplayPrimaries() {
+ ui::DisplayPrimaries primaries;
+ primaries.red.X = mFdp.ConsumeFloatingPoint<float>();
+ primaries.red.Y = mFdp.ConsumeFloatingPoint<float>();
+ primaries.red.Z = mFdp.ConsumeFloatingPoint<float>();
+ primaries.green.X = mFdp.ConsumeFloatingPoint<float>();
+ primaries.green.Y = mFdp.ConsumeFloatingPoint<float>();
+ primaries.green.Z = mFdp.ConsumeFloatingPoint<float>();
+ primaries.blue.X = mFdp.ConsumeFloatingPoint<float>();
+ primaries.blue.Y = mFdp.ConsumeFloatingPoint<float>();
+ primaries.blue.Z = mFdp.ConsumeFloatingPoint<float>();
+ primaries.white.X = mFdp.ConsumeFloatingPoint<float>();
+ primaries.white.Y = mFdp.ConsumeFloatingPoint<float>();
+ primaries.white.Z = mFdp.ConsumeFloatingPoint<float>();
+ mTestableFlinger.setInternalDisplayPrimaries(primaries);
+}
+
+void SurfaceFlingerFuzzer::setTransactionState() {
+ Vector<ComposerState> states;
+ Vector<DisplayState> displays;
+ ComposerState composerState;
+ composerState.state.what = layer_state_t::eLayerChanged;
+ composerState.state.surface = nullptr;
+ states.add(composerState);
+ uint32_t flags = mFdp.ConsumeIntegral<uint32_t>();
+ const sp<IBinder> applyToken = nullptr;
+ int64_t desiredPresentTime = mFdp.ConsumeIntegral<int64_t>();
+ bool isAutoTimestamp = mFdp.ConsumeBool();
+ bool hasListenerCallbacks = mFdp.ConsumeBool();
+ std::vector<ListenerCallbacks> listenerCallbacks{};
+ uint64_t transactionId = mFdp.ConsumeIntegral<uint64_t>();
+
+ mTestableFlinger.setTransactionState(FrameTimelineInfo{}, states, displays, flags, applyToken,
+ InputWindowCommands{}, desiredPresentTime, isAutoTimestamp,
+ {}, hasListenerCallbacks, listenerCallbacks,
+ transactionId);
+}
+
+void SurfaceFlingerFuzzer::setDisplayStateLocked() {
+ DisplayState state{};
+ mTestableFlinger.setDisplayStateLocked(state);
+}
+
+void SurfaceFlingerFuzzer::onTransact(const uint8_t *data, size_t size) {
+ Parcel fuzzedData, reply;
+ fuzzedData.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ fuzzedData.setData(data, size);
+ fuzzedData.setDataPosition(0);
+ uint32_t code = mFdp.ConsumeBool() ? mFdp.PickValueInArray(kSurfaceComposerTags)
+ : mFdp.ConsumeIntegralInRange<uint32_t>(kMinCode, kMaxCode);
+ mTestableFlinger.onTransact(code, fuzzedData, &reply, 0);
+}
+
+void SurfaceFlingerFuzzer::setUp() {
+ mTestableFlinger.setupScheduler(std::make_unique<android::mock::VsyncController>(),
+ std::make_unique<android::mock::VSyncTracker>(),
+ std::make_unique<android::mock::EventThread>(),
+ std::make_unique<android::mock::EventThread>());
+
+ mTestableFlinger.setupTimeStats(std::make_unique<android::mock::TimeStats>());
+
+ std::unique_ptr<android::renderengine::RenderEngine> renderEngine =
+ std::make_unique<android::renderengine::mock::RenderEngine>();
+ mTestableFlinger.setupRenderEngine(std::move(renderEngine));
+ mTestableFlinger.setupComposer(std::make_unique<android::Hwc2::mock::Composer>());
+}
+
+void SurfaceFlingerFuzzer::process(const uint8_t *data, size_t size) {
+ setUp();
+
+ invokeFlinger();
+
+ mTestableFlinger.fuzzSurfaceFlinger(data, size);
+
+ mTestableFlinger.setCreateBufferQueueFunction(
+ surfaceflinger::test::Factory::CreateBufferQueueFunction());
+ mTestableFlinger.setCreateNativeWindowSurface(
+ surfaceflinger::test::Factory::CreateNativeWindowSurfaceFunction());
+
+ setInternalDisplayPrimaries();
+
+ mTestableFlinger.enableHalVirtualDisplays(mFdp.ConsumeBool());
+
+ mTestableFlinger.commitTransactionsLocked(mFdp.ConsumeIntegral<uint32_t>());
+
+ mTestableFlinger.notifyPowerBoost(mFdp.ConsumeIntegral<int32_t>());
+
+ setDisplayStateLocked();
+
+ setTransactionState();
+ mTestableFlinger.flushTransactionQueues();
+
+ onTransact(data, size);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ android::fuzz::SurfaceFlingerFuzzer surfaceFlingerFuzzer(data, size);
+ surfaceFlingerFuzzer.process(data, size);
+ return 0;
+}
+
+} // namespace android::fuzz
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
new file mode 100644
index 0000000..0a458c2
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -0,0 +1,803 @@
+/*
+ * 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 <compositionengine/Display.h>
+#include <compositionengine/LayerFECompositionState.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/CompositionEngine.h>
+#include <compositionengine/impl/Display.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/ScreenCaptureResults.h>
+#include <gui/SurfaceComposerClient.h>
+#include <gui/mock/GraphicBufferProducer.h>
+#include <ui/DisplayStatInfo.h>
+#include <ui/DynamicDisplayInfo.h>
+
+#include "BufferQueueLayer.h"
+#include "BufferStateLayer.h"
+#include "ContainerLayer.h"
+#include "DisplayDevice.h"
+#include "DisplayHardware/ComposerHal.h"
+#include "EffectLayer.h"
+#include "FrameTimeline/FrameTimeline.h"
+#include "FrameTracer/FrameTracer.h"
+#include "Layer.h"
+#include "NativeWindowSurface.h"
+#include "Scheduler/EventThread.h"
+#include "Scheduler/MessageQueue.h"
+#include "Scheduler/RefreshRateConfigs.h"
+#include "Scheduler/VSyncTracker.h"
+#include "Scheduler/VsyncConfiguration.h"
+#include "Scheduler/VsyncController.h"
+#include "Scheduler/VsyncModulator.h"
+#include "StartPropertySetThread.h"
+#include "SurfaceFlinger.h"
+#include "SurfaceFlingerDefaultFactory.h"
+#include "SurfaceInterceptor.h"
+#include "TimeStats/TimeStats.h"
+
+#include "renderengine/mock/RenderEngine.h"
+#include "scheduler/TimeKeeper.h"
+#include "tests/unittests/mock/DisplayHardware/MockComposer.h"
+#include "tests/unittests/mock/DisplayHardware/MockHWC2.h"
+#include "tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h"
+#include "tests/unittests/mock/MockEventThread.h"
+#include "tests/unittests/mock/MockFrameTimeline.h"
+#include "tests/unittests/mock/MockFrameTracer.h"
+#include "tests/unittests/mock/MockNativeWindowSurface.h"
+#include "tests/unittests/mock/MockSurfaceInterceptor.h"
+#include "tests/unittests/mock/MockTimeStats.h"
+#include "tests/unittests/mock/MockVSyncTracker.h"
+#include "tests/unittests/mock/MockVsyncController.h"
+
+namespace android {
+namespace Hwc2 {
+
+class Composer;
+
+namespace types = hardware::graphics::common;
+
+namespace V2_1 = hardware::graphics::composer::V2_1;
+namespace V2_2 = hardware::graphics::composer::V2_2;
+namespace V2_3 = hardware::graphics::composer::V2_3;
+namespace V2_4 = hardware::graphics::composer::V2_4;
+
+using types::V1_0::ColorTransform;
+using types::V1_0::Transform;
+using types::V1_1::RenderIntent;
+using types::V1_2::ColorMode;
+using types::V1_2::Dataspace;
+using types::V1_2::Hdr;
+using types::V1_2::PixelFormat;
+
+using V2_1::Config;
+using V2_1::Display;
+using V2_1::Error;
+using V2_1::Layer;
+using V2_4::CommandReaderBase;
+using V2_4::CommandWriterBase;
+using V2_4::IComposer;
+using V2_4::IComposerCallback;
+using V2_4::IComposerClient;
+using V2_4::VsyncPeriodChangeTimeline;
+using V2_4::VsyncPeriodNanos;
+using DisplayCapability = IComposerClient::DisplayCapability;
+using PerFrameMetadata = IComposerClient::PerFrameMetadata;
+using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
+using PerFrameMetadataBlob = IComposerClient::PerFrameMetadataBlob;
+}; // namespace Hwc2
+
+static constexpr hal::HWDisplayId kHwDisplayId = 1000;
+
+static constexpr ui::Hdr kHdrTypes[] = {ui::Hdr::DOLBY_VISION, ui::Hdr::HDR10, ui::Hdr::HLG,
+ ui::Hdr::HDR10_PLUS};
+
+static constexpr ui::ColorMode kColormodes[] = {ui::ColorMode::NATIVE,
+ ui::ColorMode::STANDARD_BT601_625,
+ ui::ColorMode::STANDARD_BT601_625_UNADJUSTED,
+ ui::ColorMode::STANDARD_BT601_525,
+ ui::ColorMode::STANDARD_BT601_525_UNADJUSTED,
+ ui::ColorMode::STANDARD_BT709,
+ ui::ColorMode::DCI_P3,
+ ui::ColorMode::SRGB,
+ ui::ColorMode::ADOBE_RGB,
+ ui::ColorMode::DISPLAY_P3,
+ ui::ColorMode::BT2020,
+ ui::ColorMode::BT2100_PQ,
+ ui::ColorMode::BT2100_HLG,
+ ui::ColorMode::DISPLAY_BT2020};
+
+FloatRect getFuzzedFloatRect(FuzzedDataProvider *fdp) {
+ return FloatRect(fdp->ConsumeFloatingPoint<float>() /*left*/,
+ fdp->ConsumeFloatingPoint<float>() /*right*/,
+ fdp->ConsumeFloatingPoint<float>() /*top*/,
+ fdp->ConsumeFloatingPoint<float>() /*bottom*/);
+}
+
+HdrMetadata getFuzzedHdrMetadata(FuzzedDataProvider *fdp) {
+ HdrMetadata hdrMetadata;
+ if (fdp->ConsumeBool()) {
+ hdrMetadata.cta8613.maxContentLightLevel = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.cta8613.maxFrameAverageLightLevel = fdp->ConsumeFloatingPoint<float>();
+
+ hdrMetadata.validTypes |= HdrMetadata::CTA861_3;
+ } else {
+ hdrMetadata.smpte2086.displayPrimaryRed.x = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.displayPrimaryRed.y = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.displayPrimaryGreen.x = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.displayPrimaryGreen.y = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.displayPrimaryBlue.x = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.displayPrimaryBlue.y = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.whitePoint.x = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.whitePoint.y = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.minLuminance = fdp->ConsumeFloatingPoint<float>();
+ hdrMetadata.smpte2086.maxLuminance = fdp->ConsumeFloatingPoint<float>();
+
+ hdrMetadata.validTypes |= HdrMetadata::SMPTE2086;
+ }
+ return hdrMetadata;
+}
+
+class EventThread;
+
+namespace hal = android::hardware::graphics::composer::hal;
+
+struct FakePhaseOffsets : scheduler::VsyncConfiguration {
+ static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0;
+ static constexpr auto FAKE_DURATION_OFFSET_NS = std::chrono::nanoseconds(0);
+
+ VsyncConfigSet getConfigsForRefreshRate(Fps) const override { return getCurrentConfigs(); }
+
+ VsyncConfigSet getCurrentConfigs() const override {
+ return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS,
+ FAKE_DURATION_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS,
+ FAKE_DURATION_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS,
+ FAKE_DURATION_OFFSET_NS},
+ FAKE_DURATION_OFFSET_NS};
+ }
+
+ void reset() override {}
+ void setRefreshRateFps(Fps) override {}
+ void dump(std::string &) const override {}
+};
+namespace scheduler {
+class TestableScheduler : public Scheduler, private ICompositor {
+public:
+ TestableScheduler(const std::shared_ptr<scheduler::RefreshRateConfigs> &refreshRateConfigs,
+ ISchedulerCallback &callback)
+ : TestableScheduler(std::make_unique<android::mock::VsyncController>(),
+ std::make_unique<android::mock::VSyncTracker>(), refreshRateConfigs,
+ callback) {}
+
+ void scheduleFrame(){};
+ void postMessage(sp<MessageHandler> &&){};
+
+ TestableScheduler(std::unique_ptr<VsyncController> controller,
+ std::unique_ptr<VSyncTracker> tracker,
+ std::shared_ptr<RefreshRateConfigs> configs, ISchedulerCallback &callback)
+ : Scheduler(*this, callback, Feature::kContentDetection) {
+ mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
+ setRefreshRateConfigs(std::move(configs));
+ }
+
+ ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {
+ return Scheduler::createConnection(std::move(eventThread));
+ }
+
+ auto &mutablePrimaryHWVsyncEnabled() { return mPrimaryHWVsyncEnabled; }
+ auto &mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
+
+ auto &mutableLayerHistory() { return mLayerHistory; }
+
+ auto refreshRateConfigs() { return holdRefreshRateConfigs(); }
+
+ void replaceTouchTimer(int64_t millis) {
+ if (mTouchTimer) {
+ mTouchTimer.reset();
+ }
+ mTouchTimer.emplace(
+ "Testable Touch timer", std::chrono::milliseconds(millis),
+ [this] { touchTimerCallback(TimerState::Reset); },
+ [this] { touchTimerCallback(TimerState::Expired); });
+ mTouchTimer->start();
+ }
+
+ bool isTouchActive() {
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ return mPolicy.touch == Scheduler::TouchState::Active;
+ }
+
+ void dispatchCachedReportedMode() {
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ return Scheduler::dispatchCachedReportedMode();
+ }
+
+ void clearCachedReportedMode() {
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ mPolicy.cachedModeChangedParams.reset();
+ }
+
+ void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
+ return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode);
+ }
+
+private:
+ // ICompositor overrides:
+ bool commit(nsecs_t, int64_t, nsecs_t) override { return false; }
+ void composite(nsecs_t) override {}
+ void sample() override {}
+};
+}; // namespace scheduler
+
+namespace surfaceflinger::test {
+
+class Factory final : public surfaceflinger::Factory {
+public:
+ ~Factory() = default;
+
+ std::unique_ptr<HWComposer> createHWComposer(const std::string &) override { return nullptr; }
+
+ std::unique_ptr<MessageQueue> createMessageQueue(ICompositor &compositor) {
+ return std::make_unique<android::impl::MessageQueue>(compositor);
+ }
+
+ std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
+ Fps /*currentRefreshRate*/) override {
+ return std::make_unique<FakePhaseOffsets>();
+ }
+
+ std::unique_ptr<scheduler::Scheduler> createScheduler(
+ const std::shared_ptr<scheduler::RefreshRateConfigs> &,
+ scheduler::ISchedulerCallback &) {
+ return nullptr;
+ }
+
+ sp<SurfaceInterceptor> createSurfaceInterceptor() override {
+ return new android::impl::SurfaceInterceptor();
+ }
+
+ sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override {
+ return new StartPropertySetThread(timestampPropertyValue);
+ }
+
+ sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs &creationArgs) override {
+ return new DisplayDevice(creationArgs);
+ }
+
+ sp<GraphicBuffer> createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format,
+ uint32_t layerCount, uint64_t usage,
+ std::string requestorName) override {
+ return new GraphicBuffer(width, height, format, layerCount, usage, requestorName);
+ }
+
+ void createBufferQueue(sp<IGraphicBufferProducer> *outProducer,
+ sp<IGraphicBufferConsumer> *outConsumer,
+ bool consumerIsSurfaceFlinger) override {
+ if (!mCreateBufferQueue) {
+ BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
+ return;
+ }
+ mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
+ }
+
+ sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer> &producer,
+ const sp<SurfaceFlinger> &flinger,
+ const wp<Layer> &layer) override {
+ return new MonitoredProducer(producer, flinger, layer);
+ }
+
+ sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer> &consumer,
+ renderengine::RenderEngine &renderEngine,
+ uint32_t textureName, Layer *layer) override {
+ return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
+ }
+
+ std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
+ const sp<IGraphicBufferProducer> &producer) override {
+ if (!mCreateNativeWindowSurface) return nullptr;
+ return mCreateNativeWindowSurface(producer);
+ }
+
+ std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
+ return compositionengine::impl::createCompositionEngine();
+ }
+
+ sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs &) override {
+ return nullptr;
+ }
+
+ sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs &) override {
+ return nullptr;
+ }
+
+ sp<EffectLayer> createEffectLayer(const LayerCreationArgs &args) override {
+ return new EffectLayer(args);
+ }
+
+ sp<ContainerLayer> createContainerLayer(const LayerCreationArgs &args) override {
+ return new ContainerLayer(args);
+ }
+
+ std::unique_ptr<FrameTracer> createFrameTracer() override {
+ return std::make_unique<android::mock::FrameTracer>();
+ }
+
+ std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
+ std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid = 0) override {
+ return std::make_unique<android::mock::FrameTimeline>(timeStats, surfaceFlingerPid);
+ }
+
+ using CreateBufferQueueFunction =
+ std::function<void(sp<IGraphicBufferProducer> * /* outProducer */,
+ sp<IGraphicBufferConsumer> * /* outConsumer */,
+ bool /* consumerIsSurfaceFlinger */)>;
+ CreateBufferQueueFunction mCreateBufferQueue;
+
+ using CreateNativeWindowSurfaceFunction =
+ std::function<std::unique_ptr<surfaceflinger::NativeWindowSurface>(
+ const sp<IGraphicBufferProducer> &)>;
+ CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
+ using CreateCompositionEngineFunction =
+ std::function<std::unique_ptr<compositionengine::CompositionEngine>()>;
+ CreateCompositionEngineFunction mCreateCompositionEngine;
+};
+
+} // namespace surfaceflinger::test
+
+// TODO(b/189053744) : Create a common test/mock library for surfaceflinger
+class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback {
+public:
+ using HotplugEvent = SurfaceFlinger::HotplugEvent;
+
+ SurfaceFlinger *flinger() { return mFlinger.get(); }
+ scheduler::TestableScheduler *scheduler() { return mScheduler; }
+
+ // Allow reading display state without locking, as if called on the SF main thread.
+ auto onInitializeDisplays() NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->onInitializeDisplays();
+ }
+
+ void scheduleComposite(FrameHint){};
+
+ void setGlobalShadowSettings(FuzzedDataProvider *fdp) {
+ const half4 ambientColor{fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>()};
+ const half4 spotColor{fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>(),
+ fdp->ConsumeFloatingPoint<float>()};
+ float lightPosY = fdp->ConsumeFloatingPoint<float>();
+ float lightPosZ = fdp->ConsumeFloatingPoint<float>();
+ float lightRadius = fdp->ConsumeFloatingPoint<float>();
+ mFlinger->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ,
+ lightRadius);
+ }
+
+ void onPullAtom(FuzzedDataProvider *fdp) {
+ const int32_t atomId = fdp->ConsumeIntegral<uint8_t>();
+ std::string pulledData = fdp->ConsumeRandomLengthString().c_str();
+ bool success = fdp->ConsumeBool();
+ mFlinger->onPullAtom(atomId, &pulledData, &success);
+ }
+
+ void fuzzDumpsysAndDebug(FuzzedDataProvider *fdp) {
+ std::string result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->appendSfConfigString(result);
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->listLayersLocked(result);
+
+ using DumpArgs = Vector<String16>;
+ DumpArgs dumpArgs;
+ dumpArgs.push_back(String16(fdp->ConsumeRandomLengthString().c_str()));
+ mFlinger->clearStatsLocked(dumpArgs, result);
+
+ mFlinger->dumpTimeStats(dumpArgs, fdp->ConsumeBool(), result);
+ mFlinger->logFrameStats();
+
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->dumpFrameTimeline(dumpArgs, result);
+
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->dumpStaticScreenStats(result);
+
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->dumpFrameEventsLocked(result);
+
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result);
+
+ LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral<uint32_t>());
+ mFlinger->dumpOffscreenLayersProto(layersProto);
+ LayersTraceProto layersTraceProto{};
+ mFlinger->dumpDisplayProto(layersTraceProto);
+
+ result = fdp->ConsumeRandomLengthString().c_str();
+ mFlinger->dumpHwc(result);
+
+ mFlinger->calculateColorMatrix(fdp->ConsumeFloatingPoint<float>());
+ mFlinger->updateColorMatrixLocked();
+ mFlinger->CheckTransactCodeCredentials(fdp->ConsumeIntegral<uint32_t>());
+
+ const CountDownLatch transactionCommittedSignal(fdp->ConsumeIntegral<uint32_t>());
+ mFlinger->waitForSynchronousTransaction(transactionCommittedSignal);
+ mFlinger->signalSynchronousTransactions(fdp->ConsumeIntegral<uint32_t>());
+ }
+
+ void getCompositionPreference() {
+ ui::Dataspace outDataspace;
+ ui::PixelFormat outPixelFormat;
+ ui::Dataspace outWideColorGamutDataspace;
+ ui::PixelFormat outWideColorGamutPixelFormat;
+ mFlinger->getCompositionPreference(&outDataspace, &outPixelFormat,
+ &outWideColorGamutDataspace,
+ &outWideColorGamutPixelFormat);
+ }
+
+ void overrideHdrTypes(sp<IBinder> &display, FuzzedDataProvider *fdp) {
+ std::vector<ui::Hdr> hdrTypes;
+ hdrTypes.push_back(fdp->PickValueInArray(kHdrTypes));
+ mFlinger->overrideHdrTypes(display, hdrTypes);
+ }
+
+ void getDisplayedContentSample(sp<IBinder> &display, FuzzedDataProvider *fdp) {
+ DisplayedFrameStats outDisplayedFrameStats;
+ mFlinger->getDisplayedContentSample(display, fdp->ConsumeIntegral<uint64_t>(),
+ fdp->ConsumeIntegral<uint64_t>(),
+ &outDisplayedFrameStats);
+ }
+
+ void getDisplayStats(sp<IBinder> &display) {
+ android::DisplayStatInfo stats;
+ mFlinger->getDisplayStats(display, &stats);
+ }
+
+ void getDisplayState(sp<IBinder> &display) {
+ ui::DisplayState displayState;
+ mFlinger->getDisplayState(display, &displayState);
+ }
+
+ void getStaticDisplayInfo(sp<IBinder> &display) {
+ ui::StaticDisplayInfo staticDisplayInfo;
+ mFlinger->getStaticDisplayInfo(display, &staticDisplayInfo);
+ }
+
+ void getDynamicDisplayInfo(sp<IBinder> &display) {
+ android::ui::DynamicDisplayInfo dynamicDisplayInfo;
+ mFlinger->getDynamicDisplayInfo(display, &dynamicDisplayInfo);
+ }
+ void getDisplayNativePrimaries(sp<IBinder> &display) {
+ android::ui::DisplayPrimaries displayPrimaries;
+ mFlinger->getDisplayNativePrimaries(display, displayPrimaries);
+ }
+
+ void getDesiredDisplayModeSpecs(sp<IBinder> &display) {
+ ui::DisplayModeId outDefaultMode;
+ bool outAllowGroupSwitching;
+ float outPrimaryRefreshRateMin;
+ float outPrimaryRefreshRateMax;
+ float outAppRequestRefreshRateMin;
+ float outAppRequestRefreshRateMax;
+ mFlinger->getDesiredDisplayModeSpecs(display, &outDefaultMode, &outAllowGroupSwitching,
+ &outPrimaryRefreshRateMin, &outPrimaryRefreshRateMax,
+ &outAppRequestRefreshRateMin,
+ &outAppRequestRefreshRateMax);
+ }
+
+ void setVsyncConfig(FuzzedDataProvider *fdp) {
+ const scheduler::VsyncModulator::VsyncConfig vsyncConfig{};
+ mFlinger->setVsyncConfig(vsyncConfig, fdp->ConsumeIntegral<nsecs_t>());
+ }
+
+ void updateCompositorTiming(FuzzedDataProvider *fdp) {
+ std::shared_ptr<FenceTime> presentFenceTime = FenceTime::NO_FENCE;
+ mFlinger->updateCompositorTiming({}, fdp->ConsumeIntegral<nsecs_t>(), presentFenceTime);
+ }
+
+ void getCompositorTiming() {
+ CompositorTiming compositorTiming;
+ mFlinger->getCompositorTiming(&compositorTiming);
+ }
+
+ sp<IBinder> fuzzBoot(FuzzedDataProvider *fdp) {
+ mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(fdp->ConsumeBool());
+ mFlinger->createConnection();
+
+ DisplayIdGenerator<HalVirtualDisplayId> kGenerator;
+ HalVirtualDisplayId halVirtualDisplayId = kGenerator.generateId().value();
+
+ ui::Size uiSize{fdp->ConsumeIntegral<int32_t>(), fdp->ConsumeIntegral<int32_t>()};
+ ui::PixelFormat pixelFormat{};
+ mFlinger->getHwComposer().allocateVirtualDisplay(halVirtualDisplayId, uiSize, &pixelFormat);
+
+ PhysicalDisplayId physicalDisplayId = SurfaceComposerClient::getInternalDisplayId().value();
+ mFlinger->getHwComposer().allocatePhysicalDisplay(kHwDisplayId, physicalDisplayId);
+
+ sp<IBinder> display =
+ mFlinger->createDisplay(String8(fdp->ConsumeRandomLengthString().c_str()),
+ fdp->ConsumeBool());
+
+ onInitializeDisplays();
+ mFlinger->getPhysicalDisplayToken(physicalDisplayId);
+
+ mFlinger->mStartPropertySetThread =
+ mFlinger->getFactory().createStartPropertySetThread(fdp->ConsumeBool());
+
+ mFlinger->bootFinished();
+
+ return display;
+ }
+
+ void fuzzSurfaceFlinger(const uint8_t *data, size_t size) {
+ FuzzedDataProvider mFdp(data, size);
+
+ sp<IBinder> display = fuzzBoot(&mFdp);
+
+ sp<IGraphicBufferProducer> bufferProducer = sp<mock::GraphicBufferProducer>::make();
+ mFlinger->authenticateSurfaceTexture(bufferProducer.get());
+
+ mFlinger->createDisplayEventConnection();
+
+ getDisplayStats(display);
+ getDisplayState(display);
+ getStaticDisplayInfo(display);
+ getDynamicDisplayInfo(display);
+ getDisplayNativePrimaries(display);
+
+ mFlinger->setAutoLowLatencyMode(display, mFdp.ConsumeBool());
+ mFlinger->setGameContentType(display, mFdp.ConsumeBool());
+ mFlinger->setPowerMode(display, mFdp.ConsumeIntegral<int>());
+ mFlinger->clearAnimationFrameStats();
+
+ overrideHdrTypes(display, &mFdp);
+
+ onPullAtom(&mFdp);
+
+ mFlinger->injectVSync(mFdp.ConsumeIntegral<nsecs_t>());
+
+ getCompositionPreference();
+ getDisplayedContentSample(display, &mFdp);
+ getDesiredDisplayModeSpecs(display);
+
+ bool outSupport;
+ mFlinger->getDisplayBrightnessSupport(display, &outSupport);
+
+ mFlinger->notifyPowerBoost(mFdp.ConsumeIntegral<int32_t>());
+
+ setGlobalShadowSettings(&mFdp);
+
+ mFlinger->binderDied(display);
+ mFlinger->onFirstRef();
+
+ mFlinger->commitTransactions();
+ mFlinger->updateInputFlinger();
+ mFlinger->updateCursorAsync();
+
+ setVsyncConfig(&mFdp);
+
+ mFlinger->flushTransactionQueues(0);
+
+ mFlinger->setTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
+ mFlinger->clearTransactionFlags(mFdp.ConsumeIntegral<uint32_t>());
+ mFlinger->commitOffscreenLayers();
+
+ mFlinger->frameIsEarly(mFdp.ConsumeIntegral<nsecs_t>(), mFdp.ConsumeIntegral<int64_t>());
+ mFlinger->computeLayerBounds();
+ mFlinger->startBootAnim();
+
+ mFlinger->readPersistentProperties();
+
+ mFlinger->exceedsMaxRenderTargetSize(mFdp.ConsumeIntegral<uint32_t>(),
+ mFdp.ConsumeIntegral<uint32_t>());
+
+ mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mFdp.ConsumeIntegral<uid_t>());
+
+ mFlinger->postComposition();
+
+ getCompositorTiming();
+
+ updateCompositorTiming(&mFdp);
+
+ mFlinger->setCompositorTimingSnapped({}, mFdp.ConsumeIntegral<nsecs_t>());
+ mFlinger->postFrame();
+ mFlinger->calculateExpectedPresentTime({});
+
+ mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool());
+
+ fuzzDumpsysAndDebug(&mFdp);
+
+ mFlinger->destroyDisplay(display);
+ }
+
+ void setupRenderEngine(std::unique_ptr<renderengine::RenderEngine> renderEngine) {
+ mFlinger->mCompositionEngine->setRenderEngine(std::move(renderEngine));
+ }
+
+ void setupComposer(std::unique_ptr<Hwc2::Composer> composer) {
+ mFlinger->mCompositionEngine->setHwComposer(
+ std::make_unique<impl::HWComposer>(std::move(composer)));
+ }
+
+ void setupTimeStats(const std::shared_ptr<TimeStats> &timeStats) {
+ mFlinger->mCompositionEngine->setTimeStats(timeStats);
+ }
+
+ // The ISchedulerCallback argument can be nullptr for a no-op implementation.
+ 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()};
+
+ if (hasMultipleModes) {
+ modes.emplace_back(DisplayMode::Builder(1)
+ .setId(DisplayModeId(1))
+ .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
+ .setVsyncPeriod(11'111'111)
+ .setGroup(0)
+ .build());
+ }
+
+ const auto currMode = DisplayModeId(0);
+ mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
+ const auto currFps = mRefreshRateConfigs->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);
+
+ mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
+ std::move(vsyncTracker), mRefreshRateConfigs,
+ *(callback ?: this));
+
+ mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
+ mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
+ resetScheduler(mScheduler);
+ }
+
+ void resetScheduler(scheduler::Scheduler *scheduler) { mFlinger->mScheduler.reset(scheduler); }
+
+ scheduler::TestableScheduler &mutableScheduler() const { return *mScheduler; }
+
+ using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
+ void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
+ mFactory.mCreateBufferQueue = f;
+ }
+
+ using CreateNativeWindowSurfaceFunction =
+ surfaceflinger::test::Factory::CreateNativeWindowSurfaceFunction;
+ void setCreateNativeWindowSurface(CreateNativeWindowSurfaceFunction f) {
+ mFactory.mCreateNativeWindowSurface = f;
+ }
+
+ void setInternalDisplayPrimaries(const ui::DisplayPrimaries &primaries) {
+ memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries));
+ }
+
+ static auto &mutableLayerDrawingState(const sp<Layer> &layer) { return layer->mDrawingState; }
+
+ auto &mutableStateLock() { return mFlinger->mStateLock; }
+
+ static auto findOutputLayerForDisplay(const sp<Layer> &layer,
+ const sp<const DisplayDevice> &display) {
+ return layer->findOutputLayerForDisplay(display.get());
+ }
+
+ /* ------------------------------------------------------------------------
+ * Forwarding for functions being tested
+ */
+
+ void enableHalVirtualDisplays(bool enable) { mFlinger->enableHalVirtualDisplays(enable); }
+
+ auto commitTransactionsLocked(uint32_t transactionFlags) {
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ return mFlinger->commitTransactionsLocked(transactionFlags);
+ }
+
+ auto setDisplayStateLocked(const DisplayState &s) {
+ Mutex::Autolock lock(mFlinger->mStateLock);
+ return mFlinger->setDisplayStateLocked(s);
+ }
+
+ auto notifyPowerBoost(int32_t boostId) { return mFlinger->notifyPowerBoost(boostId); }
+
+ // Allow reading display state without locking, as if called on the SF main thread.
+ auto setPowerModeInternal(const sp<DisplayDevice> &display,
+ hal::PowerMode mode) NO_THREAD_SAFETY_ANALYSIS {
+ return mFlinger->setPowerModeInternal(display, mode);
+ }
+
+ auto onMessageReceived(int32_t /*what*/) { return 0; }
+
+ auto &getTransactionQueue() { return mFlinger->mTransactionQueue; }
+ auto &getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
+
+ auto setTransactionState(
+ const FrameTimelineInfo &frameTimelineInfo, const Vector<ComposerState> &states,
+ const Vector<DisplayState> &displays, uint32_t flags, const sp<IBinder> &applyToken,
+ const InputWindowCommands &inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t &uncacheBuffer, bool hasListenerCallbacks,
+ std::vector<ListenerCallbacks> &listenerCallbacks, uint64_t transactionId) {
+ return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime,
+ isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
+ listenerCallbacks, transactionId);
+ }
+
+ auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(0); };
+
+ auto onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
+ return mFlinger->onTransact(code, data, reply, flags);
+ }
+
+ auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
+
+ auto calculateMaxAcquiredBufferCount(Fps refreshRate,
+ std::chrono::nanoseconds presentLatency) const {
+ return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
+ }
+
+ /* Read-write access to private data to set up preconditions and assert
+ * post-conditions.
+ */
+
+ auto &mutableCurrentState() { return mFlinger->mCurrentState; }
+ auto &mutableDisplays() { return mFlinger->mDisplays; }
+ auto &mutableDrawingState() { return mFlinger->mDrawingState; }
+ auto &mutableInterceptor() { return mFlinger->mInterceptor; }
+
+ auto fromHandle(const sp<IBinder> &handle) { return mFlinger->fromHandle(handle); }
+
+ ~TestableSurfaceFlinger() {
+ mutableDisplays().clear();
+ mutableCurrentState().displays.clear();
+ mutableDrawingState().displays.clear();
+ mutableInterceptor().clear();
+ mFlinger->mScheduler.reset();
+ mFlinger->mCompositionEngine->setHwComposer(std::unique_ptr<HWComposer>());
+ mFlinger->mCompositionEngine->setRenderEngine(
+ std::unique_ptr<renderengine::RenderEngine>());
+ }
+
+private:
+ void scheduleRefresh(FrameHint) {}
+ 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::TestableScheduler *mScheduler = nullptr;
+ std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
+};
+} // namespace android