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

Commit a6c30105 authored by Anton Ivanov's avatar Anton Ivanov Committed by Android (Google) Code Review
Browse files

Merge "Add TransactionBarriers to TransactionState." into main

parents 175ce9ec 749dc49d
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <gui/TransactionState.h>
#include <private/gui/ParcelUtils.h>
#include <algorithm>
#include <numeric>

namespace android {

@@ -86,6 +87,8 @@ status_t TransactionState::writeToParcel(Parcel* parcel) const {
        SAFE_PARCEL(d.write, *parcel);
    }

    SAFE_PARCEL(parcel->writeParcelableVector, mBarriers);

    return NO_ERROR;
}

@@ -142,6 +145,8 @@ status_t TransactionState::readFromParcel(const Parcel* parcel) {
        mDisplayStates.emplace_back(std::move(d));
    }

    mBarriers.clear();
    SAFE_PARCEL(parcel->readParcelableVector, &mBarriers);
    return NO_ERROR;
}

@@ -206,6 +211,21 @@ void TransactionState::merge(TransactionState&& other,

    mMergedTransactionIds.insert(mMergedTransactionIds.begin(), other.mId);

    mBarriers.insert(mBarriers.end(), std::make_move_iterator(other.mBarriers.begin()),
                     std::make_move_iterator(other.mBarriers.end()));
    if (mBarriers.size() > MAX_BARRIERS_LENGTH) {
        int numToRemove = mBarriers.size() - MAX_BARRIERS_LENGTH;
        std::string droppedBarriers =
                std::accumulate(mBarriers.begin(), mBarriers.begin() + numToRemove, std::string(),
                                [](std::string&& s,
                                   const gui::TransactionBarrier& barrier) -> std::string {
                                    s += barrier.toString() + ",";
                                    return s;
                                });
        ALOGE("Dropping %d transaction barriers: %s", numToRemove, droppedBarriers.c_str());
        mBarriers.erase(mBarriers.begin(), mBarriers.begin() + numToRemove);
    }

    other.clear();
}

@@ -235,6 +255,7 @@ void TransactionState::clear() {
    mEarlyWakeupInfos.clear();
    mComposerStates.clear();
    mDisplayStates.clear();
    mBarriers.clear();
}

layer_state_t* TransactionState::getLayerState(const sp<SurfaceControl>& sc) {
+28 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2025, 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.
 */

package android.gui;

/** @hide */
parcelable TransactionBarrier {
    String barrierToken;
    enum BarrierKind  {
        KIND_INVALID,
        KIND_SIGNAL,
        KIND_WAIT,
    }
    BarrierKind kind;
}
+6 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <android/gui/FrameTimelineInfo.h>
#include <android/gui/TransactionBarrier.h>
#include <binder/Parcelable.h>
#include <gui/LayerState.h>

@@ -93,8 +94,12 @@ public:
    std::vector<gui::EarlyWakeupInfo> mEarlyWakeupInfos = {};
    std::vector<ComposerState> mComposerStates = {};
    std::vector<DisplayState> mDisplayStates = {};
    std::vector<gui::TransactionBarrier> mBarriers = {};

    // Keep track of the last MAX_BARRIERS_LENGTH transaction barriers.
    // Ordered most recently merged to least recently merged.
    static constexpr size_t MAX_BARRIERS_LENGTH = 10u;

private:
    // We keep track of the last MAX_MERGE_HISTORY_LENGTH merged transaction ids.
    // Ordered most recently merged to least recently merged.
    static constexpr size_t MAX_MERGE_HISTORY_LENGTH = 10u;
+57 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <gtest/gtest.h>
#include <unordered_map>
#include "android/gui/FocusRequest.h"
#include "android/gui/TransactionBarrier.h"
#include "binder/Binder.h"
#include "binder/Parcel.h"
#include "gtest/gtest.h"
@@ -29,6 +30,8 @@

namespace android {

using ::testing::Eq;

void sprintf(std::string& out, const char* format, ...) {
    va_list arg_list;
    va_start(arg_list, format);
@@ -83,11 +86,16 @@ void Compare(const TransactionListenerCallbacks& s1, const TransactionListenerCa
    EXPECT_EQ(s1.mFlattenedListenerCallbacks, s2.mFlattenedListenerCallbacks);
}

void Compare(const gui::TransactionBarrier& b1, const gui::TransactionBarrier& b2) {
    EXPECT_EQ(b1.barrierToken, b2.barrierToken);
    EXPECT_EQ(b1.kind, b2.kind);
}

void CompareComplex(const TransactionState& s1, const TransactionState& s2) {
    EXPECT_EQ(s1.mMergedTransactionIds, s2.mMergedTransactionIds);
    EXPECT_EQ(s1.mFrameTimelineInfo, s2.mFrameTimelineInfo);
    EXPECT_EQ(s1.mUncacheBuffers, s2.mUncacheBuffers);
    EXPECT_EQ(s1.mCallbacks, s2.mCallbacks);
    Compare(s1.mCallbacks, s2.mCallbacks);
    EXPECT_EQ(s1.mInputWindowCommands, s2.mInputWindowCommands);
    EXPECT_EQ(s1.mDisplayStates.size(), s2.mDisplayStates.size());
    for (size_t i = 0; i < s1.mDisplayStates.size(); ++i) {
@@ -97,6 +105,11 @@ void CompareComplex(const TransactionState& s1, const TransactionState& s2) {
    for (size_t i = 0; i < s1.mComposerStates.size(); ++i) {
        EXPECT_EQ(s1.mComposerStates.at(i), s2.mComposerStates.at(i));
    }

    EXPECT_EQ(s1.mBarriers.size(), s2.mBarriers.size());
    for (size_t i = 0; i < s1.mBarriers.size(); ++i) {
        Compare(s1.mBarriers.at(i), s2.mBarriers.at(i));
    }
}

// In case EXPECT_EQ fails, this function is useful to pinpoint exactly which
@@ -183,7 +196,6 @@ TransactionState createTransactionStateForTest() {
    for (size_t i = 0; i < kMaxComposerStates; i++) {
        state.mComposerStates.push_back(createComposerStateForTest(i));
    }
    return state;

    return state;
}
@@ -194,6 +206,22 @@ TransactionState createEmptyTransaction(uint64_t id) {
    return state;
}

gui::TransactionBarrier createTransactionBarrier(std::string_view token,
                                                 gui::TransactionBarrier::BarrierKind kind) {
    gui::TransactionBarrier barrier;
    barrier.barrierToken = String16(token.data(), token.size());
    barrier.kind = kind;
    return barrier;
}

gui::TransactionBarrier createSignalBarrier(std::string_view token) {
    return createTransactionBarrier(token, gui::TransactionBarrier::BarrierKind::KIND_SIGNAL);
}

gui::TransactionBarrier createWaitBarrier(std::string_view token) {
    return createTransactionBarrier(token, gui::TransactionBarrier::BarrierKind::KIND_WAIT);
}

TEST(SimpleTransactionStateTest, parcel) {
    TransactionState state = createSimpleTransactionStateForTest();
    Parcel p;
@@ -206,6 +234,7 @@ TEST(SimpleTransactionStateTest, parcel) {

TEST(TransactionStateTest, parcel) {
    TransactionState state = createTransactionStateForTest();
    state.mBarriers.emplace_back(createSignalBarrier("sig"));
    Parcel p;
    state.writeToParcel(&p);
    p.setDataPosition(0);
@@ -287,6 +316,7 @@ TEST(TransactionStateTest, merge) {
    static constexpr uint64_t kUpdateTransactionId = 200;

    TransactionState state = createTransactionStateForTest();
    state.mBarriers.emplace_back(createSignalBarrier("sig"));

    TransactionState update;
    update.mId = kUpdateTransactionId;
@@ -303,6 +333,8 @@ TEST(TransactionStateTest, merge) {
        composerState.state.what = layer_state_t::eBufferChanged;
        update.mComposerStates.push_back(composerState);
    }
    update.mBarriers.emplace_back(
            createTransactionBarrier("wait", gui::TransactionBarrier::BarrierKind::KIND_WAIT));
    int32_t overrwiteLayerId = -1;
    auto updateCopy = update;
    // Mutation.
@@ -322,11 +354,34 @@ TEST(TransactionStateTest, merge) {
    // desired present time is not merged.
    expectedMergedState.mDesiredPresentTime = state.mDesiredPresentTime;

    expectedMergedState.mBarriers.emplace_back(createSignalBarrier("sig"));
    expectedMergedState.mBarriers.emplace_back(createWaitBarrier("wait"));

    EXPECT_EQ(state.mComposerStates[0], expectedMergedState.mComposerStates[0]);
    EXPECT_EQ(state.mInputWindowCommands, expectedMergedState.mInputWindowCommands);
    EXPECT_EQ(state, expectedMergedState);
};

TEST(TransactionStateTest, mergeMoreThanMaxBarriers) {
    TransactionState state = createTransactionStateForTest();
    for (size_t i = 0; i < TransactionState::MAX_BARRIERS_LENGTH; ++i) {
        std::string token = std::format("sig{}", i);
        state.mBarriers.emplace_back(createSignalBarrier(token));
    }

    TransactionState update;
    update.mId = 200;
    update.mBarriers.emplace_back(createWaitBarrier("wait"));

    state.merge(std::move(update), [](layer_state_t) {});

    EXPECT_EQ(TransactionState::MAX_BARRIERS_LENGTH, state.mBarriers.size());
    EXPECT_THAT(state.mBarriers.front().toString(),
                Eq("TransactionBarrier{barrierToken: sig1, kind: KIND_SIGNAL}"));
    EXPECT_THAT(state.mBarriers.back().toString(),
                Eq("TransactionBarrier{barrierToken: wait, kind: KIND_WAIT}"));
}

TEST(TransactionStateTest, clear) {
    TransactionState state = createTransactionStateForTest();
    state.clear();