Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c7938ec authored by Alec Mouri's avatar Alec Mouri
Browse files

Support injecting jank into Scheduler for testing purposes

Injects a fraction of a frame's expected present time as a jank. This is
mainly to avoid thinking about hard-coding milliseconds.

Also supports delaying this jank injection, since the Perfetto UI
currently steals any ADB session

Bug: 296636083
Test: TouchLatency + perfetto
Change-Id: If08616e68c3e7b3d6eaed6f6ff5cbc6ad444481e
parent c6e03916
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -211,6 +211,17 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
        targeters.try_emplace(id, &targeter);
    }

    if (flagutils::vrrConfigEnabled() &&
        CC_UNLIKELY(mPacesetterFrameDurationFractionToSkip > 0.f)) {
        const auto period = pacesetterTargeter.target().expectedFrameDuration();
        const auto skipDuration = Duration::fromNs(
                static_cast<nsecs_t>(period.ns() * mPacesetterFrameDurationFractionToSkip));
        ATRACE_FORMAT("Injecting jank for %f%% of the frame (%" PRId64 " ns)",
                      mPacesetterFrameDurationFractionToSkip * 100, skipDuration.ns());
        std::this_thread::sleep_for(skipDuration);
        mPacesetterFrameDurationFractionToSkip = 0.f;
    }

    const auto resultsPerDisplay = compositor.composite(pacesetterId, targeters);
    compositor.sample();

+8 −0
Original line number Diff line number Diff line
@@ -323,6 +323,11 @@ public:
        return mFeatures.test(Feature::kSmallDirtyContentDetection);
    }

    // Injects a delay that is a fraction of the predicted frame duration for the next frame.
    void injectPacesetterDelay(float frameDurationFraction) REQUIRES(kMainThreadContext) {
        mPacesetterFrameDurationFractionToSkip = frameDurationFraction;
    }

private:
    friend class TestableScheduler;

@@ -452,6 +457,9 @@ private:
    // Timer used to monitor display power mode.
    ftl::Optional<OneShotTimer> mDisplayPowerTimer;

    // Injected delay prior to compositing, for simulating jank.
    float mPacesetterFrameDurationFractionToSkip GUARDED_BY(kMainThreadContext) = 0.f;

    ISchedulerCallback& mSchedulerCallback;

    // mDisplayLock may be locked while under mPolicyLock.
+35 −2
Original line number Diff line number Diff line
@@ -6660,9 +6660,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) {
        code == IBinder::SYSPROPS_TRANSACTION) {
        return OK;
    }
    // Numbers from 1000 to 1044 are currently used for backdoors. The code
    // Numbers from 1000 to 1045 are currently used for backdoors. The code
    // in onTransact verifies that the user is root, and has access to use SF.
    if (code >= 1000 && code <= 1044) {
    if (code >= 1000 && code <= 1045) {
        ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
        return OK;
    }
@@ -7151,6 +7151,39 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
                }
                return NO_ERROR;
            }
            // Inject jank
            // First argument is a float that describes the fraction of frame duration to jank by.
            // Second argument is a delay in ms for triggering the jank. This is useful for working
            // with tools that steal the adb connection. This argument is optional.
            case 1045: {
                if (flagutils::vrrConfigEnabled()) {
                    float jankAmount = data.readFloat();
                    int32_t jankDelayMs = 0;
                    if (data.readInt32(&jankDelayMs) != NO_ERROR) {
                        jankDelayMs = 0;
                    }

                    const auto jankDelayDuration = Duration(std::chrono::milliseconds(jankDelayMs));

                    const bool jankAmountValid = jankAmount > 0.0 && jankAmount < 100.0;

                    if (!jankAmountValid) {
                        ALOGD("Ignoring invalid jank amount: %f", jankAmount);
                        reply->writeInt32(BAD_VALUE);
                        return BAD_VALUE;
                    }

                    (void)mScheduler->scheduleDelayed(
                            [&, jankAmount]() FTL_FAKE_GUARD(kMainThreadContext) {
                                mScheduler->injectPacesetterDelay(jankAmount);
                                scheduleComposite(FrameHint::kActive);
                            },
                            jankDelayDuration.ns());
                    reply->writeInt32(NO_ERROR);
                    return NO_ERROR;
                }
                return err;
            }
        }
    }
    return err;