Merge "GestureConverter: add option to make 3-finger tap a shortcut" into main
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d24edc4..b012243 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1841,6 +1841,11 @@
RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
}
+ /* Dump USB information */
+ RunCommand("typec_connector_class", {"typec_connector_class"},
+ CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+ RunCommand("lsusb", {"lsusb"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
+
printf("========================================================\n");
printf("== Android Framework Services\n");
printf("========================================================\n");
diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h
index 3f32a5a..3486e9b 100644
--- a/include/android/performance_hint.h
+++ b/include/android/performance_hint.h
@@ -52,7 +52,6 @@
* - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
*/
-#include <android/api-level.h>
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 8d61e77..fe38e86 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -763,6 +763,69 @@
__INTRODUCED_IN(31);
/**
+ * Sets the intended frame rate for the given \a surface_control.
+ *
+ * On devices that are capable of running the display at different frame rates,
+ * the system may choose a display refresh rate to better match this surface's frame
+ * rate. Usage of this API won't introduce frame rate throttling, or affect other
+ * aspects of the application's frame production pipeline. However, because the system
+ * may change the display refresh rate, calls to this function may result in changes
+ * to Choreographer callback timings, and changes to the time interval at which the
+ * system releases buffers back to the application.
+ *
+ * You can register for changes in the refresh rate using
+ * \a AChoreographer_registerRefreshRateCallback.
+ *
+ * See ASurfaceTransaction_clearFrameRate().
+ *
+ * Available since API level 36.
+ *
+ * \param desiredMinRate The desired minimum frame rate (inclusive) for the surface, specifying that
+ * the surface prefers the device render rate to be at least `desiredMinRate`.
+ *
+ * <p>Set `desiredMinRate` = `desiredMaxRate` to indicate the surface prefers an exact frame rate.
+ *
+ * <p>Set `desiredMinRate` = 0 to indicate the surface has no preference
+ * and any frame rate is acceptable.
+ *
+ * <p>The value should be greater than or equal to 0.
+ *
+ * \param desiredMaxRate The desired maximum frame rate (inclusive) for the surface, specifying that
+ * the surface prefers the device render rate to be at most `desiredMaxRate`.
+ *
+ * <p>Set `desiredMaxRate` = `desiredMinRate` to indicate the surface prefers an exact frame rate.
+ *
+ * <p>Set `desiredMaxRate` = positive infinity to indicate the surface has no preference
+ * and any frame rate is acceptable.
+ *
+ * <p>The value should be greater than or equal to `desiredMinRate`.
+ *
+ * \param fixedSourceRate The "fixed source" frame rate of the surface if the content has an
+ * inherently fixed frame rate, e.g. a video that has a specific frame rate.
+ *
+ * <p>When the frame rate chosen for the surface is the `fixedSourceRate` or a
+ * multiple, the surface can render without frame pulldown, for optimal smoothness. For
+ * example, a 30 fps video (`fixedSourceRate`=30) renders just as smoothly on 30 fps,
+ * 60 fps, 90 fps, 120 fps, and so on.
+ *
+ * <p>Setting the fixed source rate can also be used together with a desired
+ * frame rate min and max via setting `desiredMinRate` and `desiredMaxRate`. This still
+ * means the surface's content has a fixed frame rate of `fixedSourceRate`, but additionally
+ * specifies the preference to be in the range [`desiredMinRate`, `desiredMaxRate`]. For example, an
+ * app might want to specify there is 30 fps video (`fixedSourceRate`=30) as well as a smooth
+ * animation on the same surface which looks good when drawing within a frame rate range such as
+ * [`desiredMinRate`, `desiredMaxRate`] = [60,120].
+ *
+ * \param changeFrameRateStrategy Whether display refresh rate transitions caused by this surface
+ * should be seamless. A seamless transition is one that doesn't have any visual interruptions, such
+ * as a black screen for a second or two.
+ */
+void ASurfaceTransaction_setFrameRateParams(
+ ASurfaceTransaction* _Nonnull transaction, ASurfaceControl* _Nonnull surface_control,
+ float desiredMinRate, float desiredMaxRate, float fixedSourceRate,
+ ANativeWindow_ChangeFrameRateStrategy changeFrameRateStrategy) __INTRODUCED_IN(36);
+
+/**
* Clears the frame rate which is set for \a surface_control.
*
* This is equivalent to calling
diff --git a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
index 392ebb5..48c0ea6 100644
--- a/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
+++ b/libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp
@@ -37,8 +37,12 @@
// Set `cid` to VMADDR_CID_LOCAL to only bind to the local vsock interface.
// Returns an opaque handle to the running server instance, or null if the server
// could not be started.
+// Set |port| to VMADDR_PORT_ANY to pick an available ephemeral port.
+// |assignedPort| will be set to the assigned port number if it is not null.
+// This will be the provided |port|, or the chosen available ephemeral port when
+// |port| is VMADDR_PORT_ANY.
[[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid,
- unsigned int port);
+ unsigned int port, unsigned int* assignedPort);
// Starts a Unix domain RPC server with an open raw socket file descriptor
// and a given root IBinder object.
diff --git a/libs/binder/libbinder_rpc_unstable.cpp b/libs/binder/libbinder_rpc_unstable.cpp
index 21537fc..a84a0c6 100644
--- a/libs/binder/libbinder_rpc_unstable.cpp
+++ b/libs/binder/libbinder_rpc_unstable.cpp
@@ -81,7 +81,8 @@
extern "C" {
#ifndef __TRUSTY__
-ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port) {
+ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid, unsigned int port,
+ unsigned int* assignedPort) {
auto server = RpcServer::make();
unsigned int bindCid = VMADDR_CID_ANY; // bind to the remote interface
@@ -90,7 +91,7 @@
cid = VMADDR_CID_ANY; // no need for a connection filter
}
- if (status_t status = server->setupVsockServer(bindCid, port); status != OK) {
+ if (status_t status = server->setupVsockServer(bindCid, port, assignedPort); status != OK) {
ALOGE("Failed to set up vsock server with port %u error: %s", port,
statusToString(status).c_str());
return nullptr;
diff --git a/libs/binder/ndk/binder_rpc.cpp b/libs/binder/ndk/binder_rpc.cpp
index 886eb4b..53ab68e 100644
--- a/libs/binder/ndk/binder_rpc.cpp
+++ b/libs/binder/ndk/binder_rpc.cpp
@@ -104,8 +104,8 @@
};
ABinderRpc_AccessorProvider* ABinderRpc_registerAccessorProvider(
- ABinderRpc_AccessorProvider_getAccessorCallback provider, const char** instances,
- size_t numInstances, void* data,
+ ABinderRpc_AccessorProvider_getAccessorCallback provider,
+ const char* const* const instances, size_t numInstances, void* data,
ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
if (provider == nullptr) {
ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
diff --git a/libs/binder/ndk/include_platform/android/binder_rpc.h b/libs/binder/ndk/include_platform/android/binder_rpc.h
index 66667d3..7d54e2d 100644
--- a/libs/binder/ndk/include_platform/android/binder_rpc.h
+++ b/libs/binder/ndk/include_platform/android/binder_rpc.h
@@ -144,8 +144,9 @@
*/
ABinderRpc_AccessorProvider* _Nullable ABinderRpc_registerAccessorProvider(
ABinderRpc_AccessorProvider_getAccessorCallback _Nonnull provider,
- const char* _Nullable* _Nonnull instances, size_t numInstances, void* _Nullable data,
- ABinderRpc_AccessorProviderUserData_deleteCallback _Nullable onDelete) __INTRODUCED_IN(36);
+ const char* _Nullable const* const _Nonnull instances, size_t numInstances,
+ void* _Nullable data, ABinderRpc_AccessorProviderUserData_deleteCallback _Nullable onDelete)
+ __INTRODUCED_IN(36);
/**
* Remove an ABinderRpc_AccessorProvider from libbinder. This will remove references
diff --git a/libs/binder/rust/rpcbinder/src/server/android.rs b/libs/binder/rust/rpcbinder/src/server/android.rs
index 2ab3447..74ce315 100644
--- a/libs/binder/rust/rpcbinder/src/server/android.rs
+++ b/libs/binder/rust/rpcbinder/src/server/android.rs
@@ -18,7 +18,7 @@
use binder::{unstable_api::AsNative, SpIBinder};
use binder_rpc_unstable_bindgen::ARpcServer;
use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
-use std::ffi::CString;
+use std::ffi::{c_uint, CString};
use std::io::{Error, ErrorKind};
use std::os::unix::io::{IntoRawFd, OwnedFd};
@@ -42,18 +42,29 @@
/// Creates a binder RPC server, serving the supplied binder service implementation on the given
/// vsock port. Only connections from the given CID are accepted.
///
- // Set `cid` to libc::VMADDR_CID_ANY to accept connections from any client.
- // Set `cid` to libc::VMADDR_CID_LOCAL to only bind to the local vsock interface.
- pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> {
+ /// Set `cid` to [`libc::VMADDR_CID_ANY`] to accept connections from any client.
+ /// Set `cid` to [`libc::VMADDR_CID_LOCAL`] to only bind to the local vsock interface.
+ /// Set `port` to [`libc::VMADDR_PORT_ANY`] to pick an ephemeral port.
+ /// The assigned port is returned with RpcServer.
+ pub fn new_vsock(
+ mut service: SpIBinder,
+ cid: u32,
+ port: u32,
+ ) -> Result<(RpcServer, u32 /* assigned_port */), Error> {
let service = service.as_native_mut();
+ let mut assigned_port: c_uint = 0;
// SAFETY: Service ownership is transferring to the server and won't be valid afterward.
// Plus the binder objects are threadsafe.
- unsafe {
+ let server = unsafe {
Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock(
- service, cid, port,
- ))
- }
+ service,
+ cid,
+ port,
+ &mut assigned_port,
+ ))?
+ };
+ Ok((server, assigned_port as _))
}
/// Creates a binder RPC server, serving the supplied binder service implementation on the given
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 66e7ddd..e41f9bb 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -2735,8 +2735,8 @@
bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
Mutex::Autolock lock(mMutex);
- if (mNextFrameNumber > lastFrame) {
- return true;
+ if (mLastFrameNumber > lastFrame) {
+ return true;
}
return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
}
diff --git a/libs/tracing_perfetto/tracing_perfetto_internal.cpp b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
index 9a0042a..c4f8663 100644
--- a/libs/tracing_perfetto/tracing_perfetto_internal.cpp
+++ b/libs/tracing_perfetto/tracing_perfetto_internal.cpp
@@ -253,15 +253,31 @@
void perfettoTraceAsyncBeginForTrack(const struct PerfettoTeCategory& category, const char* name,
const char* trackName, uint64_t cookie) {
PERFETTO_TE(
- category, PERFETTO_TE_SLICE_BEGIN(name),
- PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
+ category, PERFETTO_TE_SLICE_BEGIN(name),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, cookie,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceAsyncEndForTrack(const struct PerfettoTeCategory& category,
const char* trackName, uint64_t cookie) {
- PERFETTO_TE(
- category, PERFETTO_TE_SLICE_END(),
- PERFETTO_TE_NAMED_TRACK(trackName, cookie, PerfettoTeProcessTrackUuid()));
+ PERFETTO_TE(
+ category, PERFETTO_TE_SLICE_END(),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, cookie,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceAsyncBegin(const struct PerfettoTeCategory& category, const char* name,
@@ -281,14 +297,35 @@
void perfettoTraceInstantForTrack(const struct PerfettoTeCategory& category,
const char* trackName, const char* name) {
PERFETTO_TE(
- category, PERFETTO_TE_INSTANT(name),
- PERFETTO_TE_NAMED_TRACK(trackName, 1, PerfettoTeProcessTrackUuid()));
+ category, PERFETTO_TE_INSTANT(name),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeNamedTrackUuid(trackName, 1,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ trackName),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid())));
}
void perfettoTraceCounter(const struct PerfettoTeCategory& category,
- [[maybe_unused]] const char* name, int64_t value) {
- PERFETTO_TE(category, PERFETTO_TE_COUNTER(),
- PERFETTO_TE_INT_COUNTER(value));
+ const char* name, int64_t value) {
+ PERFETTO_TE(
+ category, PERFETTO_TE_COUNTER(),
+ PERFETTO_TE_PROTO_TRACK(
+ PerfettoTeCounterTrackUuid(name,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_CSTR(
+ perfetto_protos_TrackDescriptor_atrace_name_field_number,
+ name),
+ PERFETTO_TE_PROTO_FIELD_VARINT(
+ perfetto_protos_TrackDescriptor_parent_uuid_field_number,
+ PerfettoTeProcessTrackUuid()),
+ PERFETTO_TE_PROTO_FIELD_BYTES(
+ perfetto_protos_TrackDescriptor_counter_field_number,
+ PERFETTO_NULL, 0)),
+ PERFETTO_TE_INT_COUNTER(value));
}
} // namespace internal
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 402a3d2..c743ea2 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -201,6 +201,10 @@
return mPowerMode != hal::PowerMode::OFF;
}
+bool DisplayDevice::isRefreshable() const {
+ return mPowerMode == hal::PowerMode::DOZE || mPowerMode == hal::PowerMode::ON;
+}
+
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 3e3f558..d09a6b3 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -173,6 +173,7 @@
hardware::graphics::composer::hal::PowerMode getPowerMode() const;
void setPowerMode(hardware::graphics::composer::hal::PowerMode);
bool isPoweredOn() const;
+ bool isRefreshable() const;
void tracePowerMode();
// Enables layer caching on this DisplayDevice
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index e385f18..7729671 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -420,6 +420,16 @@
mCondition.notify_all();
}
+void EventThread::omitVsyncDispatching(bool omitted) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (!mVSyncState || mVSyncState->omitted == omitted) {
+ return;
+ }
+
+ mVSyncState->omitted = omitted;
+ mCondition.notify_all();
+}
+
void EventThread::onVsync(nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
std::lock_guard<std::mutex> lock(mMutex);
mLastVsyncCallbackTime = TimePoint::fromNs(vsyncTime);
@@ -521,7 +531,17 @@
}
if (mVSyncState && vsyncRequested) {
- mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
+ const bool vsyncOmitted =
+ FlagManager::getInstance().no_vsyncs_on_screen_off() && mVSyncState->omitted;
+ if (vsyncOmitted) {
+ mState = State::Idle;
+ SFTRACE_INT("VsyncPendingScreenOn", 1);
+ } else {
+ mState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ SFTRACE_INT("VsyncPendingScreenOn", 0);
+ }
+ }
} else {
ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
mState = State::Idle;
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index c3c7eb0..2daf126 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -106,6 +106,8 @@
// Feed clients with fake VSYNC, e.g. while the display is off.
virtual void enableSyntheticVsync(bool) = 0;
+ virtual void omitVsyncDispatching(bool) = 0;
+
virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
virtual void onHotplugConnectionError(int32_t connectionError) = 0;
@@ -165,6 +167,8 @@
void enableSyntheticVsync(bool) override;
+ void omitVsyncDispatching(bool) override;
+
void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
void onHotplugConnectionError(int32_t connectionError) override;
@@ -240,6 +244,9 @@
// True if VSYNC should be faked, e.g. when display is off.
bool synthetic = false;
+
+ // True if VSYNC should not be delivered to apps. Used when the display is off.
+ bool omitted = false;
};
// TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals,
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b83ff19..b8b1f59 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -405,6 +405,14 @@
eventThreadFor(Cycle::Render).enableSyntheticVsync(enable);
}
+void Scheduler::omitVsyncDispatching(bool omitted) {
+ eventThreadFor(Cycle::Render).omitVsyncDispatching(omitted);
+ // Note: If we don't couple Cycle::LastComposite event thread, there is a black screen
+ // after boot. This is most likely sysui or system_server dependency on sf instance
+ // Choreographer
+ eventThreadFor(Cycle::LastComposite).omitVsyncDispatching(omitted);
+}
+
void Scheduler::onFrameRateOverridesChanged() {
const auto [pacesetterId, supportsFrameRateOverrideByContent] = [this] {
std::scoped_lock lock(mDisplayLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index c88b563..d029488 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -154,6 +154,7 @@
bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&) EXCLUDES(mPolicyLock);
void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
+ void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext);
void onHdcpLevelsChanged(Cycle, PhysicalDisplayId, int32_t, int32_t);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8b204a2..cf787cf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3665,6 +3665,26 @@
return display;
}
+void SurfaceFlinger::incRefreshableDisplays() {
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ mRefreshableDisplays++;
+ if (mRefreshableDisplays == 1) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ mScheduler->omitVsyncDispatching(false);
+ }
+ }
+}
+
+void SurfaceFlinger::decRefreshableDisplays() {
+ if (FlagManager::getInstance().no_vsyncs_on_screen_off()) {
+ mRefreshableDisplays--;
+ if (mRefreshableDisplays == 0) {
+ ftl::FakeGuard guard(kMainThreadContext);
+ mScheduler->omitVsyncDispatching(true);
+ }
+ }
+}
+
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
ui::Size resolution(0, 0);
@@ -3756,6 +3776,10 @@
display->adjustRefreshRate(mScheduler->getPacesetterRefreshRate());
}
+ if (display->isRefreshable()) {
+ incRefreshableDisplays();
+ }
+
mDisplays.try_emplace(displayToken, std::move(display));
// For an external display, loadDisplayModes already attempted to select the same mode
@@ -3790,6 +3814,10 @@
} else {
mScheduler->unregisterDisplay(display->getPhysicalId(), mActiveDisplayId);
}
+
+ if (display->isRefreshable()) {
+ decRefreshableDisplays();
+ }
}
mDisplays.erase(displayToken);
@@ -3824,6 +3852,10 @@
if (display->isVirtual()) {
releaseVirtualDisplay(display->getVirtualId());
}
+
+ if (display->isRefreshable()) {
+ decRefreshableDisplays();
+ }
}
mDisplays.erase(displayToken);
@@ -5322,7 +5354,15 @@
activeDisplay->isPoweredOn(),
"Trying to change power mode on inactive display without powering off active display");
+ const bool couldRefresh = display->isRefreshable();
display->setPowerMode(mode);
+ const bool canRefresh = display->isRefreshable();
+
+ if (couldRefresh && !canRefresh) {
+ decRefreshableDisplays();
+ } else if (!couldRefresh && canRefresh) {
+ incRefreshableDisplays();
+ }
const auto activeMode = display->refreshRateSelector().getActiveMode().modePtr;
if (currentMode == hal::PowerMode::OFF) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ad3106c..c96dc6f 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1411,6 +1411,11 @@
// Whether a display should be turned on when initialized
bool mSkipPowerOnForQuiescent;
+ // used for omitting vsync callbacks to apps when the display is not updatable
+ int mRefreshableDisplays GUARDED_BY(mStateLock) = 0;
+ void incRefreshableDisplays() REQUIRES(mStateLock);
+ void decRefreshableDisplays() REQUIRES(mStateLock);
+
frontend::LayerLifecycleManager mLayerLifecycleManager GUARDED_BY(kMainThreadContext);
frontend::LayerHierarchyBuilder mLayerHierarchyBuilder GUARDED_BY(kMainThreadContext);
frontend::LayerSnapshotBuilder mLayerSnapshotBuilder GUARDED_BY(kMainThreadContext);
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index feeafcc..57ef4c7 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -139,6 +139,7 @@
DUMP_READ_ONLY_FLAG(vrr_bugfix_dropped_frame);
DUMP_READ_ONLY_FLAG(restore_blur_step);
DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
+ DUMP_READ_ONLY_FLAG(no_vsyncs_on_screen_off);
DUMP_READ_ONLY_FLAG(protected_if_client);
DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout);
DUMP_READ_ONLY_FLAG(graphite_renderengine);
@@ -156,6 +157,7 @@
DUMP_READ_ONLY_FLAG(trace_frame_rate_override);
DUMP_READ_ONLY_FLAG(true_hdr_screenshots);
DUMP_READ_ONLY_FLAG(display_config_error_hal);
+ DUMP_READ_ONLY_FLAG(connected_display_hdr);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -243,6 +245,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(renderable_buffer_usage, "")
FLAG_MANAGER_READ_ONLY_FLAG(restore_blur_step, "debug.renderengine.restore_blur_step")
FLAG_MANAGER_READ_ONLY_FLAG(dont_skip_on_early_ro, "")
+FLAG_MANAGER_READ_ONLY_FLAG(no_vsyncs_on_screen_off, "debug.sf.no_vsyncs_on_screen_off")
FLAG_MANAGER_READ_ONLY_FLAG(protected_if_client, "")
FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_24q4, "");
FLAG_MANAGER_READ_ONLY_FLAG(vrr_bugfix_dropped_frame, "")
@@ -260,6 +263,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(force_compile_graphite_renderengine, "");
FLAG_MANAGER_READ_ONLY_FLAG(true_hdr_screenshots, "debug.sf.true_hdr_screenshots");
FLAG_MANAGER_READ_ONLY_FLAG(display_config_error_hal, "");
+FLAG_MANAGER_READ_ONLY_FLAG(connected_display_hdr, "");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index e4305d3..7716762 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -77,6 +77,7 @@
bool renderable_buffer_usage() const;
bool restore_blur_step() const;
bool dont_skip_on_early_ro() const;
+ bool no_vsyncs_on_screen_off() const;
bool protected_if_client() const;
bool idle_screen_refresh_rate_timeout() const;
bool graphite_renderengine() const;
@@ -94,6 +95,7 @@
bool trace_frame_rate_override() const;
bool true_hdr_screenshots() const;
bool display_config_error_hal() const;
+ bool connected_display_hdr() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 2cb3989..ce334e4 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -57,6 +57,14 @@
} # commit_not_composited
flag {
+ name: "connected_display_hdr"
+ namespace: "core_graphics"
+ description: "enable connected display hdr capability"
+ bug: "374182788"
+ is_fixed_read_only: true
+} # connected_display_hdr
+
+flag {
name: "correct_dpi_with_display_size"
namespace: "core_graphics"
description: "indicate whether missing or likely incorrect dpi should be corrected using the display size."
@@ -158,6 +166,14 @@
} # local_tonemap_screenshots
flag {
+ name: "no_vsyncs_on_screen_off"
+ namespace: "core_graphics"
+ description: "Stop vsync / Choreographer callbacks to apps when the screen is off"
+ bug: "331636736"
+ is_fixed_read_only: true
+} # no_vsyncs_on_screen_off
+
+flag {
name: "single_hop_screenshot"
namespace: "window_surfaces"
description: "Only access SF main thread once during a screenshot"
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 7398cbe..82500fe 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -30,6 +30,7 @@
MOCK_METHOD(sp<EventThreadConnection>, createEventConnection, (EventRegistrationFlags),
(const, override));
MOCK_METHOD(void, enableSyntheticVsync, (bool), (override));
+ MOCK_METHOD(void, omitVsyncDispatching, (bool), (override));
MOCK_METHOD(void, onHotplugReceived, (PhysicalDisplayId, bool), (override));
MOCK_METHOD(void, onHotplugConnectionError, (int32_t), (override));
MOCK_METHOD(void, onModeChanged, (const scheduler::FrameRateMode&), (override));