Merge "Update language to comply with Android's inclusive language guidance"
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index ba2920e..44b588b 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "RpcServer"
+#include <inttypes.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -38,6 +39,8 @@
namespace android {
+constexpr size_t kSessionIdBytes = 32;
+
using base::ScopeGuard;
using base::unique_fd;
@@ -289,13 +292,19 @@
std::vector<uint8_t> sessionId;
if (status == OK) {
if (header.sessionIdSize > 0) {
- sessionId.resize(header.sessionIdSize);
- status = client->interruptableReadFully(server->mShutdownTrigger.get(),
- sessionId.data(), sessionId.size(), {});
- if (status != OK) {
- ALOGE("Failed to read session ID for client connecting to RPC server: %s",
- statusToString(status).c_str());
- // still need to cleanup before we can return
+ if (header.sessionIdSize == kSessionIdBytes) {
+ sessionId.resize(header.sessionIdSize);
+ status = client->interruptableReadFully(server->mShutdownTrigger.get(),
+ sessionId.data(), sessionId.size(), {});
+ if (status != OK) {
+ ALOGE("Failed to read session ID for client connecting to RPC server: %s",
+ statusToString(status).c_str());
+ // still need to cleanup before we can return
+ }
+ } else {
+ ALOGE("Malformed session ID. Expecting session ID of size %zu but got %" PRIu16,
+ kSessionIdBytes, header.sessionIdSize);
+ status = BAD_VALUE;
}
}
}
@@ -353,8 +362,7 @@
// Uniquely identify session at the application layer. Even if a
// client/server use the same certificates, if they create multiple
// sessions, we still want to distinguish between them.
- constexpr size_t kSessionIdSize = 32;
- sessionId.resize(kSessionIdSize);
+ sessionId.resize(kSessionIdBytes);
size_t tries = 0;
do {
// don't block if there is some entropy issue
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 86cc91c..ef62f20 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -183,6 +183,10 @@
status_t RpcState::flushExcessBinderRefs(const sp<RpcSession>& session, uint64_t address,
const sp<IBinder>& binder) {
+ // We can flush all references when the binder is destroyed. No need to send
+ // extra reference counting packets now.
+ if (binder->remoteBinder()) return OK;
+
std::unique_lock<std::mutex> _l(mNodeMutex);
if (mTerminated) return DEAD_OBJECT;
@@ -192,20 +196,19 @@
LOG_ALWAYS_FATAL_IF(it->second.binder != binder,
"Caller of flushExcessBinderRefs using inconsistent arguments");
- // if this is a local binder, then we want to get rid of all refcounts
- // (tell the other process it can drop the binder when it wants to - we
- // have a local sp<>, so we will drop it when we want to as well). if
- // this is a remote binder, then we need to hold onto one refcount until
- // it is dropped in BpBinder::onLastStrongRef
- size_t targetRecd = binder->localBinder() ? 0 : 1;
+ LOG_ALWAYS_FATAL_IF(it->second.timesSent <= 0, "Local binder must have been sent %p",
+ binder.get());
- // We have timesRecd RPC refcounts, but we only need to hold on to one
- // when we keep the object. All additional dec strongs are sent
- // immediately, we wait to send the last one in BpBinder::onLastDecStrong.
- if (it->second.timesRecd != targetRecd) {
+ // For a local binder, we only need to know that we sent it. Now that we
+ // have an sp<> for this call, we don't need anything more. If the other
+ // process is done with this binder, it needs to know we received the
+ // refcount associated with this call, so we can acknowledge that we
+ // received it. Once (or if) it has no other refcounts, it would reply with
+ // its own decStrong so that it could be removed from this session.
+ if (it->second.timesRecd != 0) {
_l.unlock();
- return session->sendDecStrongToTarget(address, targetRecd);
+ return session->sendDecStrongToTarget(address, 0);
}
return OK;
@@ -882,12 +885,6 @@
}
}
- // Binder refs are flushed for oneway calls only after all calls which are
- // built up are executed. Otherwise, they fill up the binder buffer.
- if (addr != 0 && replyStatus == OK && !oneway) {
- replyStatus = flushExcessBinderRefs(session, addr, target);
- }
-
if (oneway) {
if (replyStatus != OK) {
ALOGW("Oneway call failed with error: %d", replyStatus);
@@ -947,6 +944,12 @@
return OK;
}
+ // Binder refs are flushed for oneway calls only after all calls which are
+ // built up are executed. Otherwise, they fill up the binder buffer.
+ if (addr != 0 && replyStatus == OK) {
+ replyStatus = flushExcessBinderRefs(session, addr, target);
+ }
+
LOG_ALWAYS_FATAL_IF(std::numeric_limits<int32_t>::max() - sizeof(RpcWireHeader) -
sizeof(RpcWireReply) <
reply.dataSize(),
diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
index 6f054d2..8ea948c 100644
--- a/libs/binder/tests/unit_fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -30,16 +30,28 @@
"-Wall",
"-Werror",
],
- shared_libs: [
- "libbinder",
- "libutils",
- "libbase",
- ],
target: {
+ android: {
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
darwin: {
enabled: false,
- }
- }
+ },
+ },
}
cc_fuzz {
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 379b090..406272c 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -456,10 +456,10 @@
// Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
incStrong((void*)transactionCallbackThunk);
+ const bool sizeHasChanged = mRequestedSize != mSize;
+ mSize = mRequestedSize;
+ const bool updateDestinationFrame = sizeHasChanged || !mLastBufferInfo.hasBuffer;
Rect crop = computeCrop(bufferItem);
- const bool updateDestinationFrame =
- bufferItem.mScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE ||
- !mLastBufferInfo.hasBuffer;
mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(),
bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform,
bufferItem.mScalingMode, crop);
@@ -572,7 +572,6 @@
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
- mSize = mRequestedSize;
// Only reject buffers if scaling mode is freeze.
return false;
}
@@ -586,7 +585,6 @@
}
ui::Size bufferSize(bufWidth, bufHeight);
if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
- mSize = mRequestedSize;
return false;
}
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 26d902d..b474086 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -672,6 +672,83 @@
/*border*/ 0, /*outsideRegion*/ true));
}
+// b/196339769 verify we can can update the requested size while the in FREEZE scaling mode and
+// scale the buffer properly when the mode changes to SCALE_TO_WINDOW
+TEST_F(BLASTBufferQueueTest, ScalingModeChanges) {
+ uint8_t r = 255;
+ uint8_t g = 0;
+ uint8_t b = 0;
+
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight / 4);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 4,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ uint32_t* bufData;
+ buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+ fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_FREEZE, 0,
+ Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ adapter.waitForCallbacks();
+ }
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(r, g, b,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 4}));
+
+ // update the size to half the display and dequeue a buffer quarter of the display.
+ adapter.update(mSurfaceControl, mDisplayWidth, mDisplayHeight / 2);
+
+ {
+ int slot;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buf;
+ auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight / 8,
+ PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN,
+ nullptr, nullptr);
+ ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
+ ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
+
+ uint32_t* bufData;
+ buf->lock(static_cast<uint32_t>(GraphicBuffer::USAGE_SW_WRITE_OFTEN),
+ reinterpret_cast<void**>(&bufData));
+ g = 255;
+ fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight()), buf->getStride(), r, g, b);
+ buf->unlock();
+
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */,
+ HAL_DATASPACE_UNKNOWN, {},
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
+ 0, Fence::NO_FENCE);
+ igbProducer->queueBuffer(slot, input, &qbOutput);
+ adapter.waitForCallbacks();
+ }
+ // capture screen and verify that it is red
+ ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
+ // verify we still scale the buffer to the new size (half the screen height)
+ ASSERT_NO_FATAL_FAILURE(
+ checkScreenCapture(r, g, b,
+ {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2}));
+}
+
class TestProducerListener : public BnProducerListener {
public:
sp<IGraphicBufferProducer> mIgbp;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index c351676..db1a1cc 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -614,6 +614,8 @@
Return<void> SensorDevice::onDynamicSensorsConnected(
const hidl_vec<SensorInfo> &dynamicSensorsAdded) {
+ std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+
// Allocate a sensor_t structure for each dynamic sensor added and insert
// it into the dictionary of connected dynamic sensors keyed by handle.
for (size_t i = 0; i < dynamicSensorsAdded.size(); ++i) {
@@ -629,6 +631,8 @@
std::make_pair(sensor->handle, sensor));
}
+ mDynamicSensorsCv.notify_all();
+
return Return<void>();
}
@@ -1174,8 +1178,20 @@
dst->dynamic_sensor_meta.connected = dyn.connected;
dst->dynamic_sensor_meta.handle = dyn.sensorHandle;
if (dyn.connected) {
+ std::unique_lock<std::mutex> lock(mDynamicSensorsMutex);
+ // Give MAX_DYN_SENSOR_WAIT_SEC for onDynamicSensorsConnected to be invoked since it
+ // can be received out of order from this event due to a bug in the HIDL spec that
+ // marks it as oneway.
auto it = mConnectedDynamicSensors.find(dyn.sensorHandle);
- CHECK(it != mConnectedDynamicSensors.end());
+ if (it == mConnectedDynamicSensors.end()) {
+ mDynamicSensorsCv.wait_for(lock, MAX_DYN_SENSOR_WAIT,
+ [&, dyn]{
+ return mConnectedDynamicSensors.find(dyn.sensorHandle)
+ != mConnectedDynamicSensors.end();
+ });
+ it = mConnectedDynamicSensors.find(dyn.sensorHandle);
+ CHECK(it != mConnectedDynamicSensors.end());
+ }
dst->dynamic_sensor_meta.sensor = it->second;
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 75da7bb..bc8d20f 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -139,6 +139,14 @@
Vector<sensor_t> mSensorList;
std::unordered_map<int32_t, sensor_t*> mConnectedDynamicSensors;
+ // A bug in the Sensors HIDL spec which marks onDynamicSensorsConnected as oneway causes dynamic
+ // meta events and onDynamicSensorsConnected to be received out of order. This mutex + CV are
+ // used to block meta event processing until onDynamicSensorsConnected is received to simplify
+ // HAL implementations.
+ std::mutex mDynamicSensorsMutex;
+ std::condition_variable mDynamicSensorsCv;
+ static constexpr std::chrono::seconds MAX_DYN_SENSOR_WAIT{5};
+
static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz
mutable Mutex mLock; // protect mActivationCount[].batchParams
// fixed-size array after construction
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 7466c06..5ed8f4d 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -214,7 +214,7 @@
JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
}
- mFlinger->getTransactionCallbackInvoker().finalizePendingCallbackHandles(
+ mFlinger->getTransactionCallbackInvoker().addCallbackHandles(
mDrawingState.callbackHandles, jankData);
mDrawingState.callbackHandles = {};
@@ -564,10 +564,6 @@
handle->acquireTime = mCallbackHandleAcquireTime;
handle->frameNumber = mDrawingState.frameNumber;
- // Notify the transaction completed thread that there is a pending latched callback
- // handle
- mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle);
-
// Store so latched time and release fence can be set
mDrawingState.callbackHandles.push_back(handle);
@@ -765,7 +761,7 @@
std::deque<sp<CallbackHandle>> remainingHandles;
mFlinger->getTransactionCallbackInvoker()
- .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
+ .addOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles);
mDrawingState.callbackHandles = remainingHandles;
mDrawingStateModified = false;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 3f6bd6f..c9f00a0 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -22,6 +22,7 @@
#pragma clang diagnostic ignored "-Wextra"
#include "RefreshRateConfigs.h"
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <utils/Trace.h>
#include <chrono>
@@ -714,9 +715,31 @@
RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
Config config)
: mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
+ initializeIdleTimer();
updateDisplayModes(modes, currentModeId);
}
+void RefreshRateConfigs::initializeIdleTimer() {
+ if (mConfig.idleTimerTimeoutMs > 0) {
+ const auto getCallback = [this]() -> std::optional<IdleTimerCallbacks::Callbacks> {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ if (!mIdleTimerCallbacks.has_value()) return {};
+ return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel
+ : mIdleTimerCallbacks->platform;
+ };
+
+ mIdleTimer.emplace(
+ "IdleTimer", std::chrono::milliseconds(mConfig.idleTimerTimeoutMs),
+ [getCallback] {
+ if (const auto callback = getCallback()) callback->onReset();
+ },
+ [getCallback] {
+ if (const auto callback = getCallback()) callback->onExpired();
+ });
+ mIdleTimer->start();
+ }
+}
+
void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,
DisplayModeId currentModeId) {
std::lock_guard lock(mLock);
@@ -990,6 +1013,9 @@
base::StringAppendF(&result, "Supports Frame Rate Override: %s\n",
mSupportsFrameRateOverride ? "yes" : "no");
+ base::StringAppendF(&result, "Idle timer: (%s) %s\n",
+ mConfig.supportKernelIdleTimer ? "kernel" : "platform",
+ mIdleTimer ? mIdleTimer->dump().c_str() : "off");
result.append("\n");
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index ffaa029..3abf83d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -27,6 +27,7 @@
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/HWComposer.h"
#include "Fps.h"
+#include "Scheduler/OneShotTimer.h"
#include "Scheduler/SchedulerUtils.h"
#include "Scheduler/Seamlessness.h"
#include "Scheduler/StrongTyping.h"
@@ -305,11 +306,19 @@
// or heuristic, such that refresh rates higher than this value will not be voted for. 0 if
// no threshold is set.
int frameRateMultipleThreshold = 0;
+
+ // The Idle Timer timeout. 0 timeout means no idle timer.
+ int32_t idleTimerTimeoutMs = 0;
+
+ // Whether to use idle timer callbacks that support the kernel timer.
+ bool supportKernelIdleTimer = false;
};
- RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
+ RefreshRateConfigs(const DisplayModes&, DisplayModeId,
Config config = {.enableFrameRateOverride = false,
- .frameRateMultipleThreshold = 0});
+ .frameRateMultipleThreshold = 0,
+ .idleTimerTimeoutMs = 0,
+ .supportKernelIdleTimer = false});
// Returns whether switching modes (refresh rate or resolution) is possible.
// TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
@@ -349,6 +358,30 @@
Fps displayFrameRate, bool touch) const
EXCLUDES(mLock);
+ bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; }
+
+ void setIdleTimerCallbacks(std::function<void()> platformTimerReset,
+ std::function<void()> platformTimerExpired,
+ std::function<void()> kernelTimerReset,
+ std::function<void()> kernelTimerExpired) {
+ std::scoped_lock lock(mIdleTimerCallbacksMutex);
+ mIdleTimerCallbacks.emplace();
+ mIdleTimerCallbacks->platform.onReset = platformTimerReset;
+ mIdleTimerCallbacks->platform.onExpired = platformTimerExpired;
+ mIdleTimerCallbacks->kernel.onReset = kernelTimerReset;
+ mIdleTimerCallbacks->kernel.onExpired = kernelTimerExpired;
+ }
+
+ void resetIdleTimer(bool kernelOnly) {
+ if (!mIdleTimer) {
+ return;
+ }
+ if (kernelOnly && !mConfig.supportKernelIdleTimer) {
+ return;
+ }
+ mIdleTimer->reset();
+ };
+
void dump(std::string& result) const EXCLUDES(mLock);
RefreshRateConfigs(const RefreshRateConfigs&) = delete;
@@ -414,6 +447,8 @@
void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
+ void initializeIdleTimer();
+
// The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
@@ -457,6 +492,22 @@
};
mutable std::optional<GetBestRefreshRateInvocation> lastBestRefreshRateInvocation
GUARDED_BY(mLock);
+
+ // Timer that records time between requests for next vsync.
+ std::optional<scheduler::OneShotTimer> mIdleTimer;
+
+ struct IdleTimerCallbacks {
+ struct Callbacks {
+ std::function<void()> onReset;
+ std::function<void()> onExpired;
+ };
+
+ Callbacks platform;
+ Callbacks kernel;
+ };
+
+ std::mutex mIdleTimerCallbacksMutex;
+ std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex);
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index c64ccd1..12e741b 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -120,28 +120,15 @@
Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& callback)
: Scheduler(configs, callback,
- {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
- .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
+ {.useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}
Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& callback, Options options)
- : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
+ : Scheduler(createVsyncSchedule(configs->supportsKernelIdleTimer()), configs, callback,
createLayerHistory(), options) {
using namespace sysprop;
- const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
-
- if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) {
- const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback
- : &Scheduler::idleTimerCallback;
- mIdleTimer.emplace(
- "IdleTimer", std::chrono::milliseconds(millis),
- [this, callback] { std::invoke(callback, this, TimerState::Reset); },
- [this, callback] { std::invoke(callback, this, TimerState::Expired); });
- mIdleTimer->start();
- }
-
if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
// Touch events are coming to SF every 100ms, so the timer needs to be higher than that
mTouchTimer.emplace(
@@ -168,11 +155,11 @@
mVsyncSchedule(std::move(schedule)),
mLayerHistory(std::move(layerHistory)),
mSchedulerCallback(schedulerCallback),
- mRefreshRateConfigs(configs),
mPredictedVsyncTracer(
base::GetBoolProperty("debug.sf.show_predicted_vsync", false)
? std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch)
: nullptr) {
+ setRefreshRateConfigs(configs);
mSchedulerCallback.setVsyncEnabled(false);
}
@@ -180,7 +167,7 @@
// Ensure the OneShotTimer threads are joined before we start destroying state.
mDisplayPowerTimer.reset();
mTouchTimer.reset();
- mIdleTimer.reset();
+ mRefreshRateConfigs.reset();
}
Scheduler::VsyncSchedule Scheduler::createVsyncSchedule(bool supportKernelTimer) {
@@ -672,18 +659,16 @@
}
void Scheduler::resetIdleTimer() {
- if (mIdleTimer) {
- mIdleTimer->reset();
- }
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ false);
}
void Scheduler::onTouchHint() {
if (mTouchTimer) {
mTouchTimer->reset();
- if (mOptions.supportKernelTimer && mIdleTimer) {
- mIdleTimer->reset();
- }
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs->resetIdleTimer(/*kernelOnly*/ true);
}
}
@@ -755,7 +740,6 @@
void Scheduler::dump(std::string& result) const {
using base::StringAppendF;
- StringAppendF(&result, "+ Idle timer: %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Touch timer: %s\n",
mTouchTimer ? mTouchTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Content detection: %s %s\n\n",
@@ -867,7 +851,7 @@
}
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
- const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
+ const bool idle = mFeatures.idleTimer == TimerState::Expired;
return refreshRateConfigs
->getBestRefreshRate(mFeatures.contentRequirements,
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 420ba61..3f3debe 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -136,7 +136,6 @@
// Detects content using layer history, and selects a matching refresh rate.
void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock);
- bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
void resetIdleTimer();
// Indicates that touch interaction is taking place.
@@ -187,6 +186,15 @@
EXCLUDES(mRefreshRateConfigsLock) {
std::scoped_lock lock(mRefreshRateConfigsLock);
mRefreshRateConfigs = std::move(refreshRateConfigs);
+ mRefreshRateConfigs->setIdleTimerCallbacks(
+ [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Reset); },
+ [this] { std::invoke(&Scheduler::idleTimerCallback, this, TimerState::Expired); },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Reset);
+ },
+ [this] {
+ std::invoke(&Scheduler::kernelIdleTimerCallback, this, TimerState::Expired);
+ });
}
nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
@@ -206,8 +214,6 @@
enum class TouchState { Inactive, Active };
struct Options {
- // Whether to use idle timer callbacks that support the kernel timer.
- bool supportKernelTimer;
// Whether to use content detection at all.
bool useContentDetection;
};
@@ -293,8 +299,6 @@
// Used to choose refresh rate if content detection is enabled.
std::unique_ptr<LayerHistory> mLayerHistory;
- // Timer that records time between requests for next vsync.
- std::optional<scheduler::OneShotTimer> mIdleTimer;
// Timer used to monitor touch events.
std::optional<scheduler::OneShotTimer> mTouchTimer;
// Timer used to monitor display power mode.
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 7b5d462..ee973f7 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -42,6 +42,7 @@
: mClock(std::move(clock)),
mTracker(tracker),
mPendingLimit(pendingFenceLimit),
+ // TODO(adyabr): change mSupportKernelIdleTimer when the active display changes
mSupportKernelIdleTimer(supportKernelIdleTimer) {}
VSyncReactor::~VSyncReactor() = default;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4345b84..1127c3c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -277,6 +277,40 @@
ROTATE_SURFACE_FLINGER = 0x2,
};
+struct IdleTimerConfig {
+ int32_t timeoutMs;
+ bool supportKernelIdleTimer;
+};
+
+IdleTimerConfig getIdleTimerConfiguration(DisplayId displayId) {
+ // TODO(adyabr): use ro.surface_flinger.* namespace
+
+ const auto displayIdleTimerMsKey = [displayId] {
+ std::stringstream ss;
+ ss << "debug.sf.set_idle_timer_ms_" << displayId.value;
+ return ss.str();
+ }();
+
+ const auto displaySupportKernelIdleTimerKey = [displayId] {
+ std::stringstream ss;
+ ss << "debug.sf.support_kernel_idle_timer_" << displayId.value;
+ return ss.str();
+ }();
+
+ const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
+ const auto displaySupportKernelIdleTimer =
+ base::GetBoolProperty(displaySupportKernelIdleTimerKey, false);
+
+ if (displayIdleTimerMs > 0) {
+ return {displayIdleTimerMs, displaySupportKernelIdleTimer};
+ }
+
+ const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
+ const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
+
+ return {millis, sysprop::support_kernel_idle_timer(false)};
+}
+
} // namespace anonymous
// ---------------------------------------------------------------------------
@@ -462,9 +496,6 @@
useFrameRateApi = use_frame_rate_api(true);
- mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false);
- base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
-
mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0);
// Debug property overrides ro. property
@@ -2152,10 +2183,11 @@
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
+ // Send on commit callbacks
+ mTransactionCallbackInvoker.sendCallbacks();
+
bool refreshNeeded = handlePageFlip();
- // Send on commit callbacks
- mTransactionCallbackInvoker.sendCallbacks();
if (mVisibleRegionsDirty) {
computeLayerBounds();
@@ -2346,6 +2378,7 @@
mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence);
mTransactionCallbackInvoker.sendCallbacks();
+ mTransactionCallbackInvoker.clearCompletedTransactions();
if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON &&
mPreviousPresentFences[0].fenceTime->isValid()) {
@@ -2653,10 +2686,14 @@
creationArgs.connectionType = physical->type;
creationArgs.supportedModes = physical->supportedModes;
creationArgs.activeModeId = physical->activeMode->getId();
+ const auto [idleTimerTimeoutMs, supportKernelIdleTimer] =
+ getIdleTimerConfiguration(compositionDisplay->getId());
scheduler::RefreshRateConfigs::Config config =
{.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
.frameRateMultipleThreshold =
- base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
+ base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0),
+ .idleTimerTimeoutMs = idleTimerTimeoutMs,
+ .supportKernelIdleTimer = supportKernelIdleTimer};
creationArgs.refreshRateConfigs =
std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
creationArgs.activeModeId, config);
@@ -3729,8 +3766,7 @@
// that listeners with SurfaceControls will start registration during setClientStateLocked
// below.
for (const auto& listener : listenerCallbacks) {
- mTransactionCallbackInvoker.startRegistration(listener);
- mTransactionCallbackInvoker.endRegistration(listener);
+ mTransactionCallbackInvoker.addEmptyTransaction(listener);
}
std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces;
@@ -3748,10 +3784,6 @@
}
}
- for (const auto& listenerCallback : listenerCallbacksWithSurfaces) {
- mTransactionCallbackInvoker.endRegistration(listenerCallback);
- }
-
// If the state doesn't require a traversal and there are callbacks, send them now
if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) {
mTransactionCallbackInvoker.sendCallbacks();
@@ -3881,14 +3913,12 @@
ListenerCallbacks onCommitCallbacks = listener.filter(CallbackId::Type::ON_COMMIT);
if (!onCommitCallbacks.callbackIds.empty()) {
- mTransactionCallbackInvoker.startRegistration(onCommitCallbacks);
filteredListeners.push_back(onCommitCallbacks);
outListenerCallbacks.insert(onCommitCallbacks);
}
ListenerCallbacks onCompleteCallbacks = listener.filter(CallbackId::Type::ON_COMPLETE);
if (!onCompleteCallbacks.callbackIds.empty()) {
- mTransactionCallbackInvoker.startRegistration(onCompleteCallbacks);
filteredListeners.push_back(onCompleteCallbacks);
outListenerCallbacks.insert(onCompleteCallbacks);
}
@@ -5846,16 +5876,18 @@
void SurfaceFlinger::toggleKernelIdleTimer() {
using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
- // If the support for kernel idle timer is disabled in SF code, don't do anything.
- if (!mSupportKernelIdleTimer) {
- return;
- }
const auto display = getDefaultDisplayDeviceLocked();
if (!display) {
ALOGW("%s: default display is null", __func__);
return;
}
+ // If the support for kernel idle timer is disabled for the active display,
+ // don't do anything.
+ if (!display->refreshRateConfigs().supportsKernelIdleTimer()) {
+ return;
+ }
+
const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
switch (action) {
case KernelIdleTimerAction::TurnOff:
@@ -6978,6 +7010,10 @@
mScheduler->setRefreshRateConfigs(activeDisplay->holdRefreshRateConfigs());
onActiveDisplaySizeChanged(activeDisplay);
mActiveDisplayTransformHint = activeDisplay->getTransformHint();
+
+ // Update the kernel timer for the current active display, since the policy
+ // for this display might have changed when it was not the active display.
+ toggleKernelIdleTimer();
}
status_t SurfaceFlinger::addWindowInfosListener(
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6c046fc..c7f5235 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -759,8 +759,6 @@
// Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
// make calls to sys prop each time.
bool mKernelIdleTimerEnabled = false;
- // Keeps track of whether the kernel timer is supported on the SF side.
- bool mSupportKernelIdleTimer = false;
// Show spinner with refresh rate overlay
bool mRefreshRateOverlaySpinner = false;
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
index 6af69f0..4b12a26 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -49,121 +49,25 @@
return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT;
}
-TransactionCallbackInvoker::~TransactionCallbackInvoker() {
- {
- std::lock_guard lock(mMutex);
- for (const auto& [listener, transactionStats] : mCompletedTransactions) {
- listener->unlinkToDeath(mDeathRecipient);
- }
- }
-}
-
-status_t TransactionCallbackInvoker::startRegistration(const ListenerCallbacks& listenerCallbacks) {
- std::lock_guard lock(mMutex);
-
- auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
+void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) {
auto& [listener, callbackIds] = listenerCallbacks;
-
- if (inserted) {
- if (mCompletedTransactions.count(listener) == 0) {
- status_t err = listener->linkToDeath(mDeathRecipient);
- if (err != NO_ERROR) {
- ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
- return err;
- }
- }
- auto& transactionStatsDeque = mCompletedTransactions[listener];
- transactionStatsDeque.emplace_back(callbackIds);
- }
-
- return NO_ERROR;
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+ transactionStatsDeque.emplace_back(callbackIds);
}
-status_t TransactionCallbackInvoker::endRegistration(const ListenerCallbacks& listenerCallbacks) {
- std::lock_guard lock(mMutex);
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- if (itr == mRegisteringTransactions.end()) {
- ALOGE("cannot end a registration that does not exist");
- return BAD_VALUE;
- }
-
- mRegisteringTransactions.erase(itr);
-
- return NO_ERROR;
-}
-
-bool TransactionCallbackInvoker::isRegisteringTransaction(
- const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
- ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- return itr != mRegisteringTransactions.end();
-}
-
-status_t TransactionCallbackInvoker::registerPendingCallbackHandle(
- const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
-
- // If we can't find the transaction stats something has gone wrong. The client should call
- // startRegistration before trying to register a pending callback handle.
- TransactionStats* transactionStats;
- status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
- if (err != NO_ERROR) {
- ALOGE("cannot find transaction stats");
- return err;
- }
-
- mPendingTransactions[handle->listener][handle->callbackIds]++;
- return NO_ERROR;
-}
-
-status_t TransactionCallbackInvoker::finalizeCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) {
- auto listener = mPendingTransactions.find(handle->listener);
- if (listener != mPendingTransactions.end()) {
- auto& pendingCallbacks = listener->second;
- auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
-
- if (pendingCallback != pendingCallbacks.end()) {
- auto& pendingCount = pendingCallback->second;
-
- // Decrease the pending count for this listener
- if (--pendingCount == 0) {
- pendingCallbacks.erase(pendingCallback);
- }
- } else {
- ALOGW("there are more latched callbacks than there were registered callbacks");
- }
- if (listener->second.size() == 0) {
- mPendingTransactions.erase(listener);
- }
- } else {
- ALOGW("cannot find listener in mPendingTransactions");
- }
-
- status_t err = addCallbackHandle(handle, jankData);
- if (err != NO_ERROR) {
- ALOGE("could not add callback handle");
- return err;
- }
- return NO_ERROR;
-}
-
-status_t TransactionCallbackInvoker::finalizeOnCommitCallbackHandles(
+status_t TransactionCallbackInvoker::addOnCommitCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles,
std::deque<sp<CallbackHandle>>& outRemainingHandles) {
if (handles.empty()) {
return NO_ERROR;
}
- std::lock_guard lock(mMutex);
const std::vector<JankData>& jankData = std::vector<JankData>();
for (const auto& handle : handles) {
if (!containsOnCommitCallbacks(handle->callbackIds)) {
outRemainingHandles.push_back(handle);
continue;
}
- status_t err = finalizeCallbackHandle(handle, jankData);
+ status_t err = addCallbackHandle(handle, jankData);
if (err != NO_ERROR) {
return err;
}
@@ -172,14 +76,13 @@
return NO_ERROR;
}
-status_t TransactionCallbackInvoker::finalizePendingCallbackHandles(
+status_t TransactionCallbackInvoker::addCallbackHandles(
const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
if (handles.empty()) {
return NO_ERROR;
}
- std::lock_guard lock(mMutex);
for (const auto& handle : handles) {
- status_t err = finalizeCallbackHandle(handle, jankData);
+ status_t err = addCallbackHandle(handle, jankData);
if (err != NO_ERROR) {
return err;
}
@@ -190,8 +93,6 @@
status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle(
const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
-
return addCallbackHandle(handle, std::vector<JankData>());
}
@@ -208,9 +109,8 @@
return NO_ERROR;
}
}
-
- ALOGE("could not find transaction stats");
- return BAD_VALUE;
+ *outTransactionStats = &transactionStatsDeque.emplace_back(callbackIds);
+ return NO_ERROR;
}
status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle,
@@ -244,13 +144,10 @@
}
void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) {
- std::lock_guard<std::mutex> lock(mMutex);
mPresentFence = presentFence;
}
void TransactionCallbackInvoker::sendCallbacks() {
- std::lock_guard lock(mMutex);
-
// For each listener
auto completedTransactionsItr = mCompletedTransactions.begin();
while (completedTransactionsItr != mCompletedTransactions.end()) {
@@ -263,27 +160,9 @@
while (transactionStatsItr != transactionStatsDeque.end()) {
auto& transactionStats = *transactionStatsItr;
- // If this transaction is still registering, it is not safe to send a callback
- // because there could be surface controls that haven't been added to
- // transaction stats or mPendingTransactions.
- if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
- break;
- }
-
- // If we are still waiting on the callback handles for this transaction, stop
- // here because all transaction callbacks for the same listener must come in order
- auto pendingTransactions = mPendingTransactions.find(listener);
- if (pendingTransactions != mPendingTransactions.end() &&
- pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
- break;
- }
-
// If the transaction has been latched
if (transactionStats.latchTime >= 0 &&
!containsOnCommitCallbacks(transactionStats.callbackIds)) {
- if (!mPresentFence) {
- break;
- }
transactionStats.presentFence = mPresentFence;
}
@@ -303,20 +182,9 @@
// we get pointers that compare unequal in the SF process.
interface_cast<ITransactionCompletedListener>(listenerStats.listener)
->onTransactionCompleted(listenerStats);
- if (transactionStatsDeque.empty()) {
- listener->unlinkToDeath(mDeathRecipient);
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
- } else {
- completedTransactionsItr++;
- }
- } else {
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
}
- } else {
- completedTransactionsItr++;
}
+ completedTransactionsItr++;
}
if (mPresentFence) {
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h
index 6f4d812..71ca6e5 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -56,79 +56,38 @@
class TransactionCallbackInvoker {
public:
- ~TransactionCallbackInvoker();
-
- // Adds listener and callbackIds in case there are no SurfaceControls that are supposed
- // to be included in the callback. This functions should be call before attempting to register
- // any callback handles.
- status_t startRegistration(const ListenerCallbacks& listenerCallbacks);
- // Ends the registration. After this is called, no more CallbackHandles will be registered.
- // It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
- status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
-
- // Informs the TransactionCallbackInvoker that there is a Transaction with a CallbackHandle
- // that needs to be latched and presented this frame. This function should be called once the
- // layer has received the CallbackHandle so the TransactionCallbackInvoker knows not to send
- // a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
- // presented.
- status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
- // Notifies the TransactionCallbackInvoker that a pending CallbackHandle has been presented.
- status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
+ status_t addCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
const std::vector<JankData>& jankData);
- status_t finalizeOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
+ status_t addOnCommitCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
std::deque<sp<CallbackHandle>>& outRemainingHandles);
// Adds the Transaction CallbackHandle from a layer that does not need to be relatched and
// presented this frame.
status_t registerUnpresentedCallbackHandle(const sp<CallbackHandle>& handle);
+ void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks);
void addPresentFence(const sp<Fence>& presentFence);
void sendCallbacks();
-
-private:
-
- bool isRegisteringTransaction(const sp<IBinder>& transactionListener,
- const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
-
- status_t findTransactionStats(const sp<IBinder>& listener,
- const std::vector<CallbackId>& callbackIds,
- TransactionStats** outTransactionStats) REQUIRES(mMutex);
+ void clearCompletedTransactions() {
+ mCompletedTransactions.clear();
+ }
status_t addCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) REQUIRES(mMutex);
+ const std::vector<JankData>& jankData);
- status_t finalizeCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) REQUIRES(mMutex);
- class CallbackDeathRecipient : public IBinder::DeathRecipient {
- public:
- // This function is a no-op. isBinderAlive needs a linked DeathRecipient to work.
- // Death recipients needs a binderDied function.
- //
- // (isBinderAlive checks if BpBinder's mAlive is 0. mAlive is only set to 0 in sendObituary.
- // sendObituary is only called if linkToDeath was called with a DeathRecipient.)
- void binderDied(const wp<IBinder>& /*who*/) override {}
- };
- sp<CallbackDeathRecipient> mDeathRecipient =
- new CallbackDeathRecipient();
+private:
+ status_t findTransactionStats(const sp<IBinder>& listener,
+ const std::vector<CallbackId>& callbackIds,
+ TransactionStats** outTransactionStats);
- std::mutex mMutex;
- std::condition_variable_any mConditionVariable;
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> mRegisteringTransactions
- GUARDED_BY(mMutex);
-
- std::unordered_map<
- sp<IBinder>,
- std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
- IListenerHash>
- mPendingTransactions GUARDED_BY(mMutex);
std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
- mCompletedTransactions GUARDED_BY(mMutex);
+ mCompletedTransactions;
- sp<Fence> mPresentFence GUARDED_BY(mMutex);
+ sp<Fence> mPresentFence;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index 35033ea..e388a6f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -21,7 +21,6 @@
#include <gtest/gtest.h>
#include <gui/LayerMetadata.h>
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "EffectLayer.h"
#include "Layer.h"
@@ -60,7 +59,6 @@
static constexpr int32_t PRIORITY_UNSET = -1;
void setupScheduler();
- sp<BufferQueueLayer> createBufferQueueLayer();
sp<BufferStateLayer> createBufferStateLayer();
sp<EffectLayer> createEffectLayer();
@@ -90,12 +88,6 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-sp<BufferQueueLayer> RefreshRateSelectionTest::createBufferQueueLayer() {
- sp<Client> client;
- LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
- LAYER_FLAGS, LayerMetadata());
- return new BufferQueueLayer(args);
-}
sp<BufferStateLayer> RefreshRateSelectionTest::createBufferStateLayer() {
sp<Client> client;
@@ -149,46 +141,6 @@
/* ------------------------------------------------------------------------
* Test cases
*/
-TEST_F(RefreshRateSelectionTest, testPriorityOnBufferQueueLayers) {
- mParent = createBufferQueueLayer();
- mChild = createBufferQueueLayer();
- setParent(mChild.get(), mParent.get());
- mGrandChild = createBufferQueueLayer();
- setParent(mGrandChild.get(), mChild.get());
-
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mGrandChild->getFrameRateSelectionPriority());
-
- // Child has its own priority.
- mGrandChild->setFrameRateSelectionPriority(1);
- commitTransaction(mGrandChild.get());
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-
- // Child inherits from his parent.
- mChild->setFrameRateSelectionPriority(1);
- commitTransaction(mChild.get());
- mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mGrandChild.get());
-
- ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-
- // Grandchild inherits from his grand parent.
- mParent->setFrameRateSelectionPriority(1);
- commitTransaction(mParent.get());
- mChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mChild.get());
- mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET);
- commitTransaction(mGrandChild.get());
- ASSERT_EQ(1, mParent->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mChild->getFrameRateSelectionPriority());
- ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority());
-}
-
TEST_F(RefreshRateSelectionTest, testPriorityOnBufferStateLayers) {
mParent = createBufferStateLayer();
mChild = createBufferStateLayer();
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index a4e9d20..84fa1e2 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -24,7 +24,6 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "EffectLayer.h"
#include "Layer.h"
@@ -65,17 +64,6 @@
static constexpr uint32_t LAYER_FLAGS = 0;
};
-class BufferQueueLayerFactory : public LayerFactory {
-public:
- std::string name() override { return "BufferQueueLayer"; }
- sp<Layer> createLayer(TestableSurfaceFlinger& flinger) override {
- sp<Client> client;
- LayerCreationArgs args(flinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT,
- LAYER_FLAGS, LayerMetadata());
- return new BufferQueueLayer(args);
- }
-};
-
class BufferStateLayerFactory : public LayerFactory {
public:
std::string name() override { return "BufferStateLayer"; }
@@ -417,8 +405,7 @@
}
INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest,
- testing::Values(std::make_shared<BufferQueueLayerFactory>(),
- std::make_shared<BufferStateLayerFactory>(),
+ testing::Values(std::make_shared<BufferStateLayerFactory>(),
std::make_shared<EffectLayerFactory>()),
PrintToStringParamName);
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index a99dabe..1d21bd4 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -44,7 +44,7 @@
ISchedulerCallback& callback)
: Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr},
refreshRateConfigs, callback, createLayerHistory(),
- {.supportKernelTimer = false, .useContentDetection = true}) {}
+ {.useContentDetection = true}) {}
// Used to inject mock event thread.
ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {