Loading services/surfaceflinger/fuzzer/Android.bp +10 −0 Original line number Diff line number Diff line Loading @@ -92,3 +92,13 @@ cc_fuzz { "android.hardware.graphics.composer@2.4-hal", ], } cc_fuzz { name: "surfaceflinger_scheduler_fuzzer", defaults: [ "surfaceflinger_fuzz_defaults", ], srcs: [ "surfaceflinger_scheduler_fuzzer.cpp", ], } services/surfaceflinger/fuzzer/README.md +19 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ ## Table of contents + [SurfaceFlinger](#SurfaceFlinger) + [DisplayHardware](#DisplayHardware) + [Scheduler](#Scheduler) # <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger Loading Loading @@ -51,3 +52,21 @@ You can find the possible values in the fuzzer's source code. $ adb sync data $ adb shell /data/fuzz/arm64/surfaceflinger_displayhardware_fuzzer/surfaceflinger_displayhardware_fuzzer ``` # <a name="Scheduler"></a> Fuzzer for Scheduler Scheduler supports the following parameters: 1. VSync Periods (parameter name: `lowFpsPeriod`) You can find the possible values in the fuzzer's source code. #### Steps to run 1. Build the fuzzer ``` $ mm -j$(nproc) surfaceflinger_scheduler_fuzzer ``` 2. To run on device ``` $ adb sync data $ adb shell /data/fuzz/arm64/surfaceflinger_scheduler_fuzzer/surfaceflinger_scheduler_fuzzer ``` services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp 0 → 100644 +392 −0 Original line number Diff line number Diff line /* * 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 "surfaceflinger_scheduler_fuzzer.h" #include <fuzzer/FuzzedDataProvider.h> #include <processgroup/sched_policy.h> #include "Scheduler/DispSyncSource.h" #include "Scheduler/OneShotTimer.h" #include "Scheduler/VSyncDispatchTimerQueue.h" #include "Scheduler/VSyncPredictor.h" #include "Scheduler/VSyncReactor.h" #include "surfaceflinger_fuzzers_utils.h" namespace android::fuzz { using hardware::graphics::composer::hal::PowerMode; static constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF, PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND}; constexpr uint16_t kRandomStringLength = 256; constexpr std::chrono::duration kSyncPeriod(16ms); template <typename T> void dump(T* component, FuzzedDataProvider* fdp) { std::string res = fdp->ConsumeRandomLengthString(kRandomStringLength); component->dump(res); } class SchedulerFuzzer : private VSyncSource::Callback { public: SchedulerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; void process(); private: void fuzzRefreshRateSelection(); void fuzzRefreshRateConfigs(); void fuzzVSyncModulator(); void fuzzVSyncPredictor(); void fuzzVSyncReactor(); void fuzzLayerHistory(); void fuzzDispSyncSource(); void fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch); void fuzzVSyncDispatchTimerQueue(); void fuzzOneShotTimer(); void fuzzEventThread(); PhysicalDisplayId getPhysicalDisplayId(); FuzzedDataProvider mFdp; protected: void onVSyncEvent(nsecs_t /* when */, nsecs_t /* expectedVSyncTimestamp */, nsecs_t /* deadlineTimestamp */) {} }; PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() { PhysicalDisplayId internalDispId = PhysicalDisplayId::fromPort(111u); PhysicalDisplayId externalDispId = PhysicalDisplayId::fromPort(222u); PhysicalDisplayId randomDispId = PhysicalDisplayId::fromPort(mFdp.ConsumeIntegral<uint16_t>()); PhysicalDisplayId dispId64Bit = PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu); PhysicalDisplayId displayId = mFdp.PickValueInArray<PhysicalDisplayId>( {internalDispId, externalDispId, dispId64Bit, randomDispId}); return displayId; } void SchedulerFuzzer::fuzzEventThread() { const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); }; std::unique_ptr<android::impl::EventThread> thread = std::make_unique< android::impl::EventThread>(std::move(std::make_unique<FuzzImplVSyncSource>()), nullptr, nullptr, nullptr, getVsyncPeriod); thread->onHotplugReceived(getPhysicalDisplayId(), mFdp.ConsumeBool()); sp<EventThreadConnection> connection = new EventThreadConnection(thread.get(), mFdp.ConsumeIntegral<uint16_t>(), nullptr, {} /*eventRegistration*/); thread->requestNextVsync(connection); thread->setVsyncRate(mFdp.ConsumeIntegral<uint32_t>() /*rate*/, connection); thread->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); thread->registerDisplayEventConnection(connection); thread->onScreenAcquired(); thread->onScreenReleased(); dump<android::impl::EventThread>(thread.get(), &mFdp); } void SchedulerFuzzer::fuzzDispSyncSource() { std::unique_ptr<FuzzImplVSyncDispatch> vSyncDispatch = std::make_unique<FuzzImplVSyncDispatch>(); std::unique_ptr<scheduler::DispSyncSource> dispSyncSource = std::make_unique< scheduler::DispSyncSource>(*vSyncDispatch, (std::chrono::nanoseconds) mFdp.ConsumeIntegral<uint64_t>() /*workDuration*/, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>() /*readyDuration*/, mFdp.ConsumeBool(), mFdp.ConsumeRandomLengthString(kRandomStringLength).c_str()); dispSyncSource->setVSyncEnabled(true); dispSyncSource->setCallback(this); dispSyncSource->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), 0ns); dump<scheduler::DispSyncSource>(dispSyncSource.get(), &mFdp); } void SchedulerFuzzer::fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch) { scheduler::VSyncDispatch::CallbackToken tmp = dispatch->registerCallback( [&](auto, auto, auto) { dispatch->schedule(tmp, {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); }, "o.o"); dispatch->schedule(tmp, {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); dispatch->unregisterCallback(tmp); dispatch->cancel(tmp); } void SchedulerFuzzer::fuzzVSyncDispatchTimerQueue() { FuzzImplVSyncTracker stubTracker{mFdp.ConsumeIntegral<nsecs_t>()}; scheduler::VSyncDispatchTimerQueue mDispatch{std::make_unique<scheduler::ControllableClock>(), stubTracker, mFdp.ConsumeIntegral<nsecs_t>() /*dispatchGroupThreshold*/, mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/}; fuzzCallbackToken(&mDispatch); dump<scheduler::VSyncDispatchTimerQueue>(&mDispatch, &mFdp); scheduler::VSyncDispatchTimerQueueEntry entry( "fuzz", [](auto, auto, auto) {}, mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/); entry.update(stubTracker, 0); entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}, stubTracker, 0); entry.disarm(); entry.ensureNotRunning(); entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}, stubTracker, 0); auto const wakeup = entry.wakeupTime(); auto const ready = entry.readyTime(); entry.callback(entry.executing(), *wakeup, *ready); entry.addPendingWorkloadUpdate({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); dump<scheduler::VSyncDispatchTimerQueueEntry>(&entry, &mFdp); } void SchedulerFuzzer::fuzzVSyncPredictor() { uint16_t now = mFdp.ConsumeIntegral<uint16_t>(); uint16_t historySize = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX); uint16_t minimumSamplesForPrediction = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX); scheduler::VSyncPredictor tracker{mFdp.ConsumeIntegral<uint16_t>() /*period*/, historySize, minimumSamplesForPrediction, mFdp.ConsumeIntegral<uint32_t>() /*outlierTolerancePercent*/}; uint16_t period = mFdp.ConsumeIntegral<uint16_t>(); tracker.setPeriod(period); for (uint16_t i = 0; i < minimumSamplesForPrediction; ++i) { if (!tracker.needsMoreSamples()) { break; } tracker.addVsyncTimestamp(now += period); } tracker.nextAnticipatedVSyncTimeFrom(now); tracker.resetModel(); } void SchedulerFuzzer::fuzzOneShotTimer() { FakeClock* clock = new FakeClock(); std::unique_ptr<scheduler::OneShotTimer> idleTimer = std::make_unique<scheduler::OneShotTimer>( mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/, (std::chrono::milliseconds)mFdp.ConsumeIntegral<uint8_t>() /*val*/, [] {} /*resetCallback*/, [] {} /*timeoutCallback*/, std::unique_ptr<FakeClock>(clock)); idleTimer->start(); idleTimer->reset(); idleTimer->stop(); } void SchedulerFuzzer::fuzzLayerHistory() { TestableSurfaceFlinger flinger; flinger.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>()); flinger.setupTimeStats(std::make_unique<android::mock::TimeStats>()); std::unique_ptr<android::renderengine::RenderEngine> renderEngine = std::make_unique<android::renderengine::mock::RenderEngine>(); flinger.setupRenderEngine(std::move(renderEngine)); flinger.setupComposer(std::make_unique<android::Hwc2::mock::Composer>()); scheduler::TestableScheduler* scheduler = flinger.scheduler(); scheduler::LayerHistory& historyV1 = scheduler->mutableLayerHistory(); nsecs_t time1 = systemTime(); nsecs_t time2 = time1; uint8_t historySize = mFdp.ConsumeIntegral<uint8_t>(); sp<FuzzImplLayer> layer1 = new FuzzImplLayer(flinger.flinger()); sp<FuzzImplLayer> layer2 = new FuzzImplLayer(flinger.flinger()); for (int i = 0; i < historySize; ++i) { historyV1.record(layer1.get(), time1, time1, scheduler::LayerHistory::LayerUpdateType::Buffer); historyV1.record(layer2.get(), time2, time2, scheduler::LayerHistory::LayerUpdateType::Buffer); time1 += mFdp.PickValueInArray(kVsyncPeriods); time2 += mFdp.PickValueInArray(kVsyncPeriods); } historyV1.summarize(*scheduler->refreshRateConfigs(), time1); historyV1.summarize(*scheduler->refreshRateConfigs(), time2); scheduler->createConnection(std::make_unique<android::mock::EventThread>()); scheduler::ConnectionHandle handle; scheduler->createDisplayEventConnection(handle); scheduler->setDuration(handle, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); dump<scheduler::TestableScheduler>(scheduler, &mFdp); } void SchedulerFuzzer::fuzzVSyncReactor() { std::shared_ptr<FuzzImplVSyncTracker> vSyncTracker = std::make_shared<FuzzImplVSyncTracker>(); scheduler::VSyncReactor reactor(std::make_unique<ClockWrapper>( std::make_shared<FuzzImplClock>()), *vSyncTracker, mFdp.ConsumeIntegral<uint8_t>() /*pendingLimit*/, false); reactor.startPeriodTransition(mFdp.ConsumeIntegral<nsecs_t>()); bool periodFlushed = mFdp.ConsumeBool(); reactor.addHwVsyncTimestamp(0, std::nullopt, &periodFlushed); reactor.addHwVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>() /*newPeriod*/, std::nullopt, &periodFlushed); sp<Fence> fence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING)); std::shared_ptr<FenceTime> ft = std::make_shared<FenceTime>(fence); vSyncTracker->addVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>()); FenceTime::Snapshot snap(mFdp.ConsumeIntegral<nsecs_t>()); ft->applyTrustedSnapshot(snap); reactor.setIgnorePresentFences(mFdp.ConsumeBool()); reactor.addPresentFence(ft); dump<scheduler::VSyncReactor>(&reactor, &mFdp); } void SchedulerFuzzer::fuzzVSyncModulator() { enum { SF_OFFSET_LATE, APP_OFFSET_LATE, SF_DURATION_LATE, APP_DURATION_LATE, SF_OFFSET_EARLY, APP_OFFSET_EARLY, SF_DURATION_EARLY, APP_DURATION_EARLY, SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU, SF_DURATION_EARLY_GPU, APP_DURATION_EARLY_GPU, HWC_MIN_WORK_DURATION, }; using Schedule = scheduler::TransactionSchedule; using nanos = std::chrono::nanoseconds; using VsyncModulator = scheduler::VsyncModulator; using FuzzImplVsyncModulator = scheduler::FuzzImplVsyncModulator; const VsyncModulator::VsyncConfig early{SF_OFFSET_EARLY, APP_OFFSET_EARLY, nanos(SF_DURATION_LATE), nanos(APP_DURATION_LATE)}; const VsyncModulator::VsyncConfig earlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU, nanos(SF_DURATION_EARLY), nanos(APP_DURATION_EARLY)}; const VsyncModulator::VsyncConfig late{SF_OFFSET_LATE, APP_OFFSET_LATE, nanos(SF_DURATION_EARLY_GPU), nanos(APP_DURATION_EARLY_GPU)}; const VsyncModulator::VsyncConfigSet offsets = {early, earlyGpu, late, nanos(HWC_MIN_WORK_DURATION)}; sp<FuzzImplVsyncModulator> vSyncModulator = sp<FuzzImplVsyncModulator>::make(offsets, scheduler::Now); (void)vSyncModulator->setVsyncConfigSet(offsets); (void)vSyncModulator->setTransactionSchedule(Schedule::Late); const auto token = sp<BBinder>::make(); (void)vSyncModulator->setTransactionSchedule(Schedule::EarlyStart, token); vSyncModulator->binderDied(token); } void SchedulerFuzzer::fuzzRefreshRateSelection() { TestableSurfaceFlinger flinger; flinger.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>()); sp<Client> client; LayerCreationArgs args(flinger.flinger(), client, mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/, mFdp.ConsumeIntegral<uint16_t>() /*layerFlags*/, LayerMetadata()); sp<Layer> layer = new BufferQueueLayer(args); layer->setFrameRateSelectionPriority(mFdp.ConsumeIntegral<int16_t>()); } void SchedulerFuzzer::fuzzRefreshRateConfigs() { using RefreshRateConfigs = scheduler::RefreshRateConfigs; using LayerRequirement = RefreshRateConfigs::LayerRequirement; using RefreshRateStats = scheduler::RefreshRateStats; uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1); uint16_t maxRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX); DisplayModeId hwcConfigIndexType = DisplayModeId(mFdp.ConsumeIntegralInRange<uint8_t>(0, 10)); DisplayModes displayModes; for (uint16_t fps = minRefreshRate; fps < maxRefreshRate; ++fps) { constexpr int32_t kGroup = 0; const auto refreshRate = Fps::fromValue(static_cast<float>(fps)); displayModes.push_back(scheduler::createDisplayMode(hwcConfigIndexType, kGroup, refreshRate.getPeriodNsecs())); } auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(displayModes, hwcConfigIndexType); const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false}; auto layers = std::vector<LayerRequirement>{ LayerRequirement{.weight = mFdp.ConsumeFloatingPoint<float>()}}; refreshRateConfigs->getBestRefreshRate(layers, globalSignals); layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength); layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>(); layers[0].desiredRefreshRate = Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()); layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes); auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps::fromValue( mFdp.ConsumeFloatingPoint<float>()), globalSignals); refreshRateConfigs->setDisplayManagerPolicy( {hwcConfigIndexType, {Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}}); refreshRateConfigs->setCurrentModeId(hwcConfigIndexType); RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue( mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue( mFdp.ConsumeFloatingPoint<float>())); RefreshRateConfigs::getFrameRateDivider(Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())); android::mock::TimeStats timeStats; std::unique_ptr<RefreshRateStats> refreshRateStats = std::make_unique<RefreshRateStats>(timeStats, Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), PowerMode::OFF); refreshRateStats->setRefreshRate( refreshRateConfigs->getRefreshRateFromModeId(hwcConfigIndexType).getFps()); refreshRateStats->setPowerMode(mFdp.PickValueInArray(kPowerModes)); } void SchedulerFuzzer::process() { fuzzRefreshRateSelection(); fuzzRefreshRateConfigs(); fuzzVSyncModulator(); fuzzVSyncPredictor(); fuzzVSyncReactor(); fuzzLayerHistory(); fuzzDispSyncSource(); fuzzEventThread(); fuzzVSyncDispatchTimerQueue(); fuzzOneShotTimer(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { SchedulerFuzzer schedulerFuzzer(data, size); schedulerFuzzer.process(); return 0; } } // namespace android::fuzz services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h 0 → 100644 +229 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
services/surfaceflinger/fuzzer/Android.bp +10 −0 Original line number Diff line number Diff line Loading @@ -92,3 +92,13 @@ cc_fuzz { "android.hardware.graphics.composer@2.4-hal", ], } cc_fuzz { name: "surfaceflinger_scheduler_fuzzer", defaults: [ "surfaceflinger_fuzz_defaults", ], srcs: [ "surfaceflinger_scheduler_fuzzer.cpp", ], }
services/surfaceflinger/fuzzer/README.md +19 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ ## Table of contents + [SurfaceFlinger](#SurfaceFlinger) + [DisplayHardware](#DisplayHardware) + [Scheduler](#Scheduler) # <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger Loading Loading @@ -51,3 +52,21 @@ You can find the possible values in the fuzzer's source code. $ adb sync data $ adb shell /data/fuzz/arm64/surfaceflinger_displayhardware_fuzzer/surfaceflinger_displayhardware_fuzzer ``` # <a name="Scheduler"></a> Fuzzer for Scheduler Scheduler supports the following parameters: 1. VSync Periods (parameter name: `lowFpsPeriod`) You can find the possible values in the fuzzer's source code. #### Steps to run 1. Build the fuzzer ``` $ mm -j$(nproc) surfaceflinger_scheduler_fuzzer ``` 2. To run on device ``` $ adb sync data $ adb shell /data/fuzz/arm64/surfaceflinger_scheduler_fuzzer/surfaceflinger_scheduler_fuzzer ```
services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp 0 → 100644 +392 −0 Original line number Diff line number Diff line /* * 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 "surfaceflinger_scheduler_fuzzer.h" #include <fuzzer/FuzzedDataProvider.h> #include <processgroup/sched_policy.h> #include "Scheduler/DispSyncSource.h" #include "Scheduler/OneShotTimer.h" #include "Scheduler/VSyncDispatchTimerQueue.h" #include "Scheduler/VSyncPredictor.h" #include "Scheduler/VSyncReactor.h" #include "surfaceflinger_fuzzers_utils.h" namespace android::fuzz { using hardware::graphics::composer::hal::PowerMode; static constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF, PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND}; constexpr uint16_t kRandomStringLength = 256; constexpr std::chrono::duration kSyncPeriod(16ms); template <typename T> void dump(T* component, FuzzedDataProvider* fdp) { std::string res = fdp->ConsumeRandomLengthString(kRandomStringLength); component->dump(res); } class SchedulerFuzzer : private VSyncSource::Callback { public: SchedulerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){}; void process(); private: void fuzzRefreshRateSelection(); void fuzzRefreshRateConfigs(); void fuzzVSyncModulator(); void fuzzVSyncPredictor(); void fuzzVSyncReactor(); void fuzzLayerHistory(); void fuzzDispSyncSource(); void fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch); void fuzzVSyncDispatchTimerQueue(); void fuzzOneShotTimer(); void fuzzEventThread(); PhysicalDisplayId getPhysicalDisplayId(); FuzzedDataProvider mFdp; protected: void onVSyncEvent(nsecs_t /* when */, nsecs_t /* expectedVSyncTimestamp */, nsecs_t /* deadlineTimestamp */) {} }; PhysicalDisplayId SchedulerFuzzer::getPhysicalDisplayId() { PhysicalDisplayId internalDispId = PhysicalDisplayId::fromPort(111u); PhysicalDisplayId externalDispId = PhysicalDisplayId::fromPort(222u); PhysicalDisplayId randomDispId = PhysicalDisplayId::fromPort(mFdp.ConsumeIntegral<uint16_t>()); PhysicalDisplayId dispId64Bit = PhysicalDisplayId::fromEdid(0xffu, 0xffffu, 0xffff'ffffu); PhysicalDisplayId displayId = mFdp.PickValueInArray<PhysicalDisplayId>( {internalDispId, externalDispId, dispId64Bit, randomDispId}); return displayId; } void SchedulerFuzzer::fuzzEventThread() { const auto getVsyncPeriod = [](uid_t /* uid */) { return kSyncPeriod.count(); }; std::unique_ptr<android::impl::EventThread> thread = std::make_unique< android::impl::EventThread>(std::move(std::make_unique<FuzzImplVSyncSource>()), nullptr, nullptr, nullptr, getVsyncPeriod); thread->onHotplugReceived(getPhysicalDisplayId(), mFdp.ConsumeBool()); sp<EventThreadConnection> connection = new EventThreadConnection(thread.get(), mFdp.ConsumeIntegral<uint16_t>(), nullptr, {} /*eventRegistration*/); thread->requestNextVsync(connection); thread->setVsyncRate(mFdp.ConsumeIntegral<uint32_t>() /*rate*/, connection); thread->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); thread->registerDisplayEventConnection(connection); thread->onScreenAcquired(); thread->onScreenReleased(); dump<android::impl::EventThread>(thread.get(), &mFdp); } void SchedulerFuzzer::fuzzDispSyncSource() { std::unique_ptr<FuzzImplVSyncDispatch> vSyncDispatch = std::make_unique<FuzzImplVSyncDispatch>(); std::unique_ptr<scheduler::DispSyncSource> dispSyncSource = std::make_unique< scheduler::DispSyncSource>(*vSyncDispatch, (std::chrono::nanoseconds) mFdp.ConsumeIntegral<uint64_t>() /*workDuration*/, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>() /*readyDuration*/, mFdp.ConsumeBool(), mFdp.ConsumeRandomLengthString(kRandomStringLength).c_str()); dispSyncSource->setVSyncEnabled(true); dispSyncSource->setCallback(this); dispSyncSource->setDuration((std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), 0ns); dump<scheduler::DispSyncSource>(dispSyncSource.get(), &mFdp); } void SchedulerFuzzer::fuzzCallbackToken(scheduler::VSyncDispatchTimerQueue* dispatch) { scheduler::VSyncDispatch::CallbackToken tmp = dispatch->registerCallback( [&](auto, auto, auto) { dispatch->schedule(tmp, {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); }, "o.o"); dispatch->schedule(tmp, {.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); dispatch->unregisterCallback(tmp); dispatch->cancel(tmp); } void SchedulerFuzzer::fuzzVSyncDispatchTimerQueue() { FuzzImplVSyncTracker stubTracker{mFdp.ConsumeIntegral<nsecs_t>()}; scheduler::VSyncDispatchTimerQueue mDispatch{std::make_unique<scheduler::ControllableClock>(), stubTracker, mFdp.ConsumeIntegral<nsecs_t>() /*dispatchGroupThreshold*/, mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/}; fuzzCallbackToken(&mDispatch); dump<scheduler::VSyncDispatchTimerQueue>(&mDispatch, &mFdp); scheduler::VSyncDispatchTimerQueueEntry entry( "fuzz", [](auto, auto, auto) {}, mFdp.ConsumeIntegral<nsecs_t>() /*vSyncMoveThreshold*/); entry.update(stubTracker, 0); entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}, stubTracker, 0); entry.disarm(); entry.ensureNotRunning(); entry.schedule({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}, stubTracker, 0); auto const wakeup = entry.wakeupTime(); auto const ready = entry.readyTime(); entry.callback(entry.executing(), *wakeup, *ready); entry.addPendingWorkloadUpdate({.workDuration = mFdp.ConsumeIntegral<nsecs_t>(), .readyDuration = mFdp.ConsumeIntegral<nsecs_t>(), .earliestVsync = mFdp.ConsumeIntegral<nsecs_t>()}); dump<scheduler::VSyncDispatchTimerQueueEntry>(&entry, &mFdp); } void SchedulerFuzzer::fuzzVSyncPredictor() { uint16_t now = mFdp.ConsumeIntegral<uint16_t>(); uint16_t historySize = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX); uint16_t minimumSamplesForPrediction = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX); scheduler::VSyncPredictor tracker{mFdp.ConsumeIntegral<uint16_t>() /*period*/, historySize, minimumSamplesForPrediction, mFdp.ConsumeIntegral<uint32_t>() /*outlierTolerancePercent*/}; uint16_t period = mFdp.ConsumeIntegral<uint16_t>(); tracker.setPeriod(period); for (uint16_t i = 0; i < minimumSamplesForPrediction; ++i) { if (!tracker.needsMoreSamples()) { break; } tracker.addVsyncTimestamp(now += period); } tracker.nextAnticipatedVSyncTimeFrom(now); tracker.resetModel(); } void SchedulerFuzzer::fuzzOneShotTimer() { FakeClock* clock = new FakeClock(); std::unique_ptr<scheduler::OneShotTimer> idleTimer = std::make_unique<scheduler::OneShotTimer>( mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/, (std::chrono::milliseconds)mFdp.ConsumeIntegral<uint8_t>() /*val*/, [] {} /*resetCallback*/, [] {} /*timeoutCallback*/, std::unique_ptr<FakeClock>(clock)); idleTimer->start(); idleTimer->reset(); idleTimer->stop(); } void SchedulerFuzzer::fuzzLayerHistory() { TestableSurfaceFlinger flinger; flinger.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>()); flinger.setupTimeStats(std::make_unique<android::mock::TimeStats>()); std::unique_ptr<android::renderengine::RenderEngine> renderEngine = std::make_unique<android::renderengine::mock::RenderEngine>(); flinger.setupRenderEngine(std::move(renderEngine)); flinger.setupComposer(std::make_unique<android::Hwc2::mock::Composer>()); scheduler::TestableScheduler* scheduler = flinger.scheduler(); scheduler::LayerHistory& historyV1 = scheduler->mutableLayerHistory(); nsecs_t time1 = systemTime(); nsecs_t time2 = time1; uint8_t historySize = mFdp.ConsumeIntegral<uint8_t>(); sp<FuzzImplLayer> layer1 = new FuzzImplLayer(flinger.flinger()); sp<FuzzImplLayer> layer2 = new FuzzImplLayer(flinger.flinger()); for (int i = 0; i < historySize; ++i) { historyV1.record(layer1.get(), time1, time1, scheduler::LayerHistory::LayerUpdateType::Buffer); historyV1.record(layer2.get(), time2, time2, scheduler::LayerHistory::LayerUpdateType::Buffer); time1 += mFdp.PickValueInArray(kVsyncPeriods); time2 += mFdp.PickValueInArray(kVsyncPeriods); } historyV1.summarize(*scheduler->refreshRateConfigs(), time1); historyV1.summarize(*scheduler->refreshRateConfigs(), time2); scheduler->createConnection(std::make_unique<android::mock::EventThread>()); scheduler::ConnectionHandle handle; scheduler->createDisplayEventConnection(handle); scheduler->setDuration(handle, (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>(), (std::chrono::nanoseconds)mFdp.ConsumeIntegral<uint64_t>()); dump<scheduler::TestableScheduler>(scheduler, &mFdp); } void SchedulerFuzzer::fuzzVSyncReactor() { std::shared_ptr<FuzzImplVSyncTracker> vSyncTracker = std::make_shared<FuzzImplVSyncTracker>(); scheduler::VSyncReactor reactor(std::make_unique<ClockWrapper>( std::make_shared<FuzzImplClock>()), *vSyncTracker, mFdp.ConsumeIntegral<uint8_t>() /*pendingLimit*/, false); reactor.startPeriodTransition(mFdp.ConsumeIntegral<nsecs_t>()); bool periodFlushed = mFdp.ConsumeBool(); reactor.addHwVsyncTimestamp(0, std::nullopt, &periodFlushed); reactor.addHwVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>() /*newPeriod*/, std::nullopt, &periodFlushed); sp<Fence> fence = new Fence(memfd_create("fd", MFD_ALLOW_SEALING)); std::shared_ptr<FenceTime> ft = std::make_shared<FenceTime>(fence); vSyncTracker->addVsyncTimestamp(mFdp.ConsumeIntegral<nsecs_t>()); FenceTime::Snapshot snap(mFdp.ConsumeIntegral<nsecs_t>()); ft->applyTrustedSnapshot(snap); reactor.setIgnorePresentFences(mFdp.ConsumeBool()); reactor.addPresentFence(ft); dump<scheduler::VSyncReactor>(&reactor, &mFdp); } void SchedulerFuzzer::fuzzVSyncModulator() { enum { SF_OFFSET_LATE, APP_OFFSET_LATE, SF_DURATION_LATE, APP_DURATION_LATE, SF_OFFSET_EARLY, APP_OFFSET_EARLY, SF_DURATION_EARLY, APP_DURATION_EARLY, SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU, SF_DURATION_EARLY_GPU, APP_DURATION_EARLY_GPU, HWC_MIN_WORK_DURATION, }; using Schedule = scheduler::TransactionSchedule; using nanos = std::chrono::nanoseconds; using VsyncModulator = scheduler::VsyncModulator; using FuzzImplVsyncModulator = scheduler::FuzzImplVsyncModulator; const VsyncModulator::VsyncConfig early{SF_OFFSET_EARLY, APP_OFFSET_EARLY, nanos(SF_DURATION_LATE), nanos(APP_DURATION_LATE)}; const VsyncModulator::VsyncConfig earlyGpu{SF_OFFSET_EARLY_GPU, APP_OFFSET_EARLY_GPU, nanos(SF_DURATION_EARLY), nanos(APP_DURATION_EARLY)}; const VsyncModulator::VsyncConfig late{SF_OFFSET_LATE, APP_OFFSET_LATE, nanos(SF_DURATION_EARLY_GPU), nanos(APP_DURATION_EARLY_GPU)}; const VsyncModulator::VsyncConfigSet offsets = {early, earlyGpu, late, nanos(HWC_MIN_WORK_DURATION)}; sp<FuzzImplVsyncModulator> vSyncModulator = sp<FuzzImplVsyncModulator>::make(offsets, scheduler::Now); (void)vSyncModulator->setVsyncConfigSet(offsets); (void)vSyncModulator->setTransactionSchedule(Schedule::Late); const auto token = sp<BBinder>::make(); (void)vSyncModulator->setTransactionSchedule(Schedule::EarlyStart, token); vSyncModulator->binderDied(token); } void SchedulerFuzzer::fuzzRefreshRateSelection() { TestableSurfaceFlinger flinger; flinger.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>()); sp<Client> client; LayerCreationArgs args(flinger.flinger(), client, mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/, mFdp.ConsumeIntegral<uint16_t>() /*layerFlags*/, LayerMetadata()); sp<Layer> layer = new BufferQueueLayer(args); layer->setFrameRateSelectionPriority(mFdp.ConsumeIntegral<int16_t>()); } void SchedulerFuzzer::fuzzRefreshRateConfigs() { using RefreshRateConfigs = scheduler::RefreshRateConfigs; using LayerRequirement = RefreshRateConfigs::LayerRequirement; using RefreshRateStats = scheduler::RefreshRateStats; uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1); uint16_t maxRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX); DisplayModeId hwcConfigIndexType = DisplayModeId(mFdp.ConsumeIntegralInRange<uint8_t>(0, 10)); DisplayModes displayModes; for (uint16_t fps = minRefreshRate; fps < maxRefreshRate; ++fps) { constexpr int32_t kGroup = 0; const auto refreshRate = Fps::fromValue(static_cast<float>(fps)); displayModes.push_back(scheduler::createDisplayMode(hwcConfigIndexType, kGroup, refreshRate.getPeriodNsecs())); } auto refreshRateConfigs = std::make_unique<RefreshRateConfigs>(displayModes, hwcConfigIndexType); const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false}; auto layers = std::vector<LayerRequirement>{ LayerRequirement{.weight = mFdp.ConsumeFloatingPoint<float>()}}; refreshRateConfigs->getBestRefreshRate(layers, globalSignals); layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength); layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>(); layers[0].desiredRefreshRate = Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()); layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes); auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps::fromValue( mFdp.ConsumeFloatingPoint<float>()), globalSignals); refreshRateConfigs->setDisplayManagerPolicy( {hwcConfigIndexType, {Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}}); refreshRateConfigs->setCurrentModeId(hwcConfigIndexType); RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue( mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue( mFdp.ConsumeFloatingPoint<float>())); RefreshRateConfigs::getFrameRateDivider(Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())); android::mock::TimeStats timeStats; std::unique_ptr<RefreshRateStats> refreshRateStats = std::make_unique<RefreshRateStats>(timeStats, Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()), PowerMode::OFF); refreshRateStats->setRefreshRate( refreshRateConfigs->getRefreshRateFromModeId(hwcConfigIndexType).getFps()); refreshRateStats->setPowerMode(mFdp.PickValueInArray(kPowerModes)); } void SchedulerFuzzer::process() { fuzzRefreshRateSelection(); fuzzRefreshRateConfigs(); fuzzVSyncModulator(); fuzzVSyncPredictor(); fuzzVSyncReactor(); fuzzLayerHistory(); fuzzDispSyncSource(); fuzzEventThread(); fuzzVSyncDispatchTimerQueue(); fuzzOneShotTimer(); } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { SchedulerFuzzer schedulerFuzzer(data, size); schedulerFuzzer.process(); return 0; } } // namespace android::fuzz
services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h 0 → 100644 +229 −0 File added.Preview size limit exceeded, changes collapsed. Show changes