diff options
39 files changed, 519 insertions, 293 deletions
diff --git a/include/android/choreographer.h b/include/android/choreographer.h index 0389e573a2..6f579ca0af 100644 --- a/include/android/choreographer.h +++ b/include/android/choreographer.h @@ -209,13 +209,13 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineVsyncId( /** * The time in nanoseconds which the frame at given index is expected to be presented. */ -int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime( +int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos( const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33); /** * The time in nanoseconds which the frame at given index needs to be ready by. */ -int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline( +int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos( const AChoreographerFrameCallbackData* data, size_t index) __INTRODUCED_IN(33); __END_DECLS diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h index 509ee0e49b..4c83a14728 100644 --- a/include/android/multinetwork.h +++ b/include/android/multinetwork.h @@ -216,6 +216,61 @@ int android_res_nresult(int fd, */ void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29); +/* + * Set the socket tag and owning UID for traffic statistics on the specified + * socket. + * + * Subsequent calls always replace any existing parameters. The socket tag and + * uid (if set) are kept when the socket is sent to another process using binder + * IPCs or other mechanisms such as UNIX socket fd passing. Any app can accept + * blame for future traffic performed on a socket originally created by another + * app by calling this method with its own UID (or calling + * android_tag_socket(int sockfd, int tag)). However, only apps holding the + * android.Manifest.permission#UPDATE_DEVICE_STATS permission may assign blame + * to another UIDs. If unset (default) the socket tag is 0, and the uid is the + * socket creator's uid. + * + * Returns 0 on success, or a negative POSIX error code (see errno.h) on + * failure. + * + * Available since API level 33. + */ +int android_tag_socket_with_uid(int sockfd, int tag, uid_t uid) __INTRODUCED_IN(33); + +/* + * Set the socket tag for traffic statistics on the specified socket. + * + * This function tags the socket with the caller's UID (accepting blame for + * future traffic performed on this socket) even if the socket was originally + * opened by another UID or was previously tagged by another UID. Subsequent + * calls always replace any existing parameters. The socket tag is kept when the + * socket is sent to another process using binder IPCs or other mechanisms such + * as UNIX socket fd passing. + * + * Returns 0 on success, or a negative POSIX error code (see errno.h) on + * failure. + * + * Available since API level 33. + */ +int android_tag_socket(int sockfd, int tag) __INTRODUCED_IN(33); + +/* + * Untag a network socket. + * + * Future traffic on this socket will no longer be associated with any + * previously configured tag and uid. If the socket was created by another UID + * or was previously tagged by another UID, calling this function will clear the + * statistics parameters, and thus the UID blamed for traffic on the socket will + * be the UID that originally created the socket, even if the socket was + * subsequently tagged by a different UID. + * + * Returns 0 on success, or a negative POSIX error code (see errno.h) on + * failure. + * + * Available since API level 33. + */ +int android_untag_socket(int sockfd) __INTRODUCED_IN(33); + __END_DECLS #endif // ANDROID_MULTINETWORK_H diff --git a/include/android/sensor.h b/include/android/sensor.h index 9dc6983e50..45e8afc7de 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -256,6 +256,13 @@ enum { * The hinge angle sensor value is returned in degrees. */ ASENSOR_TYPE_HINGE_ANGLE = 36, + /** + * {@link ASENSOR_TYPE_HEAD_TRACKER} + * reporting-mode: continuous + * + * Measures the orientation and rotational velocity of a user's head. + */ + ASENSOR_TYPE_HEAD_TRACKER = 37, }; /** @@ -440,6 +447,38 @@ typedef struct AAdditionalInfoEvent { }; } AAdditionalInfoEvent; +typedef struct AHeadTrackerEvent { + /** + * The fields rx, ry, rz are an Euler vector (rotation vector, i.e. a vector + * whose direction indicates the axis of rotation and magnitude indicates + * the angle to rotate around that axis) representing the transform from + * the (arbitrary, possibly slowly drifting) reference frame to the + * head frame. Expressed in radians. Magnitude of the vector must be + * in the range [0, pi], while the value of individual axes are + * in the range [-pi, pi]. + */ + float rx; + float ry; + float rz; + + /** + * The fields vx, vy, vz are an Euler vector (rotation vector) representing + * the angular velocity of the head (relative to itself), in radians per + * second. The direction of this vector indicates the axis of rotation, and + * the magnitude indicates the rate of rotation. + */ + float vx; + float vy; + float vz; + + /** + * This value changes each time the reference frame is suddenly and + * significantly changed, for example if an orientation filter algorithm + * used for determining the orientation has had its state reset. + */ + int32_t discontinuity_count; +} AHeadTrackerEvent; + /** * Information that describes a sensor event, refer to * <a href="/reference/android/hardware/SensorEvent">SensorEvent</a> for additional @@ -476,6 +515,7 @@ typedef struct ASensorEvent { AHeartRateEvent heart_rate; ADynamicSensorEvent dynamic_sensor_meta; AAdditionalInfoEvent additional_info; + AHeadTrackerEvent head_tracker; }; union { uint64_t data[8]; diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp index 9abe4b50bc..269b0861e1 100644 --- a/libs/binder/ProcessState.cpp +++ b/libs/binder/ProcessState.cpp @@ -320,11 +320,6 @@ sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) // // Note that this is not race-free if the context manager // dies while this code runs. - // - // TODO: add a driver API to wait for context manager, or - // stop special casing handle 0 for context manager and add - // a driver API to get a handle to the context manager with - // proper reference counting. IPCThreadState* ipc = IPCThreadState::self(); diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h index c903998021..2c471c6e8f 100644 --- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h +++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h @@ -163,6 +163,15 @@ class ScopedAResource { const T get() const { return mT; } /** + * Release the underlying resource. + */ + [[nodiscard]] T release() { + T a = mT; + mT = DEFAULT; + return a; + } + + /** * This allows the value in this class to be set from beneath it. If you call this method and * then change the value of T*, you must take ownership of the value you are replacing and add * ownership to the object that is put in here. diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp index 58fa13afe5..357b454f7f 100644 --- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp +++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp @@ -752,6 +752,29 @@ TEST(NdkBinder, GetClassInterfaceDescriptor) { ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass)); } +static void addOne(int* to) { + if (!to) return; + ++(*to); +} +struct FakeResource : public ndk::impl::ScopedAResource<int*, addOne, nullptr> { + explicit FakeResource(int* a) : ScopedAResource(a) {} +}; + +TEST(NdkBinder_ScopedAResource, GetDelete) { + int deleteCount = 0; + { FakeResource resource(&deleteCount); } + EXPECT_EQ(deleteCount, 1); +} + +TEST(NdkBinder_ScopedAResource, Release) { + int deleteCount = 0; + { + FakeResource resource(&deleteCount); + (void)resource.release(); + } + EXPECT_EQ(deleteCount, 0); +} + int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs index 91047bea48..47dcdc2bc3 100644 --- a/libs/binder/rust/binder_tokio/lib.rs +++ b/libs/binder/rust/binder_tokio/lib.rs @@ -29,7 +29,7 @@ //! [`Tokio`]: crate::Tokio use binder::public_api::{BinderAsyncPool, BoxFuture, Strong}; -use binder::{FromIBinder, StatusCode}; +use binder::{FromIBinder, StatusCode, BinderAsyncRuntime}; use std::future::Future; /// Retrieve an existing service for a particular interface, sleeping for a few @@ -120,3 +120,24 @@ impl BinderAsyncPool for Tokio { } } } + +/// Wrapper around Tokio runtime types for providing a runtime to a binder server. +pub struct TokioRuntime<R>(pub R); + +impl BinderAsyncRuntime for TokioRuntime<tokio::runtime::Runtime> { + fn block_on<F: Future>(&self, future: F) -> F::Output { + self.0.block_on(future) + } +} + +impl BinderAsyncRuntime for TokioRuntime<std::sync::Arc<tokio::runtime::Runtime>> { + fn block_on<F: Future>(&self, future: F) -> F::Output { + self.0.block_on(future) + } +} + +impl BinderAsyncRuntime for TokioRuntime<tokio::runtime::Handle> { + fn block_on<F: Future>(&self, future: F) -> F::Output { + self.0.block_on(future) + } +} diff --git a/libs/binder/rust/src/binder_async.rs b/libs/binder/rust/src/binder_async.rs index 214c0b5f26..579f9f90b8 100644 --- a/libs/binder/rust/src/binder_async.rs +++ b/libs/binder/rust/src/binder_async.rs @@ -53,3 +53,9 @@ pub trait BinderAsyncPool { B: Send + 'a, E: From<crate::StatusCode>; } + +/// A runtime for executing an async binder server. +pub trait BinderAsyncRuntime { + /// Block on the provided future, running it to completion and returning its output. + fn block_on<F: Future>(&self, future: F) -> F::Output; +} diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 7c04a7207b..20d90f7b3c 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -112,7 +112,7 @@ pub use crate::binder::{ Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION, }; -pub use crate::binder_async::{BoxFuture, BinderAsyncPool}; +pub use crate::binder_async::{BoxFuture, BinderAsyncPool, BinderAsyncRuntime}; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::{add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service, Binder}; pub use parcel::{BorrowedParcel, Parcel}; diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index ca68b99e35..c2639e7c67 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -1517,10 +1517,11 @@ TEST(BinderRpc, Java) { auto keepAlive = sp<BBinder>::make(); auto setRpcClientDebugStatus = binder->setRpcClientDebug(std::move(socket), keepAlive); - if (!android::base::GetBoolProperty("ro.debuggable", false)) { + if (!android::base::GetBoolProperty("ro.debuggable", false) || + android::base::GetProperty("ro.build.type", "") == "user") { ASSERT_EQ(INVALID_OPERATION, setRpcClientDebugStatus) - << "setRpcClientDebug should return INVALID_OPERATION on non-debuggable builds, " - "but get " + << "setRpcClientDebug should return INVALID_OPERATION on non-debuggable or user " + "builds, but get " << statusToString(setRpcClientDebugStatus); GTEST_SKIP(); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index acd9ac5a93..27d86bb4e2 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -153,7 +153,8 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeBool, isTrustedOverlay); SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dropInputMode)); - SAFE_PARCEL(bufferData.write, output); + SAFE_PARCEL(output.writeNullableParcelable, + bufferData ? std::make_optional<BufferData>(*bufferData) : std::nullopt); return NO_ERROR; } @@ -263,7 +264,9 @@ status_t layer_state_t::read(const Parcel& input) uint32_t mode; SAFE_PARCEL(input.readUint32, &mode); dropInputMode = static_cast<gui::DropInputMode>(mode); - SAFE_PARCEL(bufferData.read, input); + std::optional<BufferData> tmpBufferData; + SAFE_PARCEL(input.readParcelable, &tmpBufferData); + bufferData = tmpBufferData ? std::make_shared<BufferData>(*tmpBufferData) : nullptr; return NO_ERROR; } @@ -518,7 +521,7 @@ bool layer_state_t::hasBufferChanges() const { } bool layer_state_t::hasValidBuffer() const { - return bufferData.buffer || bufferData.cachedBuffer.isValid(); + return bufferData && (bufferData->buffer || bufferData->cachedBuffer.isValid()); } status_t layer_state_t::matrix22_t::write(Parcel& output) const { @@ -681,64 +684,64 @@ ReleaseCallbackId BufferData::generateReleaseCallbackId() const { return {buffer->getId(), frameNumber}; } -status_t BufferData::write(Parcel& output) const { - SAFE_PARCEL(output.writeInt32, flags.get()); +status_t BufferData::writeToParcel(Parcel* output) const { + SAFE_PARCEL(output->writeInt32, flags.get()); if (buffer) { - SAFE_PARCEL(output.writeBool, true); - SAFE_PARCEL(output.write, *buffer); + SAFE_PARCEL(output->writeBool, true); + SAFE_PARCEL(output->write, *buffer); } else { - SAFE_PARCEL(output.writeBool, false); + SAFE_PARCEL(output->writeBool, false); } if (acquireFence) { - SAFE_PARCEL(output.writeBool, true); - SAFE_PARCEL(output.write, *acquireFence); + SAFE_PARCEL(output->writeBool, true); + SAFE_PARCEL(output->write, *acquireFence); } else { - SAFE_PARCEL(output.writeBool, false); + SAFE_PARCEL(output->writeBool, false); } - SAFE_PARCEL(output.writeUint64, frameNumber); - SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener)); - SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint); + SAFE_PARCEL(output->writeUint64, frameNumber); + SAFE_PARCEL(output->writeStrongBinder, IInterface::asBinder(releaseBufferListener)); + SAFE_PARCEL(output->writeStrongBinder, releaseBufferEndpoint); - SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote()); - SAFE_PARCEL(output.writeUint64, cachedBuffer.id); + SAFE_PARCEL(output->writeStrongBinder, cachedBuffer.token.promote()); + SAFE_PARCEL(output->writeUint64, cachedBuffer.id); return NO_ERROR; } -status_t BufferData::read(const Parcel& input) { +status_t BufferData::readFromParcel(const Parcel* input) { int32_t tmpInt32; - SAFE_PARCEL(input.readInt32, &tmpInt32); + SAFE_PARCEL(input->readInt32, &tmpInt32); flags = Flags<BufferDataChange>(tmpInt32); bool tmpBool = false; - SAFE_PARCEL(input.readBool, &tmpBool); + SAFE_PARCEL(input->readBool, &tmpBool); if (tmpBool) { buffer = new GraphicBuffer(); - SAFE_PARCEL(input.read, *buffer); + SAFE_PARCEL(input->read, *buffer); } - SAFE_PARCEL(input.readBool, &tmpBool); + SAFE_PARCEL(input->readBool, &tmpBool); if (tmpBool) { acquireFence = new Fence(); - SAFE_PARCEL(input.read, *acquireFence); + SAFE_PARCEL(input->read, *acquireFence); } - SAFE_PARCEL(input.readUint64, &frameNumber); + SAFE_PARCEL(input->readUint64, &frameNumber); sp<IBinder> tmpBinder = nullptr; - SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); + SAFE_PARCEL(input->readNullableStrongBinder, &tmpBinder); if (tmpBinder) { releaseBufferListener = checked_interface_cast<ITransactionCompletedListener>(tmpBinder); } - SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint); + SAFE_PARCEL(input->readNullableStrongBinder, &releaseBufferEndpoint); tmpBinder = nullptr; - SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); + SAFE_PARCEL(input->readNullableStrongBinder, &tmpBinder); cachedBuffer.token = tmpBinder; - SAFE_PARCEL(input.readUint64, &cachedBuffer.id); + SAFE_PARCEL(input->readUint64, &cachedBuffer.id); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6dbdcd0c0d..b4f6cd513c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -728,18 +728,18 @@ void SurfaceComposerClient::Transaction::releaseBufferIfOverwriting(const layer_ return; } - auto listener = state.bufferData.releaseBufferListener; + auto listener = state.bufferData->releaseBufferListener; sp<Fence> fence = - state.bufferData.acquireFence ? state.bufferData.acquireFence : Fence::NO_FENCE; - if (state.bufferData.releaseBufferEndpoint == + state.bufferData->acquireFence ? state.bufferData->acquireFence : Fence::NO_FENCE; + if (state.bufferData->releaseBufferEndpoint == IInterface::asBinder(TransactionCompletedListener::getIInstance())) { // if the callback is in process, run on a different thread to avoid any lock contigency // issues in the client. SurfaceComposerClient::getDefault() ->mReleaseCallbackThread - .addReleaseCallback(state.bufferData.generateReleaseCallbackId(), fence); + .addReleaseCallback(state.bufferData->generateReleaseCallbackId(), fence); } else { - listener->onReleaseBuffer(state.bufferData.generateReleaseCallbackId(), fence, UINT_MAX); + listener->onReleaseBuffer(state.bufferData->generateReleaseCallbackId(), fence, UINT_MAX); } } @@ -839,7 +839,8 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { layer_state_t* s = &(mComposerStates[handle].state); if (!(s->what & layer_state_t::eBufferChanged)) { continue; - } else if (s->bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged)) { + } else if (s->bufferData && + s->bufferData->flags.test(BufferData::BufferDataChange::cachedBufferChanged)) { // If eBufferChanged and eCachedBufferChanged are both trued then that means // we already cached the buffer in a previous call to cacheBuffers, perhaps // from writeToParcel on a Transaction that was merged in to this one. @@ -848,22 +849,22 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste // time trying to cache them. - if (!s->bufferData.buffer) { + if (!s->bufferData || !s->bufferData->buffer) { continue; } uint64_t cacheId = 0; - status_t ret = BufferCache::getInstance().getCacheId(s->bufferData.buffer, &cacheId); + status_t ret = BufferCache::getInstance().getCacheId(s->bufferData->buffer, &cacheId); if (ret == NO_ERROR) { // Cache-hit. Strip the buffer and send only the id. - s->bufferData.buffer = nullptr; + s->bufferData->buffer = nullptr; } else { // Cache-miss. Include the buffer and send the new cacheId. - cacheId = BufferCache::getInstance().cache(s->bufferData.buffer); + cacheId = BufferCache::getInstance().cache(s->bufferData->buffer); } - s->bufferData.flags |= BufferData::BufferDataChange::cachedBufferChanged; - s->bufferData.cachedBuffer.token = BufferCache::getInstance().getToken(); - s->bufferData.cachedBuffer.id = cacheId; + s->bufferData->flags |= BufferData::BufferDataChange::cachedBufferChanged; + s->bufferData->cachedBuffer.token = BufferCache::getInstance().getToken(); + s->bufferData->cachedBuffer.id = cacheId; // If we have more buffers than the size of the cache, we should stop caching so we don't // evict other buffers in this transaction @@ -1322,23 +1323,22 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp<Surfac return *this; } -std::optional<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer( +std::shared_ptr<BufferData> SurfaceComposerClient::Transaction::getAndClearBuffer( const sp<SurfaceControl>& sc) { layer_state_t* s = getLayerState(sc); if (!s) { - return std::nullopt; + return nullptr; } if (!(s->what & layer_state_t::eBufferChanged)) { - return std::nullopt; + return nullptr; } - BufferData bufferData = s->bufferData; + std::shared_ptr<BufferData> bufferData = std::move(s->bufferData); TransactionCompletedListener::getInstance()->removeReleaseBufferCallback( - bufferData.generateReleaseCallbackId()); - BufferData emptyBufferData; + bufferData->generateReleaseCallbackId()); s->what &= ~layer_state_t::eBufferChanged; - s->bufferData = emptyBufferData; + s->bufferData = nullptr; mContainsBuffer = false; return bufferData; @@ -1356,24 +1356,24 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe releaseBufferIfOverwriting(*s); - BufferData bufferData; - bufferData.buffer = buffer; + std::shared_ptr<BufferData> bufferData = std::make_shared<BufferData>(); + bufferData->buffer = buffer; if (frameNumber) { - bufferData.frameNumber = *frameNumber; - bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + bufferData->frameNumber = *frameNumber; + bufferData->flags |= BufferData::BufferDataChange::frameNumberChanged; } if (fence) { - bufferData.acquireFence = *fence; - bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData->acquireFence = *fence; + bufferData->flags |= BufferData::BufferDataChange::fenceChanged; } - bufferData.releaseBufferEndpoint = + bufferData->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance()); if (mIsAutoTimestamp) { mDesiredPresentTime = systemTime(); } - setReleaseBufferCallback(&bufferData, callback); + setReleaseBufferCallback(bufferData.get(), callback); s->what |= layer_state_t::eBufferChanged; - s->bufferData = bufferData; + s->bufferData = std::move(bufferData); registerSurfaceControlForCallback(sc); mContainsBuffer = true; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e48f52d13d..968ace93b9 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -58,7 +58,22 @@ struct client_cache_t { bool isValid() const { return token != nullptr; } }; -struct BufferData { +class BufferData : public Parcelable { +public: + virtual ~BufferData() = default; + virtual bool hasBuffer() const { return buffer != nullptr; } + virtual bool hasSameBuffer(const BufferData& other) const { + return buffer == other.buffer && frameNumber == other.frameNumber; + } + virtual uint32_t getWidth() const { return buffer->getWidth(); } + virtual uint32_t getHeight() const { return buffer->getHeight(); } + Rect getBounds() const { + return {0, 0, static_cast<int32_t>(getWidth()), static_cast<int32_t>(getHeight())}; + } + virtual uint64_t getId() const { return buffer->getId(); } + virtual PixelFormat getPixelFormat() const { return buffer->getPixelFormat(); } + virtual uint64_t getUsage() const { return buffer->getUsage(); } + enum class BufferDataChange : uint32_t { fenceChanged = 0x01, frameNumberChanged = 0x02, @@ -89,8 +104,9 @@ struct BufferData { // Generates the release callback id based on the buffer id and frame number. // This is used as an identifier when release callbacks are invoked. ReleaseCallbackId generateReleaseCallbackId() const; - status_t write(Parcel& output) const; - status_t read(const Parcel& input); + + status_t writeToParcel(Parcel* parcel) const override; + status_t readFromParcel(const Parcel* parcel) override; }; /* @@ -204,7 +220,7 @@ struct layer_state_t { uint32_t transform; bool transformToDisplayInverse; Rect crop; - BufferData bufferData; + std::shared_ptr<BufferData> bufferData = nullptr; ui::Dataspace dataspace; HdrMetadata hdrMetadata; Region surfaceDamageRegion; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4eef1118bd..c1923232df 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -510,7 +510,7 @@ public: const std::optional<sp<Fence>>& fence = std::nullopt, const std::optional<uint64_t>& frameNumber = std::nullopt, ReleaseBufferCallback callback = nullptr); - std::optional<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc); + std::shared_ptr<BufferData> getAndClearBuffer(const sp<SurfaceControl>& sc); Transaction& setDataspace(const sp<SurfaceControl>& sc, ui::Dataspace dataspace); Transaction& setHdrMetadata(const sp<SurfaceControl>& sc, const HdrMetadata& hdrMetadata); Transaction& setSurfaceDamageRegion(const sp<SurfaceControl>& sc, diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index fc9680babb..84daea09f0 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -556,13 +556,13 @@ int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId( const AChoreographerFrameCallbackData* data, size_t index) { return AChoreographerFrameCallbackData_getFrameTimelineVsyncId(data, index); } -int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime( +int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos( const AChoreographerFrameCallbackData* data, size_t index) { - return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime(data, index); + return AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos(data, index); } -int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline( +int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos( const AChoreographerFrameCallbackData* data, size_t index) { - return AChoreographerFrameCallbackData_getFrameTimelineDeadline(data, index); + return AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos(data, index); } int64_t AChoreographer_getFrameInterval(const AChoreographer* choreographer) { @@ -653,7 +653,7 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineVsyncId( LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds"); return frameCallbackData->frameTimelines[index].id; } -int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime( +int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos( const AChoreographerFrameCallbackData* data, size_t index) { const ChoreographerFrameCallbackDataImpl* frameCallbackData = AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); @@ -662,7 +662,7 @@ int64_t AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime( LOG_ALWAYS_FATAL_IF(index >= frameCallbackData->frameTimelines.size(), "Index out of bounds"); return frameCallbackData->frameTimelines[index].expectedPresentTime; } -int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadline( +int64_t AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos( const AChoreographerFrameCallbackData* data, size_t index) { const ChoreographerFrameCallbackDataImpl* frameCallbackData = AChoreographerFrameCallbackData_to_ChoreographerFrameCallbackDataImpl(data); diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h index 4aa7e69097..0a1fcbeb94 100644 --- a/libs/nativedisplay/include-private/private/android/choreographer.h +++ b/libs/nativedisplay/include-private/private/android/choreographer.h @@ -67,9 +67,9 @@ size_t AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex( const AChoreographerFrameCallbackData* data); int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId( const AChoreographerFrameCallbackData* data, size_t index); -int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime( +int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos( const AChoreographerFrameCallbackData* data, size_t index); -int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline( +int64_t AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos( const AChoreographerFrameCallbackData* data, size_t index); } // namespace android diff --git a/libs/nativedisplay/libnativedisplay.map.txt b/libs/nativedisplay/libnativedisplay.map.txt index 4dbfde83cd..b1b6498fe9 100644 --- a/libs/nativedisplay/libnativedisplay.map.txt +++ b/libs/nativedisplay/libnativedisplay.map.txt @@ -12,8 +12,8 @@ LIBNATIVEDISPLAY { AChoreographerFrameCallbackData_getFrameTimelinesLength; # apex # introduced=33 AChoreographerFrameCallbackData_getPreferredFrameTimelineIndex; # apex # introduced=33 AChoreographerFrameCallbackData_getFrameTimelineVsyncId; # apex # introduced=33 - AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTime; # apex # introduced=33 - AChoreographerFrameCallbackData_getFrameTimelineDeadline; # apex # introduced=33 + AChoreographerFrameCallbackData_getFrameTimelineExpectedPresentTimeNanos; # apex # introduced=33 + AChoreographerFrameCallbackData_getFrameTimelineDeadlineNanos; # apex # introduced=33 AChoreographer_create; # apex # introduced=30 AChoreographer_destroy; # apex # introduced=30 AChoreographer_getFd; # apex # introduced=30 @@ -40,8 +40,8 @@ LIBNATIVEDISPLAY_PLATFORM { android::AChoreographerFrameCallbackData_routeGetFrameTimelinesLength*; android::AChoreographerFrameCallbackData_routeGetPreferredFrameTimelineIndex*; android::AChoreographerFrameCallbackData_routeGetFrameTimelineVsyncId*; - android::AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTime*; - android::AChoreographerFrameCallbackData_routeGetFrameTimelineDeadline*; + android::AChoreographerFrameCallbackData_routeGetFrameTimelineExpectedPresentTimeNanos*; + android::AChoreographerFrameCallbackData_routeGetFrameTimelineDeadlineNanos*; android::AChoreographer_signalRefreshRateCallbacks*; android::AChoreographer_getFrameInterval*; android::ADisplay_acquirePhysicalDisplays*; diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp index 0a49008584..e1560c0740 100644 --- a/libs/sensor/Sensor.cpp +++ b/libs/sensor/Sensor.cpp @@ -276,6 +276,10 @@ Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersi mStringType = SENSOR_STRING_TYPE_HINGE_ANGLE; mFlags |= SENSOR_FLAG_ON_CHANGE_MODE; break; + case SENSOR_TYPE_HEAD_TRACKER: + mStringType = SENSOR_STRING_TYPE_HEAD_TRACKER; + mFlags |= SENSOR_FLAG_CONTINUOUS_MODE; + break; default: // Only pipe the stringType, requiredPermission and flags for custom sensors. if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) { diff --git a/services/gpuservice/OWNERS b/services/gpuservice/OWNERS index ac300d009e..0ff65bf4ae 100644 --- a/services/gpuservice/OWNERS +++ b/services/gpuservice/OWNERS @@ -1,2 +1,6 @@ chrisforbes@google.com lpy@google.com +alecmouri@google.com +lfy@google.com +paulthomson@google.com +pbaiget@google.com diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp index fdd56b364d..baa01c9ce3 100644 --- a/services/sensorservice/SensorServiceUtils.cpp +++ b/services/sensorservice/SensorServiceUtils.cpp @@ -58,6 +58,9 @@ size_t eventSizeBySensorType(int type) { case SENSOR_TYPE_HINGE_ANGLE: return 1; + case SENSOR_TYPE_HEAD_TRACKER: + return 7; + default: return 3; } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 71d563130e..a94952f415 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -714,20 +714,19 @@ RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId 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(); + [this] { + std::scoped_lock lock(mIdleTimerCallbacksMutex); + if (const auto callbacks = getIdleTimerCallbacks()) { + callbacks->onReset(); + } }, - [getCallback] { - if (const auto callback = getCallback()) callback->onExpired(); + [this] { + std::scoped_lock lock(mIdleTimerCallbacksMutex); + if (const auto callbacks = getIdleTimerCallbacks()) { + callbacks->onExpired(); + } }); } } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 4bbdab6bbe..fc45d2b909 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -348,16 +348,24 @@ public: bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; } - void setIdleTimerCallbacks(std::function<void()> platformTimerReset, - std::function<void()> platformTimerExpired, - std::function<void()> kernelTimerReset, - std::function<void()> kernelTimerExpired) { + struct IdleTimerCallbacks { + struct Callbacks { + std::function<void()> onReset; + std::function<void()> onExpired; + }; + + Callbacks platform; + Callbacks kernel; + }; + + void setIdleTimerCallbacks(IdleTimerCallbacks callbacks) EXCLUDES(mIdleTimerCallbacksMutex) { std::scoped_lock lock(mIdleTimerCallbacksMutex); - mIdleTimerCallbacks.emplace(); - mIdleTimerCallbacks->platform.onReset = std::move(platformTimerReset); - mIdleTimerCallbacks->platform.onExpired = std::move(platformTimerExpired); - mIdleTimerCallbacks->kernel.onReset = std::move(kernelTimerReset); - mIdleTimerCallbacks->kernel.onExpired = std::move(kernelTimerExpired); + mIdleTimerCallbacks = std::move(callbacks); + } + + void clearIdleTimerCallbacks() EXCLUDES(mIdleTimerCallbacksMutex) { + std::scoped_lock lock(mIdleTimerCallbacksMutex); + mIdleTimerCallbacks.reset(); } void startIdleTimer() { @@ -380,7 +388,7 @@ public: return; } mIdleTimer->reset(); - }; + } void dump(std::string& result) const EXCLUDES(mLock); @@ -448,6 +456,13 @@ private: void initializeIdleTimer(); + std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const + REQUIRES(mIdleTimerCallbacksMutex) { + if (!mIdleTimerCallbacks) return {}; + return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel + : mIdleTimerCallbacks->platform; + } + // The list of refresh rates, indexed by display modes ID. This may change after this // object is initialized. AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); @@ -492,21 +507,11 @@ private: 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; - }; - + // Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed. std::mutex mIdleTimerCallbacksMutex; std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex); + // Used to detect (lack of) frame activity. + std::optional<scheduler::OneShotTimer> mIdleTimer; }; } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index cbe4552b0b..4173088d99 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -62,6 +62,15 @@ namespace android::scheduler { Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features) : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {} +Scheduler::~Scheduler() { + // Stop timers and wait for their threads to exit. + mDisplayPowerTimer.reset(); + mTouchTimer.reset(); + + // Stop idle timer and clear callbacks, as the RefreshRateConfigs may outlive the Scheduler. + setRefreshRateConfigs(nullptr); +} + void Scheduler::startTimers() { using namespace sysprop; using namespace std::string_literals; @@ -84,11 +93,32 @@ void Scheduler::startTimers() { } } -Scheduler::~Scheduler() { - // Ensure the OneShotTimer threads are joined before we start destroying state. - mDisplayPowerTimer.reset(); - mTouchTimer.reset(); - mRefreshRateConfigs.reset(); +void Scheduler::setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> configs) { + { + // The current RefreshRateConfigs instance may outlive this call, so unbind its idle timer. + std::scoped_lock lock(mRefreshRateConfigsLock); + if (mRefreshRateConfigs) { + mRefreshRateConfigs->stopIdleTimer(); + mRefreshRateConfigs->clearIdleTimerCallbacks(); + } + } + { + // Clear state that depends on the current instance. + std::scoped_lock lock(mPolicyLock); + mPolicy = {}; + } + + std::scoped_lock lock(mRefreshRateConfigsLock); + mRefreshRateConfigs = std::move(configs); + if (!mRefreshRateConfigs) return; + + mRefreshRateConfigs->setIdleTimerCallbacks( + {.platform = {.onReset = [this] { idleTimerCallback(TimerState::Reset); }, + .onExpired = [this] { idleTimerCallback(TimerState::Expired); }}, + .kernel = {.onReset = [this] { kernelIdleTimerCallback(TimerState::Reset); }, + .onExpired = [this] { kernelIdleTimerCallback(TimerState::Expired); }}}); + + mRefreshRateConfigs->startIdleTimer(); } void Scheduler::run() { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 818f1edb41..548c34b5d2 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -74,12 +74,16 @@ class Scheduler : impl::MessageQueue { public: Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags); - ~Scheduler(); + virtual ~Scheduler(); - void createVsyncSchedule(FeatureFlags); void startTimers(); + void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs>) + EXCLUDES(mRefreshRateConfigsLock); + void run(); + void createVsyncSchedule(FeatureFlags); + using Impl::initVsync; using Impl::setInjector; @@ -198,36 +202,6 @@ public: std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock); - void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> refreshRateConfigs) - EXCLUDES(mRefreshRateConfigsLock) { - // We need to stop the idle timer on the previous RefreshRateConfigs instance - // and cleanup the scheduler's state before we switch to the other RefreshRateConfigs. - { - std::scoped_lock lock(mRefreshRateConfigsLock); - if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer(); - } - { - std::scoped_lock lock(mPolicyLock); - mPolicy = {}; - } - { - 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); - }); - mRefreshRateConfigs->startIdleTimer(); - } - } - nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) { std::scoped_lock lock(mRefreshRateConfigsLock); return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e84016fc69..51cb409235 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -384,7 +384,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)), mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)), mPowerAdvisor(*this), - mWindowInfosListenerInvoker(new WindowInfosListenerInvoker(this)) { + mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) { ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str()); } @@ -1651,7 +1651,7 @@ status_t SurfaceFlinger::getCompositionPreference( status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle, const sp<IRegionSamplingListener>& listener) { - if (!listener || samplingArea == Rect::INVALID_RECT) { + if (!listener || samplingArea == Rect::INVALID_RECT || samplingArea.isEmpty()) { return BAD_VALUE; } @@ -3821,9 +3821,9 @@ bool SurfaceFlinger::checkTransactionCanLatchUnsignaled(const TransactionState& if (transaction.states.size() == 1) { const auto& state = transaction.states.begin()->state; if ((state.flags & ~layer_state_t::eBufferChanged) == 0 && - state.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged) && - state.bufferData.acquireFence && - state.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) { + state.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) && + state.bufferData->acquireFence && + state.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) { ATRACE_NAME("transactionCanLatchUnsignaled"); return true; } @@ -3888,10 +3888,10 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied( for (const ComposerState& state : states) { const layer_state_t& s = state.state; - const bool acquireFenceChanged = - s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged); - if (acquireFenceChanged && s.bufferData.acquireFence && !allowLatchUnsignaled && - s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) { + const bool acquireFenceChanged = s.bufferData && + s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged); + if (acquireFenceChanged && s.bufferData->acquireFence && !allowLatchUnsignaled && + s.bufferData->acquireFence->getStatus() == Fence::Status::Unsignaled) { ATRACE_NAME("fence unsignaled"); return false; } @@ -4522,7 +4522,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (what & layer_state_t::eBufferChanged && - layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, + layer->setBuffer(*s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, dequeueBufferTimestamp, frameTimelineInfo)) { flags |= eTraversalNeeded; } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp index 378deb061d..849de22a41 100644 --- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp +++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp @@ -132,14 +132,14 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer, } if (layer.what & layer_state_t::eBufferChanged) { proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data(); - if (layer.bufferData.buffer) { - bufferProto->set_buffer_id(layer.bufferData.buffer->getId()); - bufferProto->set_width(layer.bufferData.buffer->getWidth()); - bufferProto->set_height(layer.bufferData.buffer->getHeight()); + if (layer.bufferData->buffer) { + bufferProto->set_buffer_id(layer.bufferData->getId()); + bufferProto->set_width(layer.bufferData->getWidth()); + bufferProto->set_height(layer.bufferData->getHeight()); } - bufferProto->set_frame_number(layer.bufferData.frameNumber); - bufferProto->set_flags(layer.bufferData.flags.get()); - bufferProto->set_cached_buffer_id(layer.bufferData.cachedBuffer.id); + bufferProto->set_frame_number(layer.bufferData->frameNumber); + bufferProto->set_flags(layer.bufferData->flags.get()); + bufferProto->set_cached_buffer_id(layer.bufferData->cachedBuffer.id); } if (layer.what & layer_state_t::eSidebandStreamChanged) { proto.set_has_sideband_stream(layer.sidebandStream != nullptr); @@ -405,10 +405,13 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, LayerProtoHelper::readFromProto(proto.crop(), layer.crop); } if (proto.what() & layer_state_t::eBufferChanged) { + if (!layer.bufferData) { + layer.bufferData = std::make_shared<BufferData>(); + } const proto::LayerState_BufferData& bufferProto = proto.buffer_data(); - layer.bufferData.frameNumber = bufferProto.frame_number(); - layer.bufferData.flags = Flags<BufferData::BufferDataChange>(bufferProto.flags()); - layer.bufferData.cachedBuffer.id = bufferProto.cached_buffer_id(); + layer.bufferData->frameNumber = bufferProto.frame_number(); + layer.bufferData->flags = Flags<BufferData::BufferDataChange>(bufferProto.flags()); + layer.bufferData->cachedBuffer.id = bufferProto.cached_buffer_id(); } if (proto.what() & layer_state_t::eApiChanged) { diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index b93d127ab8..72434e943a 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -25,24 +25,21 @@ using gui::DisplayInfo; using gui::IWindowInfosListener; using gui::WindowInfo; -struct WindowInfosReportedListener : gui::BnWindowInfosReportedListener { - explicit WindowInfosReportedListener(std::function<void()> listenerCb) - : mListenerCb(listenerCb) {} +struct WindowInfosListenerInvoker::WindowInfosReportedListener + : gui::BnWindowInfosReportedListener { + explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {} binder::Status onWindowInfosReported() override { - if (mListenerCb != nullptr) { - mListenerCb(); - } + mInvoker.windowInfosReported(); return binder::Status::ok(); } - std::function<void()> mListenerCb; + WindowInfosListenerInvoker& mInvoker; }; -WindowInfosListenerInvoker::WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf) : mSf(sf) { - mWindowInfosReportedListener = - new WindowInfosReportedListener([&]() { windowInfosReported(); }); -} +WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger) + : mFlinger(flinger), + mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {} void WindowInfosListenerInvoker::addWindowInfosListener( const sp<IWindowInfosListener>& windowInfosListener) { @@ -91,8 +88,8 @@ void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo void WindowInfosListenerInvoker::windowInfosReported() { mCallbacksPending--; if (mCallbacksPending == 0) { - mSf->windowInfosReported(); + mFlinger.windowInfosReported(); } } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h index 4e08393940..2eabf481c8 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.h +++ b/services/surfaceflinger/WindowInfosListenerInvoker.h @@ -31,7 +31,8 @@ class SurfaceFlinger; class WindowInfosListenerInvoker : public IBinder::DeathRecipient { public: - WindowInfosListenerInvoker(const sp<SurfaceFlinger>& sf); + explicit WindowInfosListenerInvoker(SurfaceFlinger&); + void addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener); @@ -42,13 +43,15 @@ protected: void binderDied(const wp<IBinder>& who) override; private: + struct WindowInfosReportedListener; void windowInfosReported(); - const sp<SurfaceFlinger> mSf; + SurfaceFlinger& mFlinger; std::mutex mListenersMutex; std::unordered_map<wp<IBinder>, const sp<gui::IWindowInfosListener>, WpHash> mWindowInfosListeners GUARDED_BY(mListenersMutex); sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener; std::atomic<size_t> mCallbacksPending{0}; }; -} // namespace android
\ No newline at end of file + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 6c96d5ff03..dee2358ab7 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -143,11 +143,10 @@ public: .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); - constexpr scheduler::ISchedulerCallback* kCallback = nullptr; - constexpr bool kHasMultipleConfigs = true; mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), - std::move(eventThread), std::move(sfEventThread), kCallback, - kHasMultipleConfigs); + std::move(eventThread), std::move(sfEventThread), + TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp, + TestableSurfaceFlinger::kTwoDisplayModes); } void setupForceGeometryDirty() { diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp index 5a0033ea7e..40a9b1aad0 100644 --- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp @@ -44,8 +44,8 @@ public: mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED); mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this) - .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120}) - .setActiveMode(kDisplayModeId60) + .setDisplayModes({kDisplayMode60, kDisplayMode90, kDisplayMode120}, + kDisplayModeId60) .inject(); } diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index c318e28ffe..2425862383 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -77,7 +77,8 @@ void DisplayTransactionTest::injectMockScheduler() { mFlinger.setupScheduler(std::unique_ptr<scheduler::VsyncController>(mVsyncController), std::unique_ptr<scheduler::VSyncTracker>(mVSyncTracker), std::unique_ptr<EventThread>(mEventThread), - std::unique_ptr<EventThread>(mSFEventThread), &mSchedulerCallback); + std::unique_ptr<EventThread>(mSFEventThread), + TestableSurfaceFlinger::SchedulerCallbackImpl::kMock); } void DisplayTransactionTest::injectMockComposer(int virtualDisplayCount) { diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 69ac26e997..45eceff96d 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -48,7 +48,6 @@ #include "mock/DisplayHardware/MockPowerAdvisor.h" #include "mock/MockEventThread.h" #include "mock/MockNativeWindowSurface.h" -#include "mock/MockSchedulerCallback.h" #include "mock/MockSurfaceInterceptor.h" #include "mock/MockVsyncController.h" #include "mock/system/window/MockNativeWindow.h" @@ -121,7 +120,6 @@ public: mock::VsyncController* mVsyncController = new mock::VsyncController; mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker; - scheduler::mock::SchedulerCallback mSchedulerCallback; mock::EventThread* mEventThread = new mock::EventThread; mock::EventThread* mSFEventThread = new mock::EventThread; diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index fe5f9e0717..2b69f13126 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -164,8 +164,9 @@ void SetFrameRateTest::setupScheduler() { .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), - std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr, - /*hasMultipleModes*/ true); + std::move(eventThread), std::move(sfEventThread), + TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp, + TestableSurfaceFlinger::kTwoDisplayModes); } namespace { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp index 56a050648d..3205952f5a 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp @@ -42,13 +42,18 @@ public: mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED); - mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this) - .setSupportedModes({kDisplayMode60, kDisplayMode90, kDisplayMode120, - kDisplayMode90DifferentResolution}) - .setActiveMode(kDisplayModeId60) - .inject(); + { + DisplayModes modes = {kDisplayMode60, kDisplayMode90, kDisplayMode120, + kDisplayMode90DifferentResolution}; + const DisplayModeId activeModeId = kDisplayModeId60; + auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId); - setupScheduler(); + mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this) + .setDisplayModes(modes, activeModeId, std::move(configs)) + .inject(); + } + + setupScheduler(mDisplay->holdRefreshRateConfigs()); // isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy // will call setActiveConfig instead of setActiveConfigWithConstraints. @@ -57,7 +62,7 @@ public: } protected: - void setupScheduler(); + void setupScheduler(std::shared_ptr<scheduler::RefreshRateConfigs>); void testChangeRefreshRate(bool isDisplayActive, bool isRefreshRequired); sp<DisplayDevice> mDisplay; @@ -108,7 +113,8 @@ protected: .build(); }; -void DisplayModeSwitchingTest::setupScheduler() { +void DisplayModeSwitchingTest::setupScheduler( + std::shared_ptr<scheduler::RefreshRateConfigs> configs) { auto eventThread = std::make_unique<mock::EventThread>(); mAppEventThread = eventThread.get(); auto sfEventThread = std::make_unique<mock::EventThread>(); @@ -132,8 +138,9 @@ void DisplayModeSwitchingTest::setupScheduler() { Return(TestableSurfaceFlinger::FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), - std::move(eventThread), std::move(sfEventThread), /*callback*/ nullptr, - /*hasMultipleModes*/ true); + std::move(eventThread), std::move(sfEventThread), + TestableSurfaceFlinger::SchedulerCallbackImpl::kNoOp, + std::move(configs)); } TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRequired) { diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp index b57feffe83..7948e60e14 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp @@ -61,7 +61,7 @@ struct DozeNotSupportedVariant { struct EventThreadBaseSupportedVariant { static void setupVsyncAndEventThreadNoCallExpectations(DisplayTransactionTest* test) { // The callback should not be notified to toggle VSYNC. - EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(_)).Times(0); + EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(_)).Times(0); // The event thread should not be notified. EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(0); @@ -88,7 +88,7 @@ struct EventThreadNotSupportedVariant : public EventThreadBaseSupportedVariant { struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant { static void setupAcquireAndEnableVsyncCallExpectations(DisplayTransactionTest* test) { // The callback should be notified to enable VSYNC. - EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(true)).Times(1); + EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(true)).Times(1); // The event thread should be notified that the screen was acquired. EXPECT_CALL(*test->mEventThread, onScreenAcquired()).Times(1); @@ -96,7 +96,7 @@ struct EventThreadIsSupportedVariant : public EventThreadBaseSupportedVariant { static void setupReleaseAndDisableVsyncCallExpectations(DisplayTransactionTest* test) { // The callback should be notified to disable VSYNC. - EXPECT_CALL(test->mSchedulerCallback, setVsyncEnabled(false)).Times(1); + EXPECT_CALL(test->mFlinger.mockSchedulerCallback(), setVsyncEnabled(false)).Times(1); // The event thread should not be notified that the screen was released. EXPECT_CALL(*test->mEventThread, onScreenReleased()).Times(1); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 361d629f1e..d292e0879d 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -16,6 +16,9 @@ #pragma once +#include <algorithm> +#include <variant> + #include <compositionengine/Display.h> #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/OutputLayer.h> @@ -24,7 +27,6 @@ #include <compositionengine/impl/OutputLayerCompositionState.h> #include <compositionengine/mock/DisplaySurface.h> #include <gui/ScreenCaptureResults.h> -#include <algorithm> #include "BufferQueueLayer.h" #include "BufferStateLayer.h" @@ -45,6 +47,7 @@ #include "mock/DisplayHardware/MockComposer.h" #include "mock/MockFrameTimeline.h" #include "mock/MockFrameTracer.h" +#include "mock/MockSchedulerCallback.h" namespace android { @@ -170,7 +173,7 @@ public: } // namespace surfaceflinger::test -class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback { +class TestableSurfaceFlinger { public: using HotplugEvent = SurfaceFlinger::HotplugEvent; @@ -193,42 +196,64 @@ public: mFlinger->mCompositionEngine->setTimeStats(timeStats); } - // The ISchedulerCallback argument can be nullptr for a no-op implementation. + enum class SchedulerCallbackImpl { kNoOp, kMock }; + + static constexpr struct OneDisplayMode { + } kOneDisplayMode; + + static constexpr struct TwoDisplayModes { + } kTwoDisplayModes; + + using RefreshRateConfigsPtr = std::shared_ptr<scheduler::RefreshRateConfigs>; + + using DisplayModesVariant = + std::variant<OneDisplayMode, TwoDisplayModes, RefreshRateConfigsPtr>; + void setupScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController, std::unique_ptr<scheduler::VSyncTracker> vsyncTracker, std::unique_ptr<EventThread> appEventThread, std::unique_ptr<EventThread> sfEventThread, - scheduler::ISchedulerCallback* callback = nullptr, - bool hasMultipleModes = false) { - DisplayModes modes{DisplayMode::Builder(0) - .setId(DisplayModeId(0)) - .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) - .setVsyncPeriod(16'666'667) - .setGroup(0) - .build()}; - - if (hasMultipleModes) { - modes.emplace_back(DisplayMode::Builder(1) - .setId(DisplayModeId(1)) - .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) - .setVsyncPeriod(11'111'111) - .setGroup(0) - .build()); + SchedulerCallbackImpl callbackImpl = SchedulerCallbackImpl::kNoOp, + DisplayModesVariant modesVariant = kOneDisplayMode) { + RefreshRateConfigsPtr configs; + if (std::holds_alternative<RefreshRateConfigsPtr>(modesVariant)) { + configs = std::move(std::get<RefreshRateConfigsPtr>(modesVariant)); + } else { + DisplayModes modes = {DisplayMode::Builder(0) + .setId(DisplayModeId(0)) + .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) + .setVsyncPeriod(16'666'667) + .setGroup(0) + .build()}; + + if (std::holds_alternative<TwoDisplayModes>(modesVariant)) { + modes.emplace_back(DisplayMode::Builder(1) + .setId(DisplayModeId(1)) + .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) + .setVsyncPeriod(11'111'111) + .setGroup(0) + .build()); + } + + configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, DisplayModeId(0)); } - const auto currMode = DisplayModeId(0); - mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode); - const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps(); + const auto currFps = configs->getCurrentRefreshRate().getFps(); mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps); mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make( mFlinger->mVsyncConfiguration->getCurrentConfigs()); mFlinger->mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps, - /*powerMode=*/hal::PowerMode::OFF); + hal::PowerMode::OFF); + + using Callback = scheduler::ISchedulerCallback; + Callback& callback = callbackImpl == SchedulerCallbackImpl::kNoOp + ? static_cast<Callback&>(mNoOpSchedulerCallback) + : static_cast<Callback&>(mSchedulerCallback); mScheduler = new scheduler::TestableScheduler(std::move(vsyncController), - std::move(vsyncTracker), mRefreshRateConfigs, - *(callback ?: this)); + std::move(vsyncTracker), std::move(configs), + callback); mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); @@ -237,7 +262,8 @@ public: void resetScheduler(scheduler::Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } - scheduler::TestableScheduler& mutableScheduler() const { return *mScheduler; } + scheduler::TestableScheduler& mutableScheduler() { return *mScheduler; } + scheduler::mock::SchedulerCallback& mockSchedulerCallback() { return mSchedulerCallback; } using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { @@ -662,23 +688,6 @@ public: mHwcDisplayId(hwcDisplayId) { mCreationArgs.connectionType = connectionType; mCreationArgs.isPrimary = isPrimary; - - mCreationArgs.activeModeId = DisplayModeId(0); - DisplayModePtr activeMode = - DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG) - .setId(mCreationArgs.activeModeId) - .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) - .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH) - .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT) - .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD) - .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI) - .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI) - .setGroup(0) - .build(); - - DisplayModes modes{activeMode}; - mCreationArgs.supportedModes = modes; - mCreationArgs.refreshRateConfigs = flinger.mRefreshRateConfigs; } sp<IBinder> token() const { return mDisplayToken; } @@ -701,13 +710,16 @@ public: auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; } - auto& setActiveMode(DisplayModeId mode) { - mCreationArgs.activeModeId = mode; - return *this; - } - - auto& setSupportedModes(DisplayModes mode) { - mCreationArgs.supportedModes = mode; + // If `configs` is nullptr, the injector creates RefreshRateConfigs from the `modes`. + // Otherwise, it uses `configs`, which the caller must create using the same `modes`. + // + // TODO(b/182939859): Once `modes` can be retrieved from RefreshRateConfigs, remove + // the `configs` parameter in favor of an alternative setRefreshRateConfigs API. + auto& setDisplayModes(DisplayModes modes, DisplayModeId activeModeId, + std::shared_ptr<scheduler::RefreshRateConfigs> configs = nullptr) { + mCreationArgs.supportedModes = std::move(modes); + mCreationArgs.activeModeId = activeModeId; + mCreationArgs.refreshRateConfigs = std::move(configs); return *this; } @@ -749,39 +761,58 @@ public: } sp<DisplayDevice> inject() NO_THREAD_SAFETY_ANALYSIS { - const auto displayId = mCreationArgs.compositionDisplay->getDisplayId(); + auto& modes = mCreationArgs.supportedModes; + auto& activeModeId = mCreationArgs.activeModeId; + + if (!mCreationArgs.refreshRateConfigs) { + if (modes.empty()) { + activeModeId = DisplayModeId(0); + modes.emplace_back( + DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG) + .setId(activeModeId) + .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) + .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH) + .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT) + .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD) + .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI) + .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI) + .setGroup(0) + .build()); + } + + mCreationArgs.refreshRateConfigs = + std::make_shared<scheduler::RefreshRateConfigs>(modes, activeModeId); + } DisplayDeviceState state; if (const auto type = mCreationArgs.connectionType) { + const auto displayId = mCreationArgs.compositionDisplay->getDisplayId(); LOG_ALWAYS_FATAL_IF(!displayId); const auto physicalId = PhysicalDisplayId::tryCast(*displayId); LOG_ALWAYS_FATAL_IF(!physicalId); LOG_ALWAYS_FATAL_IF(!mHwcDisplayId); - const DisplayModePtr activeModePtr = - *std::find_if(mCreationArgs.supportedModes.begin(), - mCreationArgs.supportedModes.end(), [&](DisplayModePtr mode) { - return mode->getId() == mCreationArgs.activeModeId; - }); + const auto it = std::find_if(modes.begin(), modes.end(), + [&activeModeId](const DisplayModePtr& mode) { + return mode->getId() == activeModeId; + }); + LOG_ALWAYS_FATAL_IF(it == modes.end()); + state.physical = {.id = *physicalId, .type = *type, .hwcDisplayId = *mHwcDisplayId, .deviceProductInfo = {}, - .supportedModes = mCreationArgs.supportedModes, - .activeMode = activeModePtr}; + .supportedModes = modes, + .activeMode = *it}; } state.isSecure = mCreationArgs.isSecure; - mCreationArgs.refreshRateConfigs = - std::make_shared<scheduler::RefreshRateConfigs>(mCreationArgs.supportedModes, - mCreationArgs.activeModeId); - - sp<DisplayDevice> device = new DisplayDevice(mCreationArgs); - if (!device->isVirtual()) { - device->setActiveMode(mCreationArgs.activeModeId); + sp<DisplayDevice> display = sp<DisplayDevice>::make(mCreationArgs); + if (!display->isVirtual()) { + display->setActiveMode(activeModeId); } - mFlinger.mutableDisplays().emplace(mDisplayToken, device); + mFlinger.mutableDisplays().emplace(mDisplayToken, display); mFlinger.mutableCurrentState().displays.add(mDisplayToken, state); mFlinger.mutableDrawingState().displays.add(mDisplayToken, state); @@ -789,7 +820,7 @@ public: mFlinger.mutablePhysicalDisplayTokens()[physical->id] = mDisplayToken; } - return device; + return display; } private: @@ -800,16 +831,12 @@ public: }; private: - void scheduleComposite(FrameHint) override {} - void setVsyncEnabled(bool) override {} - void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {} - void kernelTimerChanged(bool) override {} - void triggerOnFrameRateOverridesChanged() {} - surfaceflinger::test::Factory mFactory; sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization); + + scheduler::mock::SchedulerCallback mSchedulerCallback; + scheduler::mock::NoOpSchedulerCallback mNoOpSchedulerCallback; scheduler::TestableScheduler* mScheduler = nullptr; - std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 16d4b59250..1ce0309683 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -434,9 +434,10 @@ public: static ComposerState createComposerState(int layerId, sp<Fence> fence, uint32_t stateFlags = layer_state_t::eBufferChanged) { ComposerState composer_state; - composer_state.state.bufferData.acquireFence = std::move(fence); + composer_state.state.bufferData = std::make_shared<BufferData>(); + composer_state.state.bufferData->acquireFence = std::move(fence); composer_state.state.layerId = layerId; - composer_state.state.bufferData.flags = BufferData::BufferDataChange::fenceChanged; + composer_state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged; composer_state.state.flags = stateFlags; return composer_state; } diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp index 6e00748b45..271b1c0211 100644 --- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp @@ -39,6 +39,7 @@ TEST(TransactionProtoParserTest, parse) { layer_state_t layer; layer.layerId = 6; layer.what = std::numeric_limits<uint64_t>::max(); + layer.what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged); layer.x = 7; layer.matrix.dsdx = 15; diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h index 849e3083c4..c90b8ed6c7 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -35,7 +35,7 @@ struct NoOpSchedulerCallback final : ISchedulerCallback { void setVsyncEnabled(bool) override {} void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {} void kernelTimerChanged(bool) override {} - void triggerOnFrameRateOverridesChanged() {} + void triggerOnFrameRateOverridesChanged() override {} }; } // namespace android::scheduler::mock |