From 3a6e47d2217d501dd18310d869de47a481bedcb2 Mon Sep 17 00:00:00 2001 From: Lais Andrade Date: Thu, 2 Apr 2020 11:20:16 +0100 Subject: Replace PowerHint with Boost in SurfaceComposer callback The current implementation of this callback is only interested in the PowerHint::INTERACTION, which maps to the new Boost::INTERACTION. Bug: 150878220 Test: atest DisplayTransactionTest Change-Id: I9280def43fd3b1f6cb59673a593709dcbed5b53d --- libs/gui/SurfaceComposerClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d9cbeb71d2..2ac078fa4c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1842,8 +1842,8 @@ status_t SurfaceComposerClient::setDisplayBrightness(const sp& displayT return ComposerService::getComposerService()->setDisplayBrightness(displayToken, brightness); } -status_t SurfaceComposerClient::notifyPowerHint(int32_t hintId) { - return ComposerService::getComposerService()->notifyPowerHint(hintId); +status_t SurfaceComposerClient::notifyPowerBoost(int32_t boostId) { + return ComposerService::getComposerService()->notifyPowerBoost(boostId); } status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColor, -- cgit v1.2.3-59-g8ed1b From 0783e99d457c9d9a3ede400bdb355ba35e828de6 Mon Sep 17 00:00:00 2001 From: Chris Ye Date: Tue, 2 Jun 2020 21:34:49 -0700 Subject: AIDL-ize InputManager IInputFlinger interface. Use AIDL interface to define the IInputFlinger interface and replace the manual interface. Bug:155425003 Test: atest libgui_test, atest libinput_test. Change-Id: Ibad036b8ceb3a3f5c6d58f8de4ea8c79379d29b5 --- include/input/IInputFlinger.h | 62 ---- include/input/ISetInputWindowsListener.h | 40 -- include/input/InputApplication.h | 12 +- include/input/InputTransport.h | 49 ++- include/input/InputWindow.h | 35 +- libs/gui/LayerState.cpp | 6 +- libs/gui/SurfaceComposerClient.cpp | 2 +- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 13 +- libs/input/Android.bp | 9 +- libs/input/IInputFlinger.cpp | 101 ----- libs/input/ISetInputWindowsListener.cpp | 53 --- libs/input/InputApplication.cpp | 41 ++- libs/input/InputTransport.cpp | 67 ++-- libs/input/InputWindow.cpp | 185 ++++++---- libs/input/android/InputChannelInfo.aidl | 20 + libs/input/android/InputWindowInfo.aidl | 20 + libs/input/android/os/IInputFlinger.aidl | 30 ++ .../input/android/os/ISetInputWindowsListener.aidl | 23 ++ libs/input/tests/InputChannel_test.cpp | 32 ++ libs/input/tests/InputWindow_test.cpp | 12 +- services/inputflinger/InputManager.cpp | 29 +- services/inputflinger/InputManager.h | 23 +- .../dispatcher/include/InputDispatcherInterface.h | 9 +- .../include/InputDispatcherPolicyInterface.h | 2 +- services/inputflinger/host/Android.bp | 3 +- services/inputflinger/host/InputFlinger.h | 20 +- services/inputflinger/tests/Android.bp | 7 + .../inputflinger/tests/IInputFlingerQuery.aidl | 27 ++ .../tests/InputFlingerService_test.cpp | 408 +++++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 40 +- services/surfaceflinger/SurfaceFlinger.h | 22 +- 32 files changed, 915 insertions(+), 489 deletions(-) delete mode 100644 include/input/IInputFlinger.h delete mode 100644 include/input/ISetInputWindowsListener.h delete mode 100644 libs/input/IInputFlinger.cpp delete mode 100644 libs/input/ISetInputWindowsListener.cpp create mode 100644 libs/input/android/InputChannelInfo.aidl create mode 100644 libs/input/android/InputWindowInfo.aidl create mode 100644 libs/input/android/os/IInputFlinger.aidl create mode 100644 libs/input/android/os/ISetInputWindowsListener.aidl create mode 100644 services/inputflinger/tests/IInputFlingerQuery.aidl create mode 100644 services/inputflinger/tests/InputFlingerService_test.cpp (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/include/input/IInputFlinger.h b/include/input/IInputFlinger.h deleted file mode 100644 index d23e3b7767..0000000000 --- a/include/input/IInputFlinger.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _LIBINPUT_IINPUT_FLINGER_H -#define _LIBINPUT_IINPUT_FLINGER_H - -#include -#include - -#include - -#include -#include - -namespace android { - -/* - * This class defines the Binder IPC interface for accessing various - * InputFlinger features. - */ -class IInputFlinger : public IInterface { -public: - DECLARE_META_INTERFACE(InputFlinger) - - virtual void setInputWindows(const std::vector& inputHandles, - const sp& setInputWindowsListener) = 0; - virtual void registerInputChannel(const sp& channel) = 0; - virtual void unregisterInputChannel(const sp& channel) = 0; -}; - - -/** - * Binder implementation. - */ -class BnInputFlinger : public BnInterface { -public: - enum { - SET_INPUT_WINDOWS_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, - REGISTER_INPUT_CHANNEL_TRANSACTION, - UNREGISTER_INPUT_CHANNEL_TRANSACTION - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags = 0); -}; - -} // namespace android - -#endif // _LIBINPUT_IINPUT_FLINGER_H diff --git a/include/input/ISetInputWindowsListener.h b/include/input/ISetInputWindowsListener.h deleted file mode 100644 index 15d31b25c1..0000000000 --- a/include/input/ISetInputWindowsListener.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -namespace android { - -class ISetInputWindowsListener : public IInterface { -public: - DECLARE_META_INTERFACE(SetInputWindowsListener) - virtual void onSetInputWindowsFinished() = 0; -}; - -class BnSetInputWindowsListener: public BnInterface { -public: - enum SetInputWindowsTag : uint32_t { - ON_SET_INPUT_WINDOWS_FINISHED - }; - - virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags = 0) override; -}; - -}; // namespace android diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index ccffeb1327..b6b935329b 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -31,15 +32,17 @@ namespace android { /* * Describes the properties of an application that can receive input. */ -struct InputApplicationInfo { +struct InputApplicationInfo : public Parcelable { sp token; std::string name; std::chrono::nanoseconds dispatchingTimeout; - status_t write(Parcel& output) const; - static InputApplicationInfo read(const Parcel& from); -}; + InputApplicationInfo() = default; + + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; /* * Handle for an application that can receive input. @@ -76,6 +79,7 @@ public: * Returns true on success, or false if the handle is no longer valid. */ virtual bool updateInfo() = 0; + protected: InputApplicationHandle(); virtual ~InputApplicationHandle(); diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 7ca9031f77..0219cf7c2a 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -34,7 +34,9 @@ #include #include +#include #include +#include #include #include #include @@ -174,6 +176,18 @@ struct InputMessage { void getSanitizedCopy(InputMessage* msg) const; }; +struct InputChannelInfo : public Parcelable { + std::string mName; + android::base::unique_fd mFd; + sp mToken; + + InputChannelInfo() = default; + InputChannelInfo(const std::string& name, android::base::unique_fd fd, sp token) + : mName(name), mFd(std::move(fd)), mToken(token){}; + status_t readFromParcel(const android::Parcel* parcel) override; + status_t writeToParcel(android::Parcel* parcel) const override; +}; + /* * An input channel consists of a local unix domain socket used to send and receive * input messages across processes. Each channel has a descriptive name for debugging purposes. @@ -183,10 +197,10 @@ struct InputMessage { * The input channel is closed when all references to it are released. */ class InputChannel : public RefBase { -protected: +public: + InputChannel(); virtual ~InputChannel(); -public: static sp create(const std::string& name, android::base::unique_fd fd, sp token); @@ -200,8 +214,10 @@ public: static status_t openInputChannelPair(const std::string& name, sp& outServerChannel, sp& outClientChannel); - inline std::string getName() const { return mName; } - inline int getFd() const { return mFd.get(); } + inline std::string getName() const { return mInfo.mName; } + inline int getFd() const { return mInfo.mFd.get(); } + inline sp getToken() const { return mInfo.mToken; } + inline InputChannelInfo& getInfo() { return mInfo; } /* Send a message to the other endpoint. * @@ -231,8 +247,9 @@ public: /* Return a new object that has a duplicate of this channel's fd. */ sp dup() const; - status_t write(Parcel& out) const; - static sp read(const Parcel& from); + status_t readFromParcel(const android::Parcel* parcel); + + status_t writeToParcel(android::Parcel* parcel) const; /** * The connection token is used to identify the input connection, i.e. @@ -248,12 +265,23 @@ public: */ sp getConnectionToken() const; + bool operator==(const InputChannel& inputChannel) const { + struct stat lhsInfo, rhsInfo; + if (fstat(mInfo.mFd.get(), &lhsInfo) != 0) { + return false; + } + if (fstat(inputChannel.getFd(), &rhsInfo) != 0) { + return false; + } + // If file descriptors are pointing to same inode they are duplicated fds. + return inputChannel.getName() == getName() && + inputChannel.getConnectionToken() == mInfo.mToken && + lhsInfo.st_ino == rhsInfo.st_ino; + } + private: InputChannel(const std::string& name, android::base::unique_fd fd, sp token); - std::string mName; - android::base::unique_fd mFd; - - sp mToken; + InputChannelInfo mInfo; }; /* @@ -325,7 +353,6 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - sp mChannel; }; diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f8c759c85d..582e73d858 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -17,6 +17,8 @@ #ifndef _UI_INPUT_WINDOW_H #define _UI_INPUT_WINDOW_H +#include +#include #include #include #include @@ -27,14 +29,12 @@ #include "InputApplication.h" namespace android { -class Parcel; /* * Describes the properties of a window that can receive input. */ -struct InputWindowInfo { +struct InputWindowInfo : public Parcelable { InputWindowInfo() = default; - InputWindowInfo(const Parcel& from); // Window flags from WindowManager.LayoutParams enum : uint32_t { @@ -195,9 +195,11 @@ struct InputWindowInfo { bool overlaps(const InputWindowInfo* other) const; - status_t write(Parcel& output) const; + bool operator==(const InputWindowInfo& inputChannel) const; - static InputWindowInfo read(const Parcel& from); + status_t writeToParcel(android::Parcel* parcel) const override; + + status_t readFromParcel(const android::Parcel* parcel) override; }; std::string inputWindowFlagsToString(uint32_t flags); @@ -210,22 +212,19 @@ std::string inputWindowFlagsToString(uint32_t flags); */ class InputWindowHandle : public RefBase { public: + explicit InputWindowHandle(); + InputWindowHandle(const InputWindowHandle& other); + InputWindowHandle(const InputWindowInfo& other); - inline const InputWindowInfo* getInfo() const { - return &mInfo; - } + inline const InputWindowInfo* getInfo() const { return &mInfo; } sp getToken() const; int32_t getId() const { return mInfo.id; } - sp getApplicationToken() { - return mInfo.applicationInfo.token; - } + sp getApplicationToken() { return mInfo.applicationInfo.token; } - inline std::string getName() const { - return !mInfo.name.empty() ? mInfo.name : ""; - } + inline std::string getName() const { return !mInfo.name.empty() ? mInfo.name : ""; } inline std::chrono::nanoseconds getDispatchingTimeout( std::chrono::nanoseconds defaultValue) const { @@ -235,13 +234,14 @@ public: /** * Requests that the state of this object be updated to reflect * the most current available information about the application. + * As this class is created as RefBase object, no pure virtual function is allowed. * * This method should only be called from within the input dispatcher's * critical section. * * Returns true on success, or false if the handle is no longer valid. */ - virtual bool updateInfo() = 0; + virtual bool updateInfo() { return false; } /** * Updates from another input window handle. @@ -254,8 +254,11 @@ public: */ void releaseChannel(); + // Not override since this class is not derrived from Parcelable. + status_t readFromParcel(const android::Parcel* parcel); + status_t writeToParcel(android::Parcel* parcel) const; + protected: - explicit InputWindowHandle(); virtual ~InputWindowHandle(); InputWindowInfo mInfo; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e43446ac8c..1030b82f14 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -55,7 +55,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.g); output.writeFloat(color.b); #ifndef NO_INPUT - inputInfo.write(output); + inputHandle->writeToParcel(&output); #endif output.write(transparentRegion); output.writeUint32(transform); @@ -152,7 +152,7 @@ status_t layer_state_t::read(const Parcel& input) color.b = input.readFloat(); #ifndef NO_INPUT - inputInfo = InputWindowInfo::read(input); + inputHandle->readFromParcel(&input); #endif input.read(transparentRegion); @@ -404,7 +404,7 @@ void layer_state_t::merge(const layer_state_t& other) { #ifndef NO_INPUT if (other.what & eInputInfoChanged) { what |= eInputInfoChanged; - inputInfo = other.inputInfo; + inputHandle = new InputWindowHandle(*other.inputHandle); } #endif diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 16b46df4f6..d797a3547a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1359,7 +1359,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput mStatus = BAD_INDEX; return *this; } - s->inputInfo = info; + s->inputHandle = new InputWindowHandle(info); s->what |= layer_state_t::eInputInfoChanged; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index e60f6777ae..00ae220906 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -201,7 +201,7 @@ struct layer_state_t { mat4 colorTransform; #ifndef NO_INPUT - InputWindowInfo inputInfo; + sp inputHandle = new InputWindowHandle(); #endif client_cache_t cachedBuffer; diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 32c7fc2588..152f7ad56c 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -36,15 +36,16 @@ #include #include -#include -#include -#include +#include #include +#include +#include #include #include #include +using android::os::IInputFlinger; namespace android { namespace test { @@ -71,7 +72,7 @@ public: InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); mInputFlinger = getInputFlinger(); - mInputFlinger->registerInputChannel(mServerChannel); + mInputFlinger->registerInputChannel(mServerChannel->getInfo()); populateInputInfo(width, height); @@ -153,9 +154,7 @@ public: EXPECT_EQ(0, mev->getFlags() & VERIFIED_MOTION_EVENT_FLAGS); } - ~InputSurface() { - mInputFlinger->unregisterInputChannel(mServerChannel); - } + ~InputSurface() { mInputFlinger->unregisterInputChannel(mServerChannel->getInfo()); } void doTransaction(std::function&)> transactionBody) { diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7037680935..ade9c25c53 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -46,14 +46,14 @@ cc_library { target: { android: { srcs: [ - "IInputFlinger.cpp", "InputApplication.cpp", "InputTransport.cpp", "InputWindow.cpp", - "ISetInputWindowsListener.cpp", "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.cpp", + "android/os/IInputFlinger.aidl", + "android/os/ISetInputWindowsListener.aidl", ], shared_libs: [ @@ -72,6 +72,11 @@ cc_library { }, }, }, + + aidl: { + local_include_dirs: ["."], + export_aidl_headers: true + }, } subdirs = ["tests"] diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp deleted file mode 100644 index 8ec51653a8..0000000000 --- a/libs/input/IInputFlinger.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include - -#include - -namespace android { - -class BpInputFlinger : public BpInterface { -public: - explicit BpInputFlinger(const sp& impl) : - BpInterface(impl) { } - - virtual void setInputWindows(const std::vector& inputInfo, - const sp& setInputWindowsListener) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - - data.writeUint32(static_cast(inputInfo.size())); - for (const auto& info : inputInfo) { - info.write(data); - } - data.writeStrongBinder(IInterface::asBinder(setInputWindowsListener)); - - remote()->transact(BnInputFlinger::SET_INPUT_WINDOWS_TRANSACTION, data, &reply, - IBinder::FLAG_ONEWAY); - } - - virtual void registerInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::REGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } - - virtual void unregisterInputChannel(const sp& channel) { - Parcel data, reply; - data.writeInterfaceToken(IInputFlinger::getInterfaceDescriptor()); - channel->write(data); - remote()->transact(BnInputFlinger::UNREGISTER_INPUT_CHANNEL_TRANSACTION, data, &reply); - } -}; - -IMPLEMENT_META_INTERFACE(InputFlinger, "android.input.IInputFlinger"); - -status_t BnInputFlinger::onTransact( - uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { - switch(code) { - case SET_INPUT_WINDOWS_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - size_t count = data.readUint32(); - if (count > data.dataSize()) { - return BAD_VALUE; - } - std::vector handles; - for (size_t i = 0; i < count; i++) { - handles.push_back(InputWindowInfo::read(data)); - } - const sp setInputWindowsListener = - ISetInputWindowsListener::asInterface(data.readStrongBinder()); - setInputWindows(handles, setInputWindowsListener); - break; - } - case REGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - registerInputChannel(channel); - break; - } - case UNREGISTER_INPUT_CHANNEL_TRANSACTION: { - CHECK_INTERFACE(IInputFlinger, data, reply); - sp channel = InputChannel::read(data); - unregisterInputChannel(channel); - break; - } - default: - return BBinder::onTransact(code, data, reply, flags); - } - return NO_ERROR; -} - -}; diff --git a/libs/input/ISetInputWindowsListener.cpp b/libs/input/ISetInputWindowsListener.cpp deleted file mode 100644 index a0330da89e..0000000000 --- a/libs/input/ISetInputWindowsListener.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -namespace android { - -class BpSetInputWindowsListener : public BpInterface { -public: - explicit BpSetInputWindowsListener(const sp& impl) - : BpInterface(impl) { - } - - virtual ~BpSetInputWindowsListener() = default; - - virtual void onSetInputWindowsFinished() { - Parcel data, reply; - data.writeInterfaceToken(ISetInputWindowsListener::getInterfaceDescriptor()); - remote()->transact(BnSetInputWindowsListener::ON_SET_INPUT_WINDOWS_FINISHED, data, &reply, - IBinder::FLAG_ONEWAY); - } -}; - -IMPLEMENT_META_INTERFACE(SetInputWindowsListener, "android.input.ISetInputWindowsListener"); - -status_t BnSetInputWindowsListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags) { - switch(code) { - case ON_SET_INPUT_WINDOWS_FINISHED: { - CHECK_INTERFACE(ISetInputWindowsListener, data, reply); - onSetInputWindowsFinished(); - return NO_ERROR; - } - default: { - return BBinder::onTransact(code, data, reply, flags); - } - } -} - -} // namespace android diff --git a/libs/input/InputApplication.cpp b/libs/input/InputApplication.cpp index c745c24c66..41721a7344 100644 --- a/libs/input/InputApplication.cpp +++ b/libs/input/InputApplication.cpp @@ -22,29 +22,34 @@ namespace android { -// --- InputApplicationHandle --- - -InputApplicationHandle::InputApplicationHandle() { -} - -InputApplicationHandle::~InputApplicationHandle() { +status_t InputApplicationInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readUtf8FromUtf16(&name); + + return status; } -InputApplicationInfo InputApplicationInfo::read(const Parcel& from) { - InputApplicationInfo ret; - ret.token = from.readStrongBinder(); - ret.name = from.readString8().c_str(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); +status_t InputApplicationInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(token) + ?: parcel->writeInt64(dispatchingTimeout.count()) + ?: parcel->writeUtf8AsUtf16(name) ; - return ret; + return status; } -status_t InputApplicationInfo::write(Parcel& output) const { - output.writeStrongBinder(token); - output.writeString8(String8(name.c_str())); - output.writeInt64(dispatchingTimeout.count()); +// --- InputApplicationHandle --- - return OK; -} +InputApplicationHandle::InputApplicationHandle() {} + +InputApplicationHandle::~InputApplicationHandle() {} } // namespace android diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 11af23e1a2..c6043ac203 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -246,6 +246,28 @@ void InputMessage::getSanitizedCopy(InputMessage* msg) const { } } +// --- InputChannelInfo --- + +status_t InputChannelInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + status_t status = parcel->writeStrongBinder(mToken) + ?: parcel->writeUtf8AsUtf16(mName) ?: parcel->writeUniqueFileDescriptor(mFd); + return status; +} + +status_t InputChannelInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + mToken = parcel->readStrongBinder(); + status_t status = parcel->readUtf8FromUtf16(&mName) ?: parcel->readUniqueFileDescriptor(&mFd); + return status; +} + // --- InputChannel --- sp InputChannel::create(const std::string& name, android::base::unique_fd fd, @@ -260,15 +282,17 @@ sp InputChannel::create(const std::string& name, android::base::un } InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd, sp token) - : mName(name), mFd(std::move(fd)), mToken(token) { + : mInfo(name, std::move(fd), token) { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel constructed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel constructed: name='%s', fd=%d", mInfo.mName.c_str(), mInfo.mFd.get()); } } +InputChannel::InputChannel() {} + InputChannel::~InputChannel() { if (DEBUG_CHANNEL_LIFECYCLE) { - ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get()); + ALOGD("Input channel destroyed: name='%s', fd=%d", getName().c_str(), getFd()); } } @@ -308,7 +332,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { msg->getSanitizedCopy(&cleanMsg); ssize_t nWrite; do { - nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); + nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL); } while (nWrite == -1 && errno == EINTR); if (nWrite < 0) { @@ -343,7 +367,7 @@ status_t InputChannel::sendMessage(const InputMessage* msg) { status_t InputChannel::receiveMessage(InputMessage* msg) { ssize_t nRead; do { - nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT); + nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT); } while (nRead == -1 && errno == EINTR); if (nRead < 0) { @@ -383,7 +407,7 @@ status_t InputChannel::receiveMessage(InputMessage* msg) { sp InputChannel::dup() const { android::base::unique_fd newFd(::dup(getFd())); if (!newFd.ok()) { - ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), mName.c_str(), + ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), getName().c_str(), strerror(errno)); const bool hitFdLimit = errno == EMFILE || errno == ENFILE; // If this process is out of file descriptors, then throwing that might end up exploding @@ -394,38 +418,19 @@ sp InputChannel::dup() const { getName().c_str()); return nullptr; } - return InputChannel::create(mName, std::move(newFd), mToken); + return InputChannel::create(getName(), std::move(newFd), getConnectionToken()); } -status_t InputChannel::write(Parcel& out) const { - status_t s = out.writeCString(getName().c_str()); - if (s != OK) { - return s; - } - - s = out.writeStrongBinder(mToken); - if (s != OK) { - return s; - } - - s = out.writeUniqueFileDescriptor(mFd); - return s; +status_t InputChannel::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -sp InputChannel::read(const Parcel& from) { - std::string name = from.readCString(); - sp token = from.readStrongBinder(); - android::base::unique_fd rawFd; - status_t fdResult = from.readUniqueFileDescriptor(&rawFd); - if (fdResult != OK) { - return nullptr; - } - - return InputChannel::create(name, std::move(rawFd), token); +status_t InputChannel::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } sp InputChannel::getConnectionToken() const { - return mToken; + return mInfo.mToken; } // --- InputPublisher --- diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index 3700e8f0f8..ae9b3f0994 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -24,9 +24,6 @@ #include -#include -#include - namespace android { const char* inputWindowFlagToString(uint32_t flag) { @@ -164,96 +161,130 @@ bool InputWindowInfo::overlaps(const InputWindowInfo* other) const { && frameTop < other->frameBottom && frameBottom > other->frameTop; } -status_t InputWindowInfo::write(Parcel& output) const { +bool InputWindowInfo::operator==(const InputWindowInfo& info) const { + return info.token == token && info.id == id && info.name == name && + info.layoutParamsFlags == layoutParamsFlags && + info.layoutParamsType == layoutParamsType && + info.dispatchingTimeout == dispatchingTimeout && info.frameLeft == frameLeft && + info.frameTop == frameTop && info.frameRight == frameRight && + info.frameBottom == frameBottom && info.surfaceInset == surfaceInset && + info.globalScaleFactor == globalScaleFactor && info.windowXScale == windowXScale && + info.windowYScale == windowYScale && + info.touchableRegion.hasSameRects(touchableRegion) && info.visible == visible && + info.canReceiveKeys == canReceiveKeys && info.trustedOverlay == trustedOverlay && + info.hasFocus == hasFocus && info.hasWallpaper == hasWallpaper && + info.paused == paused && info.ownerPid == ownerPid && info.ownerUid == ownerUid && + info.inputFeatures == inputFeatures && info.displayId == displayId && + info.portalToDisplayId == portalToDisplayId && + info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop && + info.applicationInfo.name == applicationInfo.name && + info.applicationInfo.token == applicationInfo.token && + info.applicationInfo.dispatchingTimeout == applicationInfo.dispatchingTimeout; +} + +status_t InputWindowInfo::writeToParcel(android::Parcel* parcel) const { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } if (name.empty()) { - output.writeInt32(0); + parcel->writeInt32(0); return OK; } - output.writeInt32(1); - status_t s = output.writeStrongBinder(token); - if (s != OK) return s; + parcel->writeInt32(1); - output.writeInt32(id); - output.writeString8(String8(name.c_str())); - output.writeInt32(layoutParamsFlags); - output.writeInt32(layoutParamsType); - output.writeInt64(dispatchingTimeout.count()); - output.writeInt32(frameLeft); - output.writeInt32(frameTop); - output.writeInt32(frameRight); - output.writeInt32(frameBottom); - output.writeInt32(surfaceInset); - output.writeFloat(globalScaleFactor); - output.writeFloat(windowXScale); - output.writeFloat(windowYScale); - output.writeBool(visible); - output.writeBool(canReceiveKeys); - output.writeBool(hasFocus); - output.writeBool(hasWallpaper); - output.writeBool(paused); - output.writeBool(trustedOverlay); - output.writeInt32(ownerPid); - output.writeInt32(ownerUid); - output.writeInt32(inputFeatures); - output.writeInt32(displayId); - output.writeInt32(portalToDisplayId); - applicationInfo.write(output); - output.write(touchableRegion); - output.writeBool(replaceTouchableRegionWithCrop); - output.writeStrongBinder(touchableRegionCropHandle.promote()); - return OK; -} + status_t status = parcel->writeStrongBinder(token) ?: + parcel->writeInt64(dispatchingTimeout.count()) ?: + parcel->writeInt32(id) ?: + parcel->writeUtf8AsUtf16(name) ?: + parcel->writeInt32(layoutParamsFlags) ?: + parcel->writeInt32(layoutParamsType) ?: + parcel->writeInt32(frameLeft) ?: + parcel->writeInt32(frameTop) ?: + parcel->writeInt32(frameRight) ?: + parcel->writeInt32(frameBottom) ?: + parcel->writeInt32(surfaceInset) ?: + parcel->writeFloat(globalScaleFactor) ?: + parcel->writeFloat(windowXScale) ?: + parcel->writeFloat(windowYScale) ?: + parcel->writeBool(visible) ?: + parcel->writeBool(canReceiveKeys) ?: + parcel->writeBool(hasFocus) ?: + parcel->writeBool(hasWallpaper) ?: + parcel->writeBool(paused) ?: + parcel->writeBool(trustedOverlay) ?: + parcel->writeInt32(ownerPid) ?: + parcel->writeInt32(ownerUid) ?: + parcel->writeInt32(inputFeatures) ?: + parcel->writeInt32(displayId) ?: + parcel->writeInt32(portalToDisplayId) ?: + applicationInfo.writeToParcel(parcel) ?: + parcel->write(touchableRegion) ?: + parcel->writeBool(replaceTouchableRegionWithCrop) ?: + parcel->writeStrongBinder(touchableRegionCropHandle.promote()); -InputWindowInfo InputWindowInfo::read(const Parcel& from) { - InputWindowInfo ret; + return status; +} - if (from.readInt32() == 0) { - return ret; +status_t InputWindowInfo::readFromParcel(const android::Parcel* parcel) { + if (parcel == nullptr) { + ALOGE("%s: Null parcel", __func__); + return BAD_VALUE; + } + if (parcel->readInt32() == 0) { + return OK; } - ret.token = from.readStrongBinder(); - ret.id = from.readInt32(); - ret.name = from.readString8().c_str(); - ret.layoutParamsFlags = from.readInt32(); - ret.layoutParamsType = from.readInt32(); - ret.dispatchingTimeout = decltype(ret.dispatchingTimeout)(from.readInt64()); - ret.frameLeft = from.readInt32(); - ret.frameTop = from.readInt32(); - ret.frameRight = from.readInt32(); - ret.frameBottom = from.readInt32(); - ret.surfaceInset = from.readInt32(); - ret.globalScaleFactor = from.readFloat(); - ret.windowXScale = from.readFloat(); - ret.windowYScale = from.readFloat(); - ret.visible = from.readBool(); - ret.canReceiveKeys = from.readBool(); - ret.hasFocus = from.readBool(); - ret.hasWallpaper = from.readBool(); - ret.paused = from.readBool(); - ret.trustedOverlay = from.readBool(); - ret.ownerPid = from.readInt32(); - ret.ownerUid = from.readInt32(); - ret.inputFeatures = from.readInt32(); - ret.displayId = from.readInt32(); - ret.portalToDisplayId = from.readInt32(); - ret.applicationInfo = InputApplicationInfo::read(from); - from.read(ret.touchableRegion); - ret.replaceTouchableRegionWithCrop = from.readBool(); - ret.touchableRegionCropHandle = from.readStrongBinder(); + token = parcel->readStrongBinder(); + dispatchingTimeout = decltype(dispatchingTimeout)(parcel->readInt64()); + status_t status = parcel->readInt32(&id) ?: + parcel->readUtf8FromUtf16(&name) ?: + parcel->readInt32(&layoutParamsFlags) ?: + parcel->readInt32(&layoutParamsType) ?: + parcel->readInt32(&frameLeft) ?: + parcel->readInt32(&frameTop) ?: + parcel->readInt32(&frameRight) ?: + parcel->readInt32(&frameBottom) ?: + parcel->readInt32(&surfaceInset) ?: + parcel->readFloat(&globalScaleFactor) ?: + parcel->readFloat(&windowXScale) ?: + parcel->readFloat(&windowYScale) ?: + parcel->readBool(&visible) ?: + parcel->readBool(&canReceiveKeys) ?: + parcel->readBool(&hasFocus) ?: + parcel->readBool(&hasWallpaper) ?: + parcel->readBool(&paused) ?: + parcel->readBool(&trustedOverlay) ?: + parcel->readInt32(&ownerPid) ?: + parcel->readInt32(&ownerUid) ?: + parcel->readInt32(&inputFeatures) ?: + parcel->readInt32(&displayId) ?: + parcel->readInt32(&portalToDisplayId) ?: + applicationInfo.readFromParcel(parcel) ?: + parcel->read(touchableRegion) ?: + parcel->readBool(&replaceTouchableRegionWithCrop); - return ret; -} + touchableRegionCropHandle = parcel->readStrongBinder(); -InputWindowInfo::InputWindowInfo(const Parcel& from) { - *this = read(from); + return status; } // --- InputWindowHandle --- -InputWindowHandle::InputWindowHandle() { +InputWindowHandle::InputWindowHandle() {} + +InputWindowHandle::~InputWindowHandle() {} + +InputWindowHandle::InputWindowHandle(const InputWindowHandle& other) : mInfo(other.mInfo) {} + +InputWindowHandle::InputWindowHandle(const InputWindowInfo& other) : mInfo(other) {} + +status_t InputWindowHandle::writeToParcel(android::Parcel* parcel) const { + return mInfo.writeToParcel(parcel); } -InputWindowHandle::~InputWindowHandle() { +status_t InputWindowHandle::readFromParcel(const android::Parcel* parcel) { + return mInfo.readFromParcel(parcel); } void InputWindowHandle::releaseChannel() { diff --git a/libs/input/android/InputChannelInfo.aidl b/libs/input/android/InputChannelInfo.aidl new file mode 100644 index 0000000000..2e83b966f1 --- /dev/null +++ b/libs/input/android/InputChannelInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputChannelInfo cpp_header "input/InputTransport.h"; diff --git a/libs/input/android/InputWindowInfo.aidl b/libs/input/android/InputWindowInfo.aidl new file mode 100644 index 0000000000..eeaf400227 --- /dev/null +++ b/libs/input/android/InputWindowInfo.aidl @@ -0,0 +1,20 @@ +/* //device/java/android/android/view/InputChannel.aidl +** +** Copyright 2020, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android; + +parcelable InputWindowInfo cpp_header "input/InputWindow.h"; diff --git a/libs/input/android/os/IInputFlinger.aidl b/libs/input/android/os/IInputFlinger.aidl new file mode 100644 index 0000000000..8ff9dae47e --- /dev/null +++ b/libs/input/android/os/IInputFlinger.aidl @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlinger +{ + void setInputWindows(in InputWindowInfo[] inputHandles, + in @nullable ISetInputWindowsListener setInputWindowsListener); + void registerInputChannel(in InputChannelInfo info); + void unregisterInputChannel(in InputChannelInfo info); +} diff --git a/libs/input/android/os/ISetInputWindowsListener.aidl b/libs/input/android/os/ISetInputWindowsListener.aidl new file mode 100644 index 0000000000..bb58fb671b --- /dev/null +++ b/libs/input/android/os/ISetInputWindowsListener.aidl @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +/** @hide */ +oneway interface ISetInputWindowsListener +{ + void onSetInputWindowsFinished(); +} diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp index ada275d014..7f4bd6eac2 100644 --- a/libs/input/tests/InputChannel_test.cpp +++ b/libs/input/tests/InputChannel_test.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -197,5 +198,36 @@ TEST_F(InputChannelTest, SendAndReceive_MotionClassification) { } } +TEST_F(InputChannelTest, InputChannelParcelAndUnparcel) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel parceling", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + InputChannel chan; + Parcel parcel; + ASSERT_EQ(OK, serverChannel->writeToParcel(&parcel)); + parcel.setDataPosition(0); + chan.readFromParcel(&parcel); + + EXPECT_EQ(chan == *serverChannel, true) + << "inputchannel should be equal after parceling and unparceling.\n" + << "name " << chan.getName() << " name " << serverChannel->getName(); +} + +TEST_F(InputChannelTest, DuplicateChannelAndAssertEqual) { + sp serverChannel, clientChannel; + + status_t result = + InputChannel::openInputChannelPair("channel dup", serverChannel, clientChannel); + + ASSERT_EQ(OK, result) << "should have successfully opened a channel pair"; + + sp dupChan = serverChannel->dup(); + + EXPECT_EQ(*serverChannel == *dupChan, true) << "inputchannel should be equal after duplication"; +} } // namespace android diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 87505323c3..cdea922bd2 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -28,13 +28,13 @@ namespace android { namespace test { TEST(InputWindowInfo, ParcellingWithoutToken) { - InputWindowInfo i; + InputWindowInfo i, i2; i.token = nullptr; Parcel p; - ASSERT_EQ(OK, i.write(p)); + ASSERT_EQ(OK, i.writeToParcel(&p)); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + i2.readFromParcel(&p); ASSERT_TRUE(i2.token == nullptr); } @@ -69,10 +69,10 @@ TEST(InputWindowInfo, Parcelling) { i.touchableRegionCropHandle = touchableRegionCropHandle; Parcel p; - i.write(p); - + i.writeToParcel(&p); p.setDataPosition(0); - InputWindowInfo i2 = InputWindowInfo::read(p); + InputWindowInfo i2; + i2.readFromParcel(&p); ASSERT_EQ(i.token, i2.token); ASSERT_EQ(i.id, i2.id); ASSERT_EQ(i.name, i2.name); diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp index f2a0014da4..c5f60ade96 100644 --- a/services/inputflinger/InputManager.cpp +++ b/services/inputflinger/InputManager.cpp @@ -93,16 +93,15 @@ sp InputManager::getDispatcher() { class BinderWindowHandle : public InputWindowHandle { public: - BinderWindowHandle(const InputWindowInfo& info) { - mInfo = info; - } + BinderWindowHandle(const InputWindowInfo& info) { mInfo = info; } bool updateInfo() override { return true; } }; -void InputManager::setInputWindows(const std::vector& infos, +binder::Status InputManager::setInputWindows( + const std::vector& infos, const sp& setInputWindowsListener) { std::unordered_map>> handlesPerDisplay; @@ -116,22 +115,38 @@ void InputManager::setInputWindows(const std::vector& infos, if (setInputWindowsListener) { setInputWindowsListener->onSetInputWindowsFinished(); } + return binder::Status::ok(); } // Used by tests only. -void InputManager::registerInputChannel(const sp& channel) { +binder::Status InputManager::registerInputChannel(const InputChannelInfo& info) { IPCThreadState* ipc = IPCThreadState::self(); const int uid = ipc->getCallingUid(); if (uid != AID_SHELL && uid != AID_ROOT) { ALOGE("Invalid attempt to register input channel over IPC" "from non shell/root entity (PID: %d)", ipc->getCallingPid()); - return; + return binder::Status::ok(); } + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->registerInputChannel(channel); + return binder::Status::ok(); } -void InputManager::unregisterInputChannel(const sp& channel) { +binder::Status InputManager::unregisterInputChannel(const InputChannelInfo& info) { + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); mDispatcher->unregisterInputChannel(channel); + return binder::Status::ok(); +} + +status_t InputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; } } // namespace android diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 41d9478147..4993b54b5c 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -26,18 +26,23 @@ #include #include -#include +#include #include #include -#include +#include +#include #include -#include -#include #include +#include +#include + +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; namespace android { class InputChannel; +class InputDispatcherThread; /* * The input manager is the core of the system event processing. @@ -98,11 +103,13 @@ public: sp getClassifier() override; sp getDispatcher() override; - void setInputWindows(const std::vector& handles, - const sp& setInputWindowsListener) override; + status_t dump(int fd, const Vector& args) override; + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; - void registerInputChannel(const sp& channel) override; - void unregisterInputChannel(const sp& channel) override; + binder::Status registerInputChannel(const InputChannelInfo& info) override; + binder::Status unregisterInputChannel(const InputChannelInfo& info) override; private: sp mReader; diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h index 9b002f437c..f25131c7c7 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h @@ -18,15 +18,14 @@ #define _UI_INPUT_INPUTDISPATCHER_INPUTDISPATCHERINTERFACE_H #include -#include +#include +#include +#include +#include #include namespace android { -class InputApplicationHandle; -class InputChannel; -class InputWindowHandle; - /* * Constants used to report the outcome of input event injection. */ diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h index 21255dd0d6..c886bee263 100644 --- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h +++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h @@ -21,11 +21,11 @@ #include #include +#include #include namespace android { -class InputApplicationHandle; /* * Input dispatcher policy interface. diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp index b56f356dfd..2643c228ff 100644 --- a/services/inputflinger/host/Android.bp +++ b/services/inputflinger/host/Android.bp @@ -59,7 +59,8 @@ cc_binary { shared_libs: [ "libbinder", "libinputflingerhost", - "libutils" + "libutils", + "libinput" ], static_libs: [ "libarect", diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h index 973b4f92fa..9364a2a767 100644 --- a/services/inputflinger/host/InputFlinger.h +++ b/services/inputflinger/host/InputFlinger.h @@ -22,13 +22,17 @@ #include "InputHost.h" +#include +#include +#include #include -#include -#include -#include #include +#include #include +using android::os::BnInputFlinger; +using android::os::ISetInputWindowsListener; + namespace android { class InputFlinger : public BnInputFlinger { @@ -40,10 +44,12 @@ public: InputFlinger() ANDROID_API; virtual status_t dump(int fd, const Vector& args); - void setInputWindows(const std::vector&, - const sp&) {} - void registerInputChannel(const sp&) {} - void unregisterInputChannel(const sp&) {} + binder::Status setInputWindows(const std::vector&, + const sp&) { + return binder::Status::ok(); + } + binder::Status registerInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } + binder::Status unregisterInputChannel(const InputChannelInfo&) { return binder::Status::ok(); } private: virtual ~InputFlinger(); diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp index a0d2f4f172..eae09633af 100644 --- a/services/inputflinger/tests/Android.bp +++ b/services/inputflinger/tests/Android.bp @@ -35,7 +35,14 @@ cc_test { "InputClassifierConverter_test.cpp", "InputDispatcher_test.cpp", "InputReader_test.cpp", + "InputFlingerService_test.cpp", "UinputDevice.cpp", + "IInputFlingerQuery.aidl" ], + aidl: { + include_dirs: [ + "frameworks/native/libs/input", + ], + }, require_root: true, } diff --git a/services/inputflinger/tests/IInputFlingerQuery.aidl b/services/inputflinger/tests/IInputFlingerQuery.aidl new file mode 100644 index 0000000000..1edc08965f --- /dev/null +++ b/services/inputflinger/tests/IInputFlingerQuery.aidl @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.InputChannelInfo; +import android.InputWindowInfo; +import android.os.ISetInputWindowsListener; + +/** @hide */ +interface IInputFlingerQuery +{ + /* Test interfaces */ + void getInputWindows(out InputWindowInfo[] inputHandles); + void getInputChannels(out InputChannelInfo[] infos); +} diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp new file mode 100644 index 0000000000..fd3f5627b7 --- /dev/null +++ b/services/inputflinger/tests/InputFlingerService_test.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TAG "InputFlingerServiceTest" + +using android::os::BnInputFlinger; +using android::os::BnSetInputWindowsListener; +using android::os::IInputFlinger; +using android::os::ISetInputWindowsListener; + +using std::chrono_literals::operator""ms; +using std::chrono_literals::operator""s; + +namespace android { + +static const sp TestInfoToken = new BBinder(); +static constexpr int32_t TestInfoId = 1; +static const std::string TestInfoName = "InputFlingerServiceTestInputWindowInfo"; +static constexpr int32_t TestInfoLayoutParamsFlags = 0xABCD; +static constexpr int32_t TestInfoLayoutParamsType = 39; +static constexpr std::chrono::duration TestInfoDispatchingTimeout = 2532ms; +static constexpr int32_t TestInfoFrameLeft = 93; +static constexpr int32_t TestInfoFrameTop = 34; +static constexpr int32_t TestInfoFrameRight = 16; +static constexpr int32_t TestInfoFrameBottom = 19; +static constexpr int32_t TestInfoSurfaceInset = 17; +static constexpr float TestInfoGlobalScaleFactor = 0.3; +static constexpr float TestInfoWindowXScale = 0.4; +static constexpr float TestInfoWindowYScale = 0.5; +static const Rect TestInfoTouchableRegionRect = {100 /* left */, 150 /* top */, 400 /* right */, + 450 /* bottom */}; +static const Region TestInfoTouchableRegion(TestInfoTouchableRegionRect); +static constexpr bool TestInfoVisible = false; +static constexpr bool TestInfoCanReceiveKeys = false; +static constexpr bool TestInfoTrustedOverlay = true; +static constexpr bool TestInfoHasFocus = false; +static constexpr bool TestInfoHasWallpaper = false; +static constexpr bool TestInfoPaused = false; +static constexpr int32_t TestInfoOwnerPid = 19; +static constexpr int32_t TestInfoOwnerUid = 24; +static constexpr int32_t TestInfoInputFeatures = 29; +static constexpr int32_t TestInfoDisplayId = 34; +static constexpr int32_t TestInfoPortalToDisplayId = 2; +static constexpr bool TestInfoReplaceTouchableRegionWithCrop = true; +static const sp TestInfoTouchableRegionCropHandle = new BBinder(); + +static const std::string TestAppInfoName = "InputFlingerServiceTestInputApplicationInfo"; +static const sp TestAppInfoToken = new BBinder(); +static constexpr std::chrono::duration TestAppInfoDispatchingTimeout = 12345678ms; + +static const String16 kTestServiceName = String16("InputFlingerService"); +static const String16 kQueryServiceName = String16("InputFlingerQueryService"); + +struct SetInputWindowsListener; +// --- InputFlingerServiceTest --- +class InputFlingerServiceTest : public testing::Test { +public: + void SetUp() override; + void TearDown() override; + +protected: + void InitializeInputFlinger(); + void setInputWindowsByInfos(std::vector& infos); + + void setInputWindowsFinished(); + void verifyInputWindowInfo(const InputWindowInfo& info) const; + InputWindowInfo& getInfo() const { return const_cast(mInfo); } + + sp mService; + sp mQuery; + +private: + sp mSetInputWindowsListener; + sp mServerChannel, mClientChannel; + InputWindowInfo mInfo; + std::mutex mLock; + std::condition_variable mSetInputWindowsFinishedCondition; +}; + +struct SetInputWindowsListener : BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function cbFunc) : mCbFunc(cbFunc) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mCbFunc; +}; + +class TestInputManager : public BnInputFlinger { +protected: + virtual ~TestInputManager(){}; + +public: + TestInputManager(){}; + void checkFdFlags(const android::base::unique_fd& fd); + + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles); + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos); + + status_t dump(int fd, const Vector& args) override; + + binder::Status setInputWindows( + const std::vector& handles, + const sp& setInputWindowsListener) override; + + binder::Status registerInputChannel(const InputChannelInfo& channel) override; + binder::Status unregisterInputChannel(const InputChannelInfo& channel) override; + +private: + mutable Mutex mLock; + std::unordered_map>> mHandlesPerDisplay; + std::vector> mInputChannels; +}; + +class TestInputQuery : public BnInputFlingerQuery { +public: + TestInputQuery(sp manager) : mManager(manager){}; + binder::Status getInputWindows(std::vector<::android::InputWindowInfo>* inputHandles) override; + binder::Status getInputChannels(std::vector<::android::InputChannelInfo>* infos) override; + +private: + sp mManager; +}; + +binder::Status TestInputQuery::getInputWindows( + std::vector<::android::InputWindowInfo>* inputHandles) { + return mManager->getInputWindows(inputHandles); +} + +binder::Status TestInputQuery::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + return mManager->getInputChannels(infos); +} + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mCbFunc != nullptr) { + mCbFunc(); + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::setInputWindows( + const std::vector& infos, + const sp& setInputWindowsListener) { + AutoMutex _l(mLock); + + for (const auto& info : infos) { + mHandlesPerDisplay.emplace(info.displayId, std::vector>()); + mHandlesPerDisplay[info.displayId].push_back(new InputWindowHandle(info)); + } + if (setInputWindowsListener) { + setInputWindowsListener->onSetInputWindowsFinished(); + } + return binder::Status::ok(); +} + +void TestInputManager::checkFdFlags(const android::base::unique_fd& fd) { + const int result = fcntl(fd, F_GETFL); + EXPECT_NE(result, -1); + EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK); +} + +binder::Status TestInputManager::registerInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + mInputChannels.push_back(channel); + + return binder::Status::ok(); +} + +binder::Status TestInputManager::unregisterInputChannel(const InputChannelInfo& info) { + AutoMutex _l(mLock); + // check Fd flags + checkFdFlags(info.mFd); + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + + auto it = std::find_if(mInputChannels.begin(), mInputChannels.end(), + [&](sp& it) { return *it == *channel; }); + if (it != mInputChannels.end()) { + mInputChannels.erase(it); + } + + return binder::Status::ok(); +} + +status_t TestInputManager::dump(int fd, const Vector& args) { + std::string dump; + + dump += " InputFlinger dump\n"; + + ::write(fd, dump.c_str(), dump.size()); + return NO_ERROR; +} + +binder::Status TestInputManager::getInputWindows( + std::vector<::android::InputWindowInfo>* inputInfos) { + for (auto& [displayId, inputHandles] : mHandlesPerDisplay) { + for (auto& inputHandle : inputHandles) { + inputInfos->push_back(*inputHandle->getInfo()); + } + } + return binder::Status::ok(); +} + +binder::Status TestInputManager::getInputChannels(std::vector<::android::InputChannelInfo>* infos) { + infos->clear(); + for (auto& channel : mInputChannels) { + auto chanDup = channel->dup(); + infos->push_back(std::move(chanDup->getInfo())); + } + return binder::Status::ok(); +} + +void InputFlingerServiceTest::SetUp() { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { + std::unique_lock lock(mLock); + mSetInputWindowsFinishedCondition.notify_all(); + }); + InputChannel::openInputChannelPair("testchannels", mServerChannel, mClientChannel); + + mInfo.token = TestInfoToken; + mInfo.id = TestInfoId; + mInfo.name = TestInfoName; + mInfo.layoutParamsFlags = TestInfoLayoutParamsFlags; + mInfo.layoutParamsType = TestInfoLayoutParamsType; + mInfo.dispatchingTimeout = TestInfoDispatchingTimeout; + mInfo.frameLeft = TestInfoFrameLeft; + mInfo.frameTop = TestInfoFrameTop; + mInfo.frameRight = TestInfoFrameRight; + mInfo.frameBottom = TestInfoFrameBottom; + mInfo.surfaceInset = TestInfoSurfaceInset; + mInfo.globalScaleFactor = TestInfoGlobalScaleFactor; + mInfo.windowXScale = TestInfoWindowXScale; + mInfo.windowYScale = TestInfoWindowYScale; + mInfo.touchableRegion = TestInfoTouchableRegion; + mInfo.visible = TestInfoVisible; + mInfo.canReceiveKeys = TestInfoCanReceiveKeys; + mInfo.trustedOverlay = TestInfoTrustedOverlay; + mInfo.hasFocus = TestInfoHasFocus; + mInfo.hasWallpaper = TestInfoHasWallpaper; + mInfo.paused = TestInfoPaused; + mInfo.ownerPid = TestInfoOwnerPid; + mInfo.ownerUid = TestInfoOwnerUid; + mInfo.inputFeatures = TestInfoInputFeatures; + mInfo.displayId = TestInfoDisplayId; + mInfo.portalToDisplayId = TestInfoPortalToDisplayId; + mInfo.replaceTouchableRegionWithCrop = TestInfoReplaceTouchableRegionWithCrop; + mInfo.touchableRegionCropHandle = TestInfoTouchableRegionCropHandle; + + mInfo.applicationInfo.name = TestAppInfoName; + mInfo.applicationInfo.token = TestAppInfoToken; + mInfo.applicationInfo.dispatchingTimeout = TestAppInfoDispatchingTimeout; + + InitializeInputFlinger(); +} + +void InputFlingerServiceTest::TearDown() {} + +void InputFlingerServiceTest::verifyInputWindowInfo(const InputWindowInfo& info) const { + EXPECT_EQ(mInfo, info); +} + +void InputFlingerServiceTest::InitializeInputFlinger() { + sp input(defaultServiceManager()->waitForService(kTestServiceName)); + ASSERT_TRUE(input != nullptr); + mService = interface_cast(input); + + input = defaultServiceManager()->waitForService(kQueryServiceName); + ASSERT_TRUE(input != nullptr); + mQuery = interface_cast(input); +} + +void InputFlingerServiceTest::setInputWindowsByInfos(std::vector& infos) { + std::unique_lock lock(mLock); + mService->setInputWindows(infos, mSetInputWindowsListener); + // Verify listener call + EXPECT_NE(mSetInputWindowsFinishedCondition.wait_for(lock, 1s), std::cv_status::timeout); + // Verify input windows from service + std::vector<::android::InputWindowInfo> inputHandles; + mQuery->getInputWindows(&inputHandles); + for (auto& inputInfo : inputHandles) { + verifyInputWindowInfo(inputInfo); + } +} + +/** + * Test InputFlinger service interface SetInputWindows + */ +TEST_F(InputFlingerServiceTest, InputWindow_SetInputWindows) { + std::vector infos = {getInfo()}; + setInputWindowsByInfos(infos); +} + +/** + * Test InputFlinger service interface registerInputChannel + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannel) { + sp serverChannel, clientChannel; + + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + mService->registerInputChannel(serverChannel->getInfo()); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 1UL); + + auto& info = infos[0]; + android::base::unique_fd newFd(::dup(info.mFd)); + sp channel = InputChannel::create(info.mName, std::move(newFd), info.mToken); + EXPECT_EQ(*channel, *serverChannel); + + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +/** + * Test InputFlinger service interface registerInputChannel with invalid cases + */ +TEST_F(InputFlingerServiceTest, InputWindow_RegisterInputChannelInvalid) { + sp serverChannel, clientChannel; + InputChannel::openInputChannelPair("testchannels", serverChannel, clientChannel); + + std::vector<::android::InputChannelInfo> infos(2); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); + + mService->registerInputChannel(InputChannelInfo()); + mService->unregisterInputChannel(clientChannel->getInfo()); + + mService->registerInputChannel(serverChannel->getInfo()); + mService->registerInputChannel(clientChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 2UL); + + mService->unregisterInputChannel(clientChannel->getInfo()); + mService->unregisterInputChannel(serverChannel->getInfo()); + mQuery->getInputChannels(&infos); + EXPECT_EQ(infos.size(), 0UL); +} + +} // namespace android + +int main(int argc, char** argv) { + pid_t forkPid = fork(); + + if (forkPid == 0) { + // Server process + android::sp manager = new android::TestInputManager(); + android::sp query = new android::TestInputQuery(manager); + + android::defaultServiceManager()->addService(android::kTestServiceName, manager, + false /*allowIsolated*/); + android::defaultServiceManager()->addService(android::kQueryServiceName, query, + false /*allowIsolated*/); + android::ProcessState::self()->startThreadPool(); + android::IPCThreadState::self()->joinThreadPool(); + } else { + android::ProcessState::self()->startThreadPool(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + } + return 0; +} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e5e3f48732..aa7b90348a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -58,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -256,6 +257,21 @@ private: } // namespace anonymous +struct SetInputWindowsListener : os::BnSetInputWindowsListener { + explicit SetInputWindowsListener(std::function listenerCb) : mListenerCb(listenerCb) {} + + binder::Status onSetInputWindowsFinished() override; + + std::function mListenerCb; +}; + +binder::Status SetInputWindowsListener::onSetInputWindowsFinished() { + if (mListenerCb != nullptr) { + mListenerCb(); + } + return binder::Status::ok(); +} + // --------------------------------------------------------------------------- const String16 sHardwareTest("android.permission.HARDWARE_TEST"); @@ -321,7 +337,9 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)), - mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) {} + mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)) { + mSetInputWindowsListener = new SetInputWindowsListener([&]() { setInputWindowsFinished(); }); +} SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipInitialization) { ALOGI("SurfaceFlinger is starting"); @@ -623,7 +641,7 @@ void SurfaceFlinger::bootFinished() if (input == nullptr) { ALOGE("Failed to link to input service"); } else { - mInputFlinger = interface_cast(input); + mInputFlinger = interface_cast(input); } readPersistentProperties(); @@ -2892,19 +2910,19 @@ void SurfaceFlinger::updateInputFlinger() { } void SurfaceFlinger::updateInputWindowInfo() { - std::vector inputHandles; + std::vector inputInfos; mDrawingState.traverseInReverseZOrder([&](Layer* layer) { if (layer->needsInputInfo()) { // When calculating the screen bounds we ignore the transparent region since it may // result in an unwanted offset. - inputHandles.push_back(layer->fillInputInfo()); + inputInfos.push_back(layer->fillInputInfo()); } }); - mInputFlinger->setInputWindows(inputHandles, - mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener - : nullptr); + mInputFlinger->setInputWindows(inputInfos, + mInputWindowCommands.syncInputWindows ? mSetInputWindowsListener + : nullptr); } void SurfaceFlinger::commitInputWindowCommands() { @@ -3807,7 +3825,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eInputInfoChanged) { if (privileged) { - layer->setInputInfo(s.inputInfo); + layer->setInputInfo(*s.inputHandle->getInfo()); flags |= eTraversalNeeded; } else { ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); @@ -6059,10 +6077,6 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& display } } -void SurfaceFlinger::SetInputWindowsListener::onSetInputWindowsFinished() { - mFlinger->setInputWindowsFinished(); -} - wp SurfaceFlinger::fromHandle(const sp& handle) { Mutex::Autolock _l(mStateLock); return fromHandleLocked(handle); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d8ea5016e8..7ab0729f35 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -89,8 +88,8 @@ namespace android { class Client; class EventThread; class HWComposer; +struct SetInputWindowsListener; class IGraphicBufferProducer; -class IInputFlinger; class Layer; class MessageBase; class RefreshRateOverlay; @@ -99,6 +98,10 @@ class RenderArea; class TimeStats; class FrameTracer; +namespace os { + class IInputFlinger; +} + namespace compositionengine { class DisplaySurface; class OutputLayer; @@ -336,6 +339,7 @@ public: // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; + void setInputWindowsFinished(); private: friend class BufferLayer; @@ -606,7 +610,6 @@ private: void updateInputFlinger(); void updateInputWindowInfo(); void commitInputWindowCommands() REQUIRES(mStateLock); - void setInputWindowsFinished(); void updateCursorAsync(); void initScheduler(DisplayId primaryDisplayId); @@ -1254,21 +1257,12 @@ private: const float mInternalDisplayDensity; const float mEmulatedDisplayDensity; - sp mInputFlinger; + sp mInputFlinger; InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock); // Should only be accessed by the main thread. InputWindowCommands mInputWindowCommands; - struct SetInputWindowsListener : BnSetInputWindowsListener { - explicit SetInputWindowsListener(sp flinger) - : mFlinger(std::move(flinger)) {} - - void onSetInputWindowsFinished() override; - - const sp mFlinger; - }; - - const sp mSetInputWindowsListener = new SetInputWindowsListener(this); + sp mSetInputWindowsListener; bool mPendingSyncInputWindows GUARDED_BY(mStateLock) = false; Hwc2::impl::PowerAdvisor mPowerAdvisor; -- cgit v1.2.3-59-g8ed1b From e798b47821d07191a20bdb7a3a1fc3887b661635 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 23 Jul 2020 13:52:21 -0700 Subject: Add setFocusedWindow function stub This function, once implemented, will set focus on the specified window. This is the first step in changing focus selection from setInputWindows and using explicit call which will help us more easily decouple z-order from focus selection and support focus for SurfaceViewHost surfaces. Bug: 151179149 Test: presubmit Test: go/wm-smoke Test: atest inputflinger_tests Change-Id: Ib2254b4ab3ba8d579dfe49ddf3286f8ce2eecf9e --- libs/gui/Android.bp | 1 + libs/gui/LayerState.cpp | 19 ++++++- libs/gui/SurfaceComposerClient.cpp | 15 ++++++ libs/gui/include/gui/LayerState.h | 7 ++- libs/gui/include/gui/SurfaceComposerClient.h | 3 ++ libs/input/Android.bp | 1 + libs/input/android/FocusRequest.aidl | 39 ++++++++++++++ libs/input/android/os/IInputFlinger.aidl | 6 +++ services/inputflinger/InputManager.cpp | 5 ++ services/inputflinger/InputManager.h | 1 + .../inputflinger/dispatcher/InputDispatcher.cpp | 15 ++++++ services/inputflinger/dispatcher/InputDispatcher.h | 1 + .../dispatcher/include/InputDispatcherInterface.h | 6 +++ services/inputflinger/host/InputFlinger.h | 1 + services/inputflinger/tests/Android.bp | 4 +- .../inputflinger/tests/IInputFlingerQuery.aidl | 2 + .../tests/InputFlingerService_test.cpp | 61 +++++++++++++++++++++- services/surfaceflinger/SurfaceFlinger.cpp | 13 +++-- 18 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 libs/input/android/FocusRequest.aidl (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 4a4510e047..686e274a11 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -92,6 +92,7 @@ cc_library_shared { export_shared_lib_headers: [ "libbinder", + "libinput", ], // bufferhub is not used when building libgui for vendors diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 1030b82f14..117ce58719 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -448,19 +448,36 @@ void layer_state_t::merge(const layer_state_t& other) { // ------------------------------- InputWindowCommands ---------------------------------------- -void InputWindowCommands::merge(const InputWindowCommands& other) { +bool InputWindowCommands::merge(const InputWindowCommands& other) { + bool changes = false; +#ifndef NO_INPUT + changes |= !other.focusRequests.empty(); + focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()), + std::make_move_iterator(other.focusRequests.end())); +#endif + changes |= other.syncInputWindows && !syncInputWindows; syncInputWindows |= other.syncInputWindows; + return changes; } void InputWindowCommands::clear() { +#ifndef NO_INPUT + focusRequests.clear(); +#endif syncInputWindows = false; } void InputWindowCommands::write(Parcel& output) const { +#ifndef NO_INPUT + output.writeParcelableVector(focusRequests); +#endif output.writeBool(syncInputWindows); } void InputWindowCommands::read(const Parcel& input) { +#ifndef NO_INPUT + input.readParcelableVector(&focusRequests); +#endif syncInputWindows = input.readBool(); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d797a3547a..229a5c2e62 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1364,6 +1364,21 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( + const sp& token, const sp& focusedToken, nsecs_t timestampNanos) { + FocusRequest request; + request.token = token; + request.focusedToken = focusedToken; + request.timestamp = timestampNanos; + return setFocusedWindow(request); +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( + const FocusRequest& request) { + mInputWindowCommands.focusRequests.push_back(request); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() { mInputWindowCommands.syncInputWindows = true; return *this; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 00ae220906..41aad0d309 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -26,6 +26,7 @@ #include #ifndef NO_INPUT +#include #include (InputWindowInfo::Type::NAVIGATION_BAR_PANEL)); - primaryDisplayOnly = true; - } - } - switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags, @@ -3944,10 +3927,6 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return result; } - if (primaryDisplayOnly) { - layer->setPrimaryDisplayOnly(); - } - bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToCurrentState, outTransformHint); diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 962a0cf7af..3ab2ad183c 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -572,6 +572,97 @@ TEST_F(ScreenCaptureTest, CaptureDisplayWithUid) { mCapture->expectBorder(Rect(128, 128, 160, 160), Color::BLACK); } +TEST_F(ScreenCaptureTest, CaptureDisplayPrimaryDisplayOnly) { + sp layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test layer", 0, 0, ISurfaceComposerClient::eFXSurfaceEffect)); + + const Color layerColor = Color::RED; + const Rect bounds = Rect(10, 10, 40, 40); + + Transaction() + .show(layer) + .hide(mFGSurfaceControl) + .setLayerStack(layer, 0) + .setLayer(layer, INT32_MAX) + .setColor(layer, {layerColor.r / 255, layerColor.g / 255, layerColor.b / 255}) + .setCrop_legacy(layer, bounds) + .apply(); + + DisplayCaptureArgs captureArgs; + captureArgs.displayToken = mDisplay; + + { + ScreenCapture::captureDisplay(&mCapture, captureArgs); + mCapture->expectColor(bounds, layerColor); + mCapture->expectBorder(bounds, {63, 63, 195, 255}); + } + + Transaction() + .setFlags(layer, layer_state_t::eLayerSkipScreenshot, + layer_state_t::eLayerSkipScreenshot) + .apply(); + + { + // Can't screenshot test layer since it now has flag + // eLayerSkipScreenshot + ScreenCapture::captureDisplay(&mCapture, captureArgs); + mCapture->expectColor(bounds, {63, 63, 195, 255}); + mCapture->expectBorder(bounds, {63, 63, 195, 255}); + } +} + +TEST_F(ScreenCaptureTest, CaptureDisplayChildPrimaryDisplayOnly) { + sp layer; + sp childLayer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test layer", 0, 0, ISurfaceComposerClient::eFXSurfaceEffect)); + ASSERT_NO_FATAL_FAILURE(childLayer = createLayer("test layer", 0, 0, + ISurfaceComposerClient::eFXSurfaceEffect, + layer.get())); + + const Color layerColor = Color::RED; + const Color childColor = Color::BLUE; + const Rect bounds = Rect(10, 10, 40, 40); + const Rect childBounds = Rect(20, 20, 30, 30); + + Transaction() + .show(layer) + .show(childLayer) + .hide(mFGSurfaceControl) + .setLayerStack(layer, 0) + .setLayer(layer, INT32_MAX) + .setColor(layer, {layerColor.r / 255, layerColor.g / 255, layerColor.b / 255}) + .setColor(childLayer, {childColor.r / 255, childColor.g / 255, childColor.b / 255}) + .setCrop_legacy(layer, bounds) + .setCrop_legacy(childLayer, childBounds) + .apply(); + + DisplayCaptureArgs captureArgs; + captureArgs.displayToken = mDisplay; + + { + ScreenCapture::captureDisplay(&mCapture, captureArgs); + mCapture->expectColor(childBounds, childColor); + mCapture->expectBorder(childBounds, layerColor); + mCapture->expectBorder(bounds, {63, 63, 195, 255}); + } + + Transaction() + .setFlags(layer, layer_state_t::eLayerSkipScreenshot, + layer_state_t::eLayerSkipScreenshot) + .apply(); + + { + // Can't screenshot child layer since the parent has the flag + // eLayerSkipScreenshot + ScreenCapture::captureDisplay(&mCapture, captureArgs); + mCapture->expectColor(childBounds, {63, 63, 195, 255}); + mCapture->expectBorder(childBounds, {63, 63, 195, 255}); + mCapture->expectBorder(bounds, {63, 63, 195, 255}); + } +} + TEST_F(ScreenCaptureTest, CaptureLayerWithUid) { uid_t fakeUid = 12345; -- cgit v1.2.3-59-g8ed1b From 7eb7ee7e16879e07c135bc89fee7a810064492af Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Wed, 5 Aug 2020 10:57:05 +0000 Subject: Add ids to transactions and dump them in transaction trace This is required for associating dumped transactions merges on the client side to dump transaction traces on the server side Test: Make sure a transaction id is present in the dump Change-Id: I8d3ad102bedb839901f0a818779c7d35519c669a --- cmds/surfacereplayer/proto/src/trace.proto | 7 ++++--- libs/gui/ISurfaceComposer.cpp | 11 ++++++++-- libs/gui/SurfaceComposerClient.cpp | 23 ++++++++++++++++++--- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 8 +++++++- libs/gui/tests/Surface_test.cpp | 15 ++++++++------ services/surfaceflinger/SurfaceFlinger.cpp | 24 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 21 +++++++++++-------- services/surfaceflinger/SurfaceInterceptor.cpp | 13 ++++++------ services/surfaceflinger/SurfaceInterceptor.h | 11 +++++----- .../tests/unittests/TestableSurfaceFlinger.h | 6 ++++-- .../tests/unittests/TransactionApplicationTest.cpp | 13 ++++++------ .../tests/unittests/mock/MockSurfaceInterceptor.h | 4 ++-- 13 files changed, 100 insertions(+), 58 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 3ada05c73c..6c3b79b2b9 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -25,9 +25,10 @@ message Transaction { repeated SurfaceChange surface_change = 1; repeated DisplayChange display_change = 2; - required bool synchronous = 3; - required bool animation = 4; - optional Origin origin = 5; + required bool synchronous = 3; + required bool animation = 4; + optional Origin origin = 5; + optional uint64 id = 6; } message SurfaceChange { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 7a2f656b76..2f113ee47c 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -72,7 +72,8 @@ public: const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& commands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, const std::vector& listenerCallbacks) { + bool hasListenerCallbacks, const std::vector& listenerCallbacks, + uint64_t transactionId) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -100,6 +101,8 @@ public: SAFE_PARCEL(data.writeInt64Vector, callbackIds); } + SAFE_PARCEL(data.writeUint64, transactionId); + return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } @@ -1278,9 +1281,13 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(data.readInt64Vector, &callbackIds); listenerCallbacks.emplace_back(tmpBinder, callbackIds); } + + uint64_t transactionId = -1; + SAFE_PARCEL(data.readUint64, &transactionId); + return setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands, desiredPresentTime, uncachedBuffer, hasListenerCallbacks, - listenerCallbacks); + listenerCallbacks, transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8d2a7d9abc..9b6272de43 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -348,8 +348,17 @@ void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId) { // --------------------------------------------------------------------------- +// Initialize transaction id counter used to generate transaction ids +// Transactions will start counting at 1, 0 is used for invalid transactions +std::atomic SurfaceComposerClient::Transaction::idCounter = 1; + +SurfaceComposerClient::Transaction::Transaction() { + mId = generateId(); +} + SurfaceComposerClient::Transaction::Transaction(const Transaction& other) - : mForceSynchronous(other.mForceSynchronous), + : mId(other.mId), + mForceSynchronous(other.mForceSynchronous), mTransactionNestCount(other.mTransactionNestCount), mAnimation(other.mAnimation), mEarlyWakeup(other.mEarlyWakeup), @@ -372,6 +381,10 @@ SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) { return nullptr; } +int64_t SurfaceComposerClient::Transaction::generateId() { + return (((int64_t)getpid()) << 32) | idCounter++; +} + status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) { const uint32_t forceSynchronous = parcel->readUint32(); const uint32_t transactionNestCount = parcel->readUint32(); @@ -582,7 +595,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState({}, {}, 0, applyToken, {}, -1, uncacheBuffer, false, {}); + sf->setTransactionState({}, {}, 0, applyToken, {}, -1, uncacheBuffer, false, {}, + 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -709,11 +723,14 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mExplicitEarlyWakeupStart = false; mExplicitEarlyWakeupEnd = false; + uint64_t transactionId = mId; + mId = generateId(); + sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, - hasListenerCallbacks, listenerCallbacks); + hasListenerCallbacks, listenerCallbacks, transactionId); mInputWindowCommands.clear(); mStatus = NO_ERROR; return NO_ERROR; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3627debcdd..3e3570da33 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -157,7 +157,7 @@ public: uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - const std::vector& listenerCallbacks) = 0; + const std::vector& listenerCallbacks, uint64_t transactionId) = 0; /* signal that we're done booting. * Requires ACCESS_SURFACE_FLINGER permission diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6cac287d77..bbe3893789 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -339,12 +339,18 @@ public: }; class Transaction : public Parcelable { + private: + static std::atomic idCounter; + int64_t generateId(); + protected: std::unordered_map, ComposerState, IBinderHash> mComposerStates; SortedVector mDisplayStates; std::unordered_map, CallbackInfo, TCLHash> mListenerCallbacks; + uint64_t mId; + uint32_t mForceSynchronous = 0; uint32_t mTransactionNestCount = 0; bool mAnimation = false; @@ -380,7 +386,7 @@ public: void registerSurfaceControlForCallback(const sp& sc); public: - Transaction() = default; + Transaction(); virtual ~Transaction() = default; Transaction(Transaction const& other); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index b8b8e4f4cb..b72c6b4ed2 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -695,12 +695,15 @@ public: void destroyDisplay(const sp& /*display */) override {} std::vector getPhysicalDisplayIds() const override { return {}; } sp getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; } - status_t setTransactionState( - const Vector& /*state*/, const Vector& /*displays*/, - uint32_t /*flags*/, const sp& /*applyToken*/, - const InputWindowCommands& /*inputWindowCommands*/, int64_t /*desiredPresentTime*/, - const client_cache_t& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, - const std::vector& /*listenerCallbacks*/) override { + status_t setTransactionState(const Vector& /*state*/, + const Vector& /*displays*/, uint32_t /*flags*/, + const sp& /*applyToken*/, + const InputWindowCommands& /*inputWindowCommands*/, + int64_t /*desiredPresentTime*/, + const client_cache_t& /*cachedBuffer*/, + bool /*hasListenerCallbacks*/, + const std::vector& /*listenerCallbacks*/, + uint64_t /*transactionId*/) override { return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6a0f24a07a..3e93e2f690 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3200,8 +3200,8 @@ bool SurfaceFlinger::flushTransactionQueues() { mPendingInputWindowCommands, transaction.desiredPresentTime, transaction.buffer, transaction.postTime, transaction.privileged, transaction.hasListenerCallbacks, - transaction.listenerCallbacks, transaction.originPID, - transaction.originUID, /*isMainThread*/ true); + transaction.listenerCallbacks, transaction.originPid, + transaction.originUid, transaction.id, /*isMainThread*/ true); transactionQueue.pop(); flushedATransaction = true; } @@ -3249,7 +3249,7 @@ status_t SurfaceFlinger::setTransactionState( const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - const std::vector& listenerCallbacks) { + const std::vector& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); const int64_t postTime = systemTime(); @@ -3282,21 +3282,21 @@ status_t SurfaceFlinger::setTransactionState( } IPCThreadState* ipc = IPCThreadState::self(); - const int originPID = ipc->getCallingPid(); - const int originUID = ipc->getCallingUid(); + const int originPid = ipc->getCallingPid(); + const int originUid = ipc->getCallingUid(); if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, uncacheBuffer, postTime, privileged, - hasListenerCallbacks, listenerCallbacks, originPID, - originUID); + hasListenerCallbacks, listenerCallbacks, originPid, + originUid, transactionId); setTransactionFlags(eTransactionFlushNeeded); return NO_ERROR; } applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime, uncacheBuffer, postTime, privileged, hasListenerCallbacks, - listenerCallbacks, originPID, originUID, /*isMainThread*/ false); + listenerCallbacks, originPid, originUid, /*isMainThread*/ false); return NO_ERROR; } @@ -3305,7 +3305,7 @@ void SurfaceFlinger::applyTransactionState( const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, bool hasListenerCallbacks, const std::vector& listenerCallbacks, - int originPID, int originUID, bool isMainThread) { + int originPid, int originUid, uint64_t transactionId, bool isMainThread) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3396,7 +3396,7 @@ void SurfaceFlinger::applyTransactionState( if (transactionFlags) { if (mInterceptor->isEnabled()) { mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags, - originPID, originUID); + originPid, originUid, transactionId); } // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag @@ -4088,8 +4088,8 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, false, - {}); + setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, false, {}, + 0 /* Undefined transactionId */); setPowerModeInternal(display, hal::PowerMode::ON); const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3b4d5d4c8f..0fd17d19d2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -435,8 +435,8 @@ private: const Vector& displayStates, uint32_t transactionFlags, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, bool hasListenerCallbacks, - std::vector listenerCallbacks, int originPID, - int originUID) + std::vector listenerCallbacks, int originPid, + int originUid, uint64_t transactionId) : states(composerStates), displays(displayStates), flags(transactionFlags), @@ -446,8 +446,9 @@ private: privileged(privileged), hasListenerCallbacks(hasListenerCallbacks), listenerCallbacks(listenerCallbacks), - originPID(originPID), - originUID(originUID) {} + originPid(originPid), + originUid(originUid), + id(transactionId) {} Vector states; Vector displays; @@ -458,8 +459,9 @@ private: bool privileged; bool hasListenerCallbacks; std::vector listenerCallbacks; - int originPID; - int originUID; + int originPid; + int originUid; + uint64_t id; }; template >* = nullptr> @@ -514,7 +516,8 @@ private: const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - const std::vector& listenerCallbacks) override; + const std::vector& listenerCallbacks, + uint64_t transactionId) override; void bootFinished() override; bool authenticateSurfaceTexture( const sp& bufferProducer) const override; @@ -714,8 +717,8 @@ private: const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, bool hasListenerCallbacks, const std::vector& listenerCallbacks, - int originPID, int originUID, bool isMainThread = false) - REQUIRES(mStateLock); + int originPid, int originUid, uint64_t transactionId, + bool isMainThread = false) REQUIRES(mStateLock); // Returns true if at least one transaction was flushed bool flushTransactionQueues(); // Returns true if there is at least one transaction that needs to be flushed diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 9d705e5999..016951a3f5 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -527,13 +527,13 @@ void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction, void SurfaceInterceptor::addTransactionLocked( Increment* increment, const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, - const Vector& changedDisplays, uint32_t transactionFlags, int originPID, - int originUID) { + const Vector& changedDisplays, uint32_t transactionFlags, int originPid, + int originUid, uint64_t transactionId) { Transaction* transaction(increment->mutable_transaction()); transaction->set_synchronous(transactionFlags & BnSurfaceComposer::eSynchronous); transaction->set_animation(transactionFlags & BnSurfaceComposer::eAnimation); - setTransactionOriginLocked(transaction, originPID, originUID); - + setTransactionOriginLocked(transaction, originPid, originUid); + transaction->set_id(transactionId); for (const auto& compState: stateUpdates) { addSurfaceChangesLocked(transaction, compState.state); } @@ -655,14 +655,15 @@ void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t void SurfaceInterceptor::saveTransaction( const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, - const Vector& changedDisplays, uint32_t flags, int originPID, int originUID) { + const Vector& changedDisplays, uint32_t flags, int originPid, int originUid, + uint64_t transactionId) { if (!mEnabled || (stateUpdates.size() <= 0 && changedDisplays.size() <= 0)) { return; } ATRACE_CALL(); std::lock_guard protoGuard(mTraceMutex); addTransactionLocked(createTraceIncrementLocked(), stateUpdates, displays, changedDisplays, - flags, originPID, originUID); + flags, originPid, originUid, transactionId); } void SurfaceInterceptor::saveSurfaceCreation(const sp& layer) { diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 4908bae5da..46284dfd0e 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -68,8 +68,8 @@ public: virtual void saveTransaction( const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, - const Vector& changedDisplays, uint32_t flags, int originPID, - int originUID) = 0; + const Vector& changedDisplays, uint32_t flags, int originPid, + int originUid, uint64_t transactionId) = 0; // Intercept surface data virtual void saveSurfaceCreation(const sp& layer) = 0; @@ -107,8 +107,8 @@ public: // Intercept display and surface transactions void saveTransaction(const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, - const Vector& changedDisplays, uint32_t flags, int originPID, - int originUID) override; + const Vector& changedDisplays, uint32_t flags, int originPid, + int originUid, uint64_t transactionId) override; // Intercept surface data void saveSurfaceCreation(const sp& layer) override; @@ -173,7 +173,8 @@ private: void addTransactionLocked(Increment* increment, const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, const Vector& changedDisplays, - uint32_t transactionFlags, int originPID, int originUID); + uint32_t transactionFlags, int originPid, int originUid, + uint64_t transactionId); void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId); void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId); void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 98b20e8144..37f159c66c 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -354,10 +354,12 @@ public: const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - std::vector& listenerCallbacks) { + std::vector& listenerCallbacks, + uint64_t transactionId) { return mFlinger->setTransactionState(states, displays, flags, applyToken, inputWindowCommands, desiredPresentTime, uncacheBuffer, - hasListenerCallbacks, listenerCallbacks); + hasListenerCallbacks, listenerCallbacks, + transactionId); } auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); }; diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 28415bcb12..7151a52eaa 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -101,6 +101,7 @@ public: InputWindowCommands inputWindowCommands; int64_t desiredPresentTime = -1; client_cache_t uncacheBuffer; + int64_t id = -1; }; void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) { @@ -133,7 +134,7 @@ public: mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks); + mHasListenerCallbacks, mCallbacks, transaction.id); // This transaction should not have been placed on the transaction queue. // If transaction is synchronous or syncs input windows, SF @@ -167,7 +168,7 @@ public: mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks); + mHasListenerCallbacks, mCallbacks, transaction.id); nsecs_t returnedTime = systemTime(); EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); @@ -198,7 +199,7 @@ public: mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.uncacheBuffer, - mHasListenerCallbacks, mCallbacks); + mHasListenerCallbacks, mCallbacks, transactionA.id); // This thread should not have been blocked by the above transaction // (5s is the timeout period that applyTransactionState waits for SF to @@ -209,7 +210,7 @@ public: mFlinger.setTransactionState(transactionB.states, transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, transactionB.desiredPresentTime, transactionB.uncacheBuffer, - mHasListenerCallbacks, mCallbacks); + mHasListenerCallbacks, mCallbacks, transactionB.id); // this thread should have been blocked by the above transaction // if this is an animation, this thread should be blocked for 5s @@ -255,7 +256,7 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.uncacheBuffer, - mHasListenerCallbacks, mCallbacks); + mHasListenerCallbacks, mCallbacks, transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_EQ(1, transactionQueue.size()); @@ -273,7 +274,7 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { empty.applyToken = sp(); mFlinger.setTransactionState(empty.states, empty.displays, empty.flags, empty.applyToken, empty.inputWindowCommands, empty.desiredPresentTime, - empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks); + empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); // flush transaction queue should flush as desiredPresentTime has // passed diff --git a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h index e2c8a65b5f..03a04a95bc 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.h @@ -35,10 +35,10 @@ public: MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD1(addTransactionTraceListener, void(const sp&)); MOCK_METHOD1(binderDied, void(const wp&)); - MOCK_METHOD6(saveTransaction, + MOCK_METHOD7(saveTransaction, void(const Vector&, const DefaultKeyedVector, DisplayDeviceState>&, - const Vector&, uint32_t, int, int)); + const Vector&, uint32_t, int, int, uint64_t)); MOCK_METHOD1(saveSurfaceCreation, void(const sp&)); MOCK_METHOD1(saveSurfaceDeletion, void(const sp&)); MOCK_METHOD4(saveBufferUpdate, void(int32_t, uint32_t, uint32_t, uint64_t)); -- cgit v1.2.3-59-g8ed1b From 2ec1f7b970563ffd1651c36c52e9fc6831120915 Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Tue, 1 Sep 2020 14:18:49 +0000 Subject: Provide layer id on surface creation Allows for the layer state to be dumped on the client side with the layer's id so that they can then be associated with the respective layer dumped on the server side Test: Check that the layer ID is provided on the client side when createSurface is called Change-Id: I7ea851942c43fc48326bb8558a605ba6877600da --- libs/gui/ISurfaceComposerClient.cpp | 13 +++++++------ libs/gui/SurfaceComposerClient.cpp | 11 ++++++++--- libs/gui/include/gui/ISurfaceComposerClient.h | 8 +++++--- services/surfaceflinger/Client.cpp | 14 ++++++++------ services/surfaceflinger/Client.h | 7 ++++--- services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.h | 4 ++-- 7 files changed, 38 insertions(+), 25 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 621cf5950b..a814362e3c 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -49,13 +49,13 @@ public: status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, - sp* handle, sp* gbp, + sp* handle, sp* gbp, int32_t* outId, uint32_t* outTransformHint) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, format, flags, parent, std::move(metadata), - handle, gbp, + handle, gbp, outId, outTransformHint); } @@ -63,14 +63,14 @@ public: PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, + sp* gbp, int32_t* outId, uint32_t* outTransformHint) override { return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, name, width, height, format, flags, parent, std::move(metadata), handle, gbp, - outTransformHint); + outId, outTransformHint); } status_t clearLayerFrameStats(const sp& handle) const override { @@ -85,10 +85,11 @@ public: outStats); } - status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle) override { + status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, + int32_t* outId) override { return callRemote(Tag::MIRROR_SURFACE, mirrorFromHandle, - outHandle); + outHandle, outId); } }; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9b6272de43..3fda059497 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1655,8 +1655,10 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& sp gbp; uint32_t transformHint = 0; + int32_t id = -1; err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, - std::move(metadata), &handle, &gbp, &transformHint); + std::move(metadata), &handle, &gbp, &id, + &transformHint); if (outTransformHint) { *outTransformHint = transformHint; } @@ -1686,8 +1688,10 @@ status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32 } uint32_t transformHint = 0; + int32_t id = -1; err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), - &handle, &gbp, &transformHint); + &handle, &gbp, &id, &transformHint); + if (outTransformHint) { *outTransformHint = transformHint; } @@ -1706,7 +1710,8 @@ sp SurfaceComposerClient::mirrorSurface(SurfaceControl* mirrorFr sp handle; sp mirrorFromHandle = mirrorFromSurface->getHandle(); - status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle); + int32_t layer_id = -1; + status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle, &layer_id); if (err == NO_ERROR) { return new SurfaceControl(this, handle, nullptr, true /* owned */); } diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index ec0a8d11ff..f3fcebecad 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -58,7 +58,8 @@ public: virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, uint32_t* outTransformHint) = 0; + sp* gbp, int32_t* outId, + uint32_t* outTransformHint) = 0; /* * Requires ACCESS_SURFACE_FLINGER permission @@ -67,7 +68,7 @@ public: PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, + sp* gbp, int32_t* outId, uint32_t* outTransformHint) = 0; /* @@ -80,7 +81,8 @@ public: */ virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const = 0; - virtual status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle) = 0; + virtual status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, + int32_t* outId) = 0; }; class BnSurfaceComposerClient : public SafeBnInterface { diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 78bbcba4b4..07817b5a7f 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -79,17 +79,18 @@ sp Client::getLayerUser(const sp& handle) const status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parentHandle, LayerMetadata metadata, sp* handle, - sp* gbp, uint32_t* outTransformHint) { + sp* gbp, int32_t* outId, + uint32_t* outTransformHint) { // We rely on createLayer to check permissions. return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - parentHandle, nullptr, outTransformHint); + parentHandle, nullptr, outId, outTransformHint); } status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, + sp* gbp, int32_t* outId, uint32_t* outTransformHint) { if (mFlinger->authenticateSurfaceTexture(parent) == false) { ALOGE("failed to authenticate surface texture"); @@ -103,11 +104,12 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 } return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - nullptr, layer, outTransformHint); + nullptr, layer, outId, outTransformHint); } -status_t Client::mirrorSurface(const sp& mirrorFromHandle, sp* outHandle) { - return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle); +status_t Client::mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, + int32_t* outId) { + return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle, outId); } status_t Client::clearLayerFrameStats(const sp& handle) const { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index f64be3a9db..9462f1a7a3 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -50,17 +50,18 @@ private: virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, + sp* gbp, int32_t* outId, uint32_t* outTransformHint = nullptr); virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, + sp* gbp, int32_t* outId, uint32_t* outTransformHint = nullptr); - status_t mirrorSurface(const sp& mirrorFromHandle, sp* handle); + status_t mirrorSurface(const sp& mirrorFromHandle, sp* handle, + int32_t* outId); virtual status_t clearLayerFrameStats(const sp& handle) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3e93e2f690..524f4c65ac 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3836,7 +3836,7 @@ uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& input } status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp& mirrorFromHandle, - sp* outHandle) { + sp* outHandle, int32_t* outId) { if (!mirrorFromHandle) { return NAME_NOT_FOUND; } @@ -3861,6 +3861,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp mirrorLayer->mClonedChild = mirrorFrom->createClone(); } + *outId = mirrorLayer->sequence; return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false, nullptr /* outTransformHint */); } @@ -3870,7 +3871,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie LayerMetadata metadata, sp* handle, sp* gbp, const sp& parentHandle, const sp& parentLayer, - uint32_t* outTransformHint) { + int32_t* outId, uint32_t* outTransformHint) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); @@ -3936,6 +3937,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie mInterceptor->saveSurfaceCreation(layer); setTransactionFlags(eTransactionNeeded); + *outId = layer->sequence; return result; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0fd17d19d2..b991b61ff9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -748,7 +748,7 @@ private: PixelFormat format, uint32_t flags, LayerMetadata metadata, sp* handle, sp* gbp, const sp& parentHandle, const sp& parentLayer = nullptr, - uint32_t* outTransformHint = nullptr); + int32_t* outId = nullptr, uint32_t* outTransformHint = nullptr); status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, @@ -768,7 +768,7 @@ private: sp* outHandle, sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, - sp* outHandle); + sp* outHandle, int32_t* outId); std::string getUniqueLayerName(const char* name); -- cgit v1.2.3-59-g8ed1b From 421dfd5842d44a77883fac7ad2781c363e77aed3 Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Tue, 22 Sep 2020 18:11:45 +0000 Subject: Convert SurfaceControl parceling to SAFE_PARCEL Test: Existing tests Change-Id: I7618f9677e538fca90ae5cfb0693e5926701f564 --- libs/gui/SurfaceComposerClient.cpp | 4 +-- libs/gui/SurfaceControl.cpp | 49 +++++++++++++++-------------------- libs/gui/include/gui/SurfaceControl.h | 4 +-- 3 files changed, 25 insertions(+), 32 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3fda059497..0264e17b97 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -431,7 +431,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel } for (size_t j = 0; j < numSurfaces; j++) { sp surface; - surface = SurfaceControl::readFromParcel(parcel); + SAFE_PARCEL(SurfaceControl::readFromParcel, *parcel, &surface); listenerCallbacks[listener].surfaceControls.insert(surface); } } @@ -507,7 +507,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const } parcel->writeUint32(static_cast(callbackInfo.surfaceControls.size())); for (auto surfaceControl : callbackInfo.surfaceControls) { - surfaceControl->writeToParcel(parcel); + SAFE_PARCEL(surfaceControl->writeToParcel, *parcel); } } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 8dcb71bcfc..0246b7315e 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -169,42 +169,35 @@ void SurfaceControl::setTransformHint(uint32_t hint) { mTransformHint = hint; } -void SurfaceControl::writeToParcel(Parcel* parcel) -{ - parcel->writeStrongBinder(ISurfaceComposerClient::asBinder(mClient->getClient())); - parcel->writeStrongBinder(mHandle); - parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); - parcel->writeUint32(mTransformHint); +status_t SurfaceControl::writeToParcel(Parcel& parcel) { + SAFE_PARCEL(parcel.writeStrongBinder, ISurfaceComposerClient::asBinder(mClient->getClient())); + SAFE_PARCEL(parcel.writeStrongBinder, mHandle); + SAFE_PARCEL(parcel.writeStrongBinder, IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); + SAFE_PARCEL(parcel.writeUint32, mTransformHint); + + return NO_ERROR; } -sp SurfaceControl::readFromParcel(const Parcel* parcel) { - bool invalidParcel = false; - status_t status; +status_t SurfaceControl::readFromParcel(const Parcel& parcel, + sp* outSurfaceControl) { sp client; - if ((status = parcel->readStrongBinder(&client)) != OK) { - ALOGE("Failed to read client: %s", statusToString(status).c_str()); - invalidParcel = true; - } sp handle; - if ((status = parcel->readStrongBinder(&handle)) != OK) { - ALOGE("Failed to read handle: %s", statusToString(status).c_str()); - invalidParcel = true; - } sp gbp; - if ((status = parcel->readNullableStrongBinder(&gbp)) != OK) { - ALOGE("Failed to read gbp: %s", statusToString(status).c_str()); - invalidParcel = true; - } - uint32_t transformHint = parcel->readUint32(); + uint32_t transformHint; + + SAFE_PARCEL(parcel.readStrongBinder, &client); + SAFE_PARCEL(parcel.readStrongBinder, &handle); + SAFE_PARCEL(parcel.readNullableStrongBinder, &gbp); + SAFE_PARCEL(parcel.readUint32, &transformHint); - if (invalidParcel) { - return nullptr; - } // We aren't the original owner of the surface. - return new SurfaceControl(new SurfaceComposerClient( - interface_cast(client)), - handle.get(), interface_cast(gbp), + *outSurfaceControl = + new SurfaceControl(new SurfaceComposerClient( + interface_cast(client)), + handle.get(), interface_cast(gbp), transformHint); + + return NO_ERROR; } // ---------------------------------------------------------------------------- diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index ac2bbccfd2..f73a9e2667 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -44,8 +44,8 @@ class SurfaceComposerClient; class SurfaceControl : public RefBase { public: - static sp readFromParcel(const Parcel* parcel); - void writeToParcel(Parcel* parcel); + static status_t readFromParcel(const Parcel& parcel, sp* outSurfaceControl); + status_t writeToParcel(Parcel& parcel); static bool isValid(const sp& surface) { return (surface != nullptr) && surface->isValid(); -- cgit v1.2.3-59-g8ed1b From dbc31672ea7e7b8e8847db8ef70447de918d5b27 Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Tue, 1 Sep 2020 18:28:58 +0000 Subject: Add LayerId to SurfaceControl and LayerState when created Allows us to then dump the LayerState on transaction merges and have an id to associate the LayerState with a layer Test: Check if layer id is available in the LayerState when we dump the LayerState on merges Change-Id: I5046835d6a82574110125c7dbdf2098bd10ac296 --- libs/gui/LayerState.cpp | 2 ++ libs/gui/SurfaceComposerClient.cpp | 31 +++++++++++++++++----------- libs/gui/SurfaceControl.cpp | 13 ++++++++++-- libs/gui/include/gui/LayerState.h | 1 + libs/gui/include/gui/SurfaceComposerClient.h | 7 ++----- libs/gui/include/gui/SurfaceControl.h | 5 ++++- 6 files changed, 39 insertions(+), 20 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6ff4a3d4e2..885f20f434 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -31,6 +31,7 @@ namespace android { status_t layer_state_t::write(Parcel& output) const { SAFE_PARCEL(output.writeStrongBinder, surface); + SAFE_PARCEL(output.writeInt32, layerId); SAFE_PARCEL(output.writeUint64, what); SAFE_PARCEL(output.writeFloat, x); SAFE_PARCEL(output.writeFloat, y); @@ -114,6 +115,7 @@ status_t layer_state_t::write(Parcel& output) const status_t layer_state_t::read(const Parcel& input) { SAFE_PARCEL(input.readNullableStrongBinder, &surface); + SAFE_PARCEL(input.readInt32, &layerId); SAFE_PARCEL(input.readUint64, &what); SAFE_PARCEL(input.readFloat, &x); SAFE_PARCEL(input.readFloat, &y); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0264e17b97..dd24c2c9c8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -443,12 +443,14 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel std::unordered_map, ComposerState, IBinderHash> composerStates; composerStates.reserve(count); for (size_t i = 0; i < count; i++) { - sp surfaceControlHandle = parcel->readStrongBinder(); + sp surfaceControlHandle; + SAFE_PARCEL(parcel->readStrongBinder, &surfaceControlHandle); ComposerState composerState; if (composerState.read(*parcel) == BAD_VALUE) { return BAD_VALUE; } + composerStates[surfaceControlHandle] = composerState; } @@ -512,8 +514,8 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const } parcel->writeUint32(static_cast(mComposerStates.size())); - for (auto const& [surfaceHandle, composerState] : mComposerStates) { - parcel->writeStrongBinder(surfaceHandle); + for (auto const& [handle, composerState] : mComposerStates) { + SAFE_PARCEL(parcel->writeStrongBinder, handle); composerState.write(*parcel); } @@ -522,11 +524,11 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { - for (auto const& [surfaceHandle, composerState] : other.mComposerStates) { - if (mComposerStates.count(surfaceHandle) == 0) { - mComposerStates[surfaceHandle] = composerState; + for (auto const& [handle, composerState] : other.mComposerStates) { + if (mComposerStates.count(handle) == 0) { + mComposerStates[handle] = composerState; } else { - mComposerStates[surfaceHandle].state.merge(composerState.state); + mComposerStates[handle].state.merge(composerState.state); } } @@ -606,7 +608,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { size_t count = 0; for (auto& [handle, cs] : mComposerStates) { - layer_state_t* s = getLayerState(handle); + layer_state_t* s = &(mComposerStates[handle].state); if (!(s->what & layer_state_t::eBufferChanged)) { continue; } else if (s->what & layer_state_t::eCachedBufferChanged) { @@ -779,11 +781,16 @@ void SurfaceComposerClient::Transaction::setExplicitEarlyWakeupEnd() { mExplicitEarlyWakeupEnd = true; } -layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& handle) { +layer_state_t* SurfaceComposerClient::Transaction::getLayerState(const sp& sc) { + auto handle = sc->getHandle(); + if (mComposerStates.count(handle) == 0) { // we don't have it, add an initialized layer_state to our list ComposerState s; + s.state.surface = handle; + s.state.layerId = sc->getLayerId(); + mComposerStates[handle] = s; } @@ -1664,7 +1671,7 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& } ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); if (err == NO_ERROR) { - return new SurfaceControl(this, handle, gbp, transformHint); + return new SurfaceControl(this, handle, gbp, id, transformHint); } } return nullptr; @@ -1697,7 +1704,7 @@ status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32 } ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { - *outSurface = new SurfaceControl(this, handle, gbp, transformHint); + *outSurface = new SurfaceControl(this, handle, gbp, id, transformHint); } } return err; @@ -1713,7 +1720,7 @@ sp SurfaceComposerClient::mirrorSurface(SurfaceControl* mirrorFr int32_t layer_id = -1; status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle, &layer_id); if (err == NO_ERROR) { - return new SurfaceControl(this, handle, nullptr, true /* owned */); + return new SurfaceControl(this, handle, nullptr, layer_id, true /* owned */); } return nullptr; } diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 6e153d9acc..e37ff890b0 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -46,11 +46,12 @@ namespace android { // ============================================================================ SurfaceControl::SurfaceControl(const sp& client, const sp& handle, - const sp& gbp, + const sp& gbp, int32_t layerId, uint32_t transform) : mClient(client), mHandle(handle), mGraphicBufferProducer(gbp), + mLayerId(layerId), mTransformHint(transform) {} SurfaceControl::SurfaceControl(const sp& other) { @@ -58,6 +59,7 @@ SurfaceControl::SurfaceControl(const sp& other) { mHandle = other->mHandle; mGraphicBufferProducer = other->mGraphicBufferProducer; mTransformHint = other->mTransformHint; + mLayerId = other->mLayerId; } SurfaceControl::~SurfaceControl() @@ -148,6 +150,10 @@ sp SurfaceControl::getHandle() const return mHandle; } +int32_t SurfaceControl::getLayerId() const { + return mLayerId; +} + sp SurfaceControl::getIGraphicBufferProducer() const { Mutex::Autolock _l(mLock); @@ -173,6 +179,7 @@ status_t SurfaceControl::writeToParcel(Parcel& parcel) { SAFE_PARCEL(parcel.writeStrongBinder, ISurfaceComposerClient::asBinder(mClient->getClient())); SAFE_PARCEL(parcel.writeStrongBinder, mHandle); SAFE_PARCEL(parcel.writeStrongBinder, IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); + SAFE_PARCEL(parcel.writeInt32, mLayerId); SAFE_PARCEL(parcel.writeUint32, mTransformHint); return NO_ERROR; @@ -183,18 +190,20 @@ status_t SurfaceControl::readFromParcel(const Parcel& parcel, sp client; sp handle; sp gbp; + int32_t layerId; uint32_t transformHint; SAFE_PARCEL(parcel.readStrongBinder, &client); SAFE_PARCEL(parcel.readStrongBinder, &handle); SAFE_PARCEL(parcel.readNullableStrongBinder, &gbp); + SAFE_PARCEL(parcel.readInt32, &layerId); SAFE_PARCEL(parcel.readUint32, &transformHint); // We aren't the original owner of the surface. *outSurfaceControl = new SurfaceControl(new SurfaceComposerClient( interface_cast(client)), - handle.get(), interface_cast(gbp), + handle.get(), interface_cast(gbp), layerId, transformHint); return NO_ERROR; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 7a9bb120cf..5f3de1ba59 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -178,6 +178,7 @@ struct layer_state_t { status_t read(const Parcel& input); }; sp surface; + int32_t layerId; uint64_t what; float x; float y; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index bbe3893789..63a0875bb3 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -345,7 +345,7 @@ public: protected: std::unordered_map, ComposerState, IBinderHash> mComposerStates; - SortedVector mDisplayStates; + SortedVector mDisplayStates; std::unordered_map, CallbackInfo, TCLHash> mListenerCallbacks; @@ -376,10 +376,7 @@ public: InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; - layer_state_t* getLayerState(const sp& surfaceHandle); - layer_state_t* getLayerState(const sp& sc) { - return getLayerState(sc->getHandle()); - } + layer_state_t* getLayerState(const sp& sc); DisplayState& getDisplayState(const sp& token); void cacheBuffers(); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index e98ad53d0c..c0dfcdb087 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -74,6 +74,7 @@ public: sp getSurface() const; sp createSurface() const; sp getHandle() const; + int32_t getLayerId() const; sp getIGraphicBufferProducer() const; @@ -89,7 +90,8 @@ public: explicit SurfaceControl(const sp& other); SurfaceControl(const sp& client, const sp& handle, - const sp& gbp, uint32_t transformHint = 0); + const sp& gbp, int32_t layerId, + uint32_t transformHint = 0); private: // can't be copied @@ -109,6 +111,7 @@ private: sp mGraphicBufferProducer; mutable Mutex mLock; mutable sp mSurfaceData; + int32_t mLayerId; uint32_t mTransformHint; }; -- cgit v1.2.3-59-g8ed1b From 6b7c5c9425496be2166fccf2ab14e061b5a20fa3 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 29 Sep 2020 17:27:05 -0700 Subject: Pass in framenumbers if submitting buffers via BlastBufferQueue The framenumber generated by the graphics producer is forwarded to mimic BufferQueue behaviour. Test: atest SurfaceViewBufferTests Bug: 168504870 Change-Id: Ic652a585d10d7e14c9dd94afaabd0e485e209ede --- libs/gui/BLASTBufferQueue.cpp | 1 + libs/gui/LayerState.cpp | 12 +++++++++--- libs/gui/SurfaceComposerClient.cpp | 18 ++++++++++++++++-- libs/gui/include/gui/LayerState.h | 12 +++++++++--- libs/gui/include/gui/SurfaceComposerClient.h | 2 ++ services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 4 ++-- services/surfaceflinger/BufferStateLayer.h | 3 ++- services/surfaceflinger/Layer.cpp | 14 +++++++------- services/surfaceflinger/Layer.h | 6 ++++-- services/surfaceflinger/RefreshRateOverlay.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.cpp | 13 +++++++++---- services/surfaceflinger/SurfaceInterceptor.cpp | 4 ++-- 13 files changed, 68 insertions(+), 29 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 3b2788a599..ba72f9b45f 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -270,6 +270,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); t->setDesiredPresentTime(bufferItem.mTimestamp); + t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); if (applyTransaction) { t->apply(); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6ff4a3d4e2..150a36d745 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -45,7 +45,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, crop_legacy); SAFE_PARCEL(output.writeStrongBinder, barrierHandle_legacy); SAFE_PARCEL(output.writeStrongBinder, reparentHandle); - SAFE_PARCEL(output.writeUint64, frameNumber_legacy); + SAFE_PARCEL(output.writeUint64, barrierFrameNumber); SAFE_PARCEL(output.writeInt32, overrideScalingMode); SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(barrierGbp_legacy)); SAFE_PARCEL(output.writeStrongBinder, relativeLayerHandle); @@ -108,6 +108,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeFloat, frameRate); SAFE_PARCEL(output.writeByte, frameRateCompatibility); SAFE_PARCEL(output.writeUint32, fixedTransformHint); + SAFE_PARCEL(output.writeUint64, frameNumber); return NO_ERROR; } @@ -134,7 +135,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, crop_legacy); SAFE_PARCEL(input.readNullableStrongBinder, &barrierHandle_legacy); SAFE_PARCEL(input.readNullableStrongBinder, &reparentHandle); - SAFE_PARCEL(input.readUint64, &frameNumber_legacy); + SAFE_PARCEL(input.readUint64, &barrierFrameNumber); SAFE_PARCEL(input.readInt32, &overrideScalingMode); sp tmpBinder; @@ -213,6 +214,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &frameRateCompatibility); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); + SAFE_PARCEL(input.readUint64, &frameNumber); return NO_ERROR; } @@ -340,7 +342,7 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eDeferTransaction_legacy; barrierHandle_legacy = other.barrierHandle_legacy; barrierGbp_legacy = other.barrierGbp_legacy; - frameNumber_legacy = other.frameNumber_legacy; + barrierFrameNumber = other.barrierFrameNumber; } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; @@ -456,6 +458,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; } + if (other.what & eFrameNumberChanged) { + what |= eFrameNumberChanged; + frameNumber = other.frameNumber; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8d2a7d9abc..f24dfca680 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1000,7 +1000,7 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierHandle_legacy = handle; - s->frameNumber_legacy = frameNumber; + s->barrierFrameNumber = frameNumber; registerSurfaceControlForCallback(sc); return *this; @@ -1017,7 +1017,7 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); - s->frameNumber_legacy = frameNumber; + s->barrierFrameNumber = frameNumber; registerSurfaceControlForCallback(sc); return *this; @@ -1307,6 +1307,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyPr return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameNumber( + const sp& sc, uint64_t frameNumber) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eFrameNumberChanged; + s->frameNumber = frameNumber; + + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp& sc) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 7a9bb120cf..96ff61b67b 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -125,6 +125,7 @@ struct layer_state_t { eBackgroundBlurRadiusChanged = 0x80'00000000, eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, + eFrameNumberChanged = 0x400'00000000, }; layer_state_t() @@ -142,7 +143,7 @@ struct layer_state_t { crop_legacy(Rect::INVALID_RECT), cornerRadius(0.0f), backgroundBlurRadius(0), - frameNumber_legacy(0), + barrierFrameNumber(0), overrideScalingMode(-1), transform(0), transformToDisplayInverse(false), @@ -159,7 +160,8 @@ struct layer_state_t { frameRateSelectionPriority(-1), frameRate(0.0f), frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), - fixedTransformHint(ui::Transform::ROT_INVALID) { + fixedTransformHint(ui::Transform::ROT_INVALID), + frameNumber(0) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -195,7 +197,7 @@ struct layer_state_t { uint32_t backgroundBlurRadius; sp barrierHandle_legacy; sp reparentHandle; - uint64_t frameNumber_legacy; + uint64_t barrierFrameNumber; int32_t overrideScalingMode; sp barrierGbp_legacy; @@ -259,6 +261,10 @@ struct layer_state_t { // a buffer of a different size. -1 means the transform hint is not set, // otherwise the value will be a valid ui::Rotation. ui::Transform::RotationFlags fixedTransformHint; + + // Used by BlastBufferQueue to forward the framenumber generated by the + // graphics producer. + uint64_t frameNumber; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6cac287d77..ed2bf07aa4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -487,6 +487,8 @@ public: // ONLY FOR BLAST ADAPTER Transaction& notifyProducerDisconnect(const sp& sc); + // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour. + Transaction& setFrameNumber(const sp& sc, uint64_t frameNumber); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 4cbfdffd8f..1cd753b65b 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -167,7 +167,7 @@ protected: void updateCloneBufferInfo() override; uint64_t mPreviousFrameNumber = 0; - virtual uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; + uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const override; void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ea1f78c048..9f99feeea1 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -258,12 +258,12 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, - const client_cache_t& clientCacheId) { + const client_cache_t& clientCacheId, uint64_t frameNumber) { if (mCurrentState.buffer) { mReleasePreviousBuffer = true; } - mCurrentState.frameNumber++; + mCurrentState.frameNumber = frameNumber; mCurrentState.buffer = buffer; mCurrentState.clientCacheId = clientCacheId; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 81959ae2f3..c13f5e8252 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -70,7 +70,8 @@ public: bool setCrop(const Rect& crop) override; bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) override; + nsecs_t desiredPresentTime, const client_cache_t& clientCacheId, + uint64_t frameNumber) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 85046a4194..58291d4ca0 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -800,10 +800,10 @@ void Layer::pushPendingState() { // to be applied as per normal (no synchronization). mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared(mCurrentState.frameNumber_legacy, this); + auto syncPoint = std::make_shared(mCurrentState.barrierFrameNumber, this); if (barrierLayer->addSyncPoint(syncPoint)) { std::stringstream ss; - ss << "Adding sync point " << mCurrentState.frameNumber_legacy; + ss << "Adding sync point " << mCurrentState.barrierFrameNumber; ATRACE_NAME(ss.str().c_str()); mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { @@ -844,7 +844,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { } if (mRemoteSyncPoints.front()->getFrameNumber() != - mPendingStates[0].frameNumber_legacy) { + mPendingStates[0].barrierFrameNumber) { ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it @@ -1463,13 +1463,13 @@ void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t } mCurrentState.barrierLayer_legacy = barrierLayer; - mCurrentState.frameNumber_legacy = frameNumber; + mCurrentState.barrierFrameNumber = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); mCurrentState.barrierLayer_legacy = nullptr; - mCurrentState.frameNumber_legacy = 0; + mCurrentState.barrierFrameNumber = 0; mCurrentState.modified = false; } @@ -2234,7 +2234,7 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, const DisplayDevice* display) { - ui::Transform transform = getTransform(); + const ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { for (const auto& pendingState : mPendingStatesSnapshot) { @@ -2242,7 +2242,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, if (barrierLayer != nullptr) { BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); + barrierLayerProto->set_frame_number(pendingState.barrierFrameNumber); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 88ece5058b..bdc4f848dc 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -187,7 +187,7 @@ public: // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber wp barrierLayer_legacy; - uint64_t frameNumber_legacy; + uint64_t barrierFrameNumber; // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" @@ -406,7 +406,7 @@ public: virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - const client_cache_t& /*clientCacheId*/) { + const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; @@ -510,6 +510,8 @@ public: virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } + virtual uint64_t getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { return 0; } + /* * called after composition. * returns true if the layer latched a new buffer this frame. diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index d8477e7bc2..99d061daa3 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -241,7 +241,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps(); auto buffer = mBufferCache[*mCurrentFps][mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -252,7 +253,8 @@ void RefreshRateOverlay::onInvalidate() { const auto& buffers = mBufferCache[*mCurrentFps]; mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8ac459b05a..1aec382eba 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3681,13 +3681,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eDeferTransaction_legacy) { if (s.barrierHandle_legacy != nullptr) { - layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.frameNumber_legacy); + layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.barrierFrameNumber); } else if (s.barrierGbp_legacy != nullptr) { const sp& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { const auto& otherLayer = (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil_legacy(otherLayer, s.frameNumber_legacy); + layer->deferTransactionUntil_legacy(otherLayer, s.barrierFrameNumber); } else { ALOGE("Attempt to defer transaction to to an" " unrecognized GraphicBufferProducer"); @@ -3818,8 +3818,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( buffer = s.buffer; } if (buffer) { - if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, - s.cachedBuffer)) { + const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; + const uint64_t frameNumber = frameNumberChanged + ? s.frameNumber + : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; + + if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, s.cachedBuffer, + frameNumber)) { flags |= eTraversalNeeded; } } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 9d705e5999..ae7fcc3be1 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -148,7 +148,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, if (layer->mCurrentState.barrierLayer_legacy != nullptr) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer_legacy.promote(), - layer->mCurrentState.frameNumber_legacy); + layer->mCurrentState.barrierFrameNumber); } addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, @@ -483,7 +483,7 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); } } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); + addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); -- cgit v1.2.3-59-g8ed1b From 22c7b5c7ee0fd3b5581e099e715826f0fbdcdc0f Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Tue, 22 Sep 2020 19:33:40 -0700 Subject: SurfaceFlinger: add transactions to FrameTimeline Allow transaction clients to specify the vsyncId that started the transaction and plumb this data to FrameTimeline to be able to track jank associated with transactions Bug: 166302754 Test: manually see transactions in frame timeline Change-Id: Id05e0d0a73039204943d93b666cb67e3e7515a69 --- libs/gui/ISurfaceComposer.cpp | 20 ++++++---- libs/gui/SurfaceComposerClient.cpp | 30 ++++++++++++--- libs/gui/include/gui/ISurfaceComposer.h | 7 +++- libs/gui/include/gui/SurfaceComposerClient.h | 7 ++++ libs/gui/tests/Surface_test.cpp | 3 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 ++ services/surfaceflinger/BufferQueueLayer.h | 6 +++ services/surfaceflinger/BufferStateLayer.cpp | 4 ++ .../surfaceflinger/FrameTimeline/FrameTimeline.h | 3 +- services/surfaceflinger/Layer.cpp | 29 ++++++++++++-- services/surfaceflinger/Layer.h | 19 +++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 45 +++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 14 ++++--- .../tests/unittests/RefreshRateSelectionTest.cpp | 6 ++- .../tests/unittests/SetFrameRateTest.cpp | 6 ++- .../tests/unittests/TestableSurfaceFlinger.h | 8 ++-- .../tests/unittests/TransactionApplicationTest.cpp | 42 ++++++++++++-------- 17 files changed, 182 insertions(+), 71 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2f113ee47c..964195d30d 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -69,14 +69,15 @@ public: } virtual status_t setTransactionState( - const Vector& state, const Vector& displays, - uint32_t flags, const sp& applyToken, const InputWindowCommands& commands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, const std::vector& listenerCallbacks, - uint64_t transactionId) { + int64_t frameTimelineVsyncId, const Vector& state, + const Vector& displays, uint32_t flags, const sp& applyToken, + const InputWindowCommands& commands, int64_t desiredPresentTime, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + const std::vector& listenerCallbacks, uint64_t transactionId) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId); SAFE_PARCEL(data.writeUint32, static_cast(state.size())); for (const auto& s : state) { SAFE_PARCEL(s.write, data); @@ -1234,6 +1235,8 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); + int64_t frameTimelineVsyncId; + SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId); uint32_t count = 0; SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); Vector state; @@ -1285,9 +1288,10 @@ status_t BnSurfaceComposer::onTransact( uint64_t transactionId = -1; SAFE_PARCEL(data.readUint64, &transactionId); - return setTransactionState(state, displays, stateFlags, applyToken, inputWindowCommands, - desiredPresentTime, uncachedBuffer, hasListenerCallbacks, - listenerCallbacks, transactionId); + return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags, + applyToken, inputWindowCommands, desiredPresentTime, + uncachedBuffer, hasListenerCallbacks, listenerCallbacks, + transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9b6272de43..d4a9cc183a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -365,7 +365,8 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mExplicitEarlyWakeupStart(other.mExplicitEarlyWakeupStart), mExplicitEarlyWakeupEnd(other.mExplicitEarlyWakeupEnd), mContainsBuffer(other.mContainsBuffer), - mDesiredPresentTime(other.mDesiredPresentTime) { + mDesiredPresentTime(other.mDesiredPresentTime), + mFrameTimelineVsyncId(other.mFrameTimelineVsyncId) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; mInputWindowCommands = other.mInputWindowCommands; @@ -394,6 +395,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const bool explicitEarlyWakeupEnd = parcel->readBool(); const bool containsBuffer = parcel->readBool(); const int64_t desiredPresentTime = parcel->readInt64(); + const int64_t frameTimelineVsyncId = parcel->readInt64(); size_t count = static_cast(parcel->readUint32()); if (count > parcel->dataSize()) { @@ -464,6 +466,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mExplicitEarlyWakeupEnd = explicitEarlyWakeupEnd; mContainsBuffer = containsBuffer; mDesiredPresentTime = desiredPresentTime; + mFrameTimelineVsyncId = frameTimelineVsyncId; mDisplayStates = displayStates; mListenerCallbacks = listenerCallbacks; mComposerStates = composerStates; @@ -493,6 +496,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeBool(mExplicitEarlyWakeupEnd); parcel->writeBool(mContainsBuffer); parcel->writeInt64(mDesiredPresentTime); + parcel->writeInt64(mFrameTimelineVsyncId); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { displayState.write(*parcel); @@ -568,6 +572,15 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup; mExplicitEarlyWakeupStart = mExplicitEarlyWakeupStart || other.mExplicitEarlyWakeupStart; mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd; + + // When merging vsync Ids we take the oldest one + if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && + other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { + mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId); + } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { + mFrameTimelineVsyncId = other.mFrameTimelineVsyncId; + } + other.clear(); return *this; } @@ -585,6 +598,7 @@ void SurfaceComposerClient::Transaction::clear() { mExplicitEarlyWakeupStart = false; mExplicitEarlyWakeupEnd = false; mDesiredPresentTime = -1; + mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; } void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { @@ -595,8 +609,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState({}, {}, 0, applyToken, {}, -1, uncacheBuffer, false, {}, - 0 /* Undefined transactionId */); + sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, -1, + uncacheBuffer, false, {}, 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -727,8 +741,8 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { mId = generateId(); sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(composerStates, displayStates, flags, applyToken, mInputWindowCommands, - mDesiredPresentTime, + sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, + mInputWindowCommands, mDesiredPresentTime, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, hasListenerCallbacks, listenerCallbacks, transactionId); mInputWindowCommands.clear(); @@ -1517,6 +1531,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( + int64_t frameTimelineVsyncId) { + mFrameTimelineVsyncId = frameTimelineVsyncId; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 3e3570da33..a41614749d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -109,6 +109,9 @@ public: enum ConfigChanged { eConfigChangedSuppress = 0, eConfigChangedDispatch = 1 }; + // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java + static constexpr int64_t INVALID_VSYNC_ID = -1; + /* * Create a connection with SurfaceFlinger. */ @@ -153,8 +156,8 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( - const Vector& state, const Vector& displays, - uint32_t flags, const sp& applyToken, + int64_t frameTimelineVsyncId, const Vector& state, + const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) = 0; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index bbe3893789..519b26eb40 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -373,6 +373,9 @@ public: // The desired present time does not affect this ordering. int64_t mDesiredPresentTime = -1; + // The vsync Id provided by Choreographer.getVsyncId + int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; @@ -538,6 +541,10 @@ public: // a buffer of a different size. Transaction& setFixedTransformHint(const sp& sc, int32_t transformHint); + // Sets the frame timeline vsync id received from choreographer that corresponds + // to the transaction. + Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index b72c6b4ed2..5a376da05c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -695,7 +695,8 @@ public: void destroyDisplay(const sp& /*display */) override {} std::vector getPhysicalDisplayIds() const override { return {}; } sp getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; } - status_t setTransactionState(const Vector& /*state*/, + status_t setTransactionState(int64_t /*frameTimelineVsyncId*/, + const Vector& /*state*/, const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, const InputWindowCommands& /*inputWindowCommands*/, diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 33126ab77d..a5745492e5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -381,6 +381,10 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } +void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) { + mFrameTimelineVsyncId = frameTimelineVsyncId; +} + // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index fc992f78ae..fb8a0c22ee 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -103,6 +103,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; + void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override; sp createClone() override; @@ -146,6 +147,11 @@ private: std::atomic mSidebandStreamChanged{false}; sp mContentsChangedListener; + + // The last vsync id received on this layer. This will be used when we get + // a buffer to correlate the buffer with the vsync id. Can only be accessed + // with the SF state lock held. + std::optional mFrameTimelineVsyncId; }; } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ea1f78c048..f6c3cef437 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -161,6 +161,10 @@ void BufferStateLayer::pushPendingState() { bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { mCurrentStateModified = mCurrentState.modified; bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit); + if (stateUpdateAvailable && mCallbackHandleAcquireTime != -1) { + // Update the actual end time if we have a buffer + mSurfaceFrame->setActualEndTime(mCallbackHandleAcquireTime); + } mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified; mCurrentState.modified = false; return stateUpdateAvailable; diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index a42c32c1c1..2ca1e231c2 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -128,7 +129,7 @@ using namespace std::chrono_literals; class TokenManager : public android::frametimeline::TokenManager { public: - TokenManager() : mCurrentToken(0) {} + TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {} ~TokenManager() = default; int64_t generateTokenForPredictions(TimelineItem&& predictions) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 85046a4194..193804c70d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -62,6 +62,7 @@ #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" #include "EffectLayer.h" +#include "FrameTimeline.h" #include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" @@ -76,6 +77,7 @@ namespace android { using base::StringAppendF; using namespace android::flag_operators; +using PresentState = frametimeline::SurfaceFrame::PresentState; std::atomic Layer::sSequence{1}; @@ -124,6 +126,8 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.shadowRadius = 0.f; mCurrentState.treeHasFrameRateVote = false; mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; + mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mCurrentState.postTime = -1; if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. @@ -823,8 +827,8 @@ void Layer::pushPendingState() { void Layer::popPendingState(State* stateToCommit) { ATRACE_CALL(); - *stateToCommit = mPendingStates[0]; + *stateToCommit = mPendingStates[0]; mPendingStates.removeAt(0); ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } @@ -881,6 +885,20 @@ bool Layer::applyPendingStates(State* stateToCommit) { mFlinger->setTraversalNeeded(); } + if (stateUpdateAvailable) { + const auto vsyncId = + stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID + ? std::nullopt + : std::make_optional(stateToCommit->frameTimelineVsyncId); + + auto surfaceFrame = + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mTransactionName, vsyncId); + surfaceFrame->setActualQueueTime(stateToCommit->postTime); + surfaceFrame->setActualEndTime(stateToCommit->postTime); + + mSurfaceFrame = std::move(surfaceFrame); + } + mCurrentState.modified = false; return stateUpdateAvailable; } @@ -1018,6 +1036,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(const State& stateToCommit) { mDrawingState = stateToCommit; + mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mSurfaceFrame), PresentState::Presented); } uint32_t Layer::getTransactionFlags(uint32_t flags) { @@ -1434,8 +1453,12 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) { + mCurrentState.sequence++; + mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId; + mCurrentState.postTime = postTime; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); } Layer::FrameRate Layer::getFrameRateForLayerTree() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 88ece5058b..f9037587e3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -71,6 +71,10 @@ namespace impl { class SurfaceInterceptor; } +namespace frametimeline { +class SurfaceFrame; +} // namespace frametimeline + struct LayerCreationArgs { LayerCreationArgs(SurfaceFlinger*, sp, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata); @@ -267,6 +271,12 @@ public: // a buffer of a different size. ui::Transform::ROT_INVALID means the // a fixed transform hint is not set. ui::Transform::RotationFlags fixedTransformHint; + + // The vsync id that was used to start the transaction + int64_t frameTimelineVsyncId; + + // When the transaction was posted + nsecs_t postTime; }; /* @@ -821,7 +831,8 @@ public: bool setFrameRate(FrameRate); - void setFrameTimelineVsync(int64_t frameTimelineVsyncId); + virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {} + void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime); // Creates a new handle each time, so we only expect // this to be called once. @@ -1021,12 +1032,12 @@ protected: // Can only be accessed with the SF state lock held. bool mChildrenChanged{false}; - // Can only be accessed with the SF state lock held. - std::optional mFrameTimelineVsyncId; - // Window types from WindowManager.LayoutParams const InputWindowInfo::Type mWindowType; + // Can only be accessed with the SF state lock held. + std::unique_ptr mSurfaceFrame; + private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9bfc63aaa2..b4605aa15d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3195,7 +3195,8 @@ bool SurfaceFlinger::flushTransactionQueues() { break; } transactions.push_back(transaction); - applyTransactionState(transaction.states, transaction.displays, transaction.flags, + applyTransactionState(transaction.frameTimelineVsyncId, transaction.states, + transaction.displays, transaction.flags, mPendingInputWindowCommands, transaction.desiredPresentTime, transaction.buffer, transaction.postTime, transaction.privileged, transaction.hasListenerCallbacks, @@ -3245,9 +3246,10 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, } status_t SurfaceFlinger::setTransactionState( - const Vector& states, const Vector& displays, uint32_t flags, - const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + int64_t frameTimelineVsyncId, const Vector& states, + const Vector& displays, uint32_t flags, const sp& applyToken, + const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); @@ -3285,22 +3287,24 @@ status_t SurfaceFlinger::setTransactionState( const int originUid = ipc->getCallingUid(); if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states)) { - mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, - uncacheBuffer, postTime, privileged, - hasListenerCallbacks, listenerCallbacks, originPid, - originUid, transactionId); + mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, + desiredPresentTime, uncacheBuffer, postTime, + privileged, hasListenerCallbacks, listenerCallbacks, + originPid, originUid, transactionId); setTransactionFlags(eTransactionFlushNeeded); return NO_ERROR; } - applyTransactionState(states, displays, flags, inputWindowCommands, desiredPresentTime, - uncacheBuffer, postTime, privileged, hasListenerCallbacks, - listenerCallbacks, originPid, originUid, /*isMainThread*/ false); + applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, + desiredPresentTime, uncacheBuffer, postTime, privileged, + hasListenerCallbacks, listenerCallbacks, originPid, originUid, + /*isMainThread*/ false); return NO_ERROR; } void SurfaceFlinger::applyTransactionState( - const Vector& states, const Vector& displays, uint32_t flags, + int64_t frameTimelineVsyncId, const Vector& states, + const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, bool hasListenerCallbacks, const std::vector& listenerCallbacks, @@ -3338,8 +3342,9 @@ void SurfaceFlinger::applyTransactionState( std::unordered_set listenerCallbacksWithSurfaces; uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - clientStateFlags |= setClientStateLocked(state, desiredPresentTime, postTime, privileged, - listenerCallbacksWithSurfaces); + clientStateFlags |= + setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, postTime, + privileged, listenerCallbacksWithSurfaces); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), desiredPresentTime, @@ -3516,8 +3521,8 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis } uint32_t SurfaceFlinger::setClientStateLocked( - const ComposerState& composerState, int64_t desiredPresentTime, int64_t postTime, - bool privileged, + int64_t frameTimelineVsyncId, const ComposerState& composerState, + int64_t desiredPresentTime, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) { const layer_state_t& s = composerState.state; @@ -3823,6 +3828,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + + layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime); + if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener @@ -4087,7 +4095,8 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(state, displays, 0, nullptr, mPendingInputWindowCommands, -1, {}, false, {}, + setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr, + mPendingInputWindowCommands, -1, {}, false, {}, 0 /* Undefined transactionId */); setPowerModeInternal(display, hal::PowerMode::ON); @@ -6193,7 +6202,7 @@ status_t SurfaceFlinger::setFrameTimelineVsync(const sp& return BAD_VALUE; } - layer->setFrameTimelineVsync(frameTimelineVsyncId); + layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0fd17d19d2..06ea4732df 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -339,8 +339,8 @@ protected: virtual ~SurfaceFlinger(); virtual uint32_t setClientStateLocked( - const ComposerState& composerState, int64_t desiredPresentTime, int64_t postTime, - bool privileged, + int64_t frameTimelineVsyncId, const ComposerState& composerState, + int64_t desiredPresentTime, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) REQUIRES(mStateLock); virtual void commitTransactionLocked(); @@ -431,13 +431,14 @@ private: }; struct TransactionState { - TransactionState(const Vector& composerStates, + TransactionState(int64_t frameTimelineVsyncId, const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, bool hasListenerCallbacks, std::vector listenerCallbacks, int originPid, int originUid, uint64_t transactionId) - : states(composerStates), + : frameTimelineVsyncId(frameTimelineVsyncId), + states(composerStates), displays(displayStates), flags(transactionFlags), desiredPresentTime(desiredPresentTime), @@ -450,6 +451,7 @@ private: originUid(originUid), id(transactionId) {} + int64_t frameTimelineVsyncId; Vector states; Vector displays; uint32_t flags; @@ -510,7 +512,7 @@ private: void destroyDisplay(const sp& displayToken) override; std::vector getPhysicalDisplayIds() const override; sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const override; - status_t setTransactionState(const Vector& state, + status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, @@ -710,7 +712,7 @@ private: /* * Transactions */ - void applyTransactionState(const Vector& state, + void applyTransactionState(int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp index 409f90d9f9..2c8178e684 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -118,7 +118,11 @@ void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { } void RefreshRateSelectionTest::commitTransaction(Layer* layer) { - layer->commitTransaction(layer->getCurrentState()); + layer->pushPendingState(); + auto c = layer->getCurrentState(); + if (layer->applyPendingStates(&c)) { + layer->commitTransaction(c); + } } void RefreshRateSelectionTest::setupScheduler() { diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index d4591fc4f2..efee826402 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -157,7 +157,11 @@ void SetFrameRateTest::reparentChildren(sp parent, sp newParent) { void SetFrameRateTest::commitTransaction() { for (auto layer : mLayers) { - layer.get()->commitTransaction(layer.get()->getCurrentState()); + layer->pushPendingState(); + auto c = layer->getCurrentState(); + if (layer->applyPendingStates(&c)) { + layer->commitTransaction(c); + } } } diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 37f159c66c..8c12e9400a 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -348,7 +348,7 @@ public: auto& getTransactionQueue() { return mFlinger->mTransactionQueues; } - auto setTransactionState(const Vector& states, + auto setTransactionState(int64_t frameTimelineVsyncId, const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, @@ -356,9 +356,9 @@ public: bool hasListenerCallbacks, std::vector& listenerCallbacks, uint64_t transactionId) { - return mFlinger->setTransactionState(states, displays, flags, applyToken, - inputWindowCommands, desiredPresentTime, uncacheBuffer, - hasListenerCallbacks, listenerCallbacks, + return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags, + applyToken, inputWindowCommands, desiredPresentTime, + uncacheBuffer, hasListenerCallbacks, listenerCallbacks, transactionId); } diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 7151a52eaa..760bf65fee 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -100,6 +100,7 @@ public: sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); InputWindowCommands inputWindowCommands; int64_t desiredPresentTime = -1; + int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; client_cache_t uncacheBuffer; int64_t id = -1; }; @@ -115,11 +116,12 @@ public: } void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, - int64_t desiredPresentTime) { + int64_t desiredPresentTime, int64_t frameTimelineVsyncId) { mTransactionNumber++; transaction.flags |= flags; // ISurfaceComposer::eSynchronous; transaction.inputWindowCommands.syncInputWindows = syncInputWindows; transaction.desiredPresentTime = desiredPresentTime; + transaction.frameTimelineVsyncId = frameTimelineVsyncId; } void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { @@ -129,9 +131,10 @@ public: EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime())); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ -1); + /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationTime = systemTime(); - mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, + mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transaction.id); @@ -163,9 +166,10 @@ public: .WillOnce(Return(time + nsecs_t(5 * 1e8))); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ time + s2ns(1)); + /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transaction.states, transaction.displays, transaction.flags, + mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transaction.id); @@ -187,16 +191,17 @@ public: // transaction that should go on the pending thread TransactionInfo transactionA; setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ time + s2ns(1)); + /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); // transaction that would not have gone on the pending thread if not // blocked TransactionInfo transactionB; setupSingle(transactionB, flags, syncInputWindows, - /*desiredPresentTime*/ -1); + /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, + mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transactionA.id); @@ -207,7 +212,8 @@ public: EXPECT_LE(systemTime(), applicationSentTime + s2ns(5)); applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionB.states, transactionB.displays, transactionB.flags, + mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states, + transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, transactionB.desiredPresentTime, transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transactionB.id); @@ -252,11 +258,12 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { .WillOnce(Return(s2ns(2))); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ s2ns(1)); - mFlinger.setTransactionState(transactionA.states, transactionA.displays, transactionA.flags, - transactionA.applyToken, transactionA.inputWindowCommands, - transactionA.desiredPresentTime, transactionA.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transactionA.id); + /*desiredPresentTime*/ s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + transactionA.displays, transactionA.flags, transactionA.applyToken, + transactionA.inputWindowCommands, transactionA.desiredPresentTime, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_EQ(1, transactionQueue.size()); @@ -272,9 +279,10 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // different process) to re-query and reset the cached expected present time TransactionInfo empty; empty.applyToken = sp(); - mFlinger.setTransactionState(empty.states, empty.displays, empty.flags, empty.applyToken, - empty.inputWindowCommands, empty.desiredPresentTime, - empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); + mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays, + empty.flags, empty.applyToken, empty.inputWindowCommands, + empty.desiredPresentTime, empty.uncacheBuffer, + mHasListenerCallbacks, mCallbacks, empty.id); // flush transaction queue should flush as desiredPresentTime has // passed -- cgit v1.2.3-59-g8ed1b From 11dcc2207f651acf836aa611e48ce75db90258b0 Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Sat, 12 Sep 2020 15:49:39 +0000 Subject: Pass surface control instead of handle as reference to layers in LayerState Allows us to have access to the layer id stored in surface control so that it can be dumped when tracing the transaction merges Test: Existing tests Change-Id: I3e466c69585937d8ce74a29a49fdbb7b3353a460 --- cmds/surfacereplayer/replayer/Replayer.cpp | 14 ++--- libs/gui/LayerState.cpp | 68 +++++++++++++++++----- libs/gui/SurfaceComposerClient.cpp | 24 ++++---- libs/gui/SurfaceControl.cpp | 1 + libs/gui/include/gui/LayerState.h | 48 ++------------- libs/gui/include/gui/SurfaceComposerClient.h | 10 ++-- libs/gui/include/gui/SurfaceControl.h | 1 - libs/gui/tests/EndToEndNativeInputTest.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 19 +++--- services/surfaceflinger/SurfaceInterceptor.cpp | 19 ++++-- .../surfaceflinger/tests/DetachChildren_test.cpp | 10 ++-- .../tests/LayerRenderTypeTransaction_test.cpp | 23 ++++---- .../surfaceflinger/tests/LayerTransaction_test.cpp | 2 +- .../LayerTypeAndRenderTypeTransaction_test.cpp | 16 ++--- .../tests/LayerTypeTransaction_test.cpp | 16 ++--- services/surfaceflinger/tests/LayerUpdate_test.cpp | 25 ++++---- services/surfaceflinger/tests/MirrorLayer_test.cpp | 8 +-- services/surfaceflinger/tests/RelativeZ_test.cpp | 21 +++---- .../surfaceflinger/tests/ScreenCapture_test.cpp | 6 +- .../tests/SurfaceInterceptor_test.cpp | 9 ++- .../tests/fakehwc/SFFakeHwc_test.cpp | 10 ++-- 21 files changed, 171 insertions(+), 181 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 2b5667d8fe..86e4f5d773 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -584,9 +584,7 @@ void Replayer::setDeferredTransaction(SurfaceComposerClient::Transaction& t, return; } - auto handle = mLayers[dtc.layer_id()]->getHandle(); - - t.deferTransactionUntil_legacy(mLayers[id], handle, dtc.frame_number()); + t.deferTransactionUntil_legacy(mLayers[id], mLayers[dtc.layer_id()], dtc.frame_number()); } void Replayer::setDisplaySurface(SurfaceComposerClient::Transaction& t, @@ -706,11 +704,11 @@ status_t Replayer::loadSurfaceComposerClient() { void Replayer::setReparentChange(SurfaceComposerClient::Transaction& t, layer_id id, const ReparentChange& c) { - sp newParentHandle = nullptr; + sp newSurfaceControl = nullptr; if (mLayers.count(c.parent_id()) != 0 && mLayers[c.parent_id()] != nullptr) { - newParentHandle = mLayers[c.parent_id()]->getHandle(); + newSurfaceControl = mLayers[c.parent_id()]; } - t.reparent(mLayers[id], newParentHandle); + t.reparent(mLayers[id], newSurfaceControl); } void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t, @@ -719,7 +717,7 @@ void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t, ALOGE("Layer %d not found in set relative parent transaction", c.relative_parent_id()); return; } - t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()]->getHandle(), c.z()); + t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z()); } void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t, @@ -733,7 +731,7 @@ void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t, ALOGE("Layer %d not found in reparent children transaction", c.parent_id()); return; } - t.reparentChildren(mLayers[id], mLayers[c.parent_id()]->getHandle()); + t.reparentChildren(mLayers[id], mLayers[c.parent_id()]); } void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 4a57b1bfac..a4de66e8a7 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -18,16 +18,55 @@ #include -#include #include -#include #include +#include #include +#include #include namespace android { +layer_state_t::layer_state_t() + : what(0), + x(0), + y(0), + z(0), + w(0), + h(0), + layerStack(0), + alpha(0), + flags(0), + mask(0), + reserved(0), + crop_legacy(Rect::INVALID_RECT), + cornerRadius(0.0f), + backgroundBlurRadius(0), + barrierFrameNumber(0), + overrideScalingMode(-1), + transform(0), + transformToDisplayInverse(false), + crop(Rect::INVALID_RECT), + orientedDisplaySpaceRect(Rect::INVALID_RECT), + dataspace(ui::Dataspace::UNKNOWN), + surfaceDamageRegion(), + api(-1), + colorTransform(mat4()), + bgColorAlpha(0), + bgColorDataspace(ui::Dataspace::UNKNOWN), + colorSpaceAgnostic(false), + shadowRadius(0.0f), + frameRateSelectionPriority(-1), + frameRate(0.0f), + frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), + fixedTransformHint(ui::Transform::ROT_INVALID), + frameNumber(0) { + matrix.dsdx = matrix.dtdy = 1.0f; + matrix.dsdy = matrix.dtdx = 0.0f; + hdrMetadata.validTypes = 0; +} + status_t layer_state_t::write(Parcel& output) const { SAFE_PARCEL(output.writeStrongBinder, surface); @@ -44,13 +83,13 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeUint32, mask); SAFE_PARCEL(matrix.write, output); SAFE_PARCEL(output.write, crop_legacy); - SAFE_PARCEL(output.writeStrongBinder, barrierHandle_legacy); - SAFE_PARCEL(output.writeStrongBinder, reparentHandle); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, barrierSurfaceControl_legacy); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, reparentSurfaceControl); SAFE_PARCEL(output.writeUint64, barrierFrameNumber); SAFE_PARCEL(output.writeInt32, overrideScalingMode); SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(barrierGbp_legacy)); - SAFE_PARCEL(output.writeStrongBinder, relativeLayerHandle); - SAFE_PARCEL(output.writeStrongBinder, parentHandleForChild); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl); + SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild); SAFE_PARCEL(output.writeFloat, color.r); SAFE_PARCEL(output.writeFloat, color.g); SAFE_PARCEL(output.writeFloat, color.b); @@ -135,8 +174,8 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(matrix.read, input); SAFE_PARCEL(input.read, crop_legacy); - SAFE_PARCEL(input.readNullableStrongBinder, &barrierHandle_legacy); - SAFE_PARCEL(input.readNullableStrongBinder, &reparentHandle); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &barrierSurfaceControl_legacy); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &reparentSurfaceControl); SAFE_PARCEL(input.readUint64, &barrierFrameNumber); SAFE_PARCEL(input.readInt32, &overrideScalingMode); @@ -144,9 +183,10 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); barrierGbp_legacy = interface_cast(tmpBinder); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl); + SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild); + float tmpFloat = 0; - SAFE_PARCEL(input.readNullableStrongBinder, &relativeLayerHandle); - SAFE_PARCEL(input.readNullableStrongBinder, &parentHandleForChild); SAFE_PARCEL(input.readFloat, &tmpFloat); color.r = tmpFloat; SAFE_PARCEL(input.readFloat, &tmpFloat); @@ -342,7 +382,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eDeferTransaction_legacy) { what |= eDeferTransaction_legacy; - barrierHandle_legacy = other.barrierHandle_legacy; + barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy; barrierGbp_legacy = other.barrierGbp_legacy; barrierFrameNumber = other.barrierFrameNumber; } @@ -352,7 +392,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eReparentChildren) { what |= eReparentChildren; - reparentHandle = other.reparentHandle; + reparentSurfaceControl = other.reparentSurfaceControl; } if (other.what & eDetachChildren) { what |= eDetachChildren; @@ -361,11 +401,11 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eRelativeLayerChanged; what &= ~eLayerChanged; z = other.z; - relativeLayerHandle = other.relativeLayerHandle; + relativeLayerSurfaceControl = other.relativeLayerSurfaceControl; } if (other.what & eReparent) { what |= eReparent; - parentHandleForChild = other.parentHandleForChild; + parentSurfaceControlForChild = other.parentSurfaceControlForChild; } if (other.what & eDestroySurface) { what |= eDestroySurface; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2f6a34bf4f..99d9ebaa92 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -875,8 +875,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer(const sp& sc, const sp& relativeTo, - int32_t z) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelativeLayer( + const sp& sc, const sp& relativeTo, int32_t z) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; @@ -884,7 +884,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat } s->what |= layer_state_t::eRelativeLayerChanged; s->what &= ~layer_state_t::eLayerChanged; - s->relativeLayerHandle = relativeTo; + s->relativeLayerSurfaceControl = relativeTo; s->z = z; registerSurfaceControlForCallback(sc); @@ -1028,16 +1028,16 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackg } SurfaceComposerClient::Transaction& -SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, - const sp& handle, - uint64_t frameNumber) { +SurfaceComposerClient::Transaction::deferTransactionUntil_legacy( + const sp& sc, const sp& barrierSurfaceControl, + uint64_t frameNumber) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->what |= layer_state_t::eDeferTransaction_legacy; - s->barrierHandle_legacy = handle; + s->barrierSurfaceControl_legacy = barrierSurfaceControl; s->barrierFrameNumber = frameNumber; registerSurfaceControlForCallback(sc); @@ -1062,30 +1062,28 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, - const sp& newParentHandle) { + const sp& sc, const sp& newParent) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->what |= layer_state_t::eReparentChildren; - s->reparentHandle = newParentHandle; + s->reparentSurfaceControl = newParent; registerSurfaceControlForCallback(sc); return *this; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparent( - const sp& sc, - const sp& newParentHandle) { + const sp& sc, const sp& newParent) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } s->what |= layer_state_t::eReparent; - s->parentHandleForChild = newParentHandle; + s->parentSurfaceControlForChild = newParent; registerSurfaceControlForCallback(sc); return *this; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index e37ff890b0..e842382ded 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 65fd9ab588..06598e1fad 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -49,6 +49,7 @@ #include #include +#include #include #include #include @@ -128,44 +129,7 @@ struct layer_state_t { eFrameNumberChanged = 0x400'00000000, }; - layer_state_t() - : what(0), - x(0), - y(0), - z(0), - w(0), - h(0), - layerStack(0), - alpha(0), - flags(0), - mask(0), - reserved(0), - crop_legacy(Rect::INVALID_RECT), - cornerRadius(0.0f), - backgroundBlurRadius(0), - barrierFrameNumber(0), - overrideScalingMode(-1), - transform(0), - transformToDisplayInverse(false), - crop(Rect::INVALID_RECT), - orientedDisplaySpaceRect(Rect::INVALID_RECT), - dataspace(ui::Dataspace::UNKNOWN), - surfaceDamageRegion(), - api(-1), - colorTransform(mat4()), - bgColorAlpha(0), - bgColorDataspace(ui::Dataspace::UNKNOWN), - colorSpaceAgnostic(false), - shadowRadius(0.0f), - frameRateSelectionPriority(-1), - frameRate(0.0f), - frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), - fixedTransformHint(ui::Transform::ROT_INVALID), - frameNumber(0) { - matrix.dsdx = matrix.dtdy = 1.0f; - matrix.dsdy = matrix.dtdx = 0.0f; - hdrMetadata.validTypes = 0; - } + layer_state_t(); void merge(const layer_state_t& other); status_t write(Parcel& output) const; @@ -196,16 +160,16 @@ struct layer_state_t { Rect crop_legacy; float cornerRadius; uint32_t backgroundBlurRadius; - sp barrierHandle_legacy; - sp reparentHandle; + sp barrierSurfaceControl_legacy; + sp reparentSurfaceControl; uint64_t barrierFrameNumber; int32_t overrideScalingMode; sp barrierGbp_legacy; - sp relativeLayerHandle; + sp relativeLayerSurfaceControl; - sp parentHandleForChild; + sp parentSurfaceControlForChild; half3 color; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index cc82502d4e..f366c2935d 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -424,7 +424,7 @@ public: // If the relative is removed, the Surface will have no layer and be // invisible, until the next time set(Relative)Layer is called. Transaction& setRelativeLayer(const sp& sc, - const sp& relativeTo, int32_t z); + const sp& relativeTo, int32_t z); Transaction& setFlags(const sp& sc, uint32_t flags, uint32_t mask); Transaction& setTransparentRegionHint(const sp& sc, @@ -444,7 +444,8 @@ public: // by handle is removed, then we will apply this transaction regardless of // what frame number has been reached. Transaction& deferTransactionUntil_legacy(const sp& sc, - const sp& handle, uint64_t frameNumber); + const sp& barrierSurfaceControl, + uint64_t frameNumber); // A variant of deferTransactionUntil_legacy which identifies the Layer we wait for by // Surface instead of Handle. Useful for clients which may not have the // SurfaceControl for some of their Surfaces. Otherwise behaves identically. @@ -453,13 +454,12 @@ public: uint64_t frameNumber); // Reparents all children of this layer to the new parent handle. Transaction& reparentChildren(const sp& sc, - const sp& newParentHandle); + const sp& newParent); /// Reparents the current layer to the new parent handle. The new parent must not be null. // This can be used instead of reparentChildren if the caller wants to // only re-parent a specific child. - Transaction& reparent(const sp& sc, - const sp& newParentHandle); + Transaction& reparent(const sp& sc, const sp& newParent); Transaction& setColor(const sp& sc, const half3& color); diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index c0dfcdb087..35bdfc155d 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -20,7 +20,6 @@ #include #include -#include #include #include diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index ef4d870ec7..483f171564 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -381,7 +381,7 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { childSurface->doTransaction([&](auto &t, auto &sc) { t.setPosition(sc, -5, -5); - t.reparent(sc, parentSurface->mSurfaceControl->getHandle()); + t.reparent(sc, parentSurface->mSurfaceControl); }); injectTap(106, 106); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 152d872aff..ce90f1cb14 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3298,7 +3298,7 @@ status_t SurfaceFlinger::setTransactionState( applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, desiredPresentTime, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, - /*isMainThread*/ false); + transactionId, /*isMainThread*/ false); return NO_ERROR; } @@ -3591,7 +3591,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( const auto& p = layer->getParent(); if (p == nullptr) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setRelativeLayer(s.relativeLayerHandle, s.z) && idx >= 0) { + if (layer->setRelativeLayer(s.relativeLayerSurfaceControl->getHandle(), s.z) && + idx >= 0) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) @@ -3599,7 +3600,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } else { - if (p->setChildRelativeLayer(layer, s.relativeLayerHandle, s.z)) { + if (p->setChildRelativeLayer(layer, s.relativeLayerSurfaceControl->getHandle(), s.z)) { flags |= eTransactionNeeded|eTraversalNeeded; } } @@ -3685,8 +3686,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eDeferTransaction_legacy) { - if (s.barrierHandle_legacy != nullptr) { - layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.barrierFrameNumber); + if (s.barrierSurfaceControl_legacy != nullptr) { + layer->deferTransactionUntil_legacy(s.barrierSurfaceControl_legacy->getHandle(), + s.barrierFrameNumber); } else if (s.barrierGbp_legacy != nullptr) { const sp& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { @@ -3702,7 +3704,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( // changed, we don't want this to cause any more work } if (what & layer_state_t::eReparentChildren) { - if (layer->reparentChildren(s.reparentHandle)) { + if (layer->reparentChildren(s.reparentSurfaceControl->getHandle())) { flags |= eTransactionNeeded|eTraversalNeeded; } } @@ -3789,7 +3791,10 @@ uint32_t SurfaceFlinger::setClientStateLocked( // lose its relative z order. if (what & layer_state_t::eReparent) { bool hadParent = layer->hasParent(); - if (layer->reparent(s.parentHandleForChild)) { + auto parentHandle = (s.parentSurfaceControlForChild) + ? s.parentSurfaceControlForChild->getHandle() + : nullptr; + if (layer->reparent(parentHandle)) { if (!hadParent) { mCurrentState.layersSortedByZ.remove(layer); } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 4407f4c1da..2687313733 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -472,9 +472,10 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, } if (state.what & layer_state_t::eDeferTransaction_legacy) { sp otherLayer = nullptr; - if (state.barrierHandle_legacy != nullptr) { - otherLayer = - static_cast(state.barrierHandle_legacy.get())->owner.promote(); + if (state.barrierSurfaceControl_legacy != nullptr) { + otherLayer = static_cast( + state.barrierSurfaceControl_legacy->getHandle().get()) + ->owner.promote(); } else if (state.barrierGbp_legacy != nullptr) { auto const& gbp = state.barrierGbp_legacy; if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { @@ -489,17 +490,23 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); } if (state.what & layer_state_t::eReparent) { - addReparentLocked(transaction, layerId, getLayerIdFromHandle(state.parentHandleForChild)); + auto parentHandle = (state.parentSurfaceControlForChild) + ? state.parentSurfaceControlForChild->getHandle() + : nullptr; + addReparentLocked(transaction, layerId, getLayerIdFromHandle(parentHandle)); } if (state.what & layer_state_t::eReparentChildren) { - addReparentChildrenLocked(transaction, layerId, getLayerIdFromHandle(state.reparentHandle)); + addReparentChildrenLocked(transaction, layerId, + getLayerIdFromHandle(state.reparentSurfaceControl->getHandle())); } if (state.what & layer_state_t::eDetachChildren) { addDetachChildrenLocked(transaction, layerId, true); } if (state.what & layer_state_t::eRelativeLayerChanged) { addRelativeParentLocked(transaction, layerId, - getLayerIdFromHandle(state.relativeLayerHandle), state.z); + getLayerIdFromHandle( + state.relativeLayerSurfaceControl->getHandle()), + state.z); } if (state.what & layer_state_t::eShadowRadiusChanged) { addShadowRadiusLocked(transaction, layerId, state.shadowRadius); diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp index 3261308560..9c7b1fcc04 100644 --- a/services/surfaceflinger/tests/DetachChildren_test.cpp +++ b/services/surfaceflinger/tests/DetachChildren_test.cpp @@ -61,7 +61,7 @@ TEST_F(DetachChildren, RelativesAreNotDetached) { TransactionUtils::fillSurfaceRGBA8(relative, relativeColor); Transaction{} - .setRelativeLayer(relative, mMainSurface->getHandle(), 1) + .setRelativeLayer(relative, mMainSurface, 1) .setPosition(relative, relBounds.left, relBounds.top) .apply(); @@ -204,7 +204,7 @@ TEST_F(DetachChildren, DetachChildrenThenAttach) { .setLayer(newParentSurface, INT32_MAX - 1) .show(newParentSurface) .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top) - .reparent(childNewClient, newParentSurface->getHandle()) + .reparent(childNewClient, newParentSurface) .apply(); { mCapture = screenshot(); @@ -238,7 +238,7 @@ TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) { } Transaction() - .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(), + .deferTransactionUntil_legacy(childNewClient, mMainSurface, mMainSurface->getSurface()->getNextFrameNumber()) .apply(); Transaction().detachChildren(mMainSurface).apply(); @@ -290,7 +290,7 @@ TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) { Transaction().detachChildren(mMainSurface).apply(); Transaction() .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()}) - .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(), + .deferTransactionUntil_legacy(childNewClient, mMainSurface, mMainSurface->getSurface()->getNextFrameNumber()) .apply(); @@ -352,7 +352,7 @@ TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) { mCapture->expectColor(mMainSurfaceBounds, Color::BLACK); } - Transaction().reparent(mMainSurface, mBlackBgSurface->getHandle()).apply(); + Transaction().reparent(mMainSurface, mBlackBgSurface).apply(); { mCapture = screenshot(); mCapture->expectBorder(childBounds, mMainSurfaceColor); diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 83e5060830..494728953b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -211,16 +211,13 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) switch (layerType) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: - Transaction() - .setPosition(layerG, 16, 16) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); + Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() .setFrame(layerR, Rect(0, 0, 32, 32)) .setFrame(layerG, Rect(16, 16, 48, 48)) - .setRelativeLayer(layerG, layerR->getHandle(), 1) + .setRelativeLayer(layerG, layerR, 1) .apply(); break; default: @@ -233,7 +230,7 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN); } - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply(); + Transaction().setRelativeLayer(layerG, layerR, -1).apply(); { SCOPED_TRACE("layerG below"); auto shot = getScreenCapture(); @@ -266,7 +263,7 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) case ISurfaceComposerClient::eFXSurfaceBufferQueue: Transaction() .setPosition(layerG, 8, 8) - .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setRelativeLayer(layerG, layerR, 3) .setPosition(layerB, 16, 16) .setLayer(layerB, mLayerZBase + 2) .apply(); @@ -275,7 +272,7 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) Transaction() .setFrame(layerR, Rect(0, 0, 32, 32)) .setFrame(layerG, Rect(8, 8, 40, 40)) - .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setRelativeLayer(layerG, layerR, 3) .setFrame(layerB, Rect(16, 16, 48, 48)) .setLayer(layerB, mLayerZBase + 2) .apply(); @@ -303,7 +300,7 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) } // layerR = 4, layerG = layerR - 3, layerB = 2 - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply(); + Transaction().setRelativeLayer(layerG, layerR, -3).apply(); { SCOPED_TRACE("layerB < (layerG < layerR)"); auto shot = getScreenCapture(); @@ -810,7 +807,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetColorWithParentAlpha_Bug74220420) { // channel) should be less than one const uint8_t tolerance = 1; Transaction() - .reparent(colorLayer, parentLayer->getHandle()) + .reparent(colorLayer, parentLayer) .setColor(colorLayer, color) .setAlpha(parentLayer, alpha) .setLayer(parentLayer, mLayerZBase + 1) @@ -1225,7 +1222,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().reparent(child, parent->getHandle()).apply(); + Transaction().reparent(child, parent).apply(); // A layer will default to the frame of its parent auto shot = getScreenCapture(); @@ -1242,7 +1239,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().reparent(child, parent->getHandle()).apply(); + Transaction().reparent(child, parent).apply(); // A layer will default to the frame of its parent auto shot = getScreenCapture(); @@ -1272,7 +1269,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - Transaction().reparent(child, parent->getHandle()).apply(); + Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index 8d715e1597..ef992d6a40 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -50,7 +50,7 @@ TEST_F(LayerTransactionTest, ReparentToSelf) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - Transaction().reparent(layer, layer->getHandle()).apply(); + Transaction().reparent(layer, layer).apply(); { // We expect the transaction to be silently dropped, but for SurfaceFlinger diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index 7d4314f4df..c57ad4364a 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -87,10 +87,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetRelativeZBug64572777) { ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - Transaction() - .setPosition(layerG, 16, 16) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); + Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); Transaction().reparent(layerG, nullptr).apply(); @@ -154,10 +151,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZNegative) { ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - Transaction() - .reparent(layerR, parent->getHandle()) - .reparent(layerG, parent->getHandle()) - .apply(); + Transaction().reparent(layerR, parent).reparent(layerG, parent).apply(); Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); { SCOPED_TRACE("layerR"); @@ -241,7 +235,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { auto transaction = Transaction() .setCornerRadius(parent, cornerRadius) .setCrop_legacy(parent, Rect(0, 0, size, size)) - .reparent(child, parent->getHandle()) + .reparent(child, parent) .setPosition(child, 0, size) // Rotate by half PI .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); @@ -283,14 +277,14 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { Transaction() .setCornerRadius(parent, cornerRadius) .setCrop_legacy(parent, Rect(0, 0, size, size)) - .reparent(child, parent->getHandle()) + .reparent(child, parent) .setPosition(child, 0, size / 2) .apply(); } else { Transaction() .setCornerRadius(parent, cornerRadius) .setFrame(parent, Rect(0, 0, size, size)) - .reparent(child, parent->getHandle()) + .reparent(child, parent) .setFrame(child, Rect(0, size / 2, size, size)) .apply(); } diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp index ab74c50323..f8a0bc1124 100644 --- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp @@ -54,10 +54,10 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); - Transaction().reparent(layerB, parent->getHandle()).apply(); + Transaction().reparent(layerB, parent).apply(); // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); + Transaction().setRelativeLayer(layerG, layerR, -1).setLayer(layerB, -2).apply(); std::unique_ptr screenshot; // only layerB is in this range @@ -88,10 +88,7 @@ TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) { .setCrop_legacy(childLayer, Rect(0, 0, 20, 30)) .apply(); - Transaction() - .setRelativeLayer(childLayer, parent->getHandle(), -1) - .setLayer(childLayer, 1) - .apply(); + Transaction().setRelativeLayer(childLayer, parent, -1).setLayer(childLayer, 1).apply(); { SCOPED_TRACE("setLayer above"); @@ -101,10 +98,7 @@ TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) { screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); } - Transaction() - .setLayer(childLayer, 1) - .setRelativeLayer(childLayer, parent->getHandle(), -1) - .apply(); + Transaction().setLayer(childLayer, 1).setRelativeLayer(childLayer, parent, -1).apply(); { SCOPED_TRACE("setRelative below"); @@ -141,7 +135,7 @@ TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) { .setLayer(relativeParent, mLayerZBase) .apply(); - Transaction().setRelativeLayer(childLayer, relativeParent->getHandle(), 1).apply(); + Transaction().setRelativeLayer(childLayer, relativeParent, 1).apply(); { SCOPED_TRACE("setLayer above"); diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index c56d473394..38da0b195b 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -173,13 +173,13 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { // set up two deferred transactions on different frames asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl, mSyncSurfaceControl->getSurface()->getNextFrameNumber()); }); asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl, mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); }); @@ -480,9 +480,8 @@ TEST_F(ChildLayerTest, ReparentChildren) { mCapture->expectFGColor(84, 84); } - asTransaction([&](Transaction& t) { - t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle()); - }); + asTransaction( + [&](Transaction& t) { t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl); }); { mCapture = screenshot(); @@ -516,7 +515,7 @@ TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { mCapture->expectFGColor(64, 64); } - asTransaction([&](Transaction& t) { t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); }); + asTransaction([&](Transaction& t) { t.reparent(mGrandChild, mFGSurfaceControl); }); { SCOPED_TRACE("After reparenting grandchild"); @@ -531,9 +530,7 @@ TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) { TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111); // draw grand child behind the foreground surface - asTransaction([&](Transaction& t) { - t.setRelativeLayer(mGrandChild, mFGSurfaceControl->getHandle(), -1); - }); + asTransaction([&](Transaction& t) { t.setRelativeLayer(mGrandChild, mFGSurfaceControl, -1); }); { SCOPED_TRACE("Child visible"); @@ -543,7 +540,7 @@ TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) { asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); - t.reparentChildren(mChild, mFGSurfaceControl->getHandle()); + t.reparentChildren(mChild, mFGSurfaceControl); }); { @@ -739,7 +736,7 @@ TEST_F(ChildLayerTest, Bug36858924) { // Show the child layer in a deferred transaction asTransaction([&](Transaction& t) { - t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl, mFGSurfaceControl->getSurface()->getNextFrameNumber()); t.show(mChild); }); @@ -776,7 +773,7 @@ TEST_F(ChildLayerTest, Reparent) { mCapture->expectFGColor(84, 84); } - asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); }); + asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl); }); { mCapture = screenshot(); @@ -838,7 +835,7 @@ TEST_F(ChildLayerTest, ReparentFromNoParent) { mCapture->checkPixel(10, 10, 63, 195, 63); } - asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); }); + asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl); }); { mCapture = screenshot(); @@ -869,7 +866,7 @@ TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { Transaction t; t.setLayer(relative, INT32_MAX) - .setRelativeLayer(mChild, relative->getHandle(), 1) + .setRelativeLayer(mChild, relative, 1) .setPosition(mFGSurfaceControl, 0, 0) .apply(true); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index b49bd54599..16826c1f61 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -68,7 +68,7 @@ TEST_F(MirrorLayerTest, MirrorColorLayer) { // Add mirrorLayer as child of mParentLayer so it's shown on the display Transaction() - .reparent(mirrorLayer, mParentLayer->getHandle()) + .reparent(mirrorLayer, mParentLayer) .setPosition(mirrorLayer, 500, 500) .show(mirrorLayer) .apply(); @@ -127,7 +127,7 @@ TEST_F(MirrorLayerTest, MirrorColorLayer) { } // Add grandchild layer to offscreen layer - Transaction().reparent(grandchild, mChildLayer->getHandle()).apply(); + Transaction().reparent(grandchild, mChildLayer).apply(); { SCOPED_TRACE("Added Grandchild Layer"); auto shot = screenshot(); @@ -138,7 +138,7 @@ TEST_F(MirrorLayerTest, MirrorColorLayer) { } // Add child layer - Transaction().reparent(mChildLayer, mParentLayer->getHandle()).apply(); + Transaction().reparent(mChildLayer, mParentLayer).apply(); { SCOPED_TRACE("Added Child Layer"); auto shot = screenshot(); @@ -157,7 +157,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { sp mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); Transaction() - .reparent(mirrorLayer, mParentLayer->getHandle()) + .reparent(mirrorLayer, mParentLayer) .setPosition(mirrorLayer, 500, 500) .show(mirrorLayer) .apply(); diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp index 3e0b3c64e7..fde6e6eff8 100644 --- a/services/surfaceflinger/tests/RelativeZ_test.cpp +++ b/services/surfaceflinger/tests/RelativeZ_test.cpp @@ -70,10 +70,7 @@ TEST_F(RelativeZTest, LayerRemoved) { sp childLayer = createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get()); - Transaction{} - .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1) - .show(childLayer) - .apply(); + Transaction{}.setRelativeLayer(childLayer, mForegroundLayer, 1).show(childLayer).apply(); { // The childLayer should be in front of the FG control. @@ -88,7 +85,7 @@ TEST_F(RelativeZTest, LayerRemoved) { // Background layer (RED) // Child layer (WHITE) // Foregroud layer (GREEN) - Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply(); + Transaction{}.reparent(childLayer, mBackgroundLayer).apply(); { // The relative z info for child layer should be reset, leaving FG control on top. @@ -118,7 +115,7 @@ TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { createColorLayer("child level 3", Color::GREEN, childLevel2a.get()); Transaction{} - .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1) + .setRelativeLayer(childLevel3, childLevel2b, 1) .show(childLevel2a) .show(childLevel2b) .show(childLevel3) @@ -140,7 +137,7 @@ TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { // child level 2 back (BLUE) // child level 3 (GREEN) (relative to child level 2b) // child level 2 front (BLACK) - Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply(); + Transaction{}.reparent(childLevel1, mForegroundLayer).apply(); { // Nothing should change at this point since relative z info was preserved. @@ -162,7 +159,7 @@ TEST_F(RelativeZTest, LayerAndRelativeRemoved) { createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get()); Transaction{} - .setRelativeLayer(childLayer, relativeToLayer->getHandle(), 1) + .setRelativeLayer(childLayer, relativeToLayer, 1) .show(childLayer) .show(relativeToLayer) .apply(); @@ -199,7 +196,7 @@ TEST_F(RelativeZTest, LayerAndRelativeRemoved) { // Background layer (RED) // Foregroud layer (GREEN) // Child layer (BLUE) - Transaction{}.reparent(childLayer, mForegroundLayer->getHandle()).apply(); + Transaction{}.reparent(childLayer, mForegroundLayer).apply(); { // The relative z info for child layer should be reset, leaving the child layer on top. @@ -230,7 +227,7 @@ TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) { createColorLayer("child level 2b", Color::BLACK, childLevel1b.get()); Transaction{} - .setRelativeLayer(childLevel1a, childLevel2b->getHandle(), 1) + .setRelativeLayer(childLevel1a, childLevel2b, 1) .show(childLevel1a) .show(childLevel1b) .show(childLevel2a) @@ -250,7 +247,7 @@ TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) { // // Background layer (RED) // // Foregroud layer (GREEN) - Transaction{}.reparent(childLevel1a, childLevel2a->getHandle()).apply(); + Transaction{}.reparent(childLevel1a, childLevel2a).apply(); { // The childLevel1a and childLevel1b are no longer on screen @@ -264,7 +261,7 @@ TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) { // child level 2a (BLUE) // child level 1a (testLayerColor) (relative to child level 2b) // child level 2b (BLACK) - Transaction{}.reparent(childLevel1b, mForegroundLayer->getHandle()).apply(); + Transaction{}.reparent(childLevel1b, mForegroundLayer).apply(); { // Nothing should change at this point since relative z info was preserved. diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 3ab2ad183c..e1739968c0 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -239,7 +239,7 @@ TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { SurfaceComposerClient::Transaction() .show(child) // Set relative layer above fg layer so should be shown above when computing all layers. - .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1) + .setRelativeLayer(relative, mFGSurfaceControl, 1) .show(relative) .apply(true); @@ -264,7 +264,7 @@ TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { // Set relative layer below fg layer but relative to child layer so it should be shown // above child layer. .setLayer(relative, -1) - .setRelativeLayer(relative, child->getHandle(), 1) + .setRelativeLayer(relative, child, 1) .show(relative) .apply(true); @@ -707,7 +707,7 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithUid) { .setLayer(layerWithFakeUid, INT32_MAX) .setPosition(layerWithFakeUid, 128, 128) // reparent a layer that was created with a different uid to the new layer. - .reparent(layer, layerWithFakeUid->getHandle()) + .reparent(layer, layerWithFakeUid) .apply(); // Screenshot from the fakeUid caller with the uid requested allows the layer diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8570032aae..104d919216 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -397,16 +397,15 @@ void SurfaceInterceptorTest::secureFlagUpdate(Transaction& t) { } void SurfaceInterceptorTest::deferredTransactionUpdate(Transaction& t) { - t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl->getHandle(), - DEFERRED_UPDATE); + t.deferTransactionUntil_legacy(mBGSurfaceControl, mBGSurfaceControl, DEFERRED_UPDATE); } void SurfaceInterceptorTest::reparentUpdate(Transaction& t) { - t.reparent(mBGSurfaceControl, mFGSurfaceControl->getHandle()); + t.reparent(mBGSurfaceControl, mFGSurfaceControl); } void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) { - t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl->getHandle(), RELATIVE_Z); + t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z); } void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) { @@ -414,7 +413,7 @@ void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) { } void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) { - t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl->getHandle()); + t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl); } void SurfaceInterceptorTest::shadowRadiusUpdate(Transaction& t) { diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 87fc08a828..07c558f342 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1322,7 +1322,7 @@ protected: { TransactionScope ts(*sFakeComposer); ts.setAlpha(mFGSurfaceControl, 0.75); - ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl, syncSurfaceControl->getSurface()->getNextFrameNumber()); } EXPECT_TRUE(framesAreSame(referenceFrame, sFakeComposer->getLatestFrame())); @@ -1330,7 +1330,7 @@ protected: { TransactionScope ts(*sFakeComposer); ts.setPosition(mFGSurfaceControl, 128, 128); - ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl->getHandle(), + ts.deferTransactionUntil_legacy(mFGSurfaceControl, syncSurfaceControl, syncSurfaceControl->getSurface()->getNextFrameNumber() + 1); } @@ -1376,7 +1376,7 @@ protected: TransactionScope ts(*sFakeComposer); ts.setPosition(relativeSurfaceControl, 64, 64); ts.show(relativeSurfaceControl); - ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl->getHandle(), 1); + ts.setRelativeLayer(relativeSurfaceControl, mFGSurfaceControl, 1); } auto referenceFrame = mBaseFrame; // NOTE: All three layers will be visible as the surfaces are @@ -1606,7 +1606,7 @@ protected: { TransactionScope ts(*Base::sFakeComposer); - ts.reparentChildren(Base::mFGSurfaceControl, Base::mBGSurfaceControl->getHandle()); + ts.reparentChildren(Base::mFGSurfaceControl, Base::mBGSurfaceControl); } auto referenceFrame2 = referenceFrame; @@ -1761,7 +1761,7 @@ protected: // Show the child layer in a deferred transaction { TransactionScope ts(*Base::sFakeComposer); - ts.deferTransactionUntil_legacy(mChild, Base::mFGSurfaceControl->getHandle(), + ts.deferTransactionUntil_legacy(mChild, Base::mFGSurfaceControl, Base::mFGSurfaceControl->getSurface() ->getNextFrameNumber()); ts.show(mChild); -- cgit v1.2.3-59-g8ed1b From c351d6fc5c58cbb2449692eb368f21c3ca23e36d Mon Sep 17 00:00:00 2001 From: Pablo Gamito Date: Thu, 17 Sep 2020 15:34:26 +0000 Subject: Remove barrierGbp_legacy from layer state BarrierGbp is no longer used, so we can remove it to make it possible to dump all LayerState data exclusively on the client side without requiring access to Surface Flinger Test: Existing tests Change-Id: Ib1465f57ff8d39d12abfe35548c0106b434d2acf --- libs/gui/LayerState.cpp | 7 +------ libs/gui/SurfaceComposerClient.cpp | 17 ----------------- libs/gui/include/gui/LayerState.h | 2 -- libs/gui/include/gui/SurfaceComposerClient.h | 6 ------ services/surfaceflinger/SurfaceFlinger.cpp | 18 +++--------------- .../surfaceflinger/SurfaceFlingerDefaultFactory.cpp | 4 ++-- services/surfaceflinger/SurfaceFlingerDefaultFactory.h | 2 +- services/surfaceflinger/SurfaceFlingerFactory.h | 2 +- services/surfaceflinger/SurfaceInterceptor.cpp | 12 ------------ services/surfaceflinger/SurfaceInterceptor.h | 3 +-- .../tests/unittests/TestableSurfaceFlinger.h | 4 ++-- 11 files changed, 11 insertions(+), 66 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index a4de66e8a7..bde73bab2e 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -87,7 +87,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, reparentSurfaceControl); SAFE_PARCEL(output.writeUint64, barrierFrameNumber); SAFE_PARCEL(output.writeInt32, overrideScalingMode); - SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(barrierGbp_legacy)); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild); SAFE_PARCEL(output.writeFloat, color.r); @@ -179,10 +178,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readUint64, &barrierFrameNumber); SAFE_PARCEL(input.readInt32, &overrideScalingMode); - sp tmpBinder; - SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); - barrierGbp_legacy = interface_cast(tmpBinder); - SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild); @@ -230,6 +225,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float)); SAFE_PARCEL(input.readFloat, &cornerRadius); SAFE_PARCEL(input.readUint32, &backgroundBlurRadius); + sp tmpBinder; SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); cachedBuffer.token = tmpBinder; SAFE_PARCEL(input.readUint64, &cachedBuffer.id); @@ -383,7 +379,6 @@ void layer_state_t::merge(const layer_state_t& other) { if (other.what & eDeferTransaction_legacy) { what |= eDeferTransaction_legacy; barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy; - barrierGbp_legacy = other.barrierGbp_legacy; barrierFrameNumber = other.barrierFrameNumber; } if (other.what & eOverrideScalingModeChanged) { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 99d9ebaa92..0068ccfc65 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1044,23 +1044,6 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy( return *this; } -SurfaceComposerClient::Transaction& -SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const sp& sc, - const sp& barrierSurface, - uint64_t frameNumber) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eDeferTransaction_legacy; - s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); - s->barrierFrameNumber = frameNumber; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::reparentChildren( const sp& sc, const sp& newParent) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 06598e1fad..fed0ef3565 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -165,8 +165,6 @@ struct layer_state_t { uint64_t barrierFrameNumber; int32_t overrideScalingMode; - sp barrierGbp_legacy; - sp relativeLayerSurfaceControl; sp parentSurfaceControlForChild; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f366c2935d..277060fed0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -446,12 +446,6 @@ public: Transaction& deferTransactionUntil_legacy(const sp& sc, const sp& barrierSurfaceControl, uint64_t frameNumber); - // A variant of deferTransactionUntil_legacy which identifies the Layer we wait for by - // Surface instead of Handle. Useful for clients which may not have the - // SurfaceControl for some of their Surfaces. Otherwise behaves identically. - Transaction& deferTransactionUntil_legacy(const sp& sc, - const sp& barrierSurface, - uint64_t frameNumber); // Reparents all children of this layer to the new parent handle. Transaction& reparentChildren(const sp& sc, const sp& newParent); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ce90f1cb14..df87e3b1cf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -328,7 +328,7 @@ SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {} SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), - mInterceptor(mFactory.createSurfaceInterceptor(this)), + mInterceptor(mFactory.createSurfaceInterceptor()), mTimeStats(std::make_shared()), mFrameTracer(std::make_unique()), mFrameTimeline(std::make_unique()), @@ -3686,20 +3686,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } if (what & layer_state_t::eDeferTransaction_legacy) { - if (s.barrierSurfaceControl_legacy != nullptr) { - layer->deferTransactionUntil_legacy(s.barrierSurfaceControl_legacy->getHandle(), - s.barrierFrameNumber); - } else if (s.barrierGbp_legacy != nullptr) { - const sp& gbp = s.barrierGbp_legacy; - if (authenticateSurfaceTextureLocked(gbp)) { - const auto& otherLayer = - (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil_legacy(otherLayer, s.barrierFrameNumber); - } else { - ALOGE("Attempt to defer transaction to to an" - " unrecognized GraphicBufferProducer"); - } - } + layer->deferTransactionUntil_legacy(s.barrierSurfaceControl_legacy->getHandle(), + s.barrierFrameNumber); // We don't trigger a traversal here because if no other state is // changed, we don't want this to cause any more work } diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index 93d36a6c07..9a8deae67d 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -68,8 +68,8 @@ std::unique_ptr DefaultFactory::createScheduler( return std::make_unique(configs, callback); } -sp DefaultFactory::createSurfaceInterceptor(SurfaceFlinger* flinger) { - return new android::impl::SurfaceInterceptor(flinger); +sp DefaultFactory::createSurfaceInterceptor() { + return new android::impl::SurfaceInterceptor(); } sp DefaultFactory::createStartPropertySetThread( diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h index e06c2f49f1..40774ef108 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -32,7 +32,7 @@ public: const scheduler::RefreshRateConfigs&) override; std::unique_ptr createScheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&) override; - sp createSurfaceInterceptor(SurfaceFlinger*) override; + sp createSurfaceInterceptor() override; sp createStartPropertySetThread(bool timestampPropertyValue) override; sp createDisplayDevice(DisplayDeviceCreationArgs&) override; sp createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index 41ccc1011d..2dd563b416 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -73,7 +73,7 @@ public: const scheduler::RefreshRateConfigs&) = 0; virtual std::unique_ptr createScheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&) = 0; - virtual sp createSurfaceInterceptor(SurfaceFlinger*) = 0; + virtual sp createSurfaceInterceptor() = 0; virtual sp createStartPropertySetThread( bool timestampPropertyValue) = 0; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 2687313733..da58d4ea4d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -40,11 +40,6 @@ SurfaceInterceptor::~SurfaceInterceptor() = default; namespace impl { -SurfaceInterceptor::SurfaceInterceptor(SurfaceFlinger* flinger) - : mFlinger(flinger) -{ -} - void SurfaceInterceptor::addTransactionTraceListener( const sp& listener) { sp asBinder = IInterface::asBinder(listener); @@ -476,13 +471,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, otherLayer = static_cast( state.barrierSurfaceControl_legacy->getHandle().get()) ->owner.promote(); - } else if (state.barrierGbp_legacy != nullptr) { - auto const& gbp = state.barrierGbp_legacy; - if (mFlinger->authenticateSurfaceTextureLocked(gbp)) { - otherLayer = (static_cast(gbp.get()))->getLayer(); - } else { - ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); - } } addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 46284dfd0e..9ac189a492 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -92,7 +92,7 @@ namespace impl { */ class SurfaceInterceptor final : public android::SurfaceInterceptor { public: - explicit SurfaceInterceptor(SurfaceFlinger* const flinger); + SurfaceInterceptor() = default; ~SurfaceInterceptor() override = default; // Both vectors are used to capture the current state of SF as the initial snapshot in the trace @@ -202,7 +202,6 @@ private: std::string mOutputFileName {DEFAULT_FILENAME}; std::mutex mTraceMutex {}; Trace mTrace {}; - SurfaceFlinger* const mFlinger; std::mutex mListenersMutex; std::map, sp> mTraceToggledListeners GUARDED_BY(mListenersMutex); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 8c12e9400a..96e4f5bbec 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -83,8 +83,8 @@ public: return nullptr; } - sp createSurfaceInterceptor(SurfaceFlinger* flinger) override { - return new android::impl::SurfaceInterceptor(flinger); + sp createSurfaceInterceptor() override { + return new android::impl::SurfaceInterceptor(); } sp createStartPropertySetThread(bool timestampPropertyValue) override { -- cgit v1.2.3-59-g8ed1b From 916b036726e2e82f769405d25bf6b8248572246c Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 6 Oct 2020 13:53:03 -0700 Subject: SurfaceControl: Remove setOverrideScalingMode Following recent frameworks/base changes there are no callers. Bug: 161937501 Test: Existing tests pass Change-Id: I1a39d30ebd70a0b0cb430a6d1ae48086c3e1806e --- cmds/surfacereplayer/proto/src/trace.proto | 5 --- cmds/surfacereplayer/replayer/Replayer.cpp | 10 ----- cmds/surfacereplayer/replayer/Replayer.h | 2 - .../replayer/trace_creator/trace_creator.py | 9 ----- libs/gui/LayerState.cpp | 7 ---- libs/gui/SurfaceComposerClient.cpp | 29 ------------- libs/gui/include/gui/LayerState.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 5 --- services/surfaceflinger/BufferLayer.cpp | 4 -- services/surfaceflinger/BufferLayer.h | 3 +- services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 5 ++- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/Layer.cpp | 7 ---- services/surfaceflinger/Layer.h | 3 -- services/surfaceflinger/LayerRejecter.cpp | 5 +-- services/surfaceflinger/LayerRejecter.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 5 --- services/surfaceflinger/SurfaceInterceptor.cpp | 12 ------ services/surfaceflinger/SurfaceInterceptor.h | 2 - .../tests/LayerRenderTypeTransaction_test.cpp | 47 ---------------------- services/surfaceflinger/tests/LayerUpdate_test.cpp | 15 +++++-- .../tests/SurfaceInterceptor_test.cpp | 27 ------------- .../tests/fakehwc/SFFakeHwc_test.cpp | 28 ------------- 24 files changed, 23 insertions(+), 217 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index 6c3b79b2b9..bbf4f8dd38 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -41,7 +41,6 @@ message SurfaceChange { LayerChange layer = 5; CropChange crop = 6; MatrixChange matrix = 8; - OverrideScalingModeChange override_scaling_mode = 9; TransparentRegionHintChange transparent_region_hint = 10; LayerStackChange layer_stack = 11; HiddenFlagChange hidden_flag = 12; @@ -95,10 +94,6 @@ message MatrixChange { required float dtdy = 4; } -message OverrideScalingModeChange { - required int32 override_scaling_mode = 1; -} - message TransparentRegionHintChange { repeated Rectangle region = 1; } diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 86e4f5d773..c1868016d0 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -387,10 +387,6 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kMatrix: setMatrix(transaction, change.id(), change.matrix()); break; - case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: - setOverrideScalingMode(transaction, change.id(), - change.override_scaling_mode()); - break; case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint: setTransparentRegionHint(transaction, change.id(), change.transparent_region_hint()); @@ -525,12 +521,6 @@ void Replayer::setMatrix(SurfaceComposerClient::Transaction& t, t.setMatrix(mLayers[id], mc.dsdx(), mc.dtdx(), mc.dsdy(), mc.dtdy()); } -void Replayer::setOverrideScalingMode(SurfaceComposerClient::Transaction& t, - layer_id id, const OverrideScalingModeChange& osmc) { - ALOGV("Layer %d: Setting Override Scaling Mode -- mode=%d", id, osmc.override_scaling_mode()); - t.setOverrideScalingMode(mLayers[id], osmc.override_scaling_mode()); -} - void Replayer::setTransparentRegionHint(SurfaceComposerClient::Transaction& t, layer_id id, const TransparentRegionHintChange& trhc) { ALOGV("Setting Transparent Region Hint"); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 95857e1e5b..e439718bd6 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -98,8 +98,6 @@ class Replayer { layer_id id, const BackgroundBlurRadiusChange& cc); void setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc); - void setOverrideScalingMode(SurfaceComposerClient::Transaction& t, - layer_id id, const OverrideScalingModeChange& osmc); void setTransparentRegionHint(SurfaceComposerClient::Transaction& t, layer_id id, const TransparentRegionHintChange& trgc); void setLayerStack(SurfaceComposerClient::Transaction& t, diff --git a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py index d63d97f6b4..58bfbf3c43 100644 --- a/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py +++ b/cmds/surfacereplayer/replayer/trace_creator/trace_creator.py @@ -69,7 +69,6 @@ def transaction_menu(): print ("5. Crop Change") print ("6. Final Crop Change") print ("7. Matrix Change") - print ("8. Override Scaling Mode Change") print ("9. Transparent Region Hint Change") print ("10. Layer Stack Change") print ("11. Hidden Flag Change") @@ -128,9 +127,6 @@ def transaction(increment): change.matrix.dtdx,\ change.matrix.dsdy,\ change.matrix.dtdy = layer() - elif option == 8: - change.override_scaling_mode.override_scaling_mode \ - = override_scaling_mode() elif option == 9: for rect in transparent_region_hint(): new = increment.transparent_region_hint.region.add() @@ -227,11 +223,6 @@ def matrix(): return float(dsdx) -def override_scaling_mode(): - mode = input("Enter override scaling mode: ") - - return int(mode) - def transparent_region_hint(): num = input("Enter number of rectangles in region: ") diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index bde73bab2e..ed5ad3f4ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -44,7 +44,6 @@ layer_state_t::layer_state_t() cornerRadius(0.0f), backgroundBlurRadius(0), barrierFrameNumber(0), - overrideScalingMode(-1), transform(0), transformToDisplayInverse(false), crop(Rect::INVALID_RECT), @@ -86,7 +85,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, barrierSurfaceControl_legacy); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, reparentSurfaceControl); SAFE_PARCEL(output.writeUint64, barrierFrameNumber); - SAFE_PARCEL(output.writeInt32, overrideScalingMode); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::writeNullableToParcel, output, parentSurfaceControlForChild); SAFE_PARCEL(output.writeFloat, color.r); @@ -176,7 +174,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &barrierSurfaceControl_legacy); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &reparentSurfaceControl); SAFE_PARCEL(input.readUint64, &barrierFrameNumber); - SAFE_PARCEL(input.readInt32, &overrideScalingMode); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &relativeLayerSurfaceControl); SAFE_PARCEL(SurfaceControl::readNullableFromParcel, input, &parentSurfaceControlForChild); @@ -381,10 +378,6 @@ void layer_state_t::merge(const layer_state_t& other) { barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy; barrierFrameNumber = other.barrierFrameNumber; } - if (other.what & eOverrideScalingModeChanged) { - what |= eOverrideScalingModeChanged; - overrideScalingMode = other.overrideScalingMode; - } if (other.what & eReparentChildren) { what |= eReparentChildren; reparentSurfaceControl = other.reparentSurfaceControl; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0068ccfc65..105969bd42 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1353,35 +1353,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachCh return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverrideScalingMode( - const sp& sc, int32_t overrideScalingMode) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - - switch (overrideScalingMode) { - case NATIVE_WINDOW_SCALING_MODE_FREEZE: - case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: - case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: - case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: - case -1: - break; - default: - ALOGE("unknown scaling mode: %d", - overrideScalingMode); - mStatus = BAD_VALUE; - return *this; - } - - s->what |= layer_state_t::eOverrideScalingModeChanged; - s->overrideScalingMode = overrideScalingMode; - - registerSurfaceControlForCallback(sc); - return *this; -} - #ifndef NO_INPUT SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( const sp& sc, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index fed0ef3565..1d282c8dc5 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -94,7 +94,7 @@ struct layer_state_t { eLayerStackChanged = 0x00000080, eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, - eOverrideScalingModeChanged = 0x00000400, + /* was ScalingModeChanged, now available 0x00000400, */ eShadowRadiusChanged = 0x00000800, eReparentChildren = 0x00001000, eDetachChildren = 0x00002000, @@ -163,7 +163,6 @@ struct layer_state_t { sp barrierSurfaceControl_legacy; sp reparentSurfaceControl; uint64_t barrierFrameNumber; - int32_t overrideScalingMode; sp relativeLayerSurfaceControl; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 277060fed0..ce1a0a5f30 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -501,11 +501,6 @@ public: // Sometimes the WindowManager needs to extend their lifetime slightly // in order to perform an exit animation or prevent flicker. Transaction& detachChildren(const sp& sc); - // Set an override scaling mode as documented in - // the override scaling mode will take precedence over any client - // specified scaling mode. -1 will clear the override scaling mode. - Transaction& setOverrideScalingMode(const sp& sc, - int32_t overrideScalingMode); #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index c77298e161..9c3fdbb405 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -527,10 +527,6 @@ bool BufferLayer::hasReadyFrame() const { } uint32_t BufferLayer::getEffectiveScalingMode() const { - if (mOverrideScalingMode >= 0) { - return mOverrideScalingMode; - } - return mBufferInfo.mScaleMode; } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 1cd753b65b..e6a0f81622 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -94,8 +94,7 @@ public: bool hasReadyFrame() const override; - // Returns the current scaling mode, unless mOverrideScalingMode - // is set, in which case, it returns mOverrideScalingMode + // Returns the current scaling mode uint32_t getEffectiveScalingMode() const override; // Calls latchBuffer if the buffer has a frame queued and then releases the buffer. diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 0863a22659..ec828d435b 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -239,7 +239,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t bool queuedBuffer = false; const int32_t layerId = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName, mOverrideScalingMode, + getProducerStickyTransform() != 0, mName, getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 361c1f3f98..9a4571805d 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -48,7 +48,6 @@ const std::array BufferStateLayer::IDENTITY_MATRIX{ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { - mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mCurrentState.dataspace = ui::Dataspace::V0_SRGB; } @@ -681,6 +680,10 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); } +uint32_t BufferStateLayer::getEffectiveScalingMode() const { + return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; +} + Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { return s.buffer->getBounds(); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index c13f5e8252..4773286e44 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -92,7 +92,6 @@ public: return false; } bool setCrop_legacy(const Rect& /*crop*/) override { return false; } - bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -110,6 +109,7 @@ public: bool fenceHasSignaled() const override; bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; bool onPreComposition(nsecs_t refreshStartTime) override; + uint32_t getEffectiveScalingMode() const override; protected: void gatherBufferInfo() override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a79cbe455a..5616bbac59 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1295,13 +1295,6 @@ bool Layer::setCrop_legacy(const Rect& crop) { return true; } -bool Layer::setOverrideScalingMode(int32_t scalingMode) { - if (scalingMode == mOverrideScalingMode) return false; - mOverrideScalingMode = scalingMode; - setTransactionFlags(eTransactionNeeded); - return true; -} - bool Layer::setMetadata(const LayerMetadata& data) { if (!mCurrentState.metadata.merge(data, true /* eraseEmpty */)) return false; mCurrentState.sequence++; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 02593d57ef..51e392aa30 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -341,7 +341,6 @@ public: // // The first set of geometry functions are controlled by the scaling mode, described // in window.h. The scaling mode may be set by the client, as it submits buffers. - // This value may be overriden through SurfaceControl, with setOverrideScalingMode. // // Put simply, if our scaling mode is SCALING_MODE_FREEZE, then // matrix updates will not be applied while a resize is pending @@ -399,7 +398,6 @@ public: virtual void deferTransactionUntil_legacy(const sp& barrierHandle, uint64_t frameNumber); virtual void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); - virtual bool setOverrideScalingMode(int32_t overrideScalingMode); virtual bool setMetadata(const LayerMetadata& data); virtual void setChildrenDrawingParent(const sp&); virtual bool reparent(const sp& newParentHandle); @@ -1003,7 +1001,6 @@ protected: bool mIsActiveBufferUpdatedForGpu = true; // We encode unset as -1. - int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index e6c8654cbf..053b7f741e 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -29,13 +29,12 @@ namespace android { LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions, bool stickySet, const std::string& name, - int32_t overrideScalingMode, bool transformToDisplayInverse) + bool transformToDisplayInverse) : mFront(front), mCurrent(current), mRecomputeVisibleRegions(recomputeVisibleRegions), mStickyTransformSet(stickySet), mName(name), - mOverrideScalingMode(overrideScalingMode), mTransformToDisplayInverse(transformToDisplayInverse) {} bool LayerRejecter::reject(const sp& buf, const BufferItem& item) { @@ -59,7 +58,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) } } - int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode; + int actualScalingMode = item.mScalingMode; bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; if (mFront.active_legacy != mFront.requested_legacy) { if (isFixedSize || diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index fb5c750571..4981f451d9 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -24,7 +24,7 @@ namespace android { class LayerRejecter : public BufferLayerConsumer::BufferRejecter { public: LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions, - bool stickySet, const std::string& name, int32_t overrideScalingMode, + bool stickySet, const std::string& name, bool transformToDisplayInverse); virtual bool reject(const sp&, const BufferItem&); @@ -35,7 +35,6 @@ private: bool& mRecomputeVisibleRegions; const bool mStickyTransformSet; const std::string& mName; - const int32_t mOverrideScalingMode; const bool mTransformToDisplayInverse; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7edbcaa6b3..2f66d5b9e7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3703,11 +3703,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eDetachChildren) { layer->detachChildren(); } - if (what & layer_state_t::eOverrideScalingModeChanged) { - layer->setOverrideScalingMode(s.overrideScalingMode); - // We don't trigger a traversal here because if no other state is - // changed, we don't want this to cause any more work - } if (what & layer_state_t::eTransformChanged) { if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index da58d4ea4d..2d5566f42a 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -145,7 +145,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer->mCurrentState.barrierLayer_legacy.promote(), layer->mCurrentState.barrierFrameNumber); } - addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque | layer_state_t::eLayerSecure); @@ -376,14 +375,6 @@ void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int deferTransaction->set_frame_number(frameNumber); } -void SurfaceInterceptor::addOverrideScalingModeLocked(Transaction* transaction, - int32_t layerId, int32_t overrideScalingMode) -{ - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - OverrideScalingModeChange* overrideChange(change->mutable_override_scaling_mode()); - overrideChange->set_override_scaling_mode(overrideScalingMode); -} - void SurfaceInterceptor::addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); @@ -474,9 +465,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, } addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber); } - if (state.what & layer_state_t::eOverrideScalingModeChanged) { - addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); - } if (state.what & layer_state_t::eReparent) { auto parentHandle = (state.parentSurfaceControlForChild) ? state.parentSurfaceControlForChild->getHandle() diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 9ac189a492..97ff547547 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -167,8 +167,6 @@ private: int32_t backgroundBlurRadius); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber); - void addOverrideScalingModeLocked(Transaction* transaction, int32_t layerId, - int32_t overrideScalingMode); void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state); void addTransactionLocked(Increment* increment, const Vector& stateUpdates, const DefaultKeyedVector, DisplayDeviceState>& displays, diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 494728953b..52e1a4d967 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -179,19 +179,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition - Transaction() - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED); -} - TEST_P(LayerRenderTypeTransactionTest, CreateLayer_BufferState) { uint32_t transformHint = ui::Transform::ROT_INVALID; sp layer; @@ -950,40 +937,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithResize_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 128, 128), Color::RED); -} - -TEST_P(LayerRenderTypeTransactionTest, SetOverrideScalingModeBasic_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - // XXX SCALE_CROP is not respected; calling setSize and - // setOverrideScalingMode in separate transactions does not work - // (b/69315456) - Transaction() - .setSize(layer, 64, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - { - SCOPED_TRACE("SCALE_TO_WINDOW"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, true /* filtered */); - } -} - TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index 38da0b195b..0cafd001ff 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -566,7 +566,10 @@ TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { } asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + mFGSurfaceControl->getSurface()->setScalingMode( + NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // Resubmit buffer with new scaling mode + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); // We cause scaling by 2. t.setSize(mFGSurfaceControl, 128, 128); }); @@ -673,7 +676,10 @@ TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) { } asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + mFGSurfaceControl->getSurface()->setScalingMode( + NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // Resubmit buffer with new scaling mode + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); // Set a scaling by 2. t.setSize(mFGSurfaceControl, 128, 128); }); @@ -705,7 +711,10 @@ TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) { // Change the size of the foreground to 128 * 64 so we can test rotation as well. asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + mFGSurfaceControl->getSurface()->setScalingMode( + NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // Resubmit buffer with new scaling mode + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); t.setSize(mFGSurfaceControl, 128, 64); }); sp s = mFGSurfaceControl->getSurface(); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 104d919216..a5a569bb0f 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -39,7 +39,6 @@ using SurfaceChange = surfaceflinger::SurfaceChange; using Trace = surfaceflinger::Trace; using Increment = surfaceflinger::Increment; -constexpr int32_t SCALING_UPDATE = 1; constexpr uint32_t BUFFER_UPDATES = 18; constexpr uint32_t LAYER_UPDATE = INT_MAX - 2; constexpr uint32_t SIZE_UPDATE = 134; @@ -221,7 +220,6 @@ public: void cornerRadiusUpdate(Transaction&); void backgroundBlurRadiusUpdate(Transaction&); void matrixUpdate(Transaction&); - void overrideScalingModeUpdate(Transaction&); void transparentRegionHintUpdate(Transaction&); void layerStackUpdate(Transaction&); void hiddenFlagUpdate(Transaction&); @@ -371,10 +369,6 @@ void SurfaceInterceptorTest::matrixUpdate(Transaction& t) { t.setMatrix(mBGSurfaceControl, M_SQRT1_2, M_SQRT1_2, -M_SQRT1_2, M_SQRT1_2); } -void SurfaceInterceptorTest::overrideScalingModeUpdate(Transaction& t) { - t.setOverrideScalingMode(mBGSurfaceControl, SCALING_UPDATE); -} - void SurfaceInterceptorTest::transparentRegionHintUpdate(Transaction& t) { Region region(CROP_UPDATE); t.setTransparentRegionHint(mBGSurfaceControl, region); @@ -439,7 +433,6 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::layerUpdate); runInTransaction(&SurfaceInterceptorTest::cropUpdate); runInTransaction(&SurfaceInterceptorTest::matrixUpdate); - runInTransaction(&SurfaceInterceptorTest::overrideScalingModeUpdate); runInTransaction(&SurfaceInterceptorTest::transparentRegionHintUpdate); runInTransaction(&SurfaceInterceptorTest::layerStackUpdate); runInTransaction(&SurfaceInterceptorTest::hiddenFlagUpdate); @@ -561,17 +554,6 @@ bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool return foundMatrix; } -bool SurfaceInterceptorTest::scalingModeUpdateFound(const SurfaceChange& change, - bool foundScalingMode) { - bool hasScalingUpdate(change.override_scaling_mode().override_scaling_mode() == SCALING_UPDATE); - if (hasScalingUpdate && !foundScalingMode) { - foundScalingMode = true; - } else if (hasScalingUpdate && foundScalingMode) { - [] () { FAIL(); }(); - } - return foundScalingMode; -} - bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion) { auto traceRegion = change.transparent_region_hint().region(0); @@ -727,9 +709,6 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kMatrix: foundUpdate = matrixUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kOverrideScalingMode: - foundUpdate = scalingModeUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kTransparentRegionHint: foundUpdate = transparentRegionHintUpdateFound(change, foundUpdate); break; @@ -780,7 +759,6 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayer)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kCrop)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kMatrix)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kOverrideScalingMode)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kLayerStack)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kHiddenFlag)); @@ -915,11 +893,6 @@ TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) { captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix); } -TEST_F(SurfaceInterceptorTest, InterceptOverrideScalingModeUpdateWorks) { - captureTest(&SurfaceInterceptorTest::overrideScalingModeUpdate, - SurfaceChange::SurfaceChangeCase::kOverrideScalingMode); -} - TEST_F(SurfaceInterceptorTest, InterceptTransparentRegionHintUpdateWorks) { captureTest(&SurfaceInterceptorTest::transparentRegionHintUpdate, SurfaceChange::SurfaceChangeCase::kTransparentRegionHint); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 07c558f342..1606f2241e 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1691,30 +1691,6 @@ protected: EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); } - void Test_InheritNonTransformScalingFromParent() { - { - TransactionScope ts(*Base::sFakeComposer); - ts.show(mChild); - ts.setPosition(mChild, 0, 0); - ts.setPosition(Base::mFGSurfaceControl, 0, 0); - } - - { - TransactionScope ts(*Base::sFakeComposer); - ts.setOverrideScalingMode(Base::mFGSurfaceControl, - NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - // We cause scaling by 2. - ts.setSize(Base::mFGSurfaceControl, 128, 128); - } - - auto referenceFrame = Base::mBaseFrame; - referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 128, 128}; - referenceFrame[Base::FG_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 64.f, 64.f}; - referenceFrame[CHILD_LAYER].mDisplayFrame = hwc_rect_t{0, 0, 20, 20}; - referenceFrame[CHILD_LAYER].mSourceCrop = hwc_frect_t{0.f, 0.f, 10.f, 10.f}; - EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); - } - // Regression test for b/37673612 void Test_ChildrenWithParentBufferTransform() { { @@ -1823,10 +1799,6 @@ TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) { Test_DetachChildrenDifferentClient(); } -TEST_F(ChildLayerTest_2_1, DISABLED_InheritNonTransformScalingFromParent) { - Test_InheritNonTransformScalingFromParent(); -} - // Regression test for b/37673612 TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) { Test_ChildrenWithParentBufferTransform(); -- cgit v1.2.3-59-g8ed1b From 9b611b7f4d1a8b8b5e519007b5d841ace3ed696c Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 19 Oct 2020 12:00:23 -0700 Subject: BLASTBufferQueue: Support setFrameTimelineVsync Surface::setFrameTimelineVsync calls through to SurfaceFlinger using the IGBP as a token. But of course in the case of BBQ we have no IGBP on the server side, and this will produce errors. To fix this we continue overriding Surface methods in the BBQSurface , and forward through to the SurfaceControl variants of the function. Unlike the previous CL for setFrameRate, this is a currently un-released API, and so I'd also like to investigate as a follow-up...can we go SurfaceControl path only? Bug: 170890018 Test: Existing tests pass Change-Id: I5316c38f462c3808d5769ede6666594b911c8242 --- libs/gui/BLASTBufferQueue.cpp | 12 ++++++++++++ libs/gui/LayerState.cpp | 2 ++ libs/gui/Surface.cpp | 7 ++++++- libs/gui/SurfaceComposerClient.cpp | 13 +++++++++++++ libs/gui/include/gui/BLASTBufferQueue.h | 1 + libs/gui/include/gui/LayerState.h | 3 +++ libs/gui/include/gui/Surface.h | 1 + libs/gui/include/gui/SurfaceComposerClient.h | 3 +++ services/surfaceflinger/SurfaceFlinger.cpp | 9 +++++++-- 9 files changed, 48 insertions(+), 3 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 6ae6df196d..c8e1f3d1a0 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -381,6 +381,10 @@ public: } return mBbq->setFrameRate(frameRate, compatibility); } + + status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override { + return mBbq->setFrameTimelineVsync(frameTimelineVsyncId); + } }; // TODO: Can we coalesce this with frame updates? Need to confirm @@ -393,6 +397,14 @@ status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility) { .apply(); } +status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { + std::unique_lock _lock{mMutex}; + SurfaceComposerClient::Transaction t; + + return t.setFrameTimelineVsync(mSurfaceControl, frameTimelineVsyncId) + .apply(); +} + sp BLASTBufferQueue::getSurface() { return new BBQSurface(mProducer, true, this); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2e4d279a5b..433312639d 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -146,6 +146,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeByte, frameRateCompatibility); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); + SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); return NO_ERROR; } @@ -250,6 +251,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); + SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId); return NO_ERROR; } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 9ce8442579..167bef1449 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1521,7 +1521,7 @@ int Surface::dispatchSetFrameTimelineVsync(va_list args) { auto frameTimelineVsyncId = static_cast(va_arg(args, int64_t)); ALOGV("Surface::dispatchSetFrameTimelineVsync"); - return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, frameTimelineVsyncId); + return setFrameTimelineVsync(frameTimelineVsyncId); } bool Surface::transformToDisplayInverse() { @@ -2288,4 +2288,9 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility) { return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility); } +status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { + return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, + frameTimelineVsyncId); +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 105969bd42..791750fd37 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1510,6 +1510,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( + const sp& sc, int64_t frameTimelineVsyncId) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eFrameTimelineVsyncChanged; + s->frameTimelineVsyncId = frameTimelineVsyncId; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index d477bea3ac..1410b12e12 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -86,6 +86,7 @@ public: void flushShadowQueue() { mFlushShadowQueue = true; } status_t setFrameRate(float frameRate, int8_t compatibility); + status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); virtual ~BLASTBufferQueue() = default; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 5942fd03af..ff3a87d98f 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -127,6 +127,7 @@ struct layer_state_t { eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, eFrameNumberChanged = 0x400'00000000, + eFrameTimelineVsyncChanged = 0x800'00000000, }; layer_state_t(); @@ -227,6 +228,8 @@ struct layer_state_t { // Used by BlastBufferQueue to forward the framenumber generated by the // graphics producer. uint64_t frameNumber; + + int64_t frameTimelineVsyncId; }; struct ComposerState { diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 6a1eaa2075..c2b5ec4c4d 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -180,6 +180,7 @@ public: status_t getConsumerUsage(uint64_t* outUsage) const; virtual status_t setFrameRate(float frameRate, int8_t compatibility); + virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); protected: virtual ~Surface(); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index ce1a0a5f30..138f82cd21 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -532,6 +532,9 @@ public: // Sets the frame timeline vsync id received from choreographer that corresponds // to the transaction. Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId); + // Variant that only applies to a specific SurfaceControl. + Transaction& setFrameTimelineVsync(const sp& sc, + int64_t frameTimelineVsyncId); status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 964bd015f2..b6ed68fa49 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3770,6 +3770,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + if (what & layer_state_t::eFrameTimelineVsyncChanged) { + layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime); + } else { + // TODO (b/171252403) We are calling this too much, potentially triggering + // unnecessary work + layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime); + } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { flags |= eTraversalNeeded | eTransformHintUpdateNeeded; @@ -3829,8 +3836,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } - layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime); - if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener -- cgit v1.2.3-59-g8ed1b From d3efcb3ca78dba993ce9a6a57c62b54f8679eed8 Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Tue, 20 Oct 2020 18:08:22 -0700 Subject: Clear mFrameTimelineVsyncId after transaction is applied Without clearing the mFrameTimelineVsyncId, there can be stale tokens that get reused, thereby resulting in wrong classification of janks. This change cleans up the existing code and calls clear(), which does a clean clear of all the states. Bug: 171329973 Test: dumpsys SurfaceFlinger --frametimeline on cold starting an app Change-Id: Ia27520fc6dbb79a122fed40ad963ef470bc2ae35 --- libs/gui/SurfaceComposerClient.cpp | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 105969bd42..cac95d476c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -695,8 +695,6 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { } } - mListenerCallbacks.clear(); - cacheBuffers(); Vector composerStates; @@ -709,10 +707,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { composerStates.add(kv.second); } - mComposerStates.clear(); - - displayStates = mDisplayStates; - mDisplayStates.clear(); + displayStates = std::move(mDisplayStates); if (mForceSynchronous) { flags |= ISurfaceComposer::eSynchronous; @@ -733,21 +728,16 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { flags |= ISurfaceComposer::eExplicitEarlyWakeupEnd; } - mForceSynchronous = false; - mAnimation = false; - mEarlyWakeup = false; - mExplicitEarlyWakeupStart = false; - mExplicitEarlyWakeupEnd = false; - - uint64_t transactionId = mId; - mId = generateId(); - sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, - hasListenerCallbacks, listenerCallbacks, transactionId); - mInputWindowCommands.clear(); + hasListenerCallbacks, listenerCallbacks, mId); + mId = generateId(); + + // Clear the current states and flags + clear(); + mStatus = NO_ERROR; return NO_ERROR; } -- cgit v1.2.3-59-g8ed1b From 992496bd2e1af9c93bce33216034dd5419acb444 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 22 Oct 2020 17:27:21 -0700 Subject: Allow creating child surfaces from BlastBufferQueue App such as Chrome create child surfaces and parent them to surfaces provided by SurfaceView. When we enable the blast adapter for SurfaceView, the IGBP returned to the app is created in the client and SurfaceFlinger does not know about it. When the app creates a child surface and provides the IGBP as the parent surface identifier, SF fails to validate the IGBP and the surface is not created. This can be avoid if the client creates the child surface from the SV SurfaceControl but we still need to support existing APIs. To fix this, when we create a Surface from the adapter, pass in the handle of the Blast SurfaceControl. When calling ASurfaceControl_createFromWindow, use this handle to identify the parent. Bug: 168917217 Test: adb shell settings put global use_blast_adapter_sv 1 & launch chrome Change-Id: I404bbd29b63044260f5403aae60f039a36eeea8b --- libs/gui/BLASTBufferQueue.cpp | 17 ++++++++++------- libs/gui/Surface.cpp | 4 +++- libs/gui/SurfaceComposerClient.cpp | 12 ++++-------- libs/gui/include/gui/BLASTBufferQueue.h | 2 +- libs/gui/include/gui/Surface.h | 18 +++++++++++++++--- libs/gui/include/gui/SurfaceComposerClient.h | 20 ++++++++++---------- libs/gui/include/gui/view/Surface.h | 2 ++ libs/gui/view/Surface.cpp | 5 ++++- services/surfaceflinger/tests/EffectLayer_test.cpp | 6 +++--- .../surfaceflinger/tests/InvalidHandles_test.cpp | 2 +- services/surfaceflinger/tests/LayerTransactionTest.h | 5 +++-- services/surfaceflinger/tests/LayerUpdate_test.cpp | 5 +++-- .../surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp | 8 ++++---- 13 files changed, 63 insertions(+), 43 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index c8e1f3d1a0..0e47676dd6 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -357,11 +357,9 @@ class BBQSurface : public Surface { private: sp mBbq; public: - BBQSurface(const sp& igbp, bool controlledByApp, - const sp& bbq) : - Surface(igbp, controlledByApp), - mBbq(bbq) { - } + BBQSurface(const sp& igbp, bool controlledByApp, + const sp& scHandle, const sp& bbq) + : Surface(igbp, controlledByApp, scHandle), mBbq(bbq) {} void allocateBuffers() override { uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth; @@ -405,8 +403,13 @@ status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { .apply(); } -sp BLASTBufferQueue::getSurface() { - return new BBQSurface(mProducer, true, this); +sp BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) { + std::unique_lock _lock{mMutex}; + sp scHandle = nullptr; + if (includeSurfaceControlHandle && mSurfaceControl) { + scHandle = mSurfaceControl->getHandle(); + } + return new BBQSurface(mProducer, true, scHandle, this); } } // namespace android diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 167bef1449..c1155ab73a 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -63,7 +63,8 @@ bool isInterceptorRegistrationOp(int op) { } // namespace -Surface::Surface(const sp& bufferProducer, bool controlledByApp) +Surface::Surface(const sp& bufferProducer, bool controlledByApp, + const sp& surfaceControlHandle) : mGraphicBufferProducer(bufferProducer), mCrop(Rect::EMPTY_RECT), mBufferAge(0), @@ -111,6 +112,7 @@ Surface::Surface(const sp& bufferProducer, bool controll mProducerControlledByApp = controlledByApp; mSwapIntervalZero = false; mMaxBufferCount = NUM_BUFFER_SLOTS; + mSurfaceControlHandle = surfaceControlHandle; } Surface::~Surface() { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 60966e1915..4b7d4b1a5d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1628,11 +1628,11 @@ void SurfaceComposerClient::dispose() { sp SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - SurfaceControl* parent, + const sp& parentHandle, LayerMetadata metadata, uint32_t* outTransformHint) { sp s; - createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata), + createSurfaceChecked(name, w, h, format, &s, flags, parentHandle, std::move(metadata), outTransformHint); return s; } @@ -1669,20 +1669,16 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h, PixelFormat format, sp* outSurface, uint32_t flags, - SurfaceControl* parent, LayerMetadata metadata, + const sp& parentHandle, + LayerMetadata metadata, uint32_t* outTransformHint) { sp sur; status_t err = mStatus; if (mStatus == NO_ERROR) { sp handle; - sp parentHandle; sp gbp; - if (parent != nullptr) { - parentHandle = parent->getHandle(); - } - uint32_t transformHint = 0; int32_t id = -1; err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 1410b12e12..0d457bfe4a 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -72,7 +72,7 @@ public: sp getIGraphicBufferProducer() const { return mProducer; } - sp getSurface(); + sp getSurface(bool includeSurfaceControlHandle); void onBufferFreed(const wp&/* graphicBuffer*/) override { /* TODO */ } void onFrameReplaced(const BufferItem& item) override {onFrameAvailable(item);} diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index c2b5ec4c4d..4aa076e7b2 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -68,7 +68,6 @@ class Surface : public ANativeObjectBase { public: - /* * creates a Surface from the given IGraphicBufferProducer (which concrete * implementation is a BufferQueue). @@ -83,9 +82,15 @@ public: * * the controlledByApp flag indicates that this Surface (producer) is * controlled by the application. This flag is used at connect time. + * + * Pass in the SurfaceControlHandle to store a weak reference to the layer + * that the Surface was created from. This handle can be used to create a + * child surface without using the IGBP to identify the layer. This is used + * for surfaces created by the BlastBufferQueue whose IGBP is created on the + * client and cannot be verified in SF. */ - explicit Surface(const sp& bufferProducer, - bool controlledByApp = false); + explicit Surface(const sp& bufferProducer, bool controlledByApp = false, + const sp& surfaceControlHandle = nullptr); /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this * Surface was created with. Usually it's an error to use the @@ -93,6 +98,8 @@ public: */ sp getIGraphicBufferProducer() const; + sp getSurfaceControlHandle() const { return mSurfaceControlHandle; } + /* convenience function to check that the given surface is non NULL as * well as its IGraphicBufferProducer */ static bool isValid(const sp& surface) { @@ -541,6 +548,11 @@ protected: bool mEnableFrameTimestamps = false; std::unique_ptr mFrameEventHistory; + // Reference to the SurfaceFlinger layer that was used to create this + // surface. This is only populated when the Surface is created from + // a BlastBufferQueue. + sp mSurfaceControlHandle; + bool mReportRemovedBuffers = false; std::vector> mRemovedBuffers; int mMaxBufferCount; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 138f82cd21..fb01dc4ba4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -253,13 +253,13 @@ public: static sp getDefault(); //! Create a surface - sp createSurface(const String8& name, // name of the surface - uint32_t w, // width in pixel - uint32_t h, // height in pixel - PixelFormat format, // pixel-format desired - uint32_t flags = 0, // usage flags - SurfaceControl* parent = nullptr, // parent - LayerMetadata metadata = LayerMetadata(), // metadata + sp createSurface(const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0, // usage flags + const sp& parentHandle = nullptr, // parentHandle + LayerMetadata metadata = LayerMetadata(), // metadata uint32_t* outTransformHint = nullptr); status_t createSurfaceChecked(const String8& name, // name of the surface @@ -267,9 +267,9 @@ public: uint32_t h, // height in pixel PixelFormat format, // pixel-format desired sp* outSurface, - uint32_t flags = 0, // usage flags - SurfaceControl* parent = nullptr, // parent - LayerMetadata metadata = LayerMetadata(), // metadata + uint32_t flags = 0, // usage flags + const sp& parentHandle = nullptr, // parentHandle + LayerMetadata metadata = LayerMetadata(), // metadata uint32_t* outTransformHint = nullptr); //! Create a surface diff --git a/libs/gui/include/gui/view/Surface.h b/libs/gui/include/gui/view/Surface.h index cc64fd45dd..f7dcbc698d 100644 --- a/libs/gui/include/gui/view/Surface.h +++ b/libs/gui/include/gui/view/Surface.h @@ -21,6 +21,7 @@ #include #include +#include #include namespace android { @@ -43,6 +44,7 @@ class Surface : public Parcelable { String16 name; sp graphicBufferProducer; + sp surfaceControlHandle; virtual status_t writeToParcel(Parcel* parcel) const override; virtual status_t readFromParcel(const Parcel* parcel) override; diff --git a/libs/gui/view/Surface.cpp b/libs/gui/view/Surface.cpp index d64dfd55be..3e49de6dc8 100644 --- a/libs/gui/view/Surface.cpp +++ b/libs/gui/view/Surface.cpp @@ -45,7 +45,9 @@ status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const { if (res != OK) return res; } - return IGraphicBufferProducer::exportToParcel(graphicBufferProducer, parcel); + res = IGraphicBufferProducer::exportToParcel(graphicBufferProducer, parcel); + if (res != OK) return res; + return parcel->writeStrongBinder(surfaceControlHandle); } status_t Surface::readFromParcel(const Parcel* parcel) { @@ -68,6 +70,7 @@ status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) { } graphicBufferProducer = IGraphicBufferProducer::createFromParcel(parcel); + surfaceControlHandle = parcel->readStrongBinder(); return OK; } diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index 3dca3916e4..fafb49efba 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -51,7 +51,7 @@ TEST_F(EffectLayerTest, DefaultEffectLayerHasSolidBlackFill) { sp effectLayer = mClient->createSurface(String8("Effect Layer"), 0 /* width */, 0 /* height */, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect, - mParentLayer.get()); + mParentLayer->getHandle()); EXPECT_NE(nullptr, effectLayer.get()) << "failed to create SurfaceControl"; asTransaction([&](Transaction& t) { @@ -72,7 +72,7 @@ TEST_F(EffectLayerTest, EffectLayerWithNoFill) { PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect | ISurfaceComposerClient::eNoColorFill, - mParentLayer.get()); + mParentLayer->getHandle()); EXPECT_NE(nullptr, effectLayer.get()) << "failed to create SurfaceControl"; asTransaction([&](Transaction& t) { @@ -93,7 +93,7 @@ TEST_F(EffectLayerTest, EffectLayerCanSetColor) { PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect | ISurfaceComposerClient::eNoColorFill, - mParentLayer.get()); + mParentLayer->getHandle()); EXPECT_NE(nullptr, effectLayer.get()) << "failed to create SurfaceControl"; asTransaction([&](Transaction& t) { diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp index cfec0d2b51..152d2d26f4 100644 --- a/services/surfaceflinger/tests/InvalidHandles_test.cpp +++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp @@ -56,7 +56,7 @@ TEST_F(InvalidHandleTest, createSurfaceInvalidHandle) { auto notSc = makeNotSurfaceControl(); ASSERT_EQ(nullptr, mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0, - notSc.get()) + notSc->getHandle()) .get()); } diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index d4e952aa21..25d3211f6b 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -75,8 +75,9 @@ protected: PixelFormat format, uint32_t flags, SurfaceControl* parent = nullptr, uint32_t* outTransformHint = nullptr) { - auto layer = client->createSurface(String8(name), width, height, format, flags, parent, - LayerMetadata(), outTransformHint); + sp parentHandle = (parent) ? parent->getHandle() : nullptr; + auto layer = client->createSurface(String8(name), width, height, format, flags, + parentHandle, LayerMetadata(), outTransformHint); EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; return layer; } diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index 0cafd001ff..29473f20a4 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -1028,12 +1028,13 @@ TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) { TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) { sp boundlessLayer = mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, mFGSurfaceControl.get()); + 0 /* flags */, mFGSurfaceControl->getHandle()); ASSERT_TRUE(boundlessLayer != nullptr); ASSERT_TRUE(boundlessLayer->isValid()); sp colorLayer = mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceEffect, boundlessLayer.get()); + ISurfaceComposerClient::eFXSurfaceEffect, + boundlessLayer->getHandle()); ASSERT_TRUE(colorLayer != nullptr); ASSERT_TRUE(colorLayer->isValid()); asTransaction([&](Transaction& t) { diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 1606f2241e..6c654c07e3 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1469,7 +1469,7 @@ protected: Base::SetUp(); mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, - Base::mFGSurfaceControl.get()); + Base::mFGSurfaceControl->getHandle()); fillSurfaceRGBA8(mChild, LIGHT_GRAY); Base::sFakeComposer->runVSyncAndWait(); @@ -1653,7 +1653,7 @@ protected: sp childNewClient = newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, 0, - Base::mFGSurfaceControl.get()); + Base::mFGSurfaceControl->getHandle()); ASSERT_TRUE(childNewClient != nullptr); ASSERT_TRUE(childNewClient->isValid()); fillSurfaceRGBA8(childNewClient, LIGHT_GRAY); @@ -1732,7 +1732,7 @@ protected: mChild = Base::mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eHidden, - Base::mFGSurfaceControl.get()); + Base::mFGSurfaceControl->getHandle()); // Show the child layer in a deferred transaction { @@ -1819,7 +1819,7 @@ protected: Base::mComposerClient->createSurface(String8("Child surface"), 0, 0, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceEffect, - Base::mFGSurfaceControl.get()); + Base::mFGSurfaceControl->getHandle()); { TransactionScope ts(*Base::sFakeComposer); ts.setColor(Base::mChild, -- cgit v1.2.3-59-g8ed1b From 30b0b3cd9cbe5ce06814f2fce26169cb47342a17 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Tue, 13 Oct 2020 19:15:06 +0200 Subject: SF: Populate allowGroupSwitching from DM Currently we use allowGroupSwitching only for testing. This CL populates its value from DisplayManager so we can use user setting to change its value. Bug: 161776333 Test: atest libsurfaceflinger_unittest Change-Id: I851eaee7f86083d97204cf3553e728350c942dfe --- libs/gui/ISurfaceComposer.cpp | 42 ++++++-- libs/gui/SurfaceComposerClient.cpp | 31 +++--- libs/gui/include/gui/ISurfaceComposer.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 4 +- libs/gui/tests/Surface_test.cpp | 3 +- .../Scheduler/RefreshRateConfigs.cpp | 7 ++ .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 21 +++- services/surfaceflinger/SurfaceFlinger.cpp | 49 +++++---- services/surfaceflinger/SurfaceFlinger.h | 5 +- services/surfaceflinger/tests/Credentials_test.cpp | 3 + .../surfaceflinger/tests/DisplayConfigs_test.cpp | 111 +++++++++++++++------ .../surfaceflinger/tests/LayerTransactionTest.h | 7 ++ .../tests/fakehwc/SFFakeHwc_test.cpp | 11 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 6 ++ 14 files changed, 209 insertions(+), 94 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 964195d30d..6f92233935 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -888,7 +888,7 @@ public: } virtual status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, + int32_t defaultConfig, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, @@ -909,6 +909,11 @@ public: ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result); return result; } + result = data.writeBool(allowGroupSwitching); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs failed to write allowGroupSwitching: %d", result); + return result; + } result = data.writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result); @@ -943,12 +948,14 @@ public: virtual status_t getDesiredDisplayConfigSpecs(const sp& displayToken, int32_t* outDefaultConfig, + bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { - if (!outDefaultConfig || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || - !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { + if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || + !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || + !outAppRequestRefreshRateMax) { return BAD_VALUE; } Parcel data, reply; @@ -973,6 +980,11 @@ public: ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result); return result; } + result = reply.readBool(outAllowGroupSwitching); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs failed to read allowGroupSwitching: %d", result); + return result; + } result = reply.readFloat(outPrimaryRefreshRateMin); if (result != NO_ERROR) { ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result); @@ -1829,6 +1841,13 @@ status_t BnSurfaceComposer::onTransact( ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result); return result; } + bool allowGroupSwitching; + result = data.readBool(&allowGroupSwitching); + if (result != NO_ERROR) { + ALOGE("setDesiredDisplayConfigSpecs: failed to read allowGroupSwitching: %d", + result); + return result; + } float primaryRefreshRateMin; result = data.readFloat(&primaryRefreshRateMin); if (result != NO_ERROR) { @@ -1857,10 +1876,10 @@ status_t BnSurfaceComposer::onTransact( result); return result; } - result = - setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin, - primaryRefreshRateMax, appRequestRefreshRateMin, - appRequestRefreshRateMax); + result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching, + primaryRefreshRateMin, primaryRefreshRateMax, + appRequestRefreshRateMin, + appRequestRefreshRateMax); if (result != NO_ERROR) { ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: " "%d", @@ -1874,13 +1893,14 @@ status_t BnSurfaceComposer::onTransact( CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); int32_t defaultConfig; + bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; float appRequestRefreshRateMin; float appRequestRefreshRateMax; status_t result = - getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, + getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, &allowGroupSwitching, &primaryRefreshRateMin, &primaryRefreshRateMax, &appRequestRefreshRateMin, &appRequestRefreshRateMax); @@ -1896,6 +1916,12 @@ status_t BnSurfaceComposer::onTransact( ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result); return result; } + result = reply->writeBool(allowGroupSwitching); + if (result != NO_ERROR) { + ALOGE("getDesiredDisplayConfigSpecs: failed to write allowGroupSwitching: %d", + result); + return result; + } result = reply->writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d", diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 105969bd42..d3ea5ed37a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1774,27 +1774,24 @@ int SurfaceComposerClient::getActiveConfig(const sp& display) { return ComposerService::getComposerService()->getActiveConfig(display); } -status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs( + const sp& displayToken, int32_t defaultConfig, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { return ComposerService::getComposerService() - ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, primaryRefreshRateMin, - primaryRefreshRateMax, appRequestRefreshRateMin, - appRequestRefreshRateMax); + ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching, + primaryRefreshRateMin, primaryRefreshRateMax, + appRequestRefreshRateMin, appRequestRefreshRateMax); } -status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { +status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs( + const sp& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { return ComposerService::getComposerService() - ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outPrimaryRefreshRateMin, - outPrimaryRefreshRateMax, outAppRequestRefreshRateMin, + ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outAllowGroupSwitching, + outPrimaryRefreshRateMin, outPrimaryRefreshRateMax, + outAppRequestRefreshRateMin, outAppRequestRefreshRateMax); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index a41614749d..5cd9356449 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -395,7 +395,7 @@ public: * returned from getDisplayConfigs(). */ virtual status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, + int32_t defaultConfig, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, @@ -403,6 +403,7 @@ public: virtual status_t getDesiredDisplayConfigSpecs(const sp& displayToken, int32_t* outDefaultConfig, + bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index ce1a0a5f30..5d05e27f8e 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -120,13 +120,15 @@ public: // Sets the refresh rate boundaries for the display. static status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, float primaryRefreshRateMin, + int32_t defaultConfig, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, float appRequestRefreshRateMax); // Gets the refresh rate boundaries for the display. static status_t getDesiredDisplayConfigSpecs(const sp& displayToken, int32_t* outDefaultConfig, + bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 5a376da05c..0cd3962aa1 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -844,7 +844,7 @@ public: return NO_ERROR; } status_t setDesiredDisplayConfigSpecs(const sp& /*displayToken*/, - int32_t /*defaultConfig*/, + int32_t /*defaultConfig*/, bool /*allowGroupSwitching*/, float /*primaryRefreshRateMin*/, float /*primaryRefreshRateMax*/, float /*appRequestRefreshRateMin*/, @@ -853,6 +853,7 @@ public: } status_t getDesiredDisplayConfigSpecs(const sp& /*displayToken*/, int32_t* /*outDefaultConfig*/, + bool* /*outAllowGroupSwitching*/, float* /*outPrimaryRefreshRateMin*/, float* /*outPrimaryRefreshRateMax*/, float* /*outAppRequestRefreshRateMin*/, diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 8661b6ee0a..7ab49a97ab 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -48,6 +48,13 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { } } +std::string RefreshRateConfigs::Policy::toString() { + return base::StringPrintf("default config ID: %d, allowGroupSwitching = %d" + ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]", + defaultConfig.value(), allowGroupSwitching, primaryRange.min, + primaryRange.max, appRequestRange.min, appRequestRange.max); +} + const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( const std::vector& layers) const { std::lock_guard lock(mLock); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index eed8486c1c..280ed62426 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -108,6 +108,10 @@ public: std::unordered_map>; struct Policy { + private: + static constexpr int kAllowGroupSwitchingDefault = false; + + public: struct Range { float min = 0; float max = std::numeric_limits::max(); @@ -122,6 +126,8 @@ public: // The default config, used to ensure we only initiate display config switches within the // same config group as defaultConfigId's group. HwcConfigIndexType defaultConfig; + // Whether or not we switch config groups to get the best frame rate. + bool allowGroupSwitching = kAllowGroupSwitchingDefault; // The primary refresh rate range represents display manager's general guidance on the // display configs we'll consider when switching refresh rates. Unless we get an explicit // signal from an app, we should stay within this range. @@ -133,15 +139,23 @@ public: // app request range. The app request range will be greater than or equal to the primary // refresh rate range, never smaller. Range appRequestRange; - // Whether or not we switch config groups to get the best frame rate. Only used by tests. - bool allowGroupSwitching = false; Policy() = default; + Policy(HwcConfigIndexType defaultConfig, const Range& range) - : Policy(defaultConfig, range, range) {} + : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {} + + Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& range) + : Policy(defaultConfig, allowGroupSwitching, range, range) {} + Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange, const Range& appRequestRange) + : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} + + Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, + const Range& primaryRange, const Range& appRequestRange) : defaultConfig(defaultConfig), + allowGroupSwitching(allowGroupSwitching), primaryRange(primaryRange), appRequestRange(appRequestRange) {} @@ -152,6 +166,7 @@ public: } bool operator!=(const Policy& other) const { return !(*this == other); } + std::string toString(); }; // Return code set*Policy() to indicate the current policy is unchanged. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 964bd015f2..a886f5f49d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1041,7 +1041,12 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo } else { const HwcConfigIndexType config(mode); const float fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); - const scheduler::RefreshRateConfigs::Policy policy{config, {fps, fps}}; + // Keep the old switching type. + const auto allowGroupSwitching = + mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching; + const scheduler::RefreshRateConfigs::Policy policy{config, + allowGroupSwitching, + {fps, fps}}; constexpr bool kOverridePolicy = false; return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); @@ -4356,21 +4361,14 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { dispSyncPresentTimeOffset, getVsyncPeriodFromHWC()); scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy(); - StringAppendF(&result, - "DesiredDisplayConfigSpecs (DisplayManager): default config ID: %d" - ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n", - policy.defaultConfig.value(), policy.primaryRange.min, policy.primaryRange.max, - policy.appRequestRange.min, policy.appRequestRange.max); + StringAppendF(&result, "DesiredDisplayConfigSpecs (DisplayManager): %s\n\n", + policy.toString().c_str()); StringAppendF(&result, "(config override by backdoor: %s)\n\n", mDebugDisplayConfigSetByBackdoor ? "yes" : "no"); scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); if (currentPolicy != policy) { - StringAppendF(&result, - "DesiredDisplayConfigSpecs (Override): default config ID: %d" - ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]\n\n", - currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min, - currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min, - currentPolicy.appRequestRange.max); + StringAppendF(&result, "DesiredDisplayConfigSpecs (Override): %s\n\n", + currentPolicy.toString().c_str()); } mScheduler->dump(mAppConnectionHandle, result); @@ -5964,12 +5962,10 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( return NO_ERROR; } -status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +status_t SurfaceFlinger::setDesiredDisplayConfigSpecs( + const sp& displayToken, int32_t defaultConfig, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken) { @@ -5988,6 +5984,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp& display } else { using Policy = scheduler::RefreshRateConfigs::Policy; const Policy policy{HwcConfigIndexType(defaultConfig), + allowGroupSwitching, {primaryRefreshRateMin, primaryRefreshRateMax}, {appRequestRefreshRateMin, appRequestRefreshRateMax}}; constexpr bool kOverridePolicy = false; @@ -5999,12 +5996,10 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp& display return future.get(); } -status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { +status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( + const sp& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken || !outDefaultConfig || !outPrimaryRefreshRateMin || @@ -6022,6 +6017,7 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& display scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy(); *outDefaultConfig = policy.defaultConfig.value(); + *outAllowGroupSwitching = policy.allowGroupSwitching; *outPrimaryRefreshRateMin = policy.primaryRange.min; *outPrimaryRefreshRateMax = policy.primaryRange.max; *outAppRequestRefreshRateMin = policy.appRequestRange.min; @@ -6032,6 +6028,7 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(const sp& display } else { const auto displayId = display->getPhysicalId(); *outDefaultConfig = getHwComposer().getActiveConfigIndex(displayId); + *outAllowGroupSwitching = false; auto vsyncPeriod = getHwComposer().getActiveConfig(displayId)->getVsyncPeriod(); *outPrimaryRefreshRateMin = 1e9f / vsyncPeriod; *outPrimaryRefreshRateMax = 1e9f / vsyncPeriod; @@ -6162,8 +6159,8 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp* outToken) // This is a little racy, but not in a way that hurts anything. As we grab the // defaultConfig from the display manager policy, we could be setting a new display // manager policy, leaving us using a stale defaultConfig. The defaultConfig doesn't - // matter for the override policy though, since we set allowGroupSwitching to true, so - // it's not a problem. + // matter for the override policy though, since we set allowGroupSwitching to + // true, so it's not a problem. scheduler::RefreshRateConfigs::Policy overridePolicy; overridePolicy.defaultConfig = mRefreshRateConfigs->getDisplayManagerPolicy().defaultConfig; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5bb5a0de82..4f1f1c181a 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -583,11 +583,12 @@ private: const sp& listener) override; status_t removeRegionSamplingListener(const sp& listener) override; status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t displayModeId, - float primaryRefreshRateMin, float primaryRefreshRateMax, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, float appRequestRefreshRateMin, float appRequestRefreshRateMax) override; status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, + int32_t* outDefaultConfig, bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 7f541e2467..9302463190 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -218,18 +218,21 @@ TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) { TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); int32_t defaultConfig; + bool allowGroupSwitching; float primaryFpsMin; float primaryFpsMax; float appRequestFpsMin; float appRequestFpsMax; status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig, + &allowGroupSwitching, &primaryFpsMin, &primaryFpsMax, &appRequestFpsMin, &appRequestFpsMax); ASSERT_EQ(res, NO_ERROR); std::function condition = [=]() { return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, + allowGroupSwitching, primaryFpsMin, primaryFpsMax, appRequestFpsMin, appRequestFpsMax); diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index debfe83577..3a8b40fd67 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -14,15 +14,17 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" +#include +#include +#include +#include +#include +#include +#include -#include -#include "LayerTransactionTest.h" -namespace android { +#include "utils/TransactionUtils.h" -using android::hardware::graphics::common::V1_1::BufferUsage; +namespace android { ::testing::Environment* const binderEnv = ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); @@ -31,32 +33,54 @@ using android::hardware::graphics::common::V1_1::BufferUsage; * Test class for setting display configs and passing around refresh rate ranges. */ class RefreshRateRangeTest : public ::testing::Test { -protected: - void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); } - - sp mDisplayToken; -}; - -TEST_F(RefreshRateRangeTest, setAllConfigs) { +private: int32_t initialDefaultConfig; + bool initialAllowGroupSwitching; float initialPrimaryMin; float initialPrimaryMax; float initialAppRequestMin; float initialAppRequestMax; - status_t res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, - &initialDefaultConfig, - &initialPrimaryMin, - &initialPrimaryMax, - &initialAppRequestMin, - &initialAppRequestMax); - ASSERT_EQ(res, NO_ERROR); +protected: + void SetUp() override { + mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); + status_t res = + SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, + &initialDefaultConfig, + &initialAllowGroupSwitching, + &initialPrimaryMin, + &initialPrimaryMax, + &initialAppRequestMin, + &initialAppRequestMax); + ASSERT_EQ(res, NO_ERROR); + } + + void TearDown() override { + status_t res = + SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, + initialDefaultConfig, + initialAllowGroupSwitching, + initialPrimaryMin, + initialPrimaryMax, + initialAppRequestMin, + initialAppRequestMax); + ASSERT_EQ(res, NO_ERROR); + } + + void testSetAllowGroupSwitching(bool allowGroupSwitching); + + sp mDisplayToken; +}; + +TEST_F(RefreshRateRangeTest, setAllConfigs) { Vector configs; - res = SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &configs); + status_t res = SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &configs); ASSERT_EQ(res, NO_ERROR); + ASSERT_GT(configs.size(), 0); for (size_t i = 0; i < configs.size(); i++) { - res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, i, + res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, + static_cast(i), false, configs[i].refreshRate, configs[i].refreshRate, configs[i].refreshRate, @@ -64,31 +88,58 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { ASSERT_EQ(res, NO_ERROR); int defaultConfig; + bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; float appRequestRefreshRateMin; float appRequestRefreshRateMax; res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, + &allowGroupSwitching, &primaryRefreshRateMin, &primaryRefreshRateMax, &appRequestRefreshRateMin, &appRequestRefreshRateMax); ASSERT_EQ(res, NO_ERROR); ASSERT_EQ(defaultConfig, i); + ASSERT_EQ(allowGroupSwitching, false); ASSERT_EQ(primaryRefreshRateMin, configs[i].refreshRate); ASSERT_EQ(primaryRefreshRateMax, configs[i].refreshRate); ASSERT_EQ(appRequestRefreshRateMin, configs[i].refreshRate); ASSERT_EQ(appRequestRefreshRateMax, configs[i].refreshRate); } +} + +void RefreshRateRangeTest::testSetAllowGroupSwitching(bool allowGroupSwitching) { + status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 0, + allowGroupSwitching, 0.f, + 90.f, 0.f, 90.f); + ASSERT_EQ(res, NO_ERROR); + int defaultConfig; + bool newAllowGroupSwitching; + float primaryRefreshRateMin; + float primaryRefreshRateMax; + float appRequestRefreshRateMin; + float appRequestRefreshRateMax; - res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, initialDefaultConfig, - initialPrimaryMin, initialPrimaryMax, - initialAppRequestMin, - initialAppRequestMax); + res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, + &newAllowGroupSwitching, + &primaryRefreshRateMin, + &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); ASSERT_EQ(res, NO_ERROR); + ASSERT_EQ(defaultConfig, 0); + ASSERT_EQ(newAllowGroupSwitching, allowGroupSwitching); + ASSERT_EQ(primaryRefreshRateMin, 0.f); + ASSERT_EQ(primaryRefreshRateMax, 90.f); + ASSERT_EQ(appRequestRefreshRateMin, 0.f); + ASSERT_EQ(appRequestRefreshRateMax, 90.f); } -} // namespace android +TEST_F(RefreshRateRangeTest, setAllowGroupSwitching) { + testSetAllowGroupSwitching(true); + testSetAllowGroupSwitching(false); + testSetAllowGroupSwitching(true); +} -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index d4e952aa21..5fe2e40943 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -16,6 +16,10 @@ #pragma once +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -299,3 +303,6 @@ private: }; } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 1606f2241e..34993ab8ed 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -447,7 +447,7 @@ protected: const auto& config = configs[i]; if (config.resolution.getWidth() == 800) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, config.refreshRate, config.refreshRate, config.refreshRate, @@ -553,7 +553,7 @@ protected: const auto& config = configs[i]; if (config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, config.refreshRate, config.refreshRate, config.refreshRate, @@ -670,7 +670,8 @@ protected: if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, SurfaceComposerClient:: - setDesiredDisplayConfigSpecs(display, i, configs[i].refreshRate, + setDesiredDisplayConfigSpecs(display, i, false, + configs[i].refreshRate, configs[i].refreshRate, configs[i].refreshRate, configs[i].refreshRate)); @@ -716,7 +717,7 @@ protected: const auto& config = configs[i]; if (config.refreshRate == 1e9f / 8'333'333) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, config.refreshRate, config.refreshRate, config.refreshRate, @@ -763,7 +764,7 @@ protected: const auto& config = configs[i]; if (config.resolution.getWidth() == 1600 && config.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, + SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, config.refreshRate, config.refreshRate, config.refreshRate, diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 8e1f94397f..5c5b18ec1c 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -16,6 +16,9 @@ #pragma once +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -181,3 +184,6 @@ public: }; } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From c3800b88e8c8c2cd6b7f2b039d2dc6b6894f52d1 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 2 Oct 2020 16:24:48 -0700 Subject: Implement blur region in RenderEngine Blur regions should be be piped through SurfaceFlinger all the way down to the compositor, in order to render blurs. It's also necessary to cache them if multiple regions require the same blur radius. Test: manual Test: atest SurfaceInterceptor_test Test: atest OutputUpdateAndWriteCompositionStateTest Bug: 159712515 Change-Id: Id4759f65eb2522a80e9328062fe641fe29786a30 --- cmds/surfacereplayer/proto/src/trace.proto | 18 ++++++ cmds/surfacereplayer/replayer/Replayer.cpp | 24 ++++++++ cmds/surfacereplayer/replayer/Replayer.h | 4 ++ libs/gui/LayerState.cpp | 36 +++++++++++ libs/gui/SurfaceComposerClient.cpp | 12 ++++ libs/gui/include/gui/LayerState.h | 3 + libs/gui/include/gui/SurfaceComposerClient.h | 3 + .../include/renderengine/LayerSettings.h | 25 ++++++++ libs/renderengine/skia/SkiaGLRenderEngine.cpp | 70 ++++++++++++++++++++-- libs/renderengine/skia/SkiaGLRenderEngine.h | 2 + libs/renderengine/skia/filters/BlurFilter.cpp | 36 +++++++---- libs/renderengine/skia/filters/BlurFilter.h | 10 +++- libs/ui/include/ui/BlurRegion.h | 36 +++++++++++ .../compositionengine/LayerFECompositionState.h | 4 ++ .../CompositionEngine/src/Output.cpp | 3 +- .../CompositionEngine/tests/OutputTest.cpp | 28 +++++++++ services/surfaceflinger/Layer.cpp | 17 +++++- services/surfaceflinger/Layer.h | 8 +++ services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/SurfaceInterceptor.cpp | 23 +++++++ services/surfaceflinger/SurfaceInterceptor.h | 2 + services/surfaceflinger/layerproto/layers.proto | 16 +++++ .../tests/SurfaceInterceptor_test.cpp | 29 +++++++++ 23 files changed, 391 insertions(+), 21 deletions(-) create mode 100644 libs/ui/include/ui/BlurRegion.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index bbf4f8dd38..c6f656ba0c 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -54,6 +54,7 @@ message SurfaceChange { ReparentChildrenChange reparent_children = 20; BackgroundBlurRadiusChange background_blur_radius = 21; ShadowRadiusChange shadow_radius = 22; + BlurRegionsChange blur_regions = 23; } } @@ -207,6 +208,23 @@ message ShadowRadiusChange { required float radius = 1; } +message BlurRegionsChange { + repeated BlurRegionChange blur_regions = 1; +} + +message BlurRegionChange { + required uint32 blur_radius = 1; + required float corner_radius_tl = 2; + required float corner_radius_tr = 3; + required float corner_radius_bl = 4; + required float corner_radius_br = 5; + required float alpha = 6; + required int32 left = 7; + required int32 top = 8; + required int32 right = 9; + required int32 bottom = 10; +} + message Origin { required int32 pid = 1; required int32 uid = 2; diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index c1868016d0..5849212265 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -423,6 +423,9 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kShadowRadius: setShadowRadiusChange(transaction, change.id(), change.shadow_radius()); break; + case SurfaceChange::SurfaceChangeCase::kBlurRegions: + setBlurRegionsChange(transaction, change.id(), change.blur_regions()); + break; default: status = 1; break; @@ -728,3 +731,24 @@ void Replayer::setShadowRadiusChange(SurfaceComposerClient::Transaction& t, layer_id id, const ShadowRadiusChange& c) { t.setShadowRadius(mLayers[id], c.radius()); } + +void Replayer::setBlurRegionsChange(SurfaceComposerClient::Transaction& t, + layer_id id, const BlurRegionsChange& c) { + std::vector regions; + for(size_t i=0; i < c.blur_regions_size(); i++) { + auto protoRegion = c.blur_regions(i); + regions.push_back(BlurRegion{ + .blurRadius = protoRegion.blur_radius(), + .alpha = protoRegion.alpha(), + .cornerRadiusTL = protoRegion.corner_radius_tl(), + .cornerRadiusTR = protoRegion.corner_radius_tr(), + .cornerRadiusBL = protoRegion.corner_radius_bl(), + .cornerRadiusBR = protoRegion.corner_radius_br(), + .left = protoRegion.left(), + .top = protoRegion.top(), + .right = protoRegion.right(), + .bottom = protoRegion.bottom() + }); + } + t.setBlurRegions(mLayers[id], regions); +} diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index e439718bd6..a22262a24e 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -96,6 +96,8 @@ class Replayer { layer_id id, const CornerRadiusChange& cc); void setBackgroundBlurRadius(SurfaceComposerClient::Transaction& t, layer_id id, const BackgroundBlurRadiusChange& cc); + void setBlurRegions(SurfaceComposerClient::Transaction& t, + layer_id id, const BlurRegionsChange& cc); void setMatrix(SurfaceComposerClient::Transaction& t, layer_id id, const MatrixChange& mc); void setTransparentRegionHint(SurfaceComposerClient::Transaction& t, @@ -120,6 +122,8 @@ class Replayer { layer_id id, const ReparentChildrenChange& c); void setShadowRadiusChange(SurfaceComposerClient::Transaction& t, layer_id id, const ShadowRadiusChange& c); + void setBlurRegionsChange(SurfaceComposerClient::Transaction& t, + layer_id id, const BlurRegionsChange& c); void setDisplaySurface(SurfaceComposerClient::Transaction& t, display_id id, const DispSurfaceChange& dsc); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 433312639d..9722f368f4 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -147,6 +147,20 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); + + SAFE_PARCEL(output.writeUint32, blurRegions.size()); + for (auto region : blurRegions) { + SAFE_PARCEL(output.writeUint32, region.blurRadius); + SAFE_PARCEL(output.writeFloat, region.cornerRadiusTL); + SAFE_PARCEL(output.writeFloat, region.cornerRadiusTR); + SAFE_PARCEL(output.writeFloat, region.cornerRadiusBL); + SAFE_PARCEL(output.writeFloat, region.cornerRadiusBR); + SAFE_PARCEL(output.writeFloat, region.alpha); + SAFE_PARCEL(output.writeInt32, region.left); + SAFE_PARCEL(output.writeInt32, region.top); + SAFE_PARCEL(output.writeInt32, region.right); + SAFE_PARCEL(output.writeInt32, region.bottom); + } return NO_ERROR; } @@ -252,6 +266,24 @@ status_t layer_state_t::read(const Parcel& input) fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId); + + uint32_t numRegions = 0; + SAFE_PARCEL(input.readUint32, &numRegions); + blurRegions.clear(); + for (uint32_t i = 0; i < numRegions; i++) { + BlurRegion region; + SAFE_PARCEL(input.readUint32, ®ion.blurRadius); + SAFE_PARCEL(input.readFloat, ®ion.cornerRadiusTL); + SAFE_PARCEL(input.readFloat, ®ion.cornerRadiusTR); + SAFE_PARCEL(input.readFloat, ®ion.cornerRadiusBL); + SAFE_PARCEL(input.readFloat, ®ion.cornerRadiusBR); + SAFE_PARCEL(input.readFloat, ®ion.alpha); + SAFE_PARCEL(input.readInt32, ®ion.left); + SAFE_PARCEL(input.readInt32, ®ion.top); + SAFE_PARCEL(input.readInt32, ®ion.right); + SAFE_PARCEL(input.readInt32, ®ion.bottom); + blurRegions.push_back(region); + } return NO_ERROR; } @@ -375,6 +407,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eBackgroundBlurRadiusChanged; backgroundBlurRadius = other.backgroundBlurRadius; } + if (other.what & eBlurRegionsChanged) { + what |= eBlurRegionsChanged; + blurRegions = other.blurRegions; + } if (other.what & eDeferTransaction_legacy) { what |= eDeferTransaction_legacy; barrierSurfaceControl_legacy = other.barrierSurfaceControl_legacy; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 32f9695b8c..039e9008e8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1017,6 +1017,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackg return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBlurRegions( + const sp& sc, const std::vector& blurRegions) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eBlurRegionsChanged; + s->blurRegions = blurRegions; + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::deferTransactionUntil_legacy( const sp& sc, const sp& barrierSurfaceControl, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index ff3a87d98f..a73d9a68a5 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,7 @@ struct layer_state_t { eFixedTransformHintChanged = 0x200'00000000, eFrameNumberChanged = 0x400'00000000, eFrameTimelineVsyncChanged = 0x800'00000000, + eBlurRegionsChanged = 0x1000'00000000, }; layer_state_t(); @@ -186,6 +188,7 @@ struct layer_state_t { int32_t api; sp sidebandStream; mat4 colorTransform; + std::vector blurRegions; #ifndef NO_INPUT sp inputHandle = new InputWindowHandle(); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 13abed2713..73909a30bb 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -439,6 +440,8 @@ public: Transaction& setCornerRadius(const sp& sc, float cornerRadius); Transaction& setBackgroundBlurRadius(const sp& sc, int backgroundBlurRadius); + Transaction& setBlurRegions(const sp& sc, + const std::vector& regions); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); Transaction& setMetadata(const sp& sc, uint32_t key, const Parcel& p); // Defers applying any changes made in this transaction until the Layer diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 95e9367fea..d8d989e95d 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,8 @@ struct LayerSettings { ShadowSettings shadow; int backgroundBlurRadius = 0; + + std::vector blurRegions; }; // Keep in sync with custom comparison function in @@ -182,7 +185,29 @@ static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& r lhs.length == rhs.length && lhs.casterIsTranslucent == rhs.casterIsTranslucent; } +static inline bool operator==(const BlurRegion& lhs, const BlurRegion& rhs) { + return lhs.alpha == rhs.alpha && lhs.cornerRadiusTL == rhs.cornerRadiusTL && + lhs.cornerRadiusTR == rhs.cornerRadiusTR && lhs.cornerRadiusBL == rhs.cornerRadiusBL && + lhs.cornerRadiusBR == rhs.cornerRadiusBR && lhs.blurRadius == rhs.blurRadius && + lhs.left == rhs.left && lhs.top == rhs.top && lhs.right == rhs.right && + lhs.bottom == rhs.bottom; +} + +static inline bool operator!=(const BlurRegion& lhs, const BlurRegion& rhs) { + return !(lhs == rhs); +} + static inline bool operator==(const LayerSettings& lhs, const LayerSettings& rhs) { + if (lhs.blurRegions.size() != rhs.blurRegions.size()) { + return false; + } + const auto size = lhs.blurRegions.size(); + for (size_t i = 0; i < size; i++) { + if (lhs.blurRegions[i] != rhs.blurRegions[i]) { + return false; + } + } + return lhs.geometry == rhs.geometry && lhs.source == rhs.source && lhs.alpha == rhs.alpha && lhs.sourceDataspace == rhs.sourceDataspace && lhs.colorTransform == rhs.colorTransform && diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 69ad189765..03c8e80d04 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -23,6 +23,14 @@ #include #include #include +#include +#include +#include +#include +#include "../gl/GLExtensions.h" +#include "SkiaGLRenderEngine.h" +#include "filters/BlurFilter.h" + #include #include #include @@ -500,10 +508,25 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; const auto& bounds = layer->geometry.boundaries; const auto dest = getSkRect(bounds); - - if (layer->backgroundBlurRadius > 0) { - ATRACE_NAME("BackgroundBlur"); - mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius); + std::unordered_map> cachedBlurs; + + if (mBlurFilter) { + if (layer->backgroundBlurRadius > 0) { + ATRACE_NAME("BackgroundBlur"); + auto blurredSurface = + mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius); + cachedBlurs[layer->backgroundBlurRadius] = blurredSurface; + } + if (layer->blurRegions.size() > 0) { + for (auto region : layer->blurRegions) { + if (cachedBlurs[region.blurRadius]) { + continue; + } + ATRACE_NAME("BlurRegion"); + auto blurredSurface = mBlurFilter->generate(canvas, surface, region.blurRadius); + cachedBlurs[region.blurRadius] = blurredSurface; + } + } } if (layer->source.buffer.buffer) { @@ -571,7 +594,11 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } else { ATRACE_NAME("DrawColor"); const auto color = layer->source.solidColor; - paint.setColor(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, layer->alpha}); + paint.setShader(SkShaders::Color(SkColor4f{.fR = color.r, + .fG = color.g, + .fB = color.b, + layer->alpha}, + nullptr)); } paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform))); @@ -580,6 +607,10 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, canvas->save(); canvas->concat(getSkM44(layer->geometry.positionTransform)); + for (const auto effectRegion : layer->blurRegions) { + drawBlurRegion(canvas, effectRegion, dest, cachedBlurs[effectRegion.blurRadius]); + } + if (layer->shadow.length > 0) { const auto rect = layer->geometry.roundedCornersRadius > 0 ? getSkRect(layer->geometry.roundedCornersCrop) @@ -592,6 +623,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, } else { canvas->drawRect(dest, paint); } + canvas->restore(); } { @@ -678,6 +710,34 @@ void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect, flags); } +void SkiaGLRenderEngine::drawBlurRegion(SkCanvas* canvas, const BlurRegion& effectRegion, + const SkRect& layerBoundaries, + sk_sp blurredSurface) { + ATRACE_CALL(); + SkPaint paint; + paint.setAlpha(static_cast(effectRegion.alpha * 255)); + const auto rect = SkRect::MakeLTRB(effectRegion.left, effectRegion.top, effectRegion.right, + effectRegion.bottom); + + const auto matrix = mBlurFilter->getShaderMatrix( + SkMatrix::MakeTrans(layerBoundaries.left(), layerBoundaries.top())); + paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(matrix)); + + if (effectRegion.cornerRadiusTL > 0 || effectRegion.cornerRadiusTR > 0 || + effectRegion.cornerRadiusBL > 0 || effectRegion.cornerRadiusBR > 0) { + const SkVector radii[4] = + {SkVector::Make(effectRegion.cornerRadiusTL, effectRegion.cornerRadiusTL), + SkVector::Make(effectRegion.cornerRadiusTR, effectRegion.cornerRadiusTR), + SkVector::Make(effectRegion.cornerRadiusBL, effectRegion.cornerRadiusBL), + SkVector::Make(effectRegion.cornerRadiusBR, effectRegion.cornerRadiusBR)}; + SkRRect roundedRect; + roundedRect.setRectRadii(rect, radii); + canvas->drawRRect(roundedRect, paint); + } else { + canvas->drawRect(rect, paint); + } +} + EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config, EGLContext shareContext, bool useContextPriority, Protection protection) { diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index ed4ba111e8..0143445251 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -75,6 +75,8 @@ private: bool waitFence(base::unique_fd fenceFd); void drawShadow(SkCanvas* canvas, const SkRect& casterRect, float casterCornerRadius, const ShadowSettings& shadowSettings); + void drawBlurRegion(SkCanvas* canvas, const BlurRegion& blurRegion, const SkRect& layerBounds, + sk_sp blurrendSurface); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp index 8704b3ad68..f6a316fa1d 100644 --- a/libs/renderengine/skia/filters/BlurFilter.cpp +++ b/libs/renderengine/skia/filters/BlurFilter.cpp @@ -55,8 +55,10 @@ BlurFilter::BlurFilter() { mBlurEffect = std::move(blurEffect); } -void BlurFilter::draw(SkCanvas* canvas, sk_sp input, const uint32_t blurRadius) const { +sk_sp BlurFilter::generate(SkCanvas* canvas, const sk_sp input, + const uint32_t blurRadius) const { ATRACE_CALL(); + // Kawase is an approximation of Gaussian, but it behaves differently from it. // A radius transformation is required for approximating them, and also to introduce // non-integer steps, necessary to smoothly interpolate large radii. @@ -111,25 +113,35 @@ void BlurFilter::draw(SkCanvas* canvas, sk_sp input, const uint32_t b drawSurface->getCanvas()->drawIRect(scaledInfo.bounds(), paint); // Swap buffers for next iteration - auto tmp = drawSurface; + const auto tmp = drawSurface; drawSurface = readSurface; readSurface = tmp; blurBuilder.child("input") = nullptr; } lastDrawTarget = readSurface; } + lastDrawTarget->flushAndSubmit(); + return lastDrawTarget; +} - drawSurface->flushAndSubmit(); +sk_sp BlurFilter::draw(SkCanvas* canvas, const sk_sp input, + const uint32_t blurRadius) const { + ATRACE_CALL(); + auto surface = generate(canvas, input, blurRadius); + + SkPaint paint; + const auto image = surface->makeImageSnapshot(); + paint.setShader(image->makeShader(SkMatrix::MakeScale(kInverseInputScale))); + paint.setFilterQuality(kLow_SkFilterQuality); + paint.setAlpha(std::min(1.0f, (float)blurRadius / kMaxCrossFadeRadius) * 255); + canvas->drawIRect(SkIRect::MakeWH(input->width(), input->height()), paint); + return surface; +} - // do the final composition, with alpha blending to hide downscaling artifacts. - { - SkPaint paint; - paint.setShader(lastDrawTarget->makeImageSnapshot()->makeShader( - SkMatrix::MakeScale(kInverseInputScale))); - paint.setFilterQuality(kLow_SkFilterQuality); - paint.setAlpha(std::min(1.0f, (float)blurRadius / kMaxCrossFadeRadius) * 255); - canvas->drawIRect(SkIRect::MakeWH(input->width(), input->height()), paint); - } +SkMatrix BlurFilter::getShaderMatrix(const SkMatrix& transformMatrix) const { + SkMatrix matrix; + matrix.setConcat(transformMatrix, SkMatrix::MakeScale(kInverseInputScale)); + return matrix; } } // namespace skia diff --git a/libs/renderengine/skia/filters/BlurFilter.h b/libs/renderengine/skia/filters/BlurFilter.h index 94b3673fdc..6f973d790e 100644 --- a/libs/renderengine/skia/filters/BlurFilter.h +++ b/libs/renderengine/skia/filters/BlurFilter.h @@ -47,8 +47,14 @@ public: explicit BlurFilter(); virtual ~BlurFilter(){}; - // Execute blur passes, rendering to a canvas. - void draw(SkCanvas* canvas, sk_sp input, const uint32_t radius) const; + // Execute blur, saving it to a texture + sk_sp generate(SkCanvas* canvas, const sk_sp input, + const uint32_t radius) const; + // Same as generate but also drawing to the screen + sk_sp draw(SkCanvas* canvas, const sk_sp input, + const uint32_t radius) const; + // Returns a matrix that should be applied to the blur shader + SkMatrix getShaderMatrix(const SkMatrix& transformMatrix) const; private: sk_sp mBlurEffect; diff --git a/libs/ui/include/ui/BlurRegion.h b/libs/ui/include/ui/BlurRegion.h new file mode 100644 index 0000000000..c5a5d477cf --- /dev/null +++ b/libs/ui/include/ui/BlurRegion.h @@ -0,0 +1,36 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android { + +struct BlurRegion { + uint32_t blurRadius; + float cornerRadiusTL; + float cornerRadiusTR; + float cornerRadiusBL; + float cornerRadiusBR; + float alpha; + int left; + int top; + int right; + int bottom; +}; + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 77400eb42b..5a3b9ac817 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -118,6 +119,9 @@ struct LayerFECompositionState { // length of the shadow in screen space float shadowRadius{0.f}; + // List of regions that require blur + std::vector blurRegions; + /* * Geometry state */ diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index c625b2e81b..3852f45e35 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -669,7 +669,8 @@ void Output::updateAndWriteCompositionState( compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const { compositionengine::OutputLayer* layerRequestingBgComposition = nullptr; for (auto* layer : getOutputLayersOrderedByZ()) { - if (layer->getLayerFE().getCompositionState()->backgroundBlurRadius > 0) { + if (layer->getLayerFE().getCompositionState()->backgroundBlurRadius > 0 || + layer->getLayerFE().getCompositionState()->blurRegions.size() > 0) { layerRequestingBgComposition = layer; } } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 3dd18396c3..9badb99f96 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -4014,6 +4014,34 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) mOutput->updateAndWriteCompositionState(args); } +TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBlurRegionRequests) { + InjectedLayer layer1; + InjectedLayer layer2; + InjectedLayer layer3; + + // Layer requesting blur, or below, should request client composition. + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(false)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(false, true, ui::Transform::ROT_0)); + EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(false, false, ui::Transform::ROT_0)); + EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(false)); + + BlurRegion region; + layer2.layerFEState.blurRegions.push_back(region); + + injectOutputLayer(layer1); + injectOutputLayer(layer2); + injectOutputLayer(layer3); + + mOutput->editState().isEnabled = true; + + CompositionRefreshArgs args; + args.updatingGeometryThisFrame = false; + args.devOptForceClientComposition = false; + mOutput->updateAndWriteCompositionState(args); +} + TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) { // In split-screen landscape mode, the screen is rotated 90 degrees, with // one layer on the left covering the left side of the output, and one layer diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f657a00065..57493d2795 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -482,6 +482,7 @@ void Layer::prepareBasicGeometryCompositionState() { compositionState->blendMode = static_cast(blendMode); compositionState->alpha = alpha; compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius; + compositionState->blurRegions = drawingState.blurRegions; } void Layer::prepareGeometryCompositionState() { @@ -550,7 +551,8 @@ void Layer::preparePerFrameCompositionState() { isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - if (isHdrY410() || usesRoundedCorners || drawShadows()) { + if (isHdrY410() || usesRoundedCorners || drawShadows() || + getDrawingState().blurRegions.size() > 0) { compositionState->forceClientComposition = true; } } @@ -646,6 +648,7 @@ std::optional Layer::prepareClientCom layerSettings.alpha = alpha; layerSettings.sourceDataspace = getDataSpace(); layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); + layerSettings.blurRegions = getBlurRegions(); return layerSettings; } @@ -1285,6 +1288,14 @@ bool Layer::setTransparentRegionHint(const Region& transparent) { return true; } +bool Layer::setBlurRegions(const std::vector& blurRegions) { + mCurrentState.sequence++; + mCurrentState.blurRegions = blurRegions; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + bool Layer::setFlags(uint8_t flags, uint8_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); if (mCurrentState.flags == newFlags) return false; @@ -2172,6 +2183,10 @@ int32_t Layer::getBackgroundBlurRadius() const { return getDrawingState().backgroundBlurRadius; } +const std::vector& Layer::getBlurRegions() const { + return getDrawingState().blurRegions; +} + Layer::RoundedCornerState Layer::getRoundedCornerState() const { const auto& p = mDrawingParent.promote(); if (p != nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 7112cbc435..5d6c7eaf4d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -255,6 +256,9 @@ public: // be rendered around the layer. float shadowRadius; + // Layer regions that are made of custom materials, like frosted glass + std::vector blurRegions; + // Priority of the layer assigned by Window Manager. int32_t frameRateSelectionPriority; @@ -391,6 +395,7 @@ public: // When non-zero, everything below this layer will be blurred by backgroundBlurRadius, which // is specified in pixels. virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); + virtual bool setBlurRegions(const std::vector& effectRegions); virtual bool setTransparentRegionHint(const Region& transparent); virtual bool setFlags(uint8_t flags, uint8_t mask); virtual bool setLayerStack(uint32_t layerStack); @@ -1110,6 +1115,9 @@ private: // final shadow radius for this layer. If a shadow is specified for a layer, then effective // shadow radius is the set shadow radius, otherwise its the parent's shadow radius. float mEffectiveShadowRadius = 0.f; + + // A list of regions on this layer that should have blurs. + const std::vector& getBlurRegions() const; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3977e2b510..fa15d603d0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3684,6 +3684,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) { if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eBlurRegionsChanged) { + if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eLayerStackChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); // We only allow setting layer stacks for top level layers, diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 2d5566f42a..354892386b 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -140,6 +140,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, addCropLocked(transaction, layerId, layer->mCurrentState.crop_legacy); addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius); addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius); + addBlurRegionsLocked(transaction, layerId, layer->mCurrentState.blurRegions); if (layer->mCurrentState.barrierLayer_legacy != nullptr) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer_legacy.promote(), @@ -361,6 +362,25 @@ void SurfaceInterceptor::addBackgroundBlurRadiusLocked(Transaction* transaction, blurRadiusChange->set_background_blur_radius(backgroundBlurRadius); } +void SurfaceInterceptor::addBlurRegionsLocked(Transaction* transaction, int32_t layerId, + const std::vector& blurRegions) { + SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); + BlurRegionsChange* blurRegionsChange(change->mutable_blur_regions()); + for (const auto blurRegion : blurRegions) { + const auto blurRegionChange = blurRegionsChange->add_blur_regions(); + blurRegionChange->set_blur_radius(blurRegion.blurRadius); + blurRegionChange->set_corner_radius_tl(blurRegion.cornerRadiusTL); + blurRegionChange->set_corner_radius_tr(blurRegion.cornerRadiusTR); + blurRegionChange->set_corner_radius_bl(blurRegion.cornerRadiusBL); + blurRegionChange->set_corner_radius_br(blurRegion.cornerRadiusBR); + blurRegionChange->set_alpha(blurRegion.alpha); + blurRegionChange->set_left(blurRegion.left); + blurRegionChange->set_top(blurRegion.top); + blurRegionChange->set_right(blurRegion.right); + blurRegionChange->set_bottom(blurRegion.bottom); + } +} + void SurfaceInterceptor::addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber) { @@ -456,6 +476,9 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, if (state.what & layer_state_t::eBackgroundBlurRadiusChanged) { addBackgroundBlurRadiusLocked(transaction, layerId, state.backgroundBlurRadius); } + if (state.what & layer_state_t::eBlurRegionsChanged) { + addBlurRegionsLocked(transaction, layerId, state.blurRegions); + } if (state.what & layer_state_t::eDeferTransaction_legacy) { sp otherLayer = nullptr; if (state.barrierSurfaceControl_legacy != nullptr) { diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 97ff547547..3df79c6eb5 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -165,6 +165,8 @@ private: void addCornerRadiusLocked(Transaction* transaction, int32_t layerId, float cornerRadius); void addBackgroundBlurRadiusLocked(Transaction* transaction, int32_t layerId, int32_t backgroundBlurRadius); + void addBlurRegionsLocked(Transaction* transaction, int32_t layerId, + const std::vector& effectRegions); void addDeferTransactionLocked(Transaction* transaction, int32_t layerId, const sp& layer, uint64_t frameNumber); void addSurfaceChangesLocked(Transaction* transaction, const layer_state_t& state); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index f3f56265e0..9f25674f1b 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -125,6 +125,9 @@ message LayerProto { int32 background_blur_radius = 52; uint32 owner_uid = 53; + + // Regions of a layer, where blur should be applied. + repeated BlurRegion blur_regions = 54; } message PositionProto { @@ -211,3 +214,16 @@ message ColorTransformProto { // This will be a 4x4 matrix of float values repeated float val = 1; } + +message BlurRegion { + uint32 blur_radius = 1; + uint32 corner_radius_tl = 2; + uint32 corner_radius_tr = 3; + uint32 corner_radius_bl = 4; + float corner_radius_br = 5; + float alpha = 6; + int32 left = 7; + int32 top = 8; + int32 right = 9; + int32 bottom = 10; +} \ No newline at end of file diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index a5a569bb0f..81e648aaef 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -51,6 +51,7 @@ constexpr int BACKGROUND_BLUR_RADIUS_UPDATE = 24; constexpr float POSITION_UPDATE = 121; const Rect CROP_UPDATE(16, 16, 32, 32); const float SHADOW_RADIUS_UPDATE = 35.0f; +std::vector BLUR_REGIONS_UPDATE; const String8 DISPLAY_NAME("SurfaceInterceptor Display Test"); constexpr auto TEST_BG_SURFACE_NAME = "BG Interceptor Test Surface"; @@ -181,6 +182,7 @@ public: bool cornerRadiusUpdateFound(const SurfaceChange& change, bool foundCornerRadius); bool backgroundBlurRadiusUpdateFound(const SurfaceChange& change, bool foundBackgroundBlurRadius); + bool blurRegionsUpdateFound(const SurfaceChange& change, bool foundBlurRegions); bool matrixUpdateFound(const SurfaceChange& change, bool foundMatrix); bool scalingModeUpdateFound(const SurfaceChange& change, bool foundScalingMode); bool transparentRegionHintUpdateFound(const SurfaceChange& change, bool foundTransparentRegion); @@ -219,6 +221,7 @@ public: void cropUpdate(Transaction&); void cornerRadiusUpdate(Transaction&); void backgroundBlurRadiusUpdate(Transaction&); + void blurRegionsUpdate(Transaction&); void matrixUpdate(Transaction&); void transparentRegionHintUpdate(Transaction&); void layerStackUpdate(Transaction&); @@ -357,6 +360,12 @@ void SurfaceInterceptorTest::backgroundBlurRadiusUpdate(Transaction& t) { t.setBackgroundBlurRadius(mBGSurfaceControl, BACKGROUND_BLUR_RADIUS_UPDATE); } +void SurfaceInterceptorTest::blurRegionsUpdate(Transaction& t) { + BLUR_REGIONS_UPDATE.empty(); + BLUR_REGIONS_UPDATE.push_back(BlurRegion()); + t.setBlurRegions(mBGSurfaceControl, BLUR_REGIONS_UPDATE); +} + void SurfaceInterceptorTest::layerUpdate(Transaction& t) { t.setLayer(mBGSurfaceControl, LAYER_UPDATE); } @@ -430,6 +439,7 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::alphaUpdate); runInTransaction(&SurfaceInterceptorTest::cornerRadiusUpdate); runInTransaction(&SurfaceInterceptorTest::backgroundBlurRadiusUpdate); + runInTransaction(&SurfaceInterceptorTest::blurRegionsUpdate); runInTransaction(&SurfaceInterceptorTest::layerUpdate); runInTransaction(&SurfaceInterceptorTest::cropUpdate); runInTransaction(&SurfaceInterceptorTest::matrixUpdate); @@ -518,6 +528,17 @@ bool SurfaceInterceptorTest::backgroundBlurRadiusUpdateFound(const SurfaceChange return foundBackgroundBlur; } +bool SurfaceInterceptorTest::blurRegionsUpdateFound(const SurfaceChange& change, + bool foundBlurRegions) { + bool hasBlurRegions(change.blur_regions().blur_regions_size() == BLUR_REGIONS_UPDATE.size()); + if (hasBlurRegions && !foundBlurRegions) { + foundBlurRegions = true; + } else if (hasBlurRegions && foundBlurRegions) { + []() { FAIL(); }(); + } + return foundBlurRegions; +} + bool SurfaceInterceptorTest::layerUpdateFound(const SurfaceChange& change, bool foundLayer) { bool hasLayer(change.layer().layer() == LAYER_UPDATE); if (hasLayer && !foundLayer) { @@ -706,6 +727,9 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kBackgroundBlurRadius: foundUpdate = backgroundBlurRadiusUpdateFound(change, foundUpdate); break; + case SurfaceChange::SurfaceChangeCase::kBlurRegions: + foundUpdate = blurRegionsUpdateFound(change, foundUpdate); + break; case SurfaceChange::SurfaceChangeCase::kMatrix: foundUpdate = matrixUpdateFound(change, foundUpdate); break; @@ -889,6 +913,11 @@ TEST_F(SurfaceInterceptorTest, InterceptBackgroundBlurRadiusUpdateWorks) { SurfaceChange::SurfaceChangeCase::kBackgroundBlurRadius); } +TEST_F(SurfaceInterceptorTest, InterceptBlurRegionsUpdateWorks) { + captureTest(&SurfaceInterceptorTest::blurRegionsUpdate, + SurfaceChange::SurfaceChangeCase::kBlurRegions); +} + TEST_F(SurfaceInterceptorTest, InterceptMatrixUpdateWorks) { captureTest(&SurfaceInterceptorTest::matrixUpdate, SurfaceChange::SurfaceChangeCase::kMatrix); } -- cgit v1.2.3-59-g8ed1b From 4608442db90c07dccc833dbdf1cea78f57c7b96d Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Tue, 13 Oct 2020 12:33:42 +0200 Subject: Add shouldBeSeamless to setFrameRate This CL adds a new parameter shouldBeSeamless to the existing setFrameRate APIs. This parameter indicates whether the desired refresh rate should be achieved only seamlessly or also switches with visual interruptions for the user are allowed. The default value of the new parameter is "true". Test: atest RefreshRateConfigsTest Test: atest SetFrameRateTest Test: atest libsurfaceflinger_unittest Test: atest libgui_test Bug: 161776961 Change-Id: I0df16e09f77c8c198fd3733fb581a2aaadfed685 --- include/android/surface_control.h | 38 +++++-- libs/gui/BLASTBufferQueue.cpp | 10 +- libs/gui/ISurfaceComposer.cpp | 16 ++- libs/gui/LayerState.cpp | 4 + libs/gui/Surface.cpp | 8 +- libs/gui/SurfaceComposerClient.cpp | 4 +- libs/gui/include/gui/BLASTBufferQueue.h | 2 +- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/LayerState.h | 1 + libs/gui/include/gui/Surface.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 2 +- libs/gui/tests/Surface_test.cpp | 2 +- libs/nativewindow/ANativeWindow.cpp | 13 ++- libs/nativewindow/include/android/native_window.h | 51 ++++++--- libs/nativewindow/include/system/window.h | 4 +- libs/nativewindow/libnativewindow.map.txt | 1 + services/surfaceflinger/Layer.cpp | 11 +- services/surfaceflinger/Layer.h | 11 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 21 +++- .../surfaceflinger/Scheduler/LayerHistoryV2.cpp | 11 +- services/surfaceflinger/Scheduler/LayerInfoV2.cpp | 4 +- services/surfaceflinger/Scheduler/LayerInfoV2.h | 19 ++-- .../Scheduler/RefreshRateConfigs.cpp | 65 ++++++++++- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 4 + services/surfaceflinger/Scheduler/StrongTyping.h | 4 + services/surfaceflinger/SurfaceFlinger.cpp | 9 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- .../surfaceflinger/tests/LayerTransactionTest.h | 4 +- .../surfaceflinger/tests/SetFrameRate_test.cpp | 23 ++-- .../tests/TransactionTestHarnesses.h | 8 +- .../tests/unittests/LayerHistoryTestV2.cpp | 2 +- .../tests/unittests/RefreshRateConfigsTest.cpp | 122 ++++++++++++++++++++- .../tests/unittests/RefreshRateStatsTest.cpp | 46 ++++---- 33 files changed, 402 insertions(+), 124 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/include/android/surface_control.h b/include/android/surface_control.h index cbcf6ec5c0..9758c9c8c3 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -410,7 +410,23 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio #if __ANDROID_API__ >= 30 /** - * Sets the intended frame rate for |surface_control|. + * Same as ASurfaceTransaction_setFrameRateWithSeamlessness(transaction, surface_control, + * frameRate, compatibility, true). + * + * See ASurfaceTransaction_setFrameRateWithSeamlessness(). + * + * Available since API level 30. + */ +void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, float frameRate, + int8_t compatibility) __INTRODUCED_IN(30); + +#endif // __ANDROID_API__ >= 30 + +#if __ANDROID_API__ >= 31 + +/** + * Sets the intended frame rate for \a surface_control. * * On devices that are capable of running the display at different refresh rates, the system may * choose a display refresh rate to better match this surface's frame rate. Usage of this API won't @@ -419,24 +435,30 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio * callback timings, and changes to the time interval at which the system releases buffers back to * the application. * - * |frameRate| is the intended frame rate of this surface, in frames per second. 0 is a special + * \param frameRate is the intended frame rate of this surface, in frames per second. 0 is a special * value that indicates the app will accept the system's choice for the display frame rate, which is * the default behavior if this function isn't called. The frameRate param does not need to * be a valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device * that can only run the display at 60fps. * - * |compatibility| The frame rate compatibility of this surface. The compatibility value may + * \param compatibility The frame rate compatibility of this surface. The compatibility value may * influence the system's choice of display frame rate. To specify a compatibility use the * ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* enum. * - * Available since API level 30. + * \param shouldBeSeamless Whether display refresh rate transitions 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. True indicates that any frame rate changes caused by this + * request should be seamless. False indicates that non-seamless refresh rates are also + * acceptable. + * + * Available since API level 31. */ -void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction, +void ASurfaceTransaction_setFrameRateWithSeamlessness(ASurfaceTransaction* transaction, ASurfaceControl* surface_control, float frameRate, - int8_t compatibility) __INTRODUCED_IN(30); - -#endif // __ANDROID_API__ >= 30 + int8_t compatibility, bool shouldBeSeamless) + __INTRODUCED_IN(31); +#endif // __ANDROID_API__ >= 31 __END_DECLS #endif // ANDROID_SURFACE_CONTROL_H diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 678613b1ff..ac1c7369b6 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -378,11 +378,11 @@ public: }).detach(); } - status_t setFrameRate(float frameRate, int8_t compatibility) override { + status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless) override { if (!ValidateFrameRate(frameRate, compatibility, "BBQSurface::setFrameRate")) { return BAD_VALUE; } - return mBbq->setFrameRate(frameRate, compatibility); + return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless); } status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override { @@ -392,12 +392,12 @@ public: // TODO: Can we coalesce this with frame updates? Need to confirm // no timing issues. -status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility) { +status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility, + bool shouldBeSeamless) { std::unique_lock _lock{mMutex}; SurfaceComposerClient::Transaction t; - return t.setFrameRate(mSurfaceControl, frameRate, compatibility) - .apply(); + return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply(); } status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 6f92233935..a9fe5bf319 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1114,7 +1114,7 @@ public: } virtual status_t setFrameRate(const sp& surface, float frameRate, - int8_t compatibility) { + int8_t compatibility, bool shouldBeSeamless) { Parcel data, reply; status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { @@ -1140,6 +1140,12 @@ public: return err; } + err = data.writeBool(shouldBeSeamless); + if (err != NO_ERROR) { + ALOGE("setFrameRate: failed writing bool: %s (%d)", strerror(-err), -err); + return err; + } + err = remote()->transact(BnSurfaceComposer::SET_FRAME_RATE, data, &reply); if (err != NO_ERROR) { ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err); @@ -2033,7 +2039,13 @@ status_t BnSurfaceComposer::onTransact( ALOGE("setFrameRate: failed to read byte: %s (%d)", strerror(-err), -err); return err; } - status_t result = setFrameRate(surface, frameRate, compatibility); + bool shouldBeSeamless; + err = data.readBool(&shouldBeSeamless); + if (err != NO_ERROR) { + ALOGE("setFrameRate: failed to read bool: %s (%d)", strerror(-err), -err); + return err; + } + status_t result = setFrameRate(surface, frameRate, compatibility, shouldBeSeamless); reply->writeInt32(result); return NO_ERROR; } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 9722f368f4..90999faa78 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -59,6 +59,7 @@ layer_state_t::layer_state_t() frameRateSelectionPriority(-1), frameRate(0.0f), frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), + shouldBeSeamless(true), fixedTransformHint(ui::Transform::ROT_INVALID), frameNumber(0) { matrix.dsdx = matrix.dtdy = 1.0f; @@ -144,6 +145,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeInt32, frameRateSelectionPriority); SAFE_PARCEL(output.writeFloat, frameRate); SAFE_PARCEL(output.writeByte, frameRateCompatibility); + SAFE_PARCEL(output.writeBool, shouldBeSeamless); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); @@ -262,6 +264,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readInt32, &frameRateSelectionPriority); SAFE_PARCEL(input.readFloat, &frameRate); SAFE_PARCEL(input.readByte, &frameRateCompatibility); + SAFE_PARCEL(input.readBool, &shouldBeSeamless); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); @@ -521,6 +524,7 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameRateChanged; frameRate = other.frameRate; frameRateCompatibility = other.frameRateCompatibility; + shouldBeSeamless = other.shouldBeSeamless; } if (other.what & eFixedTransformHintChanged) { what |= eFixedTransformHintChanged; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index c1155ab73a..94390aa86c 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1443,7 +1443,8 @@ int Surface::dispatchGetLastQueueDuration(va_list args) { int Surface::dispatchSetFrameRate(va_list args) { float frameRate = static_cast(va_arg(args, double)); int8_t compatibility = static_cast(va_arg(args, int)); - return setFrameRate(frameRate, compatibility); + bool shouldBeSeamless = static_cast(va_arg(args, int)); + return setFrameRate(frameRate, compatibility, shouldBeSeamless); } int Surface::dispatchAddCancelInterceptor(va_list args) { @@ -2279,7 +2280,7 @@ void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vectoronBuffersDiscarded(discardedBufs); } -status_t Surface::setFrameRate(float frameRate, int8_t compatibility) { +status_t Surface::setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless) { ATRACE_CALL(); ALOGV("Surface::setFrameRate"); @@ -2287,7 +2288,8 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility) { return BAD_VALUE; } - return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility); + return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility, + shouldBeSeamless); } status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 039e9008e8..a822598d82 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1474,7 +1474,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setShado } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRate( - const sp& sc, float frameRate, int8_t compatibility) { + const sp& sc, float frameRate, int8_t compatibility, + bool shouldBeSeamless) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; @@ -1487,6 +1488,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame s->what |= layer_state_t::eFrameRateChanged; s->frameRate = frameRate; s->frameRateCompatibility = compatibility; + s->shouldBeSeamless = shouldBeSeamless; return *this; } diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 2300e81aa7..7741d8c38a 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -85,7 +85,7 @@ public: void update(const sp& surface, uint32_t width, uint32_t height); void flushShadowQueue() { mFlushShadowQueue = true; } - status_t setFrameRate(float frameRate, int8_t compatibility); + status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); virtual ~BLASTBufferQueue() = default; diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 5cd9356449..9e96b79b8c 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -475,7 +475,7 @@ public: * Sets the intended frame rate for a surface. See ANativeWindow_setFrameRate() for more info. */ virtual status_t setFrameRate(const sp& surface, float frameRate, - int8_t compatibility) = 0; + int8_t compatibility, bool shouldBeSeamless) = 0; /* * Acquire a frame rate flexibility token from SurfaceFlinger. While this token is acquired, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a73d9a68a5..d9f280684f 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -218,6 +218,7 @@ struct layer_state_t { // Layer frame rate and compatibility. See ANativeWindow_setFrameRate(). float frameRate; int8_t frameRateCompatibility; + bool shouldBeSeamless; // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 4aa076e7b2..82bc5c9efb 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -186,7 +186,7 @@ public: status_t getUniqueId(uint64_t* outId) const; status_t getConsumerUsage(uint64_t* outUsage) const; - virtual status_t setFrameRate(float frameRate, int8_t compatibility); + virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); protected: diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 73909a30bb..6289c6a3cd 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -524,7 +524,7 @@ public: Transaction& setShadowRadius(const sp& sc, float cornerRadius); Transaction& setFrameRate(const sp& sc, float frameRate, - int8_t compatibility); + int8_t compatibility, bool shouldBeSeamless); // Set by window manager indicating the layer and all its children are // in a different orientation than the display. The hint suggests that diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 0cd3962aa1..2392ae5ccd 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -869,7 +869,7 @@ public: } status_t setFrameRate(const sp& /*surface*/, float /*frameRate*/, - int8_t /*compatibility*/) override { + int8_t /*compatibility*/, bool /*shouldBeSeamless*/) override { return NO_ERROR; } diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp index fd1793b6bc..b406a9c2fe 100644 --- a/libs/nativewindow/ANativeWindow.cpp +++ b/libs/nativewindow/ANativeWindow.cpp @@ -159,10 +159,8 @@ int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) { } int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility) { - if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) { - return -EINVAL; - } - return native_window_set_frame_rate(window, frameRate, compatibility); + return ANativeWindow_setFrameRateWithSeamlessness(window, frameRate, compatibility, + /*shouldBeSeamless*/ true); } void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) { @@ -172,6 +170,13 @@ void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) { window->perform(window, NATIVE_WINDOW_ALLOCATE_BUFFERS); } +int32_t ANativeWindow_setFrameRateWithSeamlessness(ANativeWindow* window, float frameRate, + int8_t compatibility, bool shouldBeSeamless) { + if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) { + return -EINVAL; + } + return native_window_set_frame_rate(window, frameRate, compatibility, shouldBeSeamless); +} /************************************************************************************************** * vndk-stable diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h index 36aad2eced..deea59b9fb 100644 --- a/libs/nativewindow/include/android/native_window.h +++ b/libs/nativewindow/include/android/native_window.h @@ -34,6 +34,7 @@ #define ANDROID_NATIVE_WINDOW_H #include +#include #include #include @@ -255,6 +256,31 @@ enum ANativeWindow_FrameRateCompatibility { ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1 }; +/** + * Same as ANativeWindow_setFrameRateWithSeamlessness(window, frameRate, compatibility, true). + * + * See ANativeWindow_setFrameRateWithSeamlessness(). + * + * Available since API level 30. + */ +int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility) + __INTRODUCED_IN(30); + +/** + * Provides a hint to the window that buffers should be preallocated ahead of + * time. Note that the window implementation is not guaranteed to preallocate + * any buffers, for instance if an implementation disallows allocation of new + * buffers, or if there is insufficient memory in the system to preallocate + * additional buffers + * + * Available since API level 30. + */ +void ANativeWindow_tryAllocateBuffers(ANativeWindow* window); + +#endif // __ANDROID_API__ >= 30 + +#if __ANDROID_API__ >= 31 + /** * Sets the intended frame rate for this window. * @@ -271,7 +297,7 @@ enum ANativeWindow_FrameRateCompatibility { * this ANativeWindow is consumed by something other than the system compositor, * e.g. a media codec, this call has no effect. * - * Available since API level 30. + * Available since API level 31. * * \param frameRate The intended frame rate of this window, in frames per * second. 0 is a special value that indicates the app will accept the system's @@ -284,24 +310,19 @@ enum ANativeWindow_FrameRateCompatibility { * compatibility value may influence the system's choice of display refresh * rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info. * + * \param shouldBeSeamless Whether display refresh rate transitions 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. True indicates that any frame rate changes caused by this + * request should be seamless. False indicates that non-seamless refresh rates are also + * acceptable. + * * \return 0 for success, -EINVAL if the window, frame rate, or compatibility * value are invalid. */ -int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility) - __INTRODUCED_IN(30); +int32_t ANativeWindow_setFrameRateWithSeamlessness(ANativeWindow* window, float frameRate, + int8_t compatibility, bool shouldBeSeamless) __INTRODUCED_IN(31); -/** - * Provides a hint to the window that buffers should be preallocated ahead of - * time. Note that the window implementation is not guaranteed to preallocate - * any buffers, for instance if an implementation disallows allocation of new - * buffers, or if there is insufficient memory in the system to preallocate - * additional buffers - * - * Available since API level 30. - */ -void ANativeWindow_tryAllocateBuffers(ANativeWindow* window); - -#endif // __ANDROID_API__ >= 30 +#endif // __ANDROID_API__ >= 31 #ifdef __cplusplus }; diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 138e08f490..82d2e661b4 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -1018,9 +1018,9 @@ static inline int native_window_set_auto_prerotation(struct ANativeWindow* windo } static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate, - int8_t compatibility) { + int8_t compatibility, bool shouldBeSeamless) { return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate, - (int)compatibility); + (int)compatibility, (int)shouldBeSeamless); } static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window, diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt index 1b5d20dff7..de48ec25dd 100644 --- a/libs/nativewindow/libnativewindow.map.txt +++ b/libs/nativewindow/libnativewindow.map.txt @@ -46,6 +46,7 @@ LIBNATIVEWINDOW { ANativeWindow_setBuffersTransform; ANativeWindow_setDequeueTimeout; # apex # introduced=30 ANativeWindow_setFrameRate; # introduced=30 + ANativeWindow_setFrameRateWithSeamlessness; # introduced=31 ANativeWindow_setSharedBufferMode; # llndk ANativeWindow_setSwapInterval; # llndk ANativeWindow_setUsage; # llndk diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 94819664ce..79e2ad0dbd 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1687,8 +1687,9 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { crop.bottom); if (layerState.frameRate.rate != 0 || layerState.frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "% 6.2ffps %15s", layerState.frameRate.rate, - frameRateCompatibilityString(layerState.frameRate.type).c_str()); + StringAppendF(&result, "% 6.2ffps %15s seamless=%d", layerState.frameRate.rate, + frameRateCompatibilityString(layerState.frameRate.type).c_str(), + layerState.frameRate.shouldBeSeamless); } else { StringAppendF(&result, " "); } @@ -2750,6 +2751,12 @@ bool Layer::getPrimaryDisplayOnly() const { // --------------------------------------------------------------------------- +std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { + return stream << "{rate=" << rate.rate + << " type=" << Layer::frameRateCompatibilityString(rate.type) + << " shouldBeSeamless=" << rate.shouldBeSeamless << "}"; +} + }; // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b1ab9ec306..1a784aa778 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -153,12 +153,15 @@ public: struct FrameRate { float rate; FrameRateCompatibility type; + bool shouldBeSeamless; - FrameRate() : rate(0), type(FrameRateCompatibility::Default) {} - FrameRate(float rate, FrameRateCompatibility type) : rate(rate), type(type) {} + FrameRate() : rate(0), type(FrameRateCompatibility::Default), shouldBeSeamless(true) {} + FrameRate(float rate, FrameRateCompatibility type, bool shouldBeSeamless = true) + : rate(rate), type(type), shouldBeSeamless(shouldBeSeamless) {} bool operator==(const FrameRate& other) const { - return rate == other.rate && type == other.type; + return rate == other.rate && type == other.type && + shouldBeSeamless == other.shouldBeSeamless; } bool operator!=(const FrameRate& other) const { return !(*this == other); } @@ -1126,4 +1129,6 @@ private: const std::vector& getBlurRegions() const; }; +std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate); + } // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 36433c20ed..28af930bbe 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -125,12 +125,23 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { return LayerVoteType::NoVote; } }(); - summary.push_back({layer->getName(), voteType, frameRate.rate, /* weight */ 1.0f, - layerFocused}); + summary.push_back( + RefreshRateConfigs::LayerRequirement{.name = layer->getName(), + .vote = voteType, + .desiredRefreshRate = frameRate.rate, + .shouldBeSeamless = + frameRate.shouldBeSeamless, + .weight = 1.0f, + .focused = layerFocused}); } else if (recent) { - summary.push_back({layer->getName(), LayerVoteType::Heuristic, - info->getRefreshRate(now), - /* weight */ 1.0f, layerFocused}); + summary.push_back( + RefreshRateConfigs::LayerRequirement{.name = layer->getName(), + .vote = LayerVoteType::Heuristic, + .desiredRefreshRate = + info->getRefreshRate(now), + .shouldBeSeamless = true, + .weight = 1.0f, + .focused = layerFocused}); } if (CC_UNLIKELY(mTraceEnabled)) { diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp index 37e67e17fe..a63ccc1df0 100644 --- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -130,9 +130,9 @@ LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) { ALOGV("%s has priority: %d %s focused", strong->getName().c_str(), frameRateSelectionPriority, layerFocused ? "" : "not"); - const auto [type, refreshRate] = info->getRefreshRate(now); + const auto vote = info->getRefreshRateVote(now); // Skip NoVote layer as those don't have any requirements - if (type == LayerHistory::LayerVoteType::NoVote) { + if (vote.type == LayerHistory::LayerVoteType::NoVote) { continue; } @@ -144,10 +144,11 @@ LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) { const float layerArea = transformed.getWidth() * transformed.getHeight(); float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f; - summary.push_back({strong->getName(), type, refreshRate, weight, layerFocused}); + summary.push_back({strong->getName(), vote.type, vote.fps, vote.shouldBeSeamless, weight, + layerFocused}); if (CC_UNLIKELY(mTraceEnabled)) { - trace(layer, *info, type, static_cast(std::round(refreshRate))); + trace(layer, *info, vote.type, static_cast(std::round(vote.fps))); } } @@ -178,7 +179,7 @@ void LayerHistoryV2::partitionLayers(nsecs_t now) { if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) { const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote; - info->setLayerVote(type, frameRate.rate); + info->setLayerVote({type, frameRate.rate, frameRate.shouldBeSeamless}); } else { info->resetLayerVote(); } diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp index 44f20d0063..94e7e20251 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -198,10 +198,10 @@ std::optional LayerInfoV2::calculateRefreshRateIfPossible(nsecs_t now) { : std::make_optional(mLastRefreshRate.reported); } -std::pair LayerInfoV2::getRefreshRate(nsecs_t now) { +LayerInfoV2::LayerVote LayerInfoV2::getRefreshRateVote(nsecs_t now) { if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { ALOGV("%s voted %d ", mName.c_str(), static_cast(mLayerVote.type)); - return {mLayerVote.type, mLayerVote.fps}; + return mLayerVote; } if (isAnimating(now)) { diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h index 33dc66fd19..2305bc3055 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.h +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h @@ -56,6 +56,13 @@ class LayerInfoV2 { friend class LayerHistoryTestV2; public: + // Holds information about the layer vote + struct LayerVote { + LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; + float fps = 0.0f; + bool shouldBeSeamless = true; + }; + static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; } static void setRefreshRateConfigs(const RefreshRateConfigs& refreshRateConfigs) { @@ -76,7 +83,7 @@ public: // Sets an explicit layer vote. This usually comes directly from the application via // ANativeWindow_setFrameRate API - void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; } + void setLayerVote(LayerVote vote) { mLayerVote = vote; } // Sets the default layer vote. This will be the layer vote after calling to resetLayerVote(). // This is used for layers that called to setLayerVote() and then removed the vote, so that the @@ -84,9 +91,9 @@ public: void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } // Resets the layer vote to its default. - void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f}; } + void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f, true}; } - std::pair getRefreshRate(nsecs_t now); + LayerVote getRefreshRateVote(nsecs_t now); // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. @@ -130,12 +137,6 @@ private: bool animatingOrInfrequent = false; }; - // Holds information about the layer vote - struct LayerVote { - LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; - float fps = 0.0f; - }; - // Class to store past calculated refresh rate and determine whether // the refresh rate calculated is consistent with past values class RefreshRateHistory { diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 150f925fe0..0646c7dfd5 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -31,6 +31,12 @@ namespace android::scheduler { using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; +std::string RefreshRate::toString() const { + return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", + getConfigId().value(), hwcConfig->getId(), getFps(), + hwcConfig->getWidth(), hwcConfig->getHeight(), getConfigGroup()); +} + std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { switch (vote) { case LayerVoteType::NoVote: @@ -125,7 +131,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const std::vector& layers, const GlobalSignals& globalSignals, GlobalSignals* outSignalsConsidered) const { ATRACE_CALL(); - ALOGV("getRefreshRateForContent %zu layers", layers.size()); + ALOGV("getBestRefreshRate %zu layers", layers.size()); if (outSignalsConsidered) *outSignalsConsidered = {}; const auto setTouchConsidered = [&] { @@ -148,6 +154,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( int explicitDefaultVoteLayers = 0; int explicitExactOrMultipleVoteLayers = 0; float maxExplicitWeight = 0; + int seamedLayers = 0; for (const auto& layer : layers) { if (layer.vote == LayerVoteType::NoVote) { noVoteLayers++; @@ -162,6 +169,10 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( explicitExactOrMultipleVoteLayers++; maxExplicitWeight = std::max(maxExplicitWeight, layer.weight); } + + if (!layer.shouldBeSeamless) { + seamedLayers++; + } } const bool hasExplicitVoteLayers = @@ -206,6 +217,8 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( scores.emplace_back(refreshRate, 0.0f); } + const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig); + for (const auto& layer : layers) { ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(), layerVoteTypeString(layer.vote).c_str(), layer.weight); @@ -216,6 +229,30 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( auto weight = layer.weight; for (auto i = 0u; i < scores.size(); i++) { + // If there are no layers with shouldBeSeamless=false and the current + // config group is different from the default one, this means a layer with + // shouldBeSeamless=false has just disappeared and we should switch back to + // the default config group. + const bool isSeamlessSwitch = seamedLayers > 0 + ? scores[i].first->getConfigGroup() == mCurrentRefreshRate->getConfigGroup() + : scores[i].first->getConfigGroup() == defaultConfig->getConfigGroup(); + + if (layer.shouldBeSeamless && !isSeamlessSwitch) { + ALOGV("%s (weight %.2f) ignores %s (group=%d) to avoid non-seamless switch." + "Current config = %s", + layer.name.c_str(), weight, scores[i].first->name.c_str(), + scores[i].first->getConfigGroup(), mCurrentRefreshRate->toString().c_str()); + continue; + } + + if (!layer.shouldBeSeamless && !isSeamlessSwitch && !layer.focused) { + ALOGV("%s (weight %.2f) ignores %s (group=%d) because it's not focused" + " and the switch is going to be seamed. Current config = %s", + layer.name.c_str(), weight, scores[i].first->name.c_str(), + scores[i].first->getConfigGroup(), mCurrentRefreshRate->toString().c_str()); + continue; + } + bool inPrimaryRange = scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max); if ((primaryRangeIsSingleRate || !inPrimaryRange) && @@ -292,10 +329,13 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( return 1.0f / iter; }(); + // Slightly prefer seamless switches. + constexpr float kSeamedSwitchPenalty = 0.95f; + const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; ALOGV("%s (%s, weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), layerVoteTypeString(layer.vote).c_str(), weight, 1e9f / layerPeriod, scores[i].first->name.c_str(), layerScore); - scores[i].second += weight * layerScore; + scores[i].second += weight * layerScore * seamlessness; continue; } } @@ -367,6 +407,15 @@ const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { + for (auto refreshRate : mPrimaryRefreshRates) { + if (mCurrentRefreshRate->getConfigGroup() == refreshRate->getConfigGroup()) { + return *refreshRate; + } + } + ALOGE("Can't find min refresh rate by policy with the same config group" + " as the current config %s", + mCurrentRefreshRate->toString().c_str()); + // Defaulting to the lowest refresh rate return *mPrimaryRefreshRates.front(); } @@ -376,6 +425,16 @@ const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { } const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { + for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); it++) { + const auto& refreshRate = (**it); + if (mCurrentRefreshRate->getConfigGroup() == refreshRate.getConfigGroup()) { + return refreshRate; + } + } + ALOGE("Can't find max refresh rate by policy with the same config group" + " as the current config %s", + mCurrentRefreshRate->toString().c_str()); + // Defaulting to the highest refresh rate return *mPrimaryRefreshRates.back(); } @@ -414,7 +473,7 @@ RefreshRateConfigs::RefreshRateConfigs( const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique(configId, config, - base::StringPrintf("%.0ffps", fps), fps, + base::StringPrintf("%.2ffps", fps), fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 8ff92a095c..41e54a7e7b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -86,6 +86,8 @@ public: bool operator==(const RefreshRate& other) const { return !(*this != other); } + std::string toString() const; + private: friend RefreshRateConfigs; friend class RefreshRateConfigsTest; @@ -216,6 +218,8 @@ public: LayerVoteType vote = LayerVoteType::NoVote; // Layer's desired refresh rate, if applicable. float desiredRefreshRate = 0.0f; + // If a seamless mode switch is required. + bool shouldBeSeamless = true; // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer // would have on choosing the refresh rate. float weight = 0.0f; diff --git a/services/surfaceflinger/Scheduler/StrongTyping.h b/services/surfaceflinger/Scheduler/StrongTyping.h index e8ca0ba836..6a60257c81 100644 --- a/services/surfaceflinger/Scheduler/StrongTyping.h +++ b/services/surfaceflinger/Scheduler/StrongTyping.h @@ -70,6 +70,10 @@ struct StrongTyping : Ability>... { T const& value() const { return mValue; } T& value() { return mValue; } + friend std::ostream& operator<<(std::ostream& os, const StrongTyping& value) { + return os << value.value(); + } + private: T mValue; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 57c4d52653..28a8e7ac12 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3781,7 +3781,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( "SurfaceFlinger::setClientStateLocked") && layer->setFrameRate(Layer::FrameRate(s.frameRate, Layer::FrameRate::convertCompatibility( - s.frameRateCompatibility)))) { + s.frameRateCompatibility), + s.shouldBeSeamless))) { flags |= eTraversalNeeded; } } @@ -6135,7 +6136,7 @@ const std::unordered_map& SurfaceFlinger::getGenericLayer } status_t SurfaceFlinger::setFrameRate(const sp& surface, float frameRate, - int8_t compatibility) { + int8_t compatibility, bool shouldBeSeamless) { if (!ValidateFrameRate(frameRate, compatibility, "SurfaceFlinger::setFrameRate")) { return BAD_VALUE; } @@ -6148,10 +6149,10 @@ status_t SurfaceFlinger::setFrameRate(const sp& surface, ALOGE("Attempt to set frame rate on a layer that no longer exists"); return BAD_VALUE; } - if (layer->setFrameRate( Layer::FrameRate(frameRate, - Layer::FrameRate::convertCompatibility(compatibility)))) { + Layer::FrameRate::convertCompatibility(compatibility), + shouldBeSeamless))) { setTransactionFlags(eTraversalNeeded); } } else { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a821d4473f..9666f145b0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -600,7 +600,7 @@ private: status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) override; status_t setFrameRate(const sp& surface, float frameRate, - int8_t compatibility) override; + int8_t compatibility, bool shouldBeSeamless) override; status_t acquireFrameRateFlexibilityToken(sp* outToken) override; status_t setFrameTimelineVsync(const sp& surface, diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index da71dad2d4..b87c734e27 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -123,7 +123,7 @@ protected: } virtual void fillBufferQueueLayerColor(const sp& layer, const Color& color, - int32_t bufferWidth, int32_t bufferHeight) { + uint32_t bufferWidth, uint32_t bufferHeight) { ANativeWindow_Buffer buffer; ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); TransactionUtils::fillANativeWindowBufferColor(buffer, @@ -145,7 +145,7 @@ protected: } void fillLayerColor(uint32_t mLayerType, const sp& layer, const Color& color, - int32_t bufferWidth, int32_t bufferHeight) { + uint32_t bufferWidth, uint32_t bufferHeight) { switch (mLayerType) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); diff --git a/services/surfaceflinger/tests/SetFrameRate_test.cpp b/services/surfaceflinger/tests/SetFrameRate_test.cpp index 02ba9e290d..d1bed0cc83 100644 --- a/services/surfaceflinger/tests/SetFrameRate_test.cpp +++ b/services/surfaceflinger/tests/SetFrameRate_test.cpp @@ -14,10 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" - #include #include @@ -50,8 +46,8 @@ protected: } } - const int mLayerWidth = 32; - const int mLayerHeight = 32; + const uint32_t mLayerWidth = 32; + const uint32_t mLayerHeight = 32; sp mLayer; uint32_t mLayerType; }; @@ -59,26 +55,27 @@ protected: TEST_F(SetFrameRateTest, BufferQueueLayerSetFrameRate) { CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferQueue); native_window_set_frame_rate(mLayer->getSurface().get(), 100.f, - ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT); + ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + /* shouldBeSeamless */ true); ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); Transaction() - .setFrameRate(mLayer, 200.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT) + .setFrameRate(mLayer, 200.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + /* shouldBeSeamless */ true) .apply(); ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); native_window_set_frame_rate(mLayer->getSurface().get(), 300.f, - ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT); + ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + /* shouldBeSeamless */ true); ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); } TEST_F(SetFrameRateTest, BufferStateLayerSetFrameRate) { CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferState); Transaction() - .setFrameRate(mLayer, 400.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT) + .setFrameRate(mLayer, 400.f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + /* shouldBeSeamless */ true) .apply(); ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::GREEN)); } } // namespace android - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h index 01badf4ad9..a361b1e956 100644 --- a/services/surfaceflinger/tests/TransactionTestHarnesses.h +++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h @@ -98,14 +98,14 @@ public: outTransformHint, format); } - void fillLayerColor(const sp& layer, const Color& color, int32_t bufferWidth, - int32_t bufferHeight) { + void fillLayerColor(const sp& layer, const Color& color, uint32_t bufferWidth, + uint32_t bufferHeight) { ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, bufferWidth, bufferHeight)); } - void fillLayerQuadrant(const sp& layer, int32_t bufferWidth, - int32_t bufferHeight, const Color& topLeft, const Color& topRight, + void fillLayerQuadrant(const sp& layer, uint32_t bufferWidth, + uint32_t bufferHeight, const Color& topLeft, const Color& topRight, const Color& bottomLeft, const Color& bottomRight) { ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, bufferWidth, bufferHeight, diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index cb376cd7bb..3b50321102 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -78,7 +78,7 @@ protected: for (auto& [weak, info] : history().mLayerInfos) { if (auto strong = weak.promote(); strong && strong.get() == layer) { info->setDefaultLayerVote(vote); - info->setLayerVote(vote, 0); + info->setLayerVote({vote, 0, false}); return; } } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 4762fd4b66..df7611043a 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -57,6 +57,8 @@ protected: static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(2); static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3); static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4); + static inline const HwcConfigIndexType HWC_CONFIG_ID_25 = HwcConfigIndexType(5); + static inline const HwcConfigIndexType HWC_CONFIG_ID_50 = HwcConfigIndexType(6); // Test configs std::shared_ptr mConfig60 = @@ -77,8 +79,16 @@ protected: createConfig(HWC_CONFIG_ID_120, 1, static_cast(1e9f / 120)); std::shared_ptr mConfig30 = createConfig(HWC_CONFIG_ID_30, 0, static_cast(1e9f / 30)); + std::shared_ptr mConfig30DifferentGroup = + createConfig(HWC_CONFIG_ID_30, 1, static_cast(1e9f / 30)); + std::shared_ptr mConfig25DifferentGroup = + createConfig(HWC_CONFIG_ID_25, 1, static_cast(1e9f / 25)); + std::shared_ptr mConfig50 = + createConfig(HWC_CONFIG_ID_50, 0, static_cast(1e9f / 50)); // Test device configurations + // The positions of the configs in the arrays below MUST match their IDs. For example, + // the first config should always be 60Hz, the second 90Hz etc. std::vector> m60OnlyConfigDevice = {mConfig60}; std::vector> m60_90Device = {mConfig60, mConfig90}; std::vector> m60_90DeviceWithDifferentGroups = @@ -104,6 +114,14 @@ protected: {mConfig60, mConfig90, mConfig72, mConfig120DifferentGroup, mConfig30}; std::vector> m30_60_90Device = {mConfig60, mConfig90, mConfig72DifferentGroup, mConfig120DifferentGroup, mConfig30}; + std::vector> m25_30_50_60Device = + {mConfig60, + mConfig90, + mConfig72DifferentGroup, + mConfig120DifferentGroup, + mConfig30DifferentGroup, + mConfig25DifferentGroup, + mConfig50}; // Expected RefreshRate objects RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, "60fps", 60, @@ -292,8 +310,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { /*currentConfigId=*/HWC_CONFIG_ID_60); const auto makeLayerRequirements = [](float refreshRate) -> std::vector { - return {{"testLayer", LayerVoteType::Heuristic, refreshRate, /*weight*/ 1.0f, - /*focused*/ false}}; + return {{"testLayer", LayerVoteType::Heuristic, refreshRate, /*shouldBeSeamless*/ true, + /*weight*/ 1.0f, /*focused*/ false}}; }; EXPECT_EQ(mExpected90Config, @@ -1245,7 +1263,9 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { auto& layer = layers[0]; layer.vote = LayerVoteType::ExplicitDefault; layer.desiredRefreshRate = 90.0f; + layer.shouldBeSeamless = false; layer.name = "90Hz ExplicitDefault"; + layer.focused = true; ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) @@ -1258,6 +1278,104 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) .getConfigId()); + + // Verify that we won't change the group if seamless switch is required. + layer.shouldBeSeamless = true; + ASSERT_EQ(HWC_CONFIG_ID_60, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); + + // At this point the default config in the DisplayManager policy with be 60Hz. + // Verify that if the current config is in another group and there are no layers with + // shouldBeSeamless=false we'll go back to the default group. + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + layer.desiredRefreshRate = 60.0f; + layer.name = "60Hz ExplicitDefault"; + layer.shouldBeSeamless = true; + ASSERT_EQ(HWC_CONFIG_ID_60, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); + + // If there's a layer with shouldBeSeamless=false, another layer with shouldBeSeamless=true + // can't change the config group. + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + auto layer2 = LayerRequirement{.weight = 0.5f}; + layer2.vote = LayerVoteType::ExplicitDefault; + layer2.desiredRefreshRate = 90.0f; + layer2.name = "90Hz ExplicitDefault"; + layer2.shouldBeSeamless = false; + layer2.focused = false; + layers.push_back(layer2); + ASSERT_EQ(HWC_CONFIG_ID_90, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); +} + +TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { + auto refreshRateConfigs = + std::make_unique(m30_60Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + // Allow group switching. + RefreshRateConfigs::Policy policy; + policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; + policy.allowGroupSwitching = true; + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& layer = layers[0]; + layer.vote = LayerVoteType::ExplicitExactOrMultiple; + layer.desiredRefreshRate = 60.0f; + layer.shouldBeSeamless = false; + layer.name = "60Hz ExplicitExactOrMultiple"; + layer.focused = true; + + ASSERT_EQ(HWC_CONFIG_ID_60, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); + + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120); + ASSERT_EQ(HWC_CONFIG_ID_120, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); +} + +TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { + auto refreshRateConfigs = + std::make_unique(m25_30_50_60Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + // Allow group switching. + RefreshRateConfigs::Policy policy; + policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; + policy.allowGroupSwitching = true; + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); + + auto layers = std::vector< + LayerRequirement>{LayerRequirement{.name = "60Hz ExplicitDefault", + .vote = LayerVoteType::ExplicitDefault, + .desiredRefreshRate = 60.0f, + .shouldBeSeamless = false, + .weight = 0.5f, + .focused = false}, + LayerRequirement{.name = "25Hz ExplicitExactOrMultiple", + .vote = LayerVoteType::ExplicitExactOrMultiple, + .desiredRefreshRate = 25.0f, + .shouldBeSeamless = true, + .weight = 1.0f, + .focused = true}}; + auto& seamedLayer = layers[0]; + + ASSERT_EQ(HWC_CONFIG_ID_50, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); + + seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = 30.0f; + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_30); + + ASSERT_EQ(HWC_CONFIG_ID_25, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) + .getConfigId()); } TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index de66f8fb41..d0bb9e291a 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -108,7 +108,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - EXPECT_EQ(0u, times.count("90fps")); + EXPECT_EQ(0u, times.count("90.00fps")); mRefreshRateStats->setConfigMode(CONFIG_ID_0); mRefreshRateStats->setPowerMode(PowerMode::ON); @@ -116,15 +116,15 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_EQ(screenOff, times["ScreenOff"]); - ASSERT_EQ(1u, times.count("90fps")); - EXPECT_LT(0, times["90fps"]); + ASSERT_EQ(1u, times.count("90.00fps")); + EXPECT_LT(0, times["90.00fps"]); mRefreshRateStats->setPowerMode(PowerMode::DOZE); - int ninety = mRefreshRateStats->getTotalTimes()["90fps"]; + int ninety = mRefreshRateStats->getTotalTimes()["90.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); mRefreshRateStats->setConfigMode(CONFIG_ID_0); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; @@ -133,7 +133,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { // Because the power mode is not PowerMode::ON, switching the config // does not update refresh rates that come from the config. EXPECT_LT(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); } TEST_F(RefreshRateStatsTest, twoConfigsTest) { @@ -163,53 +163,53 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_EQ(screenOff, times["ScreenOff"]); - ASSERT_EQ(1u, times.count("90fps")); - EXPECT_LT(0, times["90fps"]); + ASSERT_EQ(1u, times.count("90.00fps")); + EXPECT_LT(0, times["90.00fps"]); // When power mode is normal, time for configs updates. mRefreshRateStats->setConfigMode(CONFIG_ID_1); - int ninety = mRefreshRateStats->getTotalTimes()["90fps"]; + int ninety = mRefreshRateStats->getTotalTimes()["90.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_EQ(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); - ASSERT_EQ(1u, times.count("60fps")); - EXPECT_LT(0, times["60fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); + ASSERT_EQ(1u, times.count("60.00fps")); + EXPECT_LT(0, times["60.00fps"]); mRefreshRateStats->setConfigMode(CONFIG_ID_0); - int sixty = mRefreshRateStats->getTotalTimes()["60fps"]; + int sixty = mRefreshRateStats->getTotalTimes()["60.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_EQ(screenOff, times["ScreenOff"]); - EXPECT_LT(ninety, times["90fps"]); - EXPECT_EQ(sixty, times["60fps"]); + EXPECT_LT(ninety, times["90.00fps"]); + EXPECT_EQ(sixty, times["60.00fps"]); mRefreshRateStats->setConfigMode(CONFIG_ID_1); - ninety = mRefreshRateStats->getTotalTimes()["90fps"]; + ninety = mRefreshRateStats->getTotalTimes()["90.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_EQ(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); - EXPECT_LT(sixty, times["60fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); + EXPECT_LT(sixty, times["60.00fps"]); // Because the power mode is not PowerMode::ON, switching the config // does not update refresh rates that come from the config. mRefreshRateStats->setPowerMode(PowerMode::DOZE); mRefreshRateStats->setConfigMode(CONFIG_ID_0); - sixty = mRefreshRateStats->getTotalTimes()["60fps"]; + sixty = mRefreshRateStats->getTotalTimes()["60.00fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); - EXPECT_EQ(sixty, times["60fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); + EXPECT_EQ(sixty, times["60.00fps"]); mRefreshRateStats->setConfigMode(CONFIG_ID_1); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - EXPECT_EQ(ninety, times["90fps"]); - EXPECT_EQ(sixty, times["60fps"]); + EXPECT_EQ(ninety, times["90.00fps"]); + EXPECT_EQ(sixty, times["60.00fps"]); } } // namespace } // namespace scheduler -- cgit v1.2.3-59-g8ed1b From cf26a0a9c5467ca6ff0ab71dc944ea7341ec62e1 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 13 Nov 2020 12:56:20 -0800 Subject: BlastBufferQueue: Add support for auto refresh When BQ is in shared bufer mode, the client can request the consumer to aquire frames as fast as possible before waiting for a frame to be available. To support this for BLAST, pass the state via a transaction. Fixes: 168506187 Test: atest SurfaceViewBufferTests Change-Id: I25ddd98671a08e56798612b7e5dc72095b2c4b7b --- libs/gui/BLASTBufferQueue.cpp | 5 +++++ libs/gui/LayerState.cpp | 20 +++++++++++++++++++- libs/gui/SurfaceComposerClient.cpp | 13 +++++++++++++ libs/gui/include/gui/BLASTBufferQueue.h | 4 ++++ libs/gui/include/gui/LayerState.h | 6 ++++++ libs/gui/include/gui/SurfaceComposerClient.h | 5 +++++ services/surfaceflinger/BufferLayer.h | 8 ++++++-- services/surfaceflinger/BufferQueueLayer.cpp | 12 +++--------- services/surfaceflinger/BufferQueueLayer.h | 6 ------ services/surfaceflinger/BufferStateLayer.cpp | 11 ++++------- services/surfaceflinger/BufferStateLayer.h | 6 +----- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 3 +++ 13 files changed, 70 insertions(+), 30 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 6db6112762..e6aa02a8fe 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -289,6 +289,11 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setDesiredPresentTime(bufferItem.mTimestamp); t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); + if (mAutoRefresh != bufferItem.mAutoRefresh) { + t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh); + mAutoRefresh = bufferItem.mAutoRefresh; + } + if (applyTransaction) { t->apply(); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 90999faa78..7d2c7b88df 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -61,7 +61,9 @@ layer_state_t::layer_state_t() frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), shouldBeSeamless(true), fixedTransformHint(ui::Transform::ROT_INVALID), - frameNumber(0) { + frameNumber(0), + frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), + autoRefresh(false) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -149,6 +151,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); + SAFE_PARCEL(output.writeBool, autoRefresh); SAFE_PARCEL(output.writeUint32, blurRegions.size()); for (auto region : blurRegions) { @@ -269,6 +272,7 @@ status_t layer_state_t::read(const Parcel& input) fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId); + SAFE_PARCEL(input.readBool, &autoRefresh); uint32_t numRegions = 0; SAFE_PARCEL(input.readUint32, &numRegions); @@ -534,6 +538,20 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameNumberChanged; frameNumber = other.frameNumber; } + if (other.what & eFrameTimelineVsyncChanged) { + // When merging vsync Ids we take the oldest valid one + if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && + other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { + frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId); + } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { + frameTimelineVsyncId = other.frameTimelineVsyncId; + } + what |= eFrameTimelineVsyncChanged; + } + if (other.what & eAutoRefreshChanged) { + what |= eAutoRefreshChanged; + autoRefresh = other.autoRefresh; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index a822598d82..47a08ab500 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1527,6 +1527,19 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAutoRefresh( + const sp& sc, bool autoRefresh) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eAutoRefreshChanged; + s->autoRefresh = autoRefresh; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 42427c0539..9fb7d6fd36 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -139,6 +139,10 @@ private: // If set to true, the next queue buffer will wait until the shadow queue has been processed by // the adapter. bool mFlushShadowQueue = false; + // Last requested auto refresh state set by the producer. The state indicates that the consumer + // should acquire the next frame as soon as it can and not wait for a frame to become available. + // This is only relevant for shared buffer mode. + bool mAutoRefresh GUARDED_BY(mMutex) = false; }; } // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index d9f280684f..f1c5d6712d 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -130,6 +130,7 @@ struct layer_state_t { eFrameNumberChanged = 0x400'00000000, eFrameTimelineVsyncChanged = 0x800'00000000, eBlurRegionsChanged = 0x1000'00000000, + eAutoRefreshChanged = 0x2000'00000000, }; layer_state_t(); @@ -234,6 +235,11 @@ struct layer_state_t { uint64_t frameNumber; int64_t frameTimelineVsyncId; + + // Indicates that the consumer should acquire the next frame as soon as it + // can and not wait for a frame to become available. This is only relevant + // in shared buffer mode. + bool autoRefresh; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6289c6a3cd..2eb97f27a1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -541,6 +541,11 @@ public: Transaction& setFrameTimelineVsync(const sp& sc, int64_t frameTimelineVsyncId); + // Indicates that the consumer should acquire the next frame as soon as it + // can and not wait for a frame to become available. This is only relevant + // in shared buffer mode. + Transaction& setAutoRefresh(const sp& sc, bool autoRefresh); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index deaf8461e8..63dfe5f5d9 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -178,13 +178,17 @@ protected: /// the mStateLock. ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0; + bool getAutoRefresh() const { return mAutoRefresh; } + bool getSidebandStreamChanged() const { return mSidebandStreamChanged; } + + std::atomic mAutoRefresh{false}; + std::atomic mSidebandStreamChanged{false}; + private: virtual bool fenceHasSignaled() const = 0; virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; - virtual bool getAutoRefresh() const = 0; - virtual bool getSidebandStreamChanged() const = 0; // Latch sideband stream and returns true if the dirty region should be updated. virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 71b05fd2bf..dc99986900 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -196,14 +196,6 @@ uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { return frameNumber; } -bool BufferQueueLayer::getAutoRefresh() const { - return mAutoRefresh; -} - -bool BufferQueueLayer::getSidebandStreamChanged() const { - return mSidebandStreamChanged; -} - bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // We need to update the sideband stream if the layer has both a buffer and a sideband stream. const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get(); @@ -265,8 +257,10 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t const uint64_t maxFrameNumberToAcquire = std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber); - status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, + bool autoRefresh; + status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &autoRefresh, &queuedBuffer, maxFrameNumberToAcquire); + mAutoRefresh = autoRefresh; if (updateResult == BufferQueue::PRESENT_LATER) { // Producer doesn't want buffer to be displayed yet. Signal a // layer update so we check again at the next opportunity. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index fb8a0c22ee..b45900ef4c 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -90,9 +90,6 @@ protected: private: uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; - bool getAutoRefresh() const override; - bool getSidebandStreamChanged() const override; - bool latchSidebandStream(bool& recomputeVisibleRegions) override; void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; @@ -140,11 +137,8 @@ private: std::vector mQueueItems; std::atomic mLastFrameNumberReceived{0}; - bool mAutoRefresh{false}; - // thread-safe std::atomic mQueuedFrames{0}; - std::atomic mSidebandStreamChanged{false}; sp mContentsChangedListener; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 234b6e219b..963e54105d 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -482,13 +482,10 @@ uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) return mCurrentState.frameNumber; } -bool BufferStateLayer::getAutoRefresh() const { - // TODO(marissaw): support shared buffer mode - return false; -} - -bool BufferStateLayer::getSidebandStreamChanged() const { - return mSidebandStreamChanged.load(); +void BufferStateLayer::setAutoRefresh(bool autoRefresh) { + if (!mAutoRefresh.exchange(autoRefresh)) { + mFlinger->signalLayerUpdate(); + } } bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 104a13be71..42be62a763 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -100,6 +100,7 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; Layer::RoundedCornerState getRoundedCornerState() const override; + void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- @@ -123,9 +124,6 @@ private: uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; - bool getAutoRefresh() const override; - bool getSidebandStreamChanged() const override; - bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -149,8 +147,6 @@ private: std::unique_ptr mTextureImage; - std::atomic mSidebandStreamChanged{false}; - mutable uint64_t mFrameNumber{0}; uint64_t mFrameCounter{0}; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 1a784aa778..8d67ce52cd 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -444,6 +444,7 @@ public: virtual bool setColorSpaceAgnostic(const bool agnostic); virtual bool setFrameRateSelectionPriority(int32_t priority); virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint); + virtual void setAutoRefresh(bool /* autoRefresh */) {} // If the variable is not set on the layer, it traverses up the tree to inherit the frame // rate priority from its parent. virtual int32_t getFrameRateSelectionPriority() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 91f050c017..4e398d354b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3796,6 +3796,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded | eTransformHintUpdateNeeded; } } + if (what & layer_state_t::eAutoRefreshChanged) { + layer->setAutoRefresh(s.autoRefresh); + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not -- cgit v1.2.3-59-g8ed1b From 9c03b50a30c163ad4cee13455311812ef563db40 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 24 Nov 2020 23:51:31 +0100 Subject: Add Shared timeline jank classification listener (1/2) Adds the ability to register a listener that gets informed about SF' jank classifications via the TransactionCompleted interface Bug: 17475548 Test: FrameTimelineTest Test: Register listener, ensure data flows back Change-Id: Ie42c508da605c03569eadab6ab18b7315b35d247 --- libs/gui/ITransactionCompletedListener.cpp | 88 +++++++++++----------- libs/gui/SurfaceComposerClient.cpp | 29 +++++++ .../include/gui/ITransactionCompletedListener.h | 30 +++++++- libs/gui/include/gui/SurfaceComposerClient.h | 19 +++++ services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.h | 6 +- services/surfaceflinger/BufferStateLayer.cpp | 20 ++++- services/surfaceflinger/BufferStateLayer.h | 3 + .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 20 ++--- .../surfaceflinger/FrameTimeline/FrameTimeline.h | 20 +++-- services/surfaceflinger/Layer.cpp | 10 +-- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 8 +- .../surfaceflinger/TransactionCompletedThread.cpp | 11 +-- .../surfaceflinger/TransactionCompletedThread.h | 6 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 1 + .../tests/unittests/FrameTimelineTest.cpp | 38 ++++++---- .../tests/unittests/mock/MockFrameTimeline.h | 2 +- 18 files changed, 219 insertions(+), 97 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 69f7894d07..2dacae1cad 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -17,6 +17,8 @@ #define LOG_TAG "ITransactionCompletedListener" //#define LOG_NDEBUG 0 +#include +#include #include namespace android { @@ -90,61 +92,63 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } +JankData::JankData() : + frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), + jankType(JankType::None) { +} + +status_t JankData::writeToParcel(Parcel* output) const { + SAFE_PARCEL(output->writeInt64, frameVsyncId); + SAFE_PARCEL(output->writeInt32, static_cast(jankType)); + return NO_ERROR; +} + +status_t JankData::readFromParcel(const Parcel* input) { + SAFE_PARCEL(input->readInt64, &frameVsyncId); + int32_t jankTypeInt; + SAFE_PARCEL(input->readInt32, &jankTypeInt); + jankType = static_cast(jankTypeInt); + return NO_ERROR; +} + status_t SurfaceStats::writeToParcel(Parcel* output) const { - status_t err = output->writeStrongBinder(surfaceControl); - if (err != NO_ERROR) { - return err; - } - err = output->writeInt64(acquireTime); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(output->writeStrongBinder, surfaceControl); + SAFE_PARCEL(output->writeInt64, acquireTime); if (previousReleaseFence) { - err = output->writeBool(true); - if (err != NO_ERROR) { - return err; - } - err = output->write(*previousReleaseFence); + SAFE_PARCEL(output->writeBool, true); + SAFE_PARCEL(output->write, *previousReleaseFence); } else { - err = output->writeBool(false); + SAFE_PARCEL(output->writeBool, false); } - err = output->writeUint32(transformHint); - if (err != NO_ERROR) { - return err; + SAFE_PARCEL(output->writeUint32, transformHint); + SAFE_PARCEL(output->writeParcelable, eventStats); + SAFE_PARCEL(output->writeInt32, static_cast(jankData.size())); + for (const auto& data : jankData) { + SAFE_PARCEL(output->writeParcelable, data); } - - err = output->writeParcelable(eventStats); - return err; + return NO_ERROR; } status_t SurfaceStats::readFromParcel(const Parcel* input) { - status_t err = input->readStrongBinder(&surfaceControl); - if (err != NO_ERROR) { - return err; - } - err = input->readInt64(&acquireTime); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->readStrongBinder, &surfaceControl); + SAFE_PARCEL(input->readInt64, &acquireTime); bool hasFence = false; - err = input->readBool(&hasFence); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); - err = input->read(*previousReleaseFence); - if (err != NO_ERROR) { - return err; - } + SAFE_PARCEL(input->read, *previousReleaseFence); } - err = input->readUint32(&transformHint); - if (err != NO_ERROR) { - return err; + SAFE_PARCEL(input->readUint32, &transformHint); + SAFE_PARCEL(input->readParcelable, &eventStats); + + int32_t jankData_size = 0; + SAFE_PARCEL_READ_SIZE(input->readInt32, &jankData_size, input->dataSize()); + for (int i = 0; i < jankData_size; i++) { + JankData data; + SAFE_PARCEL(input->readParcelable, &data); + jankData.push_back(data); } - - err = input->readParcelable(&eventStats); - return err; + return NO_ERROR; } status_t TransactionStats::writeToParcel(Parcel* output) const { diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 47a08ab500..9ed7d1cc19 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -125,6 +125,9 @@ sp SurfaceComposerClient::getDefault() { return DefaultComposerClient::getComposerClient(); } +JankDataListener::~JankDataListener() { +} + // --------------------------------------------------------------------------- // TransactionCompletedListener does not use ANDROID_SINGLETON_STATIC_INSTANCE because it needs @@ -174,6 +177,23 @@ CallbackId TransactionCompletedListener::addCallbackFunction( return callbackId; } +void TransactionCompletedListener::addJankListener(const sp& listener, + sp surfaceControl) { + std::lock_guard lock(mMutex); + mJankListeners.insert({surfaceControl->getHandle(), listener}); +} + +void TransactionCompletedListener::removeJankListener(const sp& listener) { + std::lock_guard lock(mMutex); + for (auto it = mJankListeners.begin(); it != mJankListeners.end();) { + if (it->second == listener) { + it = mJankListeners.erase(it); + } else { + it++; + } + } +} + void TransactionCompletedListener::addSurfaceControlToCallbacks( const sp& surfaceControl, const std::unordered_set& callbackIds) { @@ -189,6 +209,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map callbacksMap; + std::multimap, sp> jankListenersMap; { std::lock_guard lock(mMutex); @@ -204,6 +225,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener * sp that could possibly exist for the callbacks. */ callbacksMap = mCallbacks; + jankListenersMap = mJankListeners; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); @@ -236,6 +258,13 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener callbackFunction(transactionStats.latchTime, transactionStats.presentFence, surfaceControlStats); } + for (const auto& surfaceStats : transactionStats.surfaceStats) { + if (surfaceStats.jankData.empty()) continue; + for (auto it = jankListenersMap.find(surfaceStats.surfaceControl); + it != jankListenersMap.end(); it++) { + it->second->onJankDataAvailable(surfaceStats.jankData); + } + } } } diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index c58634b8a2..26b3840b5e 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -16,6 +16,8 @@ #pragma once +#include "JankInfo.h" + #include #include #include @@ -57,6 +59,27 @@ public: nsecs_t dequeueReadyTime; }; +/** + * Jank information representing SurfaceFlinger's jank classification about frames for a specific + * surface. + */ +class JankData : public Parcelable { +public: + status_t writeToParcel(Parcel* output) const override; + status_t readFromParcel(const Parcel* input) override; + + JankData(); + JankData(int64_t frameVsyncId, JankType jankType) + : frameVsyncId(frameVsyncId), + jankType(jankType) {} + + // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId + int64_t frameVsyncId; + + // The type of jank occurred + JankType jankType; +}; + class SurfaceStats : public Parcelable { public: status_t writeToParcel(Parcel* output) const override; @@ -64,18 +87,21 @@ public: SurfaceStats() = default; SurfaceStats(const sp& sc, nsecs_t time, const sp& prevReleaseFence, - uint32_t hint, FrameEventHistoryStats frameEventStats) + uint32_t hint, FrameEventHistoryStats frameEventStats, + std::vector jankData) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), - eventStats(frameEventStats) {} + eventStats(frameEventStats), + jankData(std::move(jankData)) {} sp surfaceControl; nsecs_t acquireTime = -1; sp previousReleaseFence; uint32_t transformHint = 0; FrameEventHistoryStats eventStats; + std::vector jankData; }; class TransactionStats : public Parcelable { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2eb97f27a1..f1845ee5ef 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -619,6 +619,12 @@ public: // --------------------------------------------------------------------------- +class JankDataListener : public VirtualLightRefBase { +public: + virtual ~JankDataListener() = 0; + virtual void onJankDataAvailable(const std::vector& jankData) = 0; +}; + class TransactionCompletedListener : public BnTransactionCompletedListener { TransactionCompletedListener(); @@ -637,6 +643,7 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { }; std::unordered_map mCallbacks GUARDED_BY(mMutex); + std::multimap, sp> mJankListeners GUARDED_BY(mMutex); public: static sp getInstance(); @@ -652,6 +659,18 @@ public: void addSurfaceControlToCallbacks(const sp& surfaceControl, const std::unordered_set& callbackIds); + /* + * Adds a jank listener to be informed about SurfaceFlinger's jank classification for a specific + * surface. Jank classifications arrive as part of the transaction callbacks about previous + * frames submitted to this Surface. + */ + void addJankListener(const sp& listener, sp surfaceControl); + + /** + * Removes a jank listener previously added to addJankCallback. + */ + void removeJankListener(const sp& listener); + // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted(ListenerStats stats) override; }; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc99986900..325ecfe8ae 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -440,7 +440,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mName, mFrameTimelineVsyncId); surfaceFrame->setActualQueueTime(systemTime()); - mQueueItems.push_back({item, std::move(surfaceFrame)}); + mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; // Wake up any pending callbacks diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index b45900ef4c..5a6b9bcf6c 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -129,10 +129,10 @@ private: Condition mQueueItemCondition; struct BufferData { - BufferData(BufferItem item, std::unique_ptr surfaceFrame) - : item(item), surfaceFrame(std::move(surfaceFrame)) {} + BufferData(BufferItem item, std::shared_ptr surfaceFrame) + : item(item), surfaceFrame(surfaceFrame) {} BufferItem item; - std::unique_ptr surfaceFrame; + std::shared_ptr surfaceFrame; }; std::vector mQueueItems; std::atomic mLastFrameNumberReceived{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 963e54105d..4efff75351 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -100,14 +100,30 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { } } +void BufferStateLayer::onSurfaceFrameCreated( + const std::shared_ptr& surfaceFrame) { + mPendingJankClassifications.emplace_back(surfaceFrame); +} + void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; handle->dequeueReadyTime = dequeueReadyTime; } + std::vector jankData; + jankData.reserve(mPendingJankClassifications.size()); + while (!mPendingJankClassifications.empty() + && mPendingJankClassifications.front()->getJankType()) { + std::shared_ptr surfaceFrame = + mPendingJankClassifications.front(); + mPendingJankClassifications.pop_front(); + jankData.emplace_back( + JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value())); + } + mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( - mDrawingState.callbackHandles); + mDrawingState.callbackHandles, jankData); mDrawingState.callbackHandles = {}; @@ -382,7 +398,7 @@ bool BufferStateLayer::setTransactionCompletedListeners( void BufferStateLayer::forceSendCallbacks() { mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( - mCurrentState.callbackHandles); + mCurrentState.callbackHandles, std::vector()); } bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 42be62a763..0f0b48a9d7 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -115,6 +115,7 @@ public: protected: void gatherBufferInfo() override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; + void onSurfaceFrameCreated(const std::shared_ptr& surfaceFrame); private: friend class SlotGenerationTest; @@ -158,6 +159,8 @@ private: bool mReleasePreviousBuffer = false; nsecs_t mCallbackHandleAcquireTime = -1; + std::deque> mPendingJankClassifications; + // TODO(marissaw): support sticky transform for LEGACY camera mode class HwcSlotGenerator : public ClientCache::ErasedRecipient { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index b45c213a6c..b09f07a2bb 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -265,8 +265,11 @@ void SurfaceFrame::setJankInfo(JankType jankType, int32_t jankMetadata) { mJankMetadata = jankMetadata; } -JankType SurfaceFrame::getJankType() const { +std::optional SurfaceFrame::getJankType() const { std::lock_guard lock(mMutex); + if (mActuals.presentTime == 0) { + return std::nullopt; + } return mJankType; } @@ -386,37 +389,36 @@ FrameTimeline::DisplayFrame::DisplayFrame() this->surfaceFrames.reserve(kNumSurfaceFramesInitial); } -std::unique_ptr FrameTimeline::createSurfaceFrameForToken( +std::shared_ptr FrameTimeline::createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional token) { ATRACE_CALL(); if (!token) { - return std::make_unique(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid, + return std::make_shared(ISurfaceComposer::INVALID_VSYNC_ID,ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::None, TimelineItem()); } std::optional predictions = mTokenManager.getPredictionsForToken(*token); if (predictions) { - return std::make_unique(*token, ownerPid, ownerUid, + return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::Valid, std::move(*predictions)); } - return std::make_unique(*token, ownerPid, ownerUid, std::move(layerName), + return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), std::move(debugName), PredictionState::Expired, TimelineItem()); } void FrameTimeline::addSurfaceFrame( - std::unique_ptr surfaceFrame, + std::shared_ptr surfaceFrame, SurfaceFrame::PresentState state) { ATRACE_CALL(); surfaceFrame->setPresentState(state); - std::unique_ptr implSurfaceFrame( - static_cast(surfaceFrame.release())); std::lock_guard lock(mMutex); - mCurrentDisplayFrame->surfaceFrames.push_back(std::move(implSurfaceFrame)); + mCurrentDisplayFrame->surfaceFrames.push_back( + std::static_pointer_cast(surfaceFrame)); } void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime) { diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index fe83ebf1ea..084935b877 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -120,6 +120,12 @@ public: virtual void setActualStartTime(nsecs_t actualStartTime) = 0; virtual void setActualQueueTime(nsecs_t actualQueueTime) = 0; virtual void setAcquireFenceTime(nsecs_t acquireFenceTime) = 0; + + // Retrieves jank classification, if it's already been classified. + virtual std::optional getJankType() const = 0; + + // Token identifying the frame. + virtual int64_t getToken() const = 0; }; /* @@ -138,13 +144,13 @@ public: // Create a new surface frame, set the predictions based on a token and return it to the caller. // Sets the PredictionState of SurfaceFrame. // Debug name is the human-readable debugging string for dumpsys. - virtual std::unique_ptr createSurfaceFrameForToken( + virtual std::shared_ptr createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional token) = 0; // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be // composited into one display frame. - virtual void addSurfaceFrame(std::unique_ptr surfaceFrame, + virtual void addSurfaceFrame(std::shared_ptr surfaceFrame, SurfaceFrame::PresentState state) = 0; // The first function called by SF for the current DisplayFrame. Fetches SF predictions based on @@ -209,8 +215,8 @@ public: PresentState getPresentState() const override; PredictionState getPredictionState() const override { return mPredictionState; }; pid_t getOwnerPid() const override { return mOwnerPid; }; - JankType getJankType() const; - int64_t getToken() const { return mToken; }; + std::optional getJankType() const override; + int64_t getToken() const override { return mToken; }; nsecs_t getBaseTime() const; uid_t getOwnerUid() const { return mOwnerUid; }; const std::string& getName() const { return mLayerName; }; @@ -258,10 +264,10 @@ public: ~FrameTimeline() = default; frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; } - std::unique_ptr createSurfaceFrameForToken( + std::shared_ptr createSurfaceFrameForToken( pid_t ownerPid, uid_t ownerUid, std::string layerName, std::string debugName, std::optional token) override; - void addSurfaceFrame(std::unique_ptr surfaceFrame, + void addSurfaceFrame(std::shared_ptr surfaceFrame, SurfaceFrame::PresentState state) override; void setSfWakeUp(int64_t token, nsecs_t wakeupTime) override; void setSfPresent(nsecs_t sfPresentTime, @@ -299,7 +305,7 @@ private: TimelineItem surfaceFlingerActuals; // Collection of predictions and actual values sent over by Layers - std::vector> surfaceFrames; + std::vector> surfaceFrames; PredictionState predictionState = PredictionState::None; JankType jankType = JankType::None; // Enum for the type of jank diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ab0d3df1f4..cfaa59de0b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -901,17 +901,17 @@ bool Layer::applyPendingStates(State* stateToCommit) { ? std::nullopt : std::make_optional(stateToCommit->frameTimelineVsyncId); - auto surfaceFrame = + mSurfaceFrame = mFlinger->mFrameTimeline->createSurfaceFrameForToken(getOwnerPid(), getOwnerUid(), mName, mTransactionName, vsyncId); - surfaceFrame->setActualQueueTime(stateToCommit->postTime); + mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); // For transactions we set the acquire fence time to the post time as we // don't have a buffer. For BufferStateLayer it is overridden in // BufferStateLayer::applyPendingStates - surfaceFrame->setAcquireFenceTime(stateToCommit->postTime); + mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime); - mSurfaceFrame = std::move(surfaceFrame); + onSurfaceFrameCreated(mSurfaceFrame); } mCurrentState.modified = false; @@ -1057,7 +1057,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(const State& stateToCommit) { mDrawingState = stateToCommit; - mFlinger->mFrameTimeline->addSurfaceFrame(std::move(mSurfaceFrame), PresentState::Presented); + mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame, PresentState::Presented); } uint32_t Layer::getTransactionFlags(uint32_t flags) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 75d68a16f2..b30793a360 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -942,6 +942,7 @@ protected: virtual void commitTransaction(const State& stateToCommit); virtual bool applyPendingStates(State* stateToCommit); virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); + virtual void onSurfaceFrameCreated(const std::shared_ptr&) {} // Returns mCurrentScaling mode (originating from the // Client) or mOverrideScalingMode mode (originating from @@ -1066,7 +1067,7 @@ protected: const InputWindowInfo::Type mWindowType; // Can only be accessed with the SF state lock held. - std::unique_ptr mSurfaceFrame; + std::shared_ptr mSurfaceFrame; // The owner of the layer. If created from a non system process, it will be the calling uid. // If created from a system process, the value can be passed in. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 773b3ab54d..cb56ecc7fe 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1986,12 +1986,14 @@ void SurfaceFlinger::onMessageRefresh() { mScheduler->onDisplayRefreshed(presentTime); - postFrame(); - postComposition(); - + // Set presentation information before calling postComposition, such that jank information from + // this' frame classification is already available when sending jank info to clients. mFrameTimeline->setSfPresent(systemTime(), std::make_shared(mPreviousPresentFences[0])); + postFrame(); + postComposition(); + const bool prevFrameHadClientComposition = mHadClientComposition; mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index ca244934e4..1797af4cf6 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -153,7 +153,7 @@ status_t TransactionCompletedThread::registerPendingCallbackHandle( } status_t TransactionCompletedThread::finalizePendingCallbackHandles( - const std::deque>& handles) { + const std::deque>& handles, const std::vector& jankData) { if (handles.empty()) { return NO_ERROR; } @@ -186,7 +186,7 @@ status_t TransactionCompletedThread::finalizePendingCallbackHandles( ALOGW("cannot find listener in mPendingTransactions"); } - status_t err = addCallbackHandle(handle); + status_t err = addCallbackHandle(handle, jankData); if (err != NO_ERROR) { ALOGE("could not add callback handle"); return err; @@ -204,7 +204,7 @@ status_t TransactionCompletedThread::registerUnpresentedCallbackHandle( return BAD_VALUE; } - return addCallbackHandle(handle); + return addCallbackHandle(handle, std::vector()); } status_t TransactionCompletedThread::findTransactionStats( @@ -225,7 +225,8 @@ status_t TransactionCompletedThread::findTransactionStats( return BAD_VALUE; } -status_t TransactionCompletedThread::addCallbackHandle(const sp& handle) { +status_t TransactionCompletedThread::addCallbackHandle(const sp& handle, + const std::vector& jankData) { // If we can't find the transaction stats something has gone wrong. The client should call // startRegistration before trying to add a callback handle. TransactionStats* transactionStats; @@ -246,7 +247,7 @@ status_t TransactionCompletedThread::addCallbackHandle(const sp& handle->dequeueReadyTime); transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, handle->previousReleaseFence, - handle->transformHint, eventStats); + handle->transformHint, eventStats, jankData); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h index f50147a1e9..c4ba7e49ce 100644 --- a/services/surfaceflinger/TransactionCompletedThread.h +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -73,7 +73,8 @@ public: // presented. status_t registerPendingCallbackHandle(const sp& handle); // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented. - status_t finalizePendingCallbackHandles(const std::deque>& handles); + status_t finalizePendingCallbackHandles(const std::deque>& handles, + const std::vector& jankData); // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. @@ -93,7 +94,8 @@ private: const std::vector& callbackIds, TransactionStats** outTransactionStats) REQUIRES(mMutex); - status_t addCallbackHandle(const sp& handle) REQUIRES(mMutex); + status_t addCallbackHandle(const sp& handle, + const std::vector& jankData) REQUIRES(mMutex); class ThreadDeathRecipient : public IBinder::DeathRecipient { public: diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 31a51268e6..538b10d274 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -69,6 +69,7 @@ using ::testing::SetArgPointee; using Transaction = SurfaceComposerClient::Transaction; using Attribute = V2_4::IComposerClient::Attribute; +using Display = V2_1::Display; /////////////////////////////////////////////// diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 411e7809da..43b5afe9e2 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -205,7 +205,7 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), SurfaceFrame::PresentState::Dropped); + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Dropped); mFrameTimeline->setSfPresent(25, presentFence1); presentFence1->signalForTest(30); @@ -229,11 +229,11 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { sLayerNameOne, surfaceFrameToken1); auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameTwo, - sLayerNameTwo, surfaceFrameToken1); + sLayerNameTwo, surfaceFrameToken2); mFrameTimeline->setSfWakeUp(sfToken1, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame2), + mFrameTimeline->addSurfaceFrame(surfaceFrame2, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(26, presentFence1); auto displayFrame = getDisplayFrame(0); @@ -246,13 +246,16 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 0); EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 0); + EXPECT_EQ(surfaceFrame1->getToken(), surfaceFrameToken1); + EXPECT_EQ(surfaceFrame2->getToken(), surfaceFrameToken2); + // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame3 = mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken2); mFrameTimeline->setSfWakeUp(sfToken2, 52); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame3), SurfaceFrame::PresentState::Dropped); + mFrameTimeline->addSurfaceFrame(surfaceFrame3, SurfaceFrame::PresentState::Dropped); mFrameTimeline->setSfPresent(56, presentFence2); displayFrame = getDisplayFrame(0); @@ -260,6 +263,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { EXPECT_EQ(displayFrame->surfaceFlingerActuals.presentTime, 42); EXPECT_EQ(presentedSurfaceFrame1.getActuals().presentTime, 42); EXPECT_EQ(presentedSurfaceFrame2.getActuals().presentTime, 42); + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_NE(surfaceFrame2->getJankType(), std::nullopt); } TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { @@ -275,7 +280,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); presentFence->signalForTest(32 + frameTimeFactor); @@ -297,7 +302,7 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { mFrameTimeline->createSurfaceFrameForToken(sPidOne, sUidOne, sLayerNameOne, sLayerNameOne, surfaceFrameToken); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), SurfaceFrame::PresentState::Presented); + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence); presentFence->signalForTest(32 + frameTimeFactor); displayFrame0 = getDisplayFrame(0); @@ -337,7 +342,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -353,7 +358,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -369,7 +374,7 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { sLayerNameOne, std::nullopt); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame), + mFrameTimeline->addSurfaceFrame(surfaceFrame, SurfaceFrame::PresentState::Presented); mFrameTimeline->setSfPresent(27, presentFence); } @@ -396,10 +401,10 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { sLayerNameOne, surfaceFrameToken1); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( - std::chrono::duration_cast(90ms).count()); + std::chrono::duration_cast(70ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast(59ms).count(), presentFence1); @@ -423,12 +428,14 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { sLayerNameOne, surfaceFrameToken1); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( std::chrono::duration_cast(90ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast(59ms).count(), presentFence1); + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::Display) != 0); } TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { @@ -453,12 +460,15 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count()); - mFrameTimeline->addSurfaceFrame(std::move(surfaceFrame1), + mFrameTimeline->addSurfaceFrame(surfaceFrame1, SurfaceFrame::PresentState::Presented); presentFence1->signalForTest( std::chrono::duration_cast(90ms).count()); mFrameTimeline->setSfPresent(std::chrono::duration_cast(56ms).count(), presentFence1); + + EXPECT_NE(surfaceFrame1->getJankType(), std::nullopt); + EXPECT_TRUE((surfaceFrame1->getJankType().value() & JankType::AppDeadlineMissed) != 0); } /* diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h index 81c32fe08a..6b1253647b 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h @@ -31,7 +31,7 @@ public: MOCK_METHOD0(onBootFinished, void()); MOCK_METHOD2(addSurfaceFrame, - void(std::unique_ptr, + void(std::shared_ptr, frametimeline::SurfaceFrame::PresentState)); MOCK_METHOD2(setSfWakeUp, void(int64_t, nsecs_t)); MOCK_METHOD2(setSfPresent, void(nsecs_t, const std::shared_ptr&)); -- cgit v1.2.3-59-g8ed1b From 31f2b3c097188cad216db84a45df172de149bd14 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Mon, 14 Dec 2020 14:30:09 -0800 Subject: Plumbing through GPU context priority TODO: Actually return priority from Render engine, instead of random number. Test: Compile and observe logcat. Bug: 168740533 Change-Id: Id8d93e315162708a2a8afa1e87ebdf97ab53a20f --- libs/gui/ISurfaceComposer.cpp | 21 +++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 4 ++++ libs/gui/include/gui/ISurfaceComposer.h | 6 ++++++ libs/gui/include/gui/SurfaceComposerClient.h | 5 +++++ libs/gui/tests/Surface_test.cpp | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 12 ++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 2 ++ .../tests/unittests/TestableSurfaceFlinger.h | 2 ++ 8 files changed, 52 insertions(+), 2 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index e46a415f8c..405658bf6d 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1230,6 +1230,21 @@ public: return remote()->transact(BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER, data, &reply); } + + /** + * Get priority of the RenderEngine in surface flinger. + */ + virtual int getGPUContextPriority() { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t err = + remote()->transact(BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY, data, &reply); + if (err != NO_ERROR) { + ALOGE("getGPUContextPriority failed to read data: %s (%d)", strerror(-err), err); + return 0; + } + return reply.readInt32(); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -2094,6 +2109,12 @@ status_t BnSurfaceComposer::onTransact( return addTransactionTraceListener(listener); } + case GET_GPU_CONTEXT_PRIORITY: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int priority = getGPUContextPriority(); + SAFE_PARCEL(reply->writeInt32, priority); + return NO_ERROR; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 9ed7d1cc19..0d370d3aea 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1988,6 +1988,10 @@ status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColo lightRadius); } +int SurfaceComposerClient::getGPUContextPriority() { + return ComposerService::getComposerService()->getGPUContextPriority(); +} + // ---------------------------------------------------------------------------- status_t ScreenshotClient::captureDisplay(const DisplayCaptureArgs& captureArgs, diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 86e3a25f5a..7d25d61431 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -504,6 +504,11 @@ public: */ virtual status_t addTransactionTraceListener( const sp& listener) = 0; + + /** + * Gets priority of the RenderEngine in SurfaceFlinger. + */ + virtual int getGPUContextPriority() = 0; }; // ---------------------------------------------------------------------------- @@ -565,6 +570,7 @@ public: ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, SET_FRAME_TIMELINE_VSYNC, ADD_TRANSACTION_TRACE_LISTENER, + GET_GPU_CONTEXT_PRIORITY, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f1845ee5ef..3ee4a39392 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -184,6 +184,11 @@ public: */ static bool getProtectedContentSupport(); + /** + * Gets the context priority of surface flinger's render engine. + */ + static int getGPUContextPriority(); + /** * Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is * in order with other transactions that use buffers. diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ce3afa2710..7761db8815 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -887,6 +887,8 @@ public: return NO_ERROR; } + int getGPUContextPriority() override { return 0; }; + protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9416d6495..786d331ebd 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4910,10 +4910,11 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_LAYERS: case CAPTURE_DISPLAY: case SET_DISPLAY_BRIGHTNESS: - case SET_FRAME_TIMELINE_VSYNC: { + case SET_FRAME_TIMELINE_VSYNC: + // This is not sensitive information, so should not require permission control. + case GET_GPU_CONTEXT_PRIORITY: { return OK; } - case ADD_REGION_SAMPLING_LISTENER: case REMOVE_REGION_SAMPLING_LISTENER: { // codes that require permission check @@ -6335,6 +6336,13 @@ status_t SurfaceFlinger::addTransactionTraceListener( return NO_ERROR; } +int SurfaceFlinger::getGPUContextPriority() { + // TODO(b/168740533): This is a proof of concept. Once REAL time priority is available + // in EGL, we can return it in RenderEngine and propagate it to SurfaceFlinger. Until + // then return IntentFilter.SYSTEM_HIGH_PRIORITY. + return 1000; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0509247df1..2e4d1cef43 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -608,6 +608,8 @@ private: status_t addTransactionTraceListener( const sp& listener) override; + int getGPUContextPriority() override; + // Implements IBinder::DeathRecipient. void binderDied(const wp& who) override; diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 030073ca8a..7f05a75f48 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -388,6 +388,8 @@ public: return mFlinger->onTransact(code, data, reply, flags); } + auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); } + /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ -- cgit v1.2.3-59-g8ed1b From f0c5649f2ed8ca5fba07389908b2491007d50b08 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 17 Dec 2020 18:04:15 -0800 Subject: SurfaceFlinger: correctly pass desired present time for BLAST Pass whether a desired present time is automatically populated or not to match BufferStateLayer behavior to the one we have for BufferQueueLayer. Bug: 169901895 Test: expand notification shade and observe systrace Change-Id: Ia02c5633d46dde67d2c3be33b084d63c40c2afb0 --- libs/gui/BLASTBufferQueue.cpp | 4 +- libs/gui/ISurfaceComposer.cpp | 9 ++-- libs/gui/SurfaceComposerClient.cpp | 18 ++++++-- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 ++- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 10 ++--- services/surfaceflinger/BufferStateLayer.h | 4 +- services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/RefreshRateOverlay.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 45 +++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 15 ++++--- .../tests/unittests/TestableSurfaceFlinger.h | 8 ++-- .../tests/unittests/TransactionApplicationTest.cpp | 49 +++++++++++++--------- 14 files changed, 111 insertions(+), 71 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 83283224e8..9fc5495938 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -311,7 +311,9 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); - t->setDesiredPresentTime(bufferItem.mTimestamp); + if (!bufferItem.mIsAutoTimestamp) { + t->setDesiredPresentTime(bufferItem.mTimestamp); + } t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); if (!mNextFrameTimelineVsyncIdQueue.empty()) { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 405658bf6d..a8d6832275 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -71,7 +71,7 @@ public: virtual status_t setTransactionState( int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& commands, int64_t desiredPresentTime, + const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) { Parcel data, reply; @@ -92,6 +92,7 @@ public: SAFE_PARCEL(data.writeStrongBinder, applyToken); SAFE_PARCEL(commands.write, data); SAFE_PARCEL(data.writeInt64, desiredPresentTime); + SAFE_PARCEL(data.writeBool, isAutoTimestamp); SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote()); SAFE_PARCEL(data.writeUint64, uncacheBuffer.id); SAFE_PARCEL(data.writeBool, hasListenerCallbacks); @@ -1297,7 +1298,9 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(inputWindowCommands.read, data); int64_t desiredPresentTime = 0; + bool isAutoTimestamp = true; SAFE_PARCEL(data.readInt64, &desiredPresentTime); + SAFE_PARCEL(data.readBool, &isAutoTimestamp); client_cache_t uncachedBuffer; sp tmpBinder; @@ -1323,8 +1326,8 @@ status_t BnSurfaceComposer::onTransact( return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags, applyToken, inputWindowCommands, desiredPresentTime, - uncachedBuffer, hasListenerCallbacks, listenerCallbacks, - transactionId); + isAutoTimestamp, uncachedBuffer, hasListenerCallbacks, + listenerCallbacks, transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0d370d3aea..5570d99d61 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -395,6 +395,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mExplicitEarlyWakeupEnd(other.mExplicitEarlyWakeupEnd), mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime), + mIsAutoTimestamp(other.mIsAutoTimestamp), mFrameTimelineVsyncId(other.mFrameTimelineVsyncId) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; @@ -424,6 +425,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const bool explicitEarlyWakeupEnd = parcel->readBool(); const bool containsBuffer = parcel->readBool(); const int64_t desiredPresentTime = parcel->readInt64(); + const bool isAutoTimestamp = parcel->readBool(); const int64_t frameTimelineVsyncId = parcel->readInt64(); size_t count = static_cast(parcel->readUint32()); @@ -497,6 +499,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mExplicitEarlyWakeupEnd = explicitEarlyWakeupEnd; mContainsBuffer = containsBuffer; mDesiredPresentTime = desiredPresentTime; + mIsAutoTimestamp = isAutoTimestamp; mFrameTimelineVsyncId = frameTimelineVsyncId; mDisplayStates = displayStates; mListenerCallbacks = listenerCallbacks; @@ -527,6 +530,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeBool(mExplicitEarlyWakeupEnd); parcel->writeBool(mContainsBuffer); parcel->writeInt64(mDesiredPresentTime); + parcel->writeBool(mIsAutoTimestamp); parcel->writeInt64(mFrameTimelineVsyncId); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { @@ -628,7 +632,8 @@ void SurfaceComposerClient::Transaction::clear() { mEarlyWakeup = false; mExplicitEarlyWakeupStart = false; mExplicitEarlyWakeupEnd = false; - mDesiredPresentTime = -1; + mDesiredPresentTime = 0; + mIsAutoTimestamp = true; mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; } @@ -640,8 +645,9 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, -1, - uncacheBuffer, false, {}, 0 /* Undefined transactionId */); + sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, + systemTime(), true, uncacheBuffer, false, {}, + 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -759,7 +765,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, - mInputWindowCommands, mDesiredPresentTime, + mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, hasListenerCallbacks, listenerCallbacks, mId); mId = generateId(); @@ -1201,6 +1207,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe } s->what |= layer_state_t::eBufferChanged; s->buffer = buffer; + if (mIsAutoTimestamp) { + mDesiredPresentTime = systemTime(); + } registerSurfaceControlForCallback(sc); @@ -1295,6 +1304,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime( nsecs_t desiredPresentTime) { mDesiredPresentTime = desiredPresentTime; + mIsAutoTimestamp = false; return *this; } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 7d25d61431..40316dbeea 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -166,7 +166,7 @@ public: int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) = 0; /* signal that we're done booting. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3ee4a39392..0abe72c5b7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -373,13 +373,17 @@ public: // to be presented. When it is not possible to present at exactly that time, it will be // presented after the time has passed. // + // If the client didn't pass a desired presentation time, mDesiredPresentTime will be + // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true. + // // Desired present times that are more than 1 second in the future may be ignored. // When a desired present time has already passed, the transaction will be presented as soon // as possible. // // Transactions from the same process are presented in the same order that they are applied. // The desired present time does not affect this ordering. - int64_t mDesiredPresentTime = -1; + int64_t mDesiredPresentTime = 0; + bool mIsAutoTimestamp = true; // The vsync Id provided by Choreographer.getVsyncId int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 7761db8815..fa98cd4c3c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -700,7 +700,7 @@ public: const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, const InputWindowCommands& /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/, + int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, const std::vector& /*listenerCallbacks*/, diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 0b9cabae3d..df1472d0d4 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -341,7 +341,7 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post } bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, - nsecs_t postTime, nsecs_t desiredPresentTime, + nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber) { ATRACE_CALL(); @@ -365,13 +365,13 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(), mOwnerUid, postTime); - desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime; mCurrentState.desiredPresentTime = desiredPresentTime; + mCurrentState.isAutoTimestamp = isAutoTimestamp; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, + mFlinger->mScheduler->recordLayerHistory(this, isAutoTimestamp ? 0 : desiredPresentTime, LayerHistory::LayerUpdateType::Buffer); - addFrameEvent(acquireFence, postTime, desiredPresentTime); + addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); return true; } @@ -533,7 +533,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return true; } - return mCurrentState.desiredPresentTime <= expectedPresentTime; + return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime; } bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ad00c65651..734f647b01 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -70,8 +70,8 @@ public: bool setCrop(const Rect& crop) override; bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, const client_cache_t& clientCacheId, - uint64_t frameNumber) override; + nsecs_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& clientCacheId, uint64_t frameNumber) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c9e97daf8b..d6023b66ac 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -275,7 +275,8 @@ public: // recent callback handle. std::deque> callbackHandles; bool colorSpaceAgnostic; - nsecs_t desiredPresentTime = -1; + nsecs_t desiredPresentTime = 0; + bool isAutoTimestamp = true; // Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will // be rendered around the layer. @@ -444,7 +445,8 @@ public: virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */) { + bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, + uint64_t /* frameNumber */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index a959b9a97f..c291b7f2e0 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -235,7 +235,7 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); @@ -247,7 +247,7 @@ void RefreshRateOverlay::onInvalidate() { const auto& buffers = getOrCreateBuffers(*mCurrentFps); mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 14536b3143..68d2a68322 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3262,8 +3262,9 @@ bool SurfaceFlinger::flushTransactionQueues() { applyTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, mPendingInputWindowCommands, transaction.desiredPresentTime, - transaction.buffer, transaction.postTime, - transaction.privileged, transaction.hasListenerCallbacks, + transaction.isAutoTimestamp, transaction.buffer, + transaction.postTime, transaction.privileged, + transaction.hasListenerCallbacks, transaction.listenerCallbacks, transaction.originPid, transaction.originUid, transaction.id, /*isMainThread*/ true); transactionQueue.pop(); @@ -3294,7 +3295,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, bool ready = true; // Do not present if the desiredPresentTime has not passed unless it is more than one second // in the future. We ignore timestamps more than 1 second in the future for stability reasons. - if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime && + if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime && desiredPresentTime < expectedPresentTime + s2ns(1)) { ready = false; } @@ -3331,7 +3332,7 @@ status_t SurfaceFlinger::setTransactionState( int64_t frameTimelineVsyncId, const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); @@ -3372,17 +3373,19 @@ status_t SurfaceFlinger::setTransactionState( const int originPid = ipc->getCallingPid(); const int originUid = ipc->getCallingUid(); - if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states, true)) { + if (pendingTransactions || + !transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true)) { mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, - desiredPresentTime, uncacheBuffer, postTime, - privileged, hasListenerCallbacks, listenerCallbacks, - originPid, originUid, transactionId); + desiredPresentTime, isAutoTimestamp, uncacheBuffer, + postTime, privileged, hasListenerCallbacks, + listenerCallbacks, originPid, originUid, + transactionId); setTransactionFlags(eTransactionFlushNeeded); return NO_ERROR; } applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, - desiredPresentTime, uncacheBuffer, postTime, privileged, + desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, transactionId, /*isMainThread*/ false); return NO_ERROR; @@ -3392,9 +3395,10 @@ void SurfaceFlinger::applyTransactionState( int64_t frameTimelineVsyncId, const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, - bool hasListenerCallbacks, const std::vector& listenerCallbacks, - int originPid, int originUid, uint64_t transactionId, bool isMainThread) { + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, + bool privileged, bool hasListenerCallbacks, + const std::vector& listenerCallbacks, int originPid, int originUid, + uint64_t transactionId, bool isMainThread) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3428,12 +3432,13 @@ void SurfaceFlinger::applyTransactionState( std::unordered_set listenerCallbacksWithSurfaces; uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - clientStateFlags |= - setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, postTime, - privileged, listenerCallbacksWithSurfaces); + clientStateFlags |= setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, + isAutoTimestamp, postTime, privileged, + listenerCallbacksWithSurfaces); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { - mScheduler->recordLayerHistory(layer.get(), desiredPresentTime, + mScheduler->recordLayerHistory(layer.get(), + isAutoTimestamp ? 0 : desiredPresentTime, LayerHistory::LayerUpdateType::AnimationTX); } } @@ -3608,7 +3613,7 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis uint32_t SurfaceFlinger::setClientStateLocked( int64_t frameTimelineVsyncId, const ComposerState& composerState, - int64_t desiredPresentTime, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) { const layer_state_t& s = composerState.state; @@ -3919,8 +3924,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( ? s.frameNumber : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; - if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, s.cachedBuffer, - frameNumber)) { + if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, + s.cachedBuffer, frameNumber)) { flags |= eTraversalNeeded; } } @@ -4198,7 +4203,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.height = 0; displays.add(d); setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr, - mPendingInputWindowCommands, -1, {}, false, {}, + mPendingInputWindowCommands, systemTime(), true, {}, false, {}, 0 /* Undefined transactionId */); setPowerModeInternal(display, hal::PowerMode::ON); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e3e9c4f229..db75312cd3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -341,7 +341,7 @@ protected: virtual uint32_t setClientStateLocked( int64_t frameTimelineVsyncId, const ComposerState& composerState, - int64_t desiredPresentTime, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) REQUIRES(mStateLock); virtual void commitTransactionLocked(); @@ -434,8 +434,9 @@ private: struct TransactionState { TransactionState(int64_t frameTimelineVsyncId, const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - int64_t postTime, bool privileged, bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, + bool hasListenerCallbacks, std::vector listenerCallbacks, int originPid, int originUid, uint64_t transactionId) : frameTimelineVsyncId(frameTimelineVsyncId), @@ -443,6 +444,7 @@ private: displays(displayStates), flags(transactionFlags), desiredPresentTime(desiredPresentTime), + isAutoTimestamp(isAutoTimestamp), buffer(uncacheBuffer), postTime(postTime), privileged(privileged), @@ -457,6 +459,7 @@ private: Vector displays; uint32_t flags; const int64_t desiredPresentTime; + const bool isAutoTimestamp; client_cache_t buffer; const int64_t postTime; bool privileged; @@ -520,8 +523,8 @@ private: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) override; void bootFinished() override; @@ -723,7 +726,7 @@ private: void applyTransactionState(int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, + const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c98004a8ab..25aaa14bb1 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -371,14 +371,14 @@ public: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, std::vector& listenerCallbacks, uint64_t transactionId) { return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags, applyToken, inputWindowCommands, desiredPresentTime, - uncacheBuffer, hasListenerCallbacks, listenerCallbacks, - transactionId); + isAutoTimestamp, uncacheBuffer, hasListenerCallbacks, + listenerCallbacks, transactionId); } auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); }; diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index c36d9947b7..fa6ff301af 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -97,7 +97,8 @@ public: uint32_t flags = 0; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); InputWindowCommands inputWindowCommands; - int64_t desiredPresentTime = -1; + int64_t desiredPresentTime = 0; + bool isAutoTimestamp = true; int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; client_cache_t uncacheBuffer; int64_t id = -1; @@ -114,11 +115,13 @@ public: } void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, - int64_t desiredPresentTime, int64_t frameTimelineVsyncId) { + int64_t desiredPresentTime, bool isAutoTimestamp, + int64_t frameTimelineVsyncId) { mTransactionNumber++; transaction.flags |= flags; // ISurfaceComposer::eSynchronous; transaction.inputWindowCommands.syncInputWindows = syncInputWindows; transaction.desiredPresentTime = desiredPresentTime; + transaction.isAutoTimestamp = isAutoTimestamp; transaction.frameTimelineVsyncId = frameTimelineVsyncId; } @@ -129,13 +132,15 @@ public: EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime())); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationTime = systemTime(); mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transaction.id); + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); // This transaction should not have been placed on the transaction queue. // If transaction is synchronous or syncs input windows, SF @@ -164,13 +169,15 @@ public: .WillOnce(Return(time + nsecs_t(5 * 1e8))); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transaction.id); + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); nsecs_t returnedTime = systemTime(); EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); @@ -189,20 +196,23 @@ public: // transaction that should go on the pending thread TransactionInfo transactionA; setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, + ISurfaceComposer::INVALID_VSYNC_ID); // transaction that would not have gone on the pending thread if not // blocked TransactionInfo transactionB; setupSingle(transactionB, flags, syncInputWindows, - /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, - transactionA.desiredPresentTime, transactionA.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transactionA.id); + transactionA.desiredPresentTime, transactionA.isAutoTimestamp, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); // This thread should not have been blocked by the above transaction // (5s is the timeout period that applyTransactionState waits for SF to @@ -213,8 +223,9 @@ public: mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states, transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, - transactionB.desiredPresentTime, transactionB.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transactionB.id); + transactionB.desiredPresentTime, transactionB.isAutoTimestamp, + transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionB.id); // this thread should have been blocked by the above transaction // if this is an animation, this thread should be blocked for 5s @@ -256,12 +267,12 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { .WillOnce(Return(s2ns(2))); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID); mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, - transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, - transactionA.id); + transactionA.isAutoTimestamp, transactionA.uncacheBuffer, + mHasListenerCallbacks, mCallbacks, transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_EQ(1, transactionQueue.size()); @@ -279,8 +290,8 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { empty.applyToken = sp(); mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays, empty.flags, empty.applyToken, empty.inputWindowCommands, - empty.desiredPresentTime, empty.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, empty.id); + empty.desiredPresentTime, empty.isAutoTimestamp, + empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); // flush transaction queue should flush as desiredPresentTime has // passed -- cgit v1.2.3-59-g8ed1b From 277142c594918f828712a2412d3f95164eebffeb Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 5 Jan 2021 18:35:29 -0800 Subject: SurfaceFlinger: Support out of order transactions With BLAST, buffers are submitted via transactions and they are subjected to the same transaction queueing logic - transactions from a client must be applied in the order they came in. This poses a problem when clients use multiple blast adapters. Transactions from one window can get queued up if the buffer is not ready to be presented, preventing transactions from another window to be applied in a timely manner. We fix this by using a different apply token for every bast adapter so their transactions are handled independently. Bug: b/176411039, b/168917217 Test: atest BlastBufferQueueTest Test: YouTube minimize video and scroll, notice scrolling is at 60/90fps Change-Id: I0005dfa3c221a2b33545e39af16ae4b1ef08d269 --- libs/gui/BLASTBufferQueue.cpp | 2 +- libs/gui/SurfaceComposerClient.cpp | 21 ++++++++-- libs/gui/include/gui/BLASTBufferQueue.h | 4 ++ libs/gui/include/gui/SurfaceComposerClient.h | 9 ++++ libs/gui/tests/BLASTBufferQueue_test.cpp | 61 ++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 4 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 89de629442..eaa47f9680 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -371,7 +371,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mPendingTransactions.end()); if (applyTransaction) { - t->apply(); + t->setApplyToken(mApplyToken).apply(); } BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5570d99d61..97c2693f29 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -396,7 +396,8 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime), mIsAutoTimestamp(other.mIsAutoTimestamp), - mFrameTimelineVsyncId(other.mFrameTimelineVsyncId) { + mFrameTimelineVsyncId(other.mFrameTimelineVsyncId), + mApplyToken(other.mApplyToken) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; mInputWindowCommands = other.mInputWindowCommands; @@ -427,7 +428,8 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const int64_t desiredPresentTime = parcel->readInt64(); const bool isAutoTimestamp = parcel->readBool(); const int64_t frameTimelineVsyncId = parcel->readInt64(); - + sp applyToken; + parcel->readNullableStrongBinder(&applyToken); size_t count = static_cast(parcel->readUint32()); if (count > parcel->dataSize()) { return BAD_VALUE; @@ -505,6 +507,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mListenerCallbacks = listenerCallbacks; mComposerStates = composerStates; mInputWindowCommands = inputWindowCommands; + mApplyToken = applyToken; return NO_ERROR; } @@ -532,6 +535,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeInt64(mDesiredPresentTime); parcel->writeBool(mIsAutoTimestamp); parcel->writeInt64(mFrameTimelineVsyncId); + parcel->writeStrongBinder(mApplyToken); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { displayState.write(*parcel); @@ -607,6 +611,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mEarlyWakeup = mEarlyWakeup || other.mEarlyWakeup; mExplicitEarlyWakeupStart = mExplicitEarlyWakeupStart || other.mExplicitEarlyWakeupStart; mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd; + mApplyToken = other.mApplyToken; // When merging vsync Ids we take the oldest one if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && @@ -635,6 +640,7 @@ void SurfaceComposerClient::Transaction::clear() { mDesiredPresentTime = 0; mIsAutoTimestamp = true; mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mApplyToken = nullptr; } void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { @@ -763,7 +769,10 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { flags |= ISurfaceComposer::eExplicitEarlyWakeupEnd; } - sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + sp applyToken = mApplyToken + ? mApplyToken + : IInterface::asBinder(TransactionCompletedListener::getIInstance()); + sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, @@ -1579,6 +1588,12 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAutoR return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApplyToken( + const sp& applyToken) { + mApplyToken = applyToken; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index c4cdb65537..1198135b0c 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -165,6 +165,10 @@ private: std::function mTransactionCompleteCallback GUARDED_BY(mMutex) = nullptr; uint64_t mTransactionCompleteFrameNumber GUARDED_BY(mMutex){0}; + + // Queues up transactions using this token in SurfaceFlinger. This prevents queued up + // transactions from other parts of the client from blocking this transaction. + const sp mApplyToken = new BBinder(); }; } // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 0abe72c5b7..48bc5d5398 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -388,6 +388,10 @@ public: // The vsync Id provided by Choreographer.getVsyncId int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + // If not null, transactions will be queued up using this token otherwise a common token + // per process will be used. + sp mApplyToken = nullptr; + InputWindowCommands mInputWindowCommands; int mStatus = NO_ERROR; @@ -555,6 +559,11 @@ public: // in shared buffer mode. Transaction& setAutoRefresh(const sp& sc, bool autoRefresh); + // Queues up transactions using this token in SurfaceFlinger. By default, all transactions + // from a client are placed on the same queue. This can be used to prevent multiple + // transactions from blocking each other. + Transaction& setApplyToken(const sp& token); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 170ad87993..d69b7c38a3 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -221,6 +221,32 @@ protected: return captureResults.result; } + void queueBuffer(sp igbp, uint8_t r, uint8_t g, uint8_t b, + nsecs_t presentTimeDelay) { + int slot; + sp fence; + sp buf; + auto ret = igbp->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight, + PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN, + nullptr, nullptr); + ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); + ASSERT_EQ(OK, igbp->requestBuffer(slot, &buf)); + + uint32_t* bufData; + buf->lock(static_cast(GraphicBuffer::USAGE_SW_WRITE_OFTEN), + reinterpret_cast(&bufData)); + fillBuffer(bufData, Rect(buf->getWidth(), buf->getHeight() / 2), buf->getStride(), r, g, b); + buf->unlock(); + + IGraphicBufferProducer::QueueBufferOutput qbOutput; + nsecs_t timestampNanos = systemTime() + presentTimeDelay; + IGraphicBufferProducer::QueueBufferInput input(timestampNanos, false, HAL_DATASPACE_UNKNOWN, + Rect(mDisplayWidth, mDisplayHeight / 2), + NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, + Fence::NO_FENCE); + igbp->queueBuffer(slot, input, &qbOutput); + } + sp mClient; sp mComposer; @@ -528,6 +554,41 @@ TEST_F(BLASTBufferQueueTest, QueryNativeWindowQueuesToWindowComposer) { ASSERT_EQ(queuesToNativeWindow, 1); } +TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { + sp bgSurface = + mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceBufferState); + ASSERT_NE(nullptr, bgSurface.get()); + Transaction t; + t.setLayerStack(bgSurface, 0) + .show(bgSurface) + .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) + .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) + .setLayer(bgSurface, std::numeric_limits::max() - 1) + .apply(); + + BLASTBufferQueueHelper slowAdapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); + sp slowIgbProducer; + setUpProducer(slowAdapter, slowIgbProducer); + nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count(); + queueBuffer(slowIgbProducer, 0 /* r */, 0 /* g */, 0 /* b */, presentTimeDelay); + + BLASTBufferQueueHelper fastAdapter(bgSurface, mDisplayWidth, mDisplayHeight); + sp fastIgbProducer; + setUpProducer(fastAdapter, fastIgbProducer); + uint8_t r = 255; + uint8_t g = 0; + uint8_t b = 0; + queueBuffer(fastIgbProducer, r, g, b, 0 /* presentTimeDelay */); + fastAdapter.waitForCallbacks(); + + // capture screen and verify that it is red + ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); + + ASSERT_NO_FATAL_FAILURE( + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); +} + class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { public: void test(uint32_t tr) { -- cgit v1.2.3-59-g8ed1b From 9ad01462a742d3b44fd4258bc794f99b130ef73a Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 15 Jan 2021 12:55:14 -0800 Subject: Pass in window name along with focus request Used for generating focus event logs and debug logs. Test: go/wm-smoke, check event logs and logcat Change-Id: I7d96c706ea350ec122c254fb4c327756e8267df5 --- libs/gui/SurfaceComposerClient.cpp | 11 ----------- libs/gui/include/gui/SurfaceComposerClient.h | 2 -- libs/gui/tests/EndToEndNativeInputTest.cpp | 10 ++++++++-- libs/input/android/FocusRequest.aidl | 2 ++ 4 files changed, 10 insertions(+), 15 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 97c2693f29..4a372bba1e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1417,17 +1417,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInput return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( - const sp& token, const sp& focusedToken, nsecs_t timestampNanos, - int32_t displayId) { - FocusRequest request; - request.token = token; - request.focusedToken = focusedToken; - request.timestamp = timestampNanos; - request.displayId = displayId; - return setFocusedWindow(request); -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFocusedWindow( const FocusRequest& request) { mInputWindowCommands.focusRequests.push_back(request); diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 48bc5d5398..11db658de2 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -522,8 +522,6 @@ public: #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); - Transaction& setFocusedWindow(const sp& token, const sp& focusedToken, - nsecs_t timestampNanos, int32_t displayId); Transaction& setFocusedWindow(const FocusRequest& request); Transaction& syncInputWindows(); #endif diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 3965ea0fdb..31cbbdc75c 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -202,8 +202,14 @@ public: void requestFocus() { SurfaceComposerClient::Transaction t; - t.setFocusedWindow(mInputInfo.token, nullptr, systemTime(SYSTEM_TIME_MONOTONIC), - 0 /* displayId */); + FocusRequest request; + request.token = mInputInfo.token; + request.windowName = mInputInfo.name; + request.focusedToken = nullptr; + request.focusedWindowName = ""; + request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); + request.displayId = 0; + t.setFocusedWindow(request); t.apply(true); } diff --git a/libs/input/android/FocusRequest.aidl b/libs/input/android/FocusRequest.aidl index 303dd1c349..8812d34a72 100644 --- a/libs/input/android/FocusRequest.aidl +++ b/libs/input/android/FocusRequest.aidl @@ -22,6 +22,7 @@ parcelable FocusRequest { * Input channel token used to identify the window that should gain focus. */ IBinder token; + @utf8InCpp String windowName; /** * The token that the caller expects currently to be focused. If the * specified token does not match the currently focused window, this request will be dropped. @@ -30,6 +31,7 @@ parcelable FocusRequest { * is. */ @nullable IBinder focusedToken; + @utf8InCpp String focusedWindowName; /** * SYSTEM_TIME_MONOTONIC timestamp in nanos set by the client (wm) when requesting the focus * change. This determines which request gets precedence if there is a focus change request -- cgit v1.2.3-59-g8ed1b From dd5bfa93b0c6633b7372c87fc8d7a83a73a5cd1c Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 7 Jan 2021 17:56:08 -0800 Subject: SurfaceFlinger: handle high refresh rate deny list Add visibility to SurfaceFlinger into the high refresh rate deny list and let SurfaceFlinger handle it. Previously WM was setting the preferredDisplayModeId on the denied app's window. The old way prevented SurfaceFlinger to use the frame rate override feature as it didn't know that a specific app is causing the refresh rate spec to be limited. With this change, SurfaceFlinger will limit the display refresh rate based on the high refresh rate deny list, and if possible, will use the frame rate override feature to change the display rate to a multiple, allowing other animations to be smooth while the denied app remains in the low refresh rate. Bug: 170502573 Test: SF unit tests Change-Id: Idc8a5fe6bc12dbd949ad5e09ff50e339ffaeac36 Merged-In: Idc8a5fe6bc12dbd949ad5e09ff50e339ffaeac36 --- libs/gui/LayerState.cpp | 10 +- libs/gui/SurfaceComposerClient.cpp | 5 +- libs/gui/include/gui/LayerState.h | 13 +- libs/nativewindow/include/apex/window.h | 13 ++ services/surfaceflinger/Layer.cpp | 9 +- services/surfaceflinger/Layer.h | 2 + services/surfaceflinger/Scheduler/LayerHistory.cpp | 3 + .../Scheduler/RefreshRateConfigs.cpp | 88 ++++++++--- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 20 ++- services/surfaceflinger/Scheduler/Scheduler.cpp | 10 +- services/surfaceflinger/SurfaceFlinger.cpp | 6 +- .../tests/unittests/RefreshRateConfigsTest.cpp | 176 +++++++++++++++++++-- .../tests/unittests/SetFrameRateTest.cpp | 15 ++ 13 files changed, 308 insertions(+), 62 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 63be3edf94..e5e10a0014 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "LayerState" +#include #include #include @@ -620,7 +621,8 @@ status_t InputWindowCommands::read(const Parcel& input) { return NO_ERROR; } -bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) { +bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName, + bool privileged) { const char* functionName = inFunctionName != nullptr ? inFunctionName : "call"; int floatClassification = std::fpclassify(frameRate); if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { @@ -629,8 +631,10 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc } if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && - compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) { - ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility); + compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && + (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { + ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, + compatibility, privileged ? "yes" : "no"); return false; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4a372bba1e..78f655a71b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1518,7 +1518,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame mStatus = BAD_INDEX; return *this; } - if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate")) { + // Allow privileged values as well here, those will be ignored by SF if + // the caller is not privileged + if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate", + /*privileged=*/true)) { mStatus = BAD_VALUE; return *this; } diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 4a291aeb02..83a9d3356e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -309,11 +309,14 @@ static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) return compare_type(lhs.token, rhs.token); } -// Returns true if the frameRate and compatibility are valid values, false -// othwerise. If either of the params are invalid, an error log is printed, and -// functionName is added to the log to indicate which function call failed. -// functionName can be null. -bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName); +// Returns true if the frameRate is valid. +// +// @param frameRate the frame rate in Hz +// @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* +// @param functionName calling function or nullptr. Used for logging +// @param privileged whether caller has unscoped surfaceflinger access +bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName, + bool privileged = false); struct CaptureArgs { const static int32_t UNSET_UID = -1; diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h index 2d1354cdf1..0923438eec 100644 --- a/libs/nativewindow/include/apex/window.h +++ b/libs/nativewindow/include/apex/window.h @@ -39,6 +39,19 @@ enum ANativeWindowPerform { // clang-format on }; +/* + * Internal extension of compatibility value for ANativeWindow_setFrameRate. */ +enum ANativeWindow_FrameRateCompatibilityInternal { + /** + * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display + * to operate at the exact frame rate. + * + * This is used internally by the platform and should not be used by apps. + * @hide + */ + ANATIVEWINDOW_FRAME_RATE_EXACT = 100, +}; + /** * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 24d1b52a49..66ce3f1a44 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1441,11 +1441,14 @@ void Layer::updateTreeHasFrameRateVote() { layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; + const auto layerVotedWithExactCompatibility = + layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact; // We do not count layers that are ExactOrMultiple for the same reason // we are allowing touch boost for those layers. See // RefreshRateConfigs::getBestRefreshRate for more details. - if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) { + if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote || + layerVotedWithExactCompatibility) { layersWithVote++; } @@ -1662,6 +1665,8 @@ std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility co return "ExactOrMultiple"; case FrameRateCompatibility::NoVote: return "NoVote"; + case FrameRateCompatibility::Exact: + return "Exact"; } } @@ -2763,6 +2768,8 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::Default; case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: return FrameRateCompatibility::ExactOrMultiple; + case ANATIVEWINDOW_FRAME_RATE_EXACT: + return FrameRateCompatibility::Exact; default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f78b5f31e9..359340eb64 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -145,6 +145,8 @@ public: enum class FrameRateCompatibility { Default, // Layer didn't specify any specific handling strategy + Exact, // Layer needs the exact frame rate. + ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the // content properly. Any other value will result in a pull down. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 170933d9b3..7ef531df63 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -71,6 +71,7 @@ void trace(const wp& weak, const LayerInfo& info, LayerHistory::LayerVote traceType(LayerHistory::LayerVoteType::Heuristic, fps); traceType(LayerHistory::LayerVoteType::ExplicitDefault, fps); traceType(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, fps); + traceType(LayerHistory::LayerVoteType::ExplicitExact, fps); traceType(LayerHistory::LayerVoteType::Min, 1); traceType(LayerHistory::LayerVoteType::Max, 1); @@ -172,6 +173,8 @@ void LayerHistory::partitionLayers(nsecs_t now) { return LayerVoteType::ExplicitExactOrMultiple; case Layer::FrameRateCompatibility::NoVote: return LayerVoteType::NoVote; + case Layer::FrameRateCompatibility::Exact: + return LayerVoteType::ExplicitExact; } }(); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 0f1e26750e..81ffe0f20e 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -83,6 +83,8 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { return "ExplicitDefault"; case LayerVoteType::ExplicitExactOrMultiple: return "ExplicitExactOrMultiple"; + case LayerVoteType::ExplicitExact: + return "ExplicitExact"; } } @@ -165,6 +167,18 @@ float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& laye return (1.0f / iter) * seamlessness; } + if (layer.vote == LayerVoteType::ExplicitExact) { + const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate); + if (mSupportsFrameRateOverride) { + // Since we support frame rate override, allow refresh rates which are + // multiples of the layer's request, as those apps would be throttled + // down to run at the desired refresh rate. + return divider > 0; + } + + return divider == 1; + } + return 0; } @@ -199,21 +213,34 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector 0 || explicitExactOrMultipleVoteLayers > 0; + const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 || + explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0; // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've // selected a refresh rate to see if we should apply touch boost. @@ -318,7 +345,9 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vectorinPolicy(policy->primaryRange.min, policy->primaryRange.max); if ((primaryRangeIsSingleRate || !inPrimaryRange) && - !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) { + !(layer.focused && + (layer.vote == LayerVoteType::ExplicitDefault || + layer.vote == LayerVoteType::ExplicitExact))) { // Only focused layers with ExplicitDefault frame rate settings are allowed to score // refresh rates outside the primary range. continue; @@ -358,7 +387,8 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vectorfps.lessThanWithMargin(touchRefreshRate.fps)) { setTouchConsidered(); ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str()); @@ -412,7 +442,7 @@ std::vector initializeScoresForAllRefreshRates( } RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides( - const std::vector& layers, Fps displayFrameRate) const { + const std::vector& layers, Fps displayFrameRate, bool touch) const { ATRACE_CALL(); if (!mSupportsFrameRateOverride) return {}; @@ -423,6 +453,17 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr groupLayersByUid(layers); UidToFrameRateOverride frameRateOverrides; for (const auto& [uid, layersWithSameUid] : layersByUid) { + // Layers with ExplicitExactOrMultiple expect touch boost + const bool hasExplicitExactOrMultiple = + std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(), + [](const auto& layer) { + return layer->vote == LayerVoteType::ExplicitExactOrMultiple; + }); + + if (touch && hasExplicitExactOrMultiple) { + continue; + } + for (auto& score : scores) { score.score = 0; } @@ -433,7 +474,8 @@ RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverr } LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault && - layer->vote != LayerVoteType::ExplicitExactOrMultiple); + layer->vote != LayerVoteType::ExplicitExactOrMultiple && + layer->vote != LayerVoteType::ExplicitExact); for (RefreshRateScore& score : scores) { const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate, /*isSeamlessSwitch*/ true); @@ -559,8 +601,10 @@ void RefreshRateConfigs::setCurrentConfigId(DisplayModeId configId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); } -RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId) - : mKnownFrameRates(constructKnownFrameRates(configs)) { +RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, + bool enableFrameRateOverride) + : mKnownFrameRates(constructKnownFrameRates(configs)), + mEnableFrameRateOverride(enableFrameRateOverride) { updateDisplayConfigs(configs, currentConfigId); } @@ -589,7 +633,7 @@ void RefreshRateConfigs::updateDisplayConfigs(const DisplayModes& configs, mMaxSupportedRefreshRate = sortedConfigs.back(); mSupportsFrameRateOverride = false; - if (android::sysprop::enable_frame_rate_override(true)) { + if (mEnableFrameRateOverride) { for (const auto& config1 : sortedConfigs) { for (const auto& config2 : sortedConfigs) { if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) { @@ -826,4 +870,4 @@ void RefreshRateConfigs::dump(std::string& result) const { } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 29402f5a70..0c7dc0515c 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -211,8 +211,11 @@ public: Heuristic, // Specific refresh rate that was calculated by platform using a heuristic ExplicitDefault, // Specific refresh rate that was provided by the app with Default // compatibility - ExplicitExactOrMultiple // Specific refresh rate that was provided by the app with - // ExactOrMultiple compatibility + ExplicitExactOrMultiple, // Specific refresh rate that was provided by the app with + // ExactOrMultiple compatibility + ExplicitExact, // Specific refresh rate that was provided by the app with + // Exact compatibility + }; // Captures the layer requirements for a refresh rate. This will be used to determine the @@ -298,7 +301,8 @@ public: // Returns a known frame rate that is the closest to frameRate Fps findClosestKnownFrameRate(Fps frameRate) const; - RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId); + RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, + bool enableFrameRateOverride = false); void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig) EXCLUDES(mLock); @@ -327,10 +331,15 @@ public: // Returns a divider for the current refresh rate int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock); - // Returns the frame rate override for each uid using UidToFrameRateOverride = std::map; + // Returns the frame rate override for each uid. + // + // @param layers list of visible layers + // @param displayFrameRate the display frame rate + // @param touch whether touch timer is active (i.e. user touched the screen recently) UidToFrameRateOverride getFrameRateOverrides(const std::vector& layers, - Fps displayFrameRate) const EXCLUDES(mLock); + Fps displayFrameRate, bool touch) const + EXCLUDES(mLock); void dump(std::string& result) const EXCLUDES(mLock); @@ -410,6 +419,7 @@ private: // from based on the closest value. const std::vector mKnownFrameRates; + const bool mEnableFrameRateOverride; bool mSupportsFrameRateOverride; }; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 588b83d774..d8612098ec 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -763,17 +763,11 @@ bool Scheduler::updateFrameRateOverrides( return false; } - if (consideredSignals.touch) { - std::lock_guard lock(mFrameRateOverridesMutex); - const bool changed = !mFrameRateOverridesByContent.empty(); - mFrameRateOverridesByContent.clear(); - return changed; - } - if (!consideredSignals.idle) { const auto frameRateOverrides = mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements, - displayRefreshRate); + displayRefreshRate, + consideredSignals.touch); std::lock_guard lock(mFrameRateOverridesMutex); if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(), frameRateOverrides.begin(), frameRateOverrides.end(), diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a51659681..c1fabf8322 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2920,7 +2920,9 @@ void SurfaceFlinger::initScheduler(PhysicalDisplayId primaryDisplayId) { auto currentConfig = getHwComposer().getActiveMode(primaryDisplayId)->getId(); const auto modes = getHwComposer().getModes(primaryDisplayId); - mRefreshRateConfigs = std::make_unique(modes, currentConfig); + mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(modes, currentConfig, + android::sysprop::enable_frame_rate_override(true)); const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig); mRefreshRateStats = std::make_unique(*mTimeStats, currRefreshRate.getFps(), @@ -3873,7 +3875,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eFrameRateChanged) { if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility, - "SurfaceFlinger::setClientStateLocked") && + "SurfaceFlinger::setClientStateLocked", privileged) && layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate), Layer::FrameRate::convertCompatibility( s.frameRateCompatibility), diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 0a747ab7e3..738ded18ac 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -1506,6 +1506,89 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { } } +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact) { + auto refreshRateConfigs = + std::make_unique(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 0.5f}}; + auto& explicitExactLayer = layers[0]; + auto& explicitExactOrMultipleLayer = layers[1]; + + explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; + explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60); + + explicitExactLayer.vote = LayerVoteType::ExplicitExact; + explicitExactLayer.name = "ExplicitExact"; + explicitExactLayer.desiredRefreshRate = Fps(30); + + EXPECT_EQ(mExpected30Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + EXPECT_EQ(mExpected30Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); + + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120); + explicitExactLayer.desiredRefreshRate = Fps(60); + EXPECT_EQ(mExpected60Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(72); + EXPECT_EQ(mExpected72Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(90); + EXPECT_EQ(mExpected90Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(120); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); +} + +TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) { + auto refreshRateConfigs = + std::make_unique(m30_60_72_90_120Device, + /*currentConfigId=*/HWC_CONFIG_ID_60, + /*enableFrameRateOverride=*/true); + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 0.5f}}; + auto& explicitExactLayer = layers[0]; + auto& explicitExactOrMultipleLayer = layers[1]; + + explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple; + explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple"; + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60); + + explicitExactLayer.vote = LayerVoteType::ExplicitExact; + explicitExactLayer.name = "ExplicitExact"; + explicitExactLayer.desiredRefreshRate = Fps(30); + + EXPECT_EQ(mExpected60Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); + + explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120); + explicitExactLayer.desiredRefreshRate = Fps(60); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(72); + EXPECT_EQ(mExpected72Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(90); + EXPECT_EQ(mExpected90Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); + + explicitExactLayer.desiredRefreshRate = Fps(120); + EXPECT_EQ(mExpected120Config, + refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); +} + TEST_F(RefreshRateConfigsTest, testComparisonOperator) { EXPECT_TRUE(mExpected60Config < mExpected90Config); EXPECT_FALSE(mExpected60Config < mExpected60Config); @@ -1537,7 +1620,7 @@ TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) { EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction()); } -TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { +TEST_F(RefreshRateConfigsTest, getRefreshRateDivider) { auto refreshRateConfigs = std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/HWC_CONFIG_ID_30); @@ -1562,57 +1645,66 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f))); } -TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_noLayers) { +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) { auto refreshRateConfigs = std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/ HWC_CONFIG_ID_120); auto layers = std::vector{}; - ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)).empty()); + ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false) + .empty()); } TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_60on120) { auto refreshRateConfigs = std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/ - HWC_CONFIG_ID_120); + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; layers[0].name = "Test layer"; layers[0].ownerUid = 1234; layers[0].desiredRefreshRate = Fps(60.0f); layers[0].vote = LayerVoteType::ExplicitDefault; - auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[0].vote = LayerVoteType::NoVote; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Min; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Max; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); layers[0].vote = LayerVoteType::Heuristic; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_TRUE(frameRateOverrides.empty()); } -TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_twoUids) { auto refreshRateConfigs = std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/ - HWC_CONFIG_ID_120); + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); auto layers = std::vector{ LayerRequirement{.ownerUid = 1234, .weight = 1.0f}, @@ -1626,7 +1718,8 @@ TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { layers[1].name = "Test layer 5678"; layers[1].desiredRefreshRate = Fps(30.0f); layers[1].vote = LayerVoteType::ExplicitDefault; - auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(2, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); @@ -1635,13 +1728,66 @@ TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { ASSERT_EQ(30.0f, frameRateOverrides.at(5678).getValue()); layers[1].vote = LayerVoteType::Heuristic; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); ASSERT_EQ(1, frameRateOverrides.size()); ASSERT_EQ(1, frameRateOverrides.count(1234)); ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); layers[1].ownerUid = 1234; - frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)); + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_TRUE(frameRateOverrides.empty()); +} + +TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) { + auto refreshRateConfigs = + std::make_unique(m30_60_72_90_120Device, /*currentConfigId=*/ + HWC_CONFIG_ID_120, + /*enableFrameRateOverride=*/true); + + auto layers = std::vector{ + LayerRequirement{.ownerUid = 1234, .weight = 1.0f}, + }; + + layers[0].name = "Test layer"; + layers[0].desiredRefreshRate = Fps(60.0f); + layers[0].vote = LayerVoteType::ExplicitDefault; + + auto frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + layers[0].vote = LayerVoteType::ExplicitExact; + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + layers[0].vote = LayerVoteType::ExplicitExactOrMultiple; + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false); + ASSERT_EQ(1, frameRateOverrides.size()); + ASSERT_EQ(1, frameRateOverrides.count(1234)); + ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue()); + + frameRateOverrides = + refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true); ASSERT_TRUE(frameRateOverrides.empty()); } diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index c8f4cb4c19..e060df2420 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -473,5 +473,20 @@ INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest, std::make_shared()), PrintToStringParamName); +TEST_F(SetFrameRateTest, ValidateFrameRate) { + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, "")); + EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "", /*privileged=*/true)); + + EXPECT_FALSE(ValidateFrameRate(-1, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_FALSE( + ValidateFrameRate(1.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + EXPECT_FALSE( + ValidateFrameRate(0.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, "")); + + EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "")); +} + } // namespace } // namespace android -- cgit v1.2.3-59-g8ed1b From 8ba8b076a0335155a57a9e8004614c302d07c154 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 25 Jan 2021 14:55:46 -0800 Subject: Remove detachChildren Since there are no longer callers of detachChildren, remove code and test that involve detachChildren Test: Builds and remaining tests pass Bug: 177557720 Change-Id: Id5b7120b7f2c289d4e7ffb5565b29e2be18d6587 --- cmds/surfacereplayer/proto/src/trace.proto | 13 +- cmds/surfacereplayer/replayer/Replayer.cpp | 8 - cmds/surfacereplayer/replayer/Replayer.h | 2 - libs/gui/LayerState.cpp | 3 - libs/gui/SurfaceComposerClient.cpp | 13 - libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 12 - services/surfaceflinger/BufferStateLayer.cpp | 8 +- services/surfaceflinger/BufferStateLayer.h | 1 - services/surfaceflinger/Layer.cpp | 73 ---- services/surfaceflinger/Layer.h | 6 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - services/surfaceflinger/SurfaceInterceptor.cpp | 11 - services/surfaceflinger/SurfaceInterceptor.h | 1 - services/surfaceflinger/tests/Android.bp | 1 - .../surfaceflinger/tests/DetachChildren_test.cpp | 377 --------------------- .../tests/SurfaceInterceptor_test.cpp | 26 -- .../tests/fakehwc/SFFakeHwc_test.cpp | 84 ----- 18 files changed, 6 insertions(+), 638 deletions(-) delete mode 100644 services/surfaceflinger/tests/DetachChildren_test.cpp (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto index c6f656ba0c..79aab822e4 100644 --- a/cmds/surfacereplayer/proto/src/trace.proto +++ b/cmds/surfacereplayer/proto/src/trace.proto @@ -50,11 +50,10 @@ message SurfaceChange { CornerRadiusChange corner_radius = 16; ReparentChange reparent = 17; RelativeParentChange relative_parent = 18; - DetachChildrenChange detach_children = 19; - ReparentChildrenChange reparent_children = 20; - BackgroundBlurRadiusChange background_blur_radius = 21; - ShadowRadiusChange shadow_radius = 22; - BlurRegionsChange blur_regions = 23; + ReparentChildrenChange reparent_children = 19; + BackgroundBlurRadiusChange background_blur_radius = 20; + ShadowRadiusChange shadow_radius = 21; + BlurRegionsChange blur_regions = 22; } } @@ -200,10 +199,6 @@ message RelativeParentChange { required int32 z = 2; } -message DetachChildrenChange { - required bool detach_children = 1; -} - message ShadowRadiusChange { required float radius = 1; } diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 5849212265..58d6582e0b 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -417,9 +417,6 @@ status_t Replayer::doSurfaceTransaction( case SurfaceChange::SurfaceChangeCase::kRelativeParent: setRelativeParentChange(transaction, change.id(), change.relative_parent()); break; - case SurfaceChange::SurfaceChangeCase::kDetachChildren: - setDetachChildrenChange(transaction, change.id(), change.detach_children()); - break; case SurfaceChange::SurfaceChangeCase::kShadowRadius: setShadowRadiusChange(transaction, change.id(), change.shadow_radius()); break; @@ -713,11 +710,6 @@ void Replayer::setRelativeParentChange(SurfaceComposerClient::Transaction& t, t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z()); } -void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t, - layer_id id, const DetachChildrenChange& c) { - t.detachChildren(mLayers[id]); -} - void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t, layer_id id, const ReparentChildrenChange& c) { if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) { diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index a22262a24e..324d591eaa 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -116,8 +116,6 @@ class Replayer { layer_id id, const ReparentChange& c); void setRelativeParentChange(SurfaceComposerClient::Transaction& t, layer_id id, const RelativeParentChange& c); - void setDetachChildrenChange(SurfaceComposerClient::Transaction& t, - layer_id id, const DetachChildrenChange& c); void setReparentChildrenChange(SurfaceComposerClient::Transaction& t, layer_id id, const ReparentChildrenChange& c); void setShadowRadiusChange(SurfaceComposerClient::Transaction& t, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 63be3edf94..e1aba42911 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -427,9 +427,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eReparentChildren; reparentSurfaceControl = other.reparentSurfaceControl; } - if (other.what & eDetachChildren) { - what |= eDetachChildren; - } if (other.what & eRelativeLayerChanged) { what |= eRelativeLayerChanged; what &= ~eLayerChanged; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 4a372bba1e..d203b3d513 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1390,19 +1390,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( - const sp& sc) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eDetachChildren; - - registerSurfaceControlForCallback(sc); - return *this; -} - #ifndef NO_INPUT SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( const sp& sc, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 4a291aeb02..042f901dc9 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -98,7 +98,7 @@ struct layer_state_t { /* was ScalingModeChanged, now available 0x00000400, */ eShadowRadiusChanged = 0x00000800, eReparentChildren = 0x00001000, - eDetachChildren = 0x00002000, + /* was eDetachChildren, now available 0x00002000, */ eRelativeLayerChanged = 0x00004000, eReparent = 0x00008000, eColorChanged = 0x00010000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 11db658de2..884f0546d0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -508,18 +508,6 @@ public: // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour. Transaction& setFrameNumber(const sp& sc, uint64_t frameNumber); - // Detaches all child surfaces (and their children recursively) - // from their SurfaceControl. - // The child SurfaceControls will not throw exceptions or return errors, - // but transactions will have no effect. - // The child surfaces will continue to follow their parent surfaces, - // and remain eligible for rendering, but their relative state will be - // frozen. We use this in the WindowManager, in app shutdown/relaunch - // scenarios, where the app would otherwise clean up its child Surfaces. - // Sometimes the WindowManager needs to extend their lifetime slightly - // in order to perform an exit animation or prevent flicker. - Transaction& detachChildren(const sp& sc); - #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); Transaction& setFocusedWindow(const FocusRequest& request); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 0cc15c2acd..3dc62e3091 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -216,8 +216,7 @@ bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. return (getSidebandStreamChanged() || getAutoRefresh() || (mCurrentState.modified && - (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) && - !mLayerDetached; + (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))); } /* TODO: vhau uncomment once deferred transaction migration complete in @@ -461,11 +460,6 @@ bool BufferStateLayer::setTransactionCompletedListeners( return willPresent; } -void BufferStateLayer::forceSendCallbacks() { - mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( - mCurrentState.callbackHandles, std::vector()); -} - bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { mCurrentState.transparentRegionHint = transparent; mCurrentState.modified = true; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index f638caa4f3..b93d567e20 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -80,7 +80,6 @@ public: bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; bool setTransactionCompletedListeners(const std::vector>& handles) override; - void forceSendCallbacks() override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a545d186dd..da888f64d1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1004,19 +1004,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); - if (mLayerDetached) { - // Ensure BLAST buffer callbacks are processed. - // detachChildren and mLayerDetached were implemented to avoid geometry updates - // to layers in the cases of animation. For BufferQueue layers buffers are still - // consumed as normal. This is useful as otherwise the client could get hung - // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue - // even though it is a little consistent. detachChildren is shortly slated for removal - // by the hierarchy mirroring work so we don't need to worry about it too much. - forceSendCallbacks(); - mCurrentState.callbackHandles = {}; - return flags; - } - if (mChildrenChanged) { flags |= eVisibleRegion; mChildrenChanged = false; @@ -1512,12 +1499,6 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); - if (mLayerDetached) { - // If the layer is detached, then we don't defer this transaction since we will not - // commit the pending state while the layer is detached. Adding sync points may cause - // the barrier layer to wait for the states to be committed before dequeuing a buffer. - return; - } mCurrentState.barrierLayer_legacy = barrierLayer; mCurrentState.barrierFrameNumber = frameNumber; @@ -1801,10 +1782,6 @@ ssize_t Layer::removeChild(const sp& layer) { } void Layer::reparentChildren(const sp& newParent) { - if (attachChildren()) { - setTransactionFlags(eTransactionNeeded); - } - for (const sp& child : mCurrentChildren) { newParent->addChild(child); } @@ -1840,17 +1817,6 @@ void Layer::setChildrenDrawingParent(const sp& newParent) { } bool Layer::reparent(const sp& newParentHandle) { - bool callSetTransactionFlags = false; - - // While layers are detached, we allow most operations - // and simply halt performing the actual transaction. However - // for reparent != null we would enter the mRemovedFromCurrentState - // state, regardless of whether doTransaction was called, and - // so we need to prevent the update here. - if (mLayerDetached && newParentHandle == nullptr) { - return false; - } - sp newParent; if (newParentHandle != nullptr) { auto handle = static_cast(newParentHandle.get()); @@ -1877,52 +1843,13 @@ bool Layer::reparent(const sp& newParentHandle) { } else { onRemovedFromCurrentState(); } - - if (mLayerDetached) { - mLayerDetached = false; - callSetTransactionFlags = true; - } } else { onRemovedFromCurrentState(); } - if (attachChildren() || callSetTransactionFlags) { - setTransactionFlags(eTransactionNeeded); - } return true; } -bool Layer::detachChildren() { - for (const sp& child : mCurrentChildren) { - sp parentClient = mClientRef.promote(); - sp client(child->mClientRef.promote()); - if (client != nullptr && parentClient != client) { - child->mLayerDetached = true; - child->detachChildren(); - child->removeRemoteSyncPoints(); - } - } - - return true; -} - -bool Layer::attachChildren() { - bool changed = false; - for (const sp& child : mCurrentChildren) { - sp parentClient = mClientRef.promote(); - sp client(child->mClientRef.promote()); - if (client != nullptr && parentClient != client) { - if (child->mLayerDetached) { - child->mLayerDetached = false; - child->attachChildren(); - changed = true; - } - } - } - - return changed; -} - bool Layer::setColorTransform(const mat4& matrix) { static const mat4 identityMatrix = mat4(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f78b5f31e9..50c0597de2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -432,7 +432,6 @@ public: virtual bool setMetadata(const LayerMetadata& data); virtual void setChildrenDrawingParent(const sp&); virtual bool reparent(const sp& newParentHandle); - virtual bool detachChildren(); virtual bool setColorTransform(const mat4& matrix); virtual mat4 getColorTransform() const; virtual bool hasColorTransform() const; @@ -459,7 +458,6 @@ public: const std::vector>& /*handles*/) { return false; }; - virtual void forceSendCallbacks() {} virtual bool addFrameEvent(const sp& /*acquireFence*/, nsecs_t /*postedTime*/, nsecs_t /*requestedPresentTime*/) { return false; @@ -664,8 +662,6 @@ public: bool reparentChildren(const sp& newParentHandle); void reparentChildren(const sp& newParent); - bool attachChildren(); - bool isLayerDetached() const { return mLayerDetached; } bool setShadowRadius(float shadowRadius); // Before color management is introduced, contents on Android have to be @@ -1097,8 +1093,6 @@ protected: wp mCurrentParent; wp mDrawingParent; - // Can only be accessed with the SF state lock held. - bool mLayerDetached{false}; // Can only be accessed with the SF state lock held. bool mChildrenChanged{false}; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0a51659681..83a83e05b1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3811,9 +3811,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTransactionNeeded|eTraversalNeeded; } } - if (what & layer_state_t::eDetachChildren) { - layer->detachChildren(); - } if (what & layer_state_t::eTransformChanged) { if (layer->setTransform(s.transform)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 354892386b..61005c92df 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -150,7 +150,6 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque | layer_state_t::eLayerSecure); addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent)); - addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached()); addRelativeParentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf), layer->mCurrentState.z); @@ -409,13 +408,6 @@ void SurfaceInterceptor::addReparentChildrenLocked(Transaction* transaction, int overrideChange->set_parent_id(parentId); } -void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId, - bool detached) { - SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); - DetachChildrenChange* overrideChange(change->mutable_detach_children()); - overrideChange->set_detach_children(detached); -} - void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z) { SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId)); @@ -498,9 +490,6 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, addReparentChildrenLocked(transaction, layerId, getLayerIdFromHandle(state.reparentSurfaceControl->getHandle())); } - if (state.what & layer_state_t::eDetachChildren) { - addDetachChildrenLocked(transaction, layerId, true); - } if (state.what & layer_state_t::eRelativeLayerChanged) { addRelativeParentLocked(transaction, layerId, getLayerIdFromHandle( diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 3df79c6eb5..3e27e83b02 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -177,7 +177,6 @@ private: uint64_t transactionId); void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId); void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId); - void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached); void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId, int z); void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius); diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index e8b24b49bc..cfaf229bde 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -21,7 +21,6 @@ cc_test { "CommonTypes_test.cpp", "Credentials_test.cpp", "DereferenceSurfaceControl_test.cpp", - "DetachChildren_test.cpp", "DisplayConfigs_test.cpp", "EffectLayer_test.cpp", "InvalidHandles_test.cpp", diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp deleted file mode 100644 index abf8b1a2b9..0000000000 --- a/services/surfaceflinger/tests/DetachChildren_test.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" - -#include "LayerTransactionTest.h" - -namespace android { - -class DetachChildren : public LayerTransactionTest { -protected: - virtual void SetUp() { - LayerTransactionTest::SetUp(); - - mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(), - mMainSurfaceBounds.height(), 0, mBlackBgSurface.get()); - - ASSERT_TRUE(mMainSurface != nullptr); - ASSERT_TRUE(mMainSurface->isValid()); - - TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor); - - asTransaction([&](Transaction& t) { - t.setLayer(mMainSurface, INT32_MAX - 1) - .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top) - .show(mMainSurface); - }); - } - - virtual void TearDown() { - LayerTransactionTest::TearDown(); - mMainSurface = 0; - } - - sp mMainSurface; - Color mMainSurfaceColor = {195, 63, 63, 255}; - Rect mMainSurfaceBounds = Rect(64, 64, 128, 128); - std::unique_ptr mCapture; -}; - -TEST_F(DetachChildren, RelativesAreNotDetached) { - Color relativeColor = {10, 10, 10, 255}; - Rect relBounds = Rect(64, 64, 74, 74); - - sp relative = - createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0); - TransactionUtils::fillSurfaceRGBA8(relative, relativeColor); - - Transaction{} - .setRelativeLayer(relative, mMainSurface, 1) - .setPosition(relative, relBounds.left, relBounds.top) - .apply(); - - { - // The relative should be on top of the FG control. - mCapture = screenshot(); - mCapture->expectColor(relBounds, relativeColor); - } - Transaction{}.detachChildren(mMainSurface).apply(); - - { - // Nothing should change at this point. - mCapture = screenshot(); - mCapture->expectColor(relBounds, relativeColor); - } - - Transaction{}.hide(relative).apply(); - - { - // Ensure that the relative was actually hidden, rather than - // being left in the detached but visible state. - mCapture = screenshot(); - mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor); - } -} - -TEST_F(DetachChildren, DetachChildrenSameClient) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 84, 84); - sp child = createLayer(String8("Child surface"), childBounds.width(), - childBounds.height(), 0, mMainSurface.get()); - ASSERT_TRUE(child->isValid()); - - TransactionUtils::fillSurfaceRGBA8(child, childColor); - - asTransaction([&](Transaction& t) { - t.show(child); - t.setPosition(child, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top); - }); - - { - mCapture = screenshot(); - // Expect main color around the child surface - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); }); - - asTransaction([&](Transaction& t) { t.hide(child); }); - - // Since the child has the same client as the parent, it will not get - // detached and will be hidden. - { - mCapture = screenshot(); - mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor); - } -} - -TEST_F(DetachChildren, DetachChildrenDifferentClient) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 84, 84); - - sp newComposerClient = new SurfaceComposerClient; - sp childNewClient = - createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), - childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); - - asTransaction([&](Transaction& t) { - t.show(childNewClient); - t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top); - }); - - { - mCapture = screenshot(); - // Expect main color around the child surface - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); }); - - asTransaction([&](Transaction& t) { t.hide(childNewClient); }); - - // Nothing should have changed. - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } -} - -TEST_F(DetachChildren, DetachChildrenThenAttach) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 84, 84); - - sp newComposerClient = new SurfaceComposerClient; - sp childNewClient = - createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), - childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); - - Transaction() - .show(childNewClient) - .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top) - .apply(); - - { - mCapture = screenshot(); - // Expect main color around the child surface - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - Transaction().detachChildren(mMainSurface).apply(); - Transaction().hide(childNewClient).apply(); - - // Nothing should have changed. - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - Color newParentColor = Color::RED; - Rect newParentBounds = Rect(20, 20, 52, 52); - sp newParentSurface = - createLayer(String8("New Parent Surface"), newParentBounds.width(), - newParentBounds.height(), 0); - TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor); - Transaction() - .setLayer(newParentSurface, INT32_MAX - 1) - .show(newParentSurface) - .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top) - .reparent(childNewClient, newParentSurface) - .apply(); - { - mCapture = screenshot(); - // Child is now hidden. - mCapture->expectColor(newParentBounds, newParentColor); - } -} - -TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 84, 84); - - sp newComposerClient = new SurfaceComposerClient; - sp childNewClient = - createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), - childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); - - Transaction() - .show(childNewClient) - .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top) - .apply(); - - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - Transaction() - .deferTransactionUntil_legacy(childNewClient, mMainSurface, - mMainSurface->getSurface()->getNextFrameNumber()) - .apply(); - Transaction().detachChildren(mMainSurface).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED, - mMainSurfaceBounds.width(), - mMainSurfaceBounds.height())); - - // BufferLayer can still dequeue buffers even though there's a detached layer with a - // deferred transaction. - { - SCOPED_TRACE("new buffer"); - mCapture = screenshot(); - mCapture->expectBorder(childBounds, Color::RED); - mCapture->expectColor(childBounds, childColor); - } -} - -/** - * Tests that a deferring transaction on an already detached layer will be dropped gracefully and - * allow the barrier layer to dequeue buffers. - * - * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer - * to commit its pending states. - */ -TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 84, 84); - - sp newComposerClient = new SurfaceComposerClient; - sp childNewClient = - createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), - childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); - - Transaction() - .show(childNewClient) - .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top) - .apply(); - - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectColor(childBounds, childColor); - } - - Transaction().detachChildren(mMainSurface).apply(); - Transaction() - .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()}) - .deferTransactionUntil_legacy(childNewClient, mMainSurface, - mMainSurface->getSurface()->getNextFrameNumber()) - .apply(); - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED, - mMainSurfaceBounds.width(), - mMainSurfaceBounds.height())); - - // BufferLayer can still dequeue buffers even though there's a detached layer with a - // deferred transaction. - { - SCOPED_TRACE("new buffer"); - mCapture = screenshot(); - mCapture->expectBorder(childBounds, Color::RED); - mCapture->expectColor(childBounds, childColor); - } -} - -TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) { - Color childColor = {200, 200, 200, 255}; - Rect childBounds = Rect(74, 74, 94, 94); - Color grandchildColor = Color::RED; - Rect grandchildBounds = Rect(80, 80, 90, 90); - - sp newClient1 = new SurfaceComposerClient; - sp newClient2 = new SurfaceComposerClient; - - sp childSurface = - createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(), - PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); - sp grandchildSurface = - createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(), - grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get()); - - TransactionUtils::fillSurfaceRGBA8(childSurface, childColor); - TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor); - - Transaction() - .show(childSurface) - .show(grandchildSurface) - .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left, - childBounds.top - mMainSurfaceBounds.top) - .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left, - grandchildBounds.top - childBounds.top) - .apply(); - - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectBorder(grandchildBounds, childColor); - mCapture->expectColor(grandchildBounds, grandchildColor); - } - - Transaction().detachChildren(childSurface).apply(); - - // Remove main surface offscreen - Transaction().reparent(mMainSurface, nullptr).apply(); - { - mCapture = screenshot(); - mCapture->expectColor(mMainSurfaceBounds, Color::BLACK); - } - - Transaction().reparent(mMainSurface, mBlackBgSurface).apply(); - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectBorder(grandchildBounds, childColor); - mCapture->expectColor(grandchildBounds, grandchildColor); - } - - Transaction().hide(grandchildSurface).apply(); - - // grandchild is still detached so it will not hide - { - mCapture = screenshot(); - mCapture->expectBorder(childBounds, mMainSurfaceColor); - mCapture->expectBorder(grandchildBounds, childColor); - mCapture->expectColor(grandchildBounds, grandchildColor); - } -} - -} // namespace android - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 8dc9a1212f..fa88ca5c57 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -194,7 +194,6 @@ public: bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred); bool reparentUpdateFound(const SurfaceChange& change, bool found); bool relativeParentUpdateFound(const SurfaceChange& change, bool found); - bool detachChildrenUpdateFound(const SurfaceChange& change, bool found); bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found); bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found); bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase); @@ -232,7 +231,6 @@ public: void deferredTransactionUpdate(Transaction&); void reparentUpdate(Transaction&); void relativeParentUpdate(Transaction&); - void detachChildrenUpdate(Transaction&); void reparentChildrenUpdate(Transaction&); void shadowRadiusUpdate(Transaction&); void surfaceCreation(Transaction&); @@ -412,10 +410,6 @@ void SurfaceInterceptorTest::relativeParentUpdate(Transaction& t) { t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z); } -void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) { - t.detachChildren(mBGSurfaceControl); -} - void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) { t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl); } @@ -452,7 +446,6 @@ void SurfaceInterceptorTest::runAllUpdates() { runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate); runInTransaction(&SurfaceInterceptorTest::reparentUpdate); runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate); - runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate); runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate); runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate); } @@ -667,16 +660,6 @@ bool SurfaceInterceptorTest::relativeParentUpdateFound(const SurfaceChange& chan return found; } -bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) { - bool detachChildren(change.detach_children().detach_children()); - if (detachChildren && !found) { - found = true; - } else if (detachChildren && found) { - []() { FAIL(); }(); - } - return found; -} - bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) { bool hasId(change.reparent_children().parent_id() == mFGLayerId); if (hasId && !found) { @@ -761,9 +744,6 @@ bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace, case SurfaceChange::SurfaceChangeCase::kRelativeParent: foundUpdate = relativeParentUpdateFound(change, foundUpdate); break; - case SurfaceChange::SurfaceChangeCase::kDetachChildren: - foundUpdate = detachChildrenUpdateFound(change, foundUpdate); - break; case SurfaceChange::SurfaceChangeCase::kShadowRadius: foundUpdate = shadowRadiusUpdateFound(change, foundUpdate); break; @@ -793,7 +773,6 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren)); ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent)); - ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren)); } bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) { @@ -968,11 +947,6 @@ TEST_F(SurfaceInterceptorTest, InterceptRelativeParentUpdateWorks) { SurfaceChange::SurfaceChangeCase::kRelativeParent); } -TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) { - captureTest(&SurfaceInterceptorTest::detachChildrenUpdate, - SurfaceChange::SurfaceChangeCase::kDetachChildren); -} - TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) { captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate, SurfaceChange::SurfaceChangeCase::kShadowRadius); diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index bd49728215..4d7b396dda 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1639,82 +1639,6 @@ protected: EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame())); } - void Test_DetachChildrenSameClient() { - { - TransactionScope ts(*Base::sFakeComposer); - ts.show(mChild); - ts.setPosition(mChild, 10, 10); - ts.setPosition(Base::mFGSurfaceControl, 64, 64); - } - - auto referenceFrame = Base::mBaseFrame; - referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; - referenceFrame[CHILD_LAYER].mDisplayFrame = - hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; - EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); - - { - TransactionScope ts(*Base::sFakeComposer); - ts.setPosition(Base::mFGSurfaceControl, 0, 0); - ts.detachChildren(Base::mFGSurfaceControl); - } - - { - TransactionScope ts(*Base::sFakeComposer); - ts.setPosition(Base::mFGSurfaceControl, 64, 64); - ts.hide(mChild); - } - - std::vector refFrame(2); - refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER]; - refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER]; - - EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame())); - } - - void Test_DetachChildrenDifferentClient() { - sp newComposerClient = new SurfaceComposerClient; - sp childNewClient = - newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, - Base::mFGSurfaceControl->getHandle()); - ASSERT_TRUE(childNewClient != nullptr); - ASSERT_TRUE(childNewClient->isValid()); - fillSurfaceRGBA8(childNewClient, LIGHT_GRAY); - - { - TransactionScope ts(*Base::sFakeComposer); - ts.hide(mChild); - ts.show(childNewClient); - ts.setPosition(childNewClient, 10, 10); - ts.setPosition(Base::mFGSurfaceControl, 64, 64); - } - - auto referenceFrame = Base::mBaseFrame; - referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64}; - referenceFrame[CHILD_LAYER].mDisplayFrame = - hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10}; - EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); - - { - TransactionScope ts(*Base::sFakeComposer); - ts.detachChildren(Base::mFGSurfaceControl); - ts.setPosition(Base::mFGSurfaceControl, 0, 0); - } - - { - TransactionScope ts(*Base::sFakeComposer); - ts.setPosition(Base::mFGSurfaceControl, 64, 64); - ts.setPosition(childNewClient, 0, 0); - ts.hide(childNewClient); - } - - // Nothing should have changed. The child control becomes a no-op - // zombie on detach. See comments for detachChildren in the - // SurfaceControl.h file. - EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame())); - } - // Regression test for b/37673612 void Test_ChildrenWithParentBufferTransform() { { @@ -1815,14 +1739,6 @@ TEST_F(ChildLayerTest_2_1, DISABLED_ReparentChildren) { Test_ReparentChildren(); } -TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) { - Test_DetachChildrenSameClient(); -} - -TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) { - Test_DetachChildrenDifferentClient(); -} - // Regression test for b/37673612 TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) { Test_ChildrenWithParentBufferTransform(); -- cgit v1.2.3-59-g8ed1b From f6eddb6b42a9548f1298e899ea06a7a042182783 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 27 Jan 2021 22:02:11 -0800 Subject: Enable backpressure for BufferStateLayer The default behaviour of buffer state layer is to drop older buffers if there are newer buffers that are ready to be presented. When emulating BufferQueue behavior via the adapter, we want to queue up buffers without any present timestamps. To solve this, we introduce a layer state flag to keep the buffer in the transaction queue if there is already a buffer that is ready to be applied. Test: atest SurfaceViewBufferTests:BufferPresentationTests Bug: 176967609 Change-Id: I33f6347bd1c7a2d80dc4214e596bb864abe8c6bf --- libs/gui/BLASTBufferQueue.cpp | 21 +++++++++++++++++---- libs/gui/LayerState.cpp | 8 +++----- libs/gui/SurfaceComposerClient.cpp | 3 ++- libs/gui/include/gui/LayerState.h | 8 ++++++-- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 7 +++++-- services/surfaceflinger/SurfaceFlinger.cpp | 29 ++++++++++++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 2 +- 8 files changed, 55 insertions(+), 25 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 0a3d44d336..490495596b 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -146,6 +146,10 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const spgetTransformHint(); mBufferItemConsumer->setTransformHint(mTransformHint); + SurfaceComposerClient::Transaction() + .setFlags(surface, layer_state_t::eEnableBackpressure, + layer_state_t::eEnableBackpressure) + .apply(); mNumAcquired = 0; mNumFrameAvailable = 0; @@ -169,13 +173,20 @@ BLASTBufferQueue::~BLASTBufferQueue() { void BLASTBufferQueue::update(const sp& surface, uint32_t width, uint32_t height, int32_t format) { std::unique_lock _lock{mMutex}; - mSurfaceControl = surface; - if (mFormat != format) { mFormat = format; mBufferItemConsumer->setDefaultBufferFormat(format); } + SurfaceComposerClient::Transaction t; + bool applyTransaction = false; + if (!SurfaceControl::isSameSurface(mSurfaceControl, surface)) { + mSurfaceControl = surface; + t.setFlags(mSurfaceControl, layer_state_t::eEnableBackpressure, + layer_state_t::eEnableBackpressure); + applyTransaction = true; + } + ui::Size newSize(width, height); if (mRequestedSize != newSize) { mRequestedSize.set(newSize); @@ -184,13 +195,15 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - SurfaceComposerClient::Transaction t; t.setFrame(mSurfaceControl, {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); - t.apply(); + applyTransaction = true; } } + if (applyTransaction) { + t.apply(); + } } static void transactionCallbackThunk(void* context, nsecs_t latchTime, diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e5e10a0014..2946aaed37 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -183,12 +183,9 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readUint32, &layerStack); SAFE_PARCEL(input.readFloat, &alpha); - uint32_t tmpUint32 = 0; - SAFE_PARCEL(input.readUint32, &tmpUint32); - flags = static_cast(tmpUint32); + SAFE_PARCEL(input.readUint32, &flags); - SAFE_PARCEL(input.readUint32, &tmpUint32); - mask = static_cast(tmpUint32); + SAFE_PARCEL(input.readUint32, &mask); SAFE_PARCEL(matrix.read, input); SAFE_PARCEL(input.read, crop_legacy); @@ -229,6 +226,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, *acquireFence); } + uint32_t tmpUint32 = 0; SAFE_PARCEL(input.readUint32, &tmpUint32); dataspace = static_cast(tmpUint32); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 78f655a71b..96c099be23 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -934,7 +934,8 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags return *this; } if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) || - (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot)) { + (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) || + (mask & layer_state_t::eEnableBackpressure)) { s->what |= layer_state_t::eFlagsChanged; } s->flags &= ~mask; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 83a9d3356e..b1305c6607 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -82,6 +82,10 @@ struct layer_state_t { eLayerOpaque = 0x02, // SURFACE_OPAQUE eLayerSkipScreenshot = 0x40, // SKIP_SCREENSHOT eLayerSecure = 0x80, // SECURE + // Queue up BufferStateLayer buffers instead of dropping the oldest buffer when this flag is + // set. This blocks the client until all the buffers have been presented. If the buffers + // have presentation timestamps, then we may drop buffers. + eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE }; enum { @@ -157,8 +161,8 @@ struct layer_state_t { uint32_t h; uint32_t layerStack; float alpha; - uint8_t flags; - uint8_t mask; + uint32_t flags; + uint32_t mask; uint8_t reserved; matrix22_t matrix; Rect crop_legacy; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66ce3f1a44..177a81a7bc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1312,7 +1312,7 @@ bool Layer::setBlurRegions(const std::vector& blurRegions) { return true; } -bool Layer::setFlags(uint8_t flags, uint8_t mask) { +bool Layer::setFlags(uint32_t flags, uint32_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); if (mCurrentState.flags == newFlags) return false; mCurrentState.sequence++; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 359340eb64..357c4a4dee 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -207,7 +207,7 @@ public: // to achieve mirroring. uint32_t layerStack; - uint8_t flags; + uint32_t flags; uint8_t reserved[2]; int32_t sequence; // changes when visible regions can change bool modified; @@ -425,7 +425,7 @@ public: virtual bool setBackgroundBlurRadius(int backgroundBlurRadius); virtual bool setBlurRegions(const std::vector& effectRegions); virtual bool setTransparentRegionHint(const Region& transparent); - virtual bool setFlags(uint8_t flags, uint8_t mask); + virtual bool setFlags(uint32_t flags, uint32_t mask); virtual bool setLayerStack(uint32_t layerStack); virtual uint32_t getLayerStack() const; virtual void deferTransactionUntil_legacy(const sp& barrierHandle, @@ -906,6 +906,9 @@ public: bool mPendingHWCDestroy{false}; + bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; } + bool hasPendingBuffer() { return mCurrentState.buffer != mDrawingState.buffer; }; + protected: class SyncPoint { public: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c1fabf8322..bf0c2d69f5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3258,7 +3258,8 @@ bool SurfaceFlinger::flushTransactionQueues() { while (!transactionQueue.empty()) { const auto& transaction = transactionQueue.front(); - if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime, + if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp, + transaction.desiredPresentTime, transaction.states)) { setTransactionFlags(eTransactionFlushNeeded); break; @@ -3291,16 +3292,14 @@ bool SurfaceFlinger::transactionFlushNeeded() { return !mTransactionQueues.empty(); } - -bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, +bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime, const Vector& states, bool updateTransactionCounters) { - const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); bool ready = true; // Do not present if the desiredPresentTime has not passed unless it is more than one second // in the future. We ignore timestamps more than 1 second in the future for stability reasons. - if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime && + if (!isAutoTimestamp && desiredPresentTime >= expectedPresentTime && desiredPresentTime < expectedPresentTime + s2ns(1)) { ready = false; } @@ -3320,14 +3319,26 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, ALOGW("Transaction with buffer, but no Layer?"); continue; } - if (layer && !mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) { + if (!layer) { + continue; + } + + if (!mScheduler->isVsyncValid(expectedPresentTime, layer->getOwnerUid())) { ATRACE_NAME("!isVsyncValidForUid"); ready = false; } if (updateTransactionCounters) { - // See BufferStateLayer::mPendingBufferTransactions - if (layer) layer->incrementPendingBufferCount(); + // See BufferStateLayer::mPendingBufferTransactions + layer->incrementPendingBufferCount(); + } + // If backpressure is enabled and we already have a buffer to commit, keep the transaction + // in the queue. + bool hasBuffer = s.what & layer_state_t::eBufferChanged || + s.what & layer_state_t::eCachedBufferChanged; + if (hasBuffer && layer->backpressureEnabled() && layer->hasPendingBuffer() && + isAutoTimestamp) { + ready = false; } } return ready; @@ -3385,7 +3396,7 @@ status_t SurfaceFlinger::setTransactionState( // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount // if the transaction contains a buffer. - if (!transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true) || + if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) || pendingTransactions) { mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, desiredPresentTime, isAutoTimestamp, uncacheBuffer, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c90fb4aca3..194131db32 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -751,7 +751,7 @@ private: uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule); void commitTransaction() REQUIRES(mStateLock); void commitOffscreenLayers(); - bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, + bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime, const Vector& states, bool updateTransactionCounters = false) REQUIRES(mStateLock); uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock); -- cgit v1.2.3-59-g8ed1b From fc434acf530cbde198c8936bf1bc09fad5861031 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 13 Jan 2021 10:28:00 -1000 Subject: Add inputEventId to SurfaceFrame SurfaceFrame will now be aware of the id of the input event that caused the current frame. The flow of input event id is inputflinger -> app -> surfaceflinger. Here, we are adding the 'inputEventId' parameter to the 'setFrameTimelineVsync' call. This call will now be responsible for setting two pieces of information: the vsync id, and the input event id. Since it will no longer be limited to the vsync id, we rename this call to "setFrameTimelineInfo". Once the inputEventId is stored in SurfaceFrame, we will add a binder call to send the frame timing information to inputflinger (separate, future CL). This will allow input to reconstruct the entire sequence of events (at what time was input event getting processed in system_server, app, and surfaceflinger) and will provide the ability to measure end-to-end touch latency. In a separate change, we will also add ATRACE calls to allow manual / script-based latency analysis for local debugging. We will now know which input event is being processed in surfaceflinger. Bug: 169866723 Bug: 129481165 Design doc: https://docs.google.com/document/d/1G3bLaZYSmbe6AKcL-6ZChvrw_B_LXEz29Z6Ed9QoYXY/edit# Test: atest WMShellUnitTests SurfaceParcelable_test libgui_test IPC_test SurfaceFlinger_test Change-Id: If7e0eee82603b38b396b53ad7ced660973efcb50 Merged-In: If7e0eee82603b38b396b53ad7ced660973efcb50 --- libs/gui/Android.bp | 3 + libs/gui/BLASTBufferQueue.cpp | 14 +- libs/gui/FrameTimelineInfo.cpp | 62 +++++ libs/gui/ISurfaceComposer.cpp | 251 ++++++++++----------- libs/gui/ITransactionCompletedListener.cpp | 6 +- libs/gui/LayerState.cpp | 18 +- libs/gui/Surface.cpp | 16 +- libs/gui/SurfaceComposerClient.cpp | 41 ++-- libs/gui/include/gui/BLASTBufferQueue.h | 4 +- libs/gui/include/gui/DisplayEventDispatcher.h | 2 +- libs/gui/include/gui/FrameTimelineInfo.h | 43 ++++ libs/gui/include/gui/ISurfaceComposer.h | 14 +- libs/gui/include/gui/LayerState.h | 4 +- libs/gui/include/gui/Surface.h | 5 +- libs/gui/include/gui/SurfaceComposerClient.h | 13 +- libs/gui/tests/Surface_test.cpp | 6 +- libs/input/android/os/IInputConstants.aidl | 9 + libs/nativewindow/include/system/window.h | 11 +- services/surfaceflinger/BufferQueueLayer.cpp | 14 +- services/surfaceflinger/BufferQueueLayer.h | 6 +- .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 97 ++++---- .../surfaceflinger/FrameTimeline/FrameTimeline.h | 28 +-- services/surfaceflinger/Layer.cpp | 16 +- services/surfaceflinger/Layer.h | 9 +- services/surfaceflinger/SurfaceFlinger.cpp | 40 ++-- services/surfaceflinger/SurfaceFlinger.h | 18 +- services/surfaceflinger/tests/LayerState_test.cpp | 29 +++ .../tests/unittests/FrameTimelineTest.cpp | 187 +++++++-------- .../tests/unittests/TestableSurfaceFlinger.h | 18 +- .../tests/unittests/TransactionApplicationTest.cpp | 72 +++--- 30 files changed, 589 insertions(+), 467 deletions(-) create mode 100644 libs/gui/FrameTimelineInfo.cpp create mode 100644 libs/gui/include/gui/FrameTimelineInfo.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 38ae353a68..fa5044cc16 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -49,6 +49,7 @@ cc_library_shared { srcs: [ ":framework_native_aidl", + ":inputconstants_aidl", ":libgui_aidl", ":libgui_bufferqueue_sources", @@ -62,6 +63,7 @@ cc_library_shared { "DebugEGLImageTracker.cpp", "DisplayEventDispatcher.cpp", "DisplayEventReceiver.cpp", + "FrameTimelineInfo.cpp", "GLConsumer.cpp", "IConsumerListener.cpp", "IDisplayEventConnection.cpp", @@ -154,6 +156,7 @@ cc_library_static { defaults: ["libgui_bufferqueue-defaults"], srcs: [ + ":inputconstants_aidl", ":libgui_aidl", ":libgui_bufferqueue_sources", ], diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 42d2895950..c62d9ad440 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -370,9 +370,9 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { } t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); - if (!mNextFrameTimelineVsyncIdQueue.empty()) { - t->setFrameTimelineVsync(mSurfaceControl, mNextFrameTimelineVsyncIdQueue.front()); - mNextFrameTimelineVsyncIdQueue.pop(); + if (!mNextFrameTimelineInfoQueue.empty()) { + t->setFrameTimelineInfo(mSurfaceControl, mNextFrameTimelineInfoQueue.front()); + mNextFrameTimelineInfoQueue.pop(); } if (mAutoRefresh != bufferItem.mAutoRefresh) { @@ -534,8 +534,8 @@ public: return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless); } - status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override { - return mBbq->setFrameTimelineVsync(frameTimelineVsyncId); + status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override { + return mBbq->setFrameTimelineInfo(frameTimelineInfo); } }; @@ -549,9 +549,9 @@ status_t BLASTBufferQueue::setFrameRate(float frameRate, int8_t compatibility, return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply(); } -status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { +status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { std::unique_lock _lock{mMutex}; - mNextFrameTimelineVsyncIdQueue.push(frameTimelineVsyncId); + mNextFrameTimelineInfoQueue.push(frameTimelineInfo); return OK; } diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp new file mode 100644 index 0000000000..f40077403a --- /dev/null +++ b/libs/gui/FrameTimelineInfo.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "FrameTimelineInfo" + +#include + +#include +#include +#include +#include + +#include + +using android::os::IInputConstants; + +namespace android { + +status_t FrameTimelineInfo::write(Parcel& output) const { + SAFE_PARCEL(output.writeInt64, vsyncId); + SAFE_PARCEL(output.writeInt32, inputEventId); + return NO_ERROR; +} + +status_t FrameTimelineInfo::read(const Parcel& input) { + SAFE_PARCEL(input.readInt64, &vsyncId); + SAFE_PARCEL(input.readInt32, &inputEventId); + return NO_ERROR; +} + +void FrameTimelineInfo::merge(const FrameTimelineInfo& other) { + // When merging vsync Ids we take the oldest valid one + if (vsyncId != INVALID_VSYNC_ID && other.vsyncId != INVALID_VSYNC_ID) { + if (other.vsyncId > vsyncId) { + vsyncId = other.vsyncId; + inputEventId = other.inputEventId; + } + } else if (vsyncId == INVALID_VSYNC_ID) { + vsyncId = other.vsyncId; + inputEventId = other.inputEventId; + } +} + +void FrameTimelineInfo::clear() { + vsyncId = INVALID_VSYNC_ID; + inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID; +} + +}; // namespace android diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index a8d6832275..f68f3e134e 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -68,16 +68,19 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual status_t setTransactionState( - int64_t frameTimelineVsyncId, const Vector& state, - const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - const std::vector& listenerCallbacks, uint64_t transactionId) { + status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& state, + const Vector& displays, uint32_t flags, + const sp& applyToken, const InputWindowCommands& commands, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + const std::vector& listenerCallbacks, + uint64_t transactionId) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.write, data); + SAFE_PARCEL(data.writeUint32, static_cast(state.size())); for (const auto& s : state) { SAFE_PARCEL(s.write, data); @@ -108,15 +111,14 @@ public: return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply); } - virtual void bootFinished() - { + void bootFinished() override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply); } - virtual status_t captureDisplay(const DisplayCaptureArgs& args, - const sp& captureListener) { + status_t captureDisplay(const DisplayCaptureArgs& args, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(args.write, data); @@ -125,8 +127,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply); } - virtual status_t captureDisplay(uint64_t displayOrLayerStack, - const sp& captureListener) { + status_t captureDisplay(uint64_t displayOrLayerStack, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(data.writeUint64, displayOrLayerStack); @@ -135,8 +137,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply); } - virtual status_t captureLayers(const LayerCaptureArgs& args, - const sp& captureListener) { + status_t captureLayers(const LayerCaptureArgs& args, + const sp& captureListener) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(args.write, data); @@ -145,9 +147,8 @@ public: return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); } - virtual bool authenticateSurfaceTexture( - const sp& bufferProducer) const - { + bool authenticateSurfaceTexture( + const sp& bufferProducer) const override { Parcel data, reply; int err = NO_ERROR; err = data.writeInterfaceToken( @@ -180,8 +181,7 @@ public: return result != 0; } - virtual status_t getSupportedFrameTimestamps( - std::vector* outSupported) const { + status_t getSupportedFrameTimestamps(std::vector* outSupported) const override { if (!outSupported) { return UNEXPECTED_NULL; } @@ -224,8 +224,8 @@ public: return NO_ERROR; } - virtual sp createDisplayEventConnection( - VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) { + sp createDisplayEventConnection( + VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override { Parcel data, reply; sp result; int err = data.writeInterfaceToken( @@ -247,8 +247,7 @@ public: return result; } - virtual sp createDisplay(const String8& displayName, bool secure) - { + sp createDisplay(const String8& displayName, bool secure) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t status = data.writeString8(displayName); @@ -272,15 +271,14 @@ public: return display; } - virtual void destroyDisplay(const sp& display) - { + void destroyDisplay(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply); } - virtual std::vector getPhysicalDisplayIds() const { + std::vector getPhysicalDisplayIds() const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) == @@ -297,7 +295,7 @@ public: return {}; } - virtual sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const { + sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeUint64(displayId.value); @@ -305,8 +303,7 @@ public: return reply.readStrongBinder(); } - virtual void setPowerMode(const sp& display, int mode) - { + void setPowerMode(const sp& display, int mode) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -314,7 +311,7 @@ public: remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply); } - virtual status_t getDisplayState(const sp& display, ui::DisplayState* state) { + status_t getDisplayState(const sp& display, ui::DisplayState* state) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -326,7 +323,7 @@ public: return result; } - virtual status_t getDisplayInfo(const sp& display, DisplayInfo* info) { + status_t getDisplayInfo(const sp& display, DisplayInfo* info) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -336,7 +333,8 @@ public: return reply.read(*info); } - virtual status_t getDisplayConfigs(const sp& display, Vector* configs) { + status_t getDisplayConfigs(const sp& display, + Vector* configs) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -354,9 +352,7 @@ public: return result; } - virtual status_t getDisplayStats(const sp& display, - DisplayStatInfo* stats) - { + status_t getDisplayStats(const sp& display, DisplayStatInfo* stats) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -370,8 +366,7 @@ public: return result; } - virtual int getActiveConfig(const sp& display) - { + int getActiveConfig(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -379,8 +374,8 @@ public: return reply.readInt32(); } - virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) { + status_t getDisplayColorModes(const sp& display, + Vector* outColorModes) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -409,8 +404,8 @@ public: return result; } - virtual status_t getDisplayNativePrimaries(const sp& display, - ui::DisplayPrimaries& primaries) { + status_t getDisplayNativePrimaries(const sp& display, + ui::DisplayPrimaries& primaries) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -435,7 +430,7 @@ public: return result; } - virtual ColorMode getActiveColorMode(const sp& display) { + ColorMode getActiveColorMode(const sp& display) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -455,8 +450,7 @@ public: return static_cast(reply.readInt32()); } - virtual status_t setActiveColorMode(const sp& display, - ColorMode colorMode) { + status_t setActiveColorMode(const sp& display, ColorMode colorMode) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -481,8 +475,8 @@ public: return static_cast(reply.readInt32()); } - virtual status_t getAutoLowLatencyModeSupport(const sp& display, - bool* outSupport) const { + status_t getAutoLowLatencyModeSupport(const sp& display, + bool* outSupport) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -499,7 +493,7 @@ public: return reply.readBool(outSupport); } - virtual void setAutoLowLatencyMode(const sp& display, bool on) { + void setAutoLowLatencyMode(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -524,7 +518,8 @@ public: } } - virtual status_t getGameContentTypeSupport(const sp& display, bool* outSupport) const { + status_t getGameContentTypeSupport(const sp& display, + bool* outSupport) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -540,7 +535,7 @@ public: return reply.readBool(outSupport); } - virtual void setGameContentType(const sp& display, bool on) { + void setGameContentType(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -563,7 +558,7 @@ public: } } - virtual status_t clearAnimationFrameStats() { + status_t clearAnimationFrameStats() override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -578,7 +573,7 @@ public: return reply.readInt32(); } - virtual status_t getAnimationFrameStats(FrameStats* outStats) const { + status_t getAnimationFrameStats(FrameStats* outStats) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply); @@ -586,8 +581,8 @@ public: return reply.readInt32(); } - virtual status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const { + status_t getHdrCapabilities(const sp& display, + HdrCapabilities* outCapabilities) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t result = data.writeStrongBinder(display); @@ -608,7 +603,7 @@ public: return result; } - virtual status_t enableVSyncInjections(bool enable) { + status_t enableVSyncInjections(bool enable) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -629,7 +624,7 @@ public: return result; } - virtual status_t injectVSync(nsecs_t when) { + status_t injectVSync(nsecs_t when) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -650,7 +645,7 @@ public: return result; } - virtual status_t getLayerDebugInfo(std::vector* outLayers) { + status_t getLayerDebugInfo(std::vector* outLayers) override { if (!outLayers) { return UNEXPECTED_NULL; } @@ -680,10 +675,10 @@ public: return reply.readParcelableVector(outLayers); } - virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace, - ui::PixelFormat* defaultPixelFormat, - ui::Dataspace* wideColorGamutDataspace, - ui::PixelFormat* wideColorGamutPixelFormat) const { + status_t getCompositionPreference(ui::Dataspace* defaultDataspace, + ui::PixelFormat* defaultPixelFormat, + ui::Dataspace* wideColorGamutDataspace, + ui::PixelFormat* wideColorGamutPixelFormat) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -703,7 +698,7 @@ public: return error; } - virtual status_t getColorManagement(bool* outGetColorManagement) const { + status_t getColorManagement(bool* outGetColorManagement) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply); @@ -715,10 +710,10 @@ public: return err; } - virtual status_t getDisplayedContentSamplingAttributes(const sp& display, - ui::PixelFormat* outFormat, - ui::Dataspace* outDataspace, - uint8_t* outComponentMask) const { + status_t getDisplayedContentSamplingAttributes(const sp& display, + ui::PixelFormat* outFormat, + ui::Dataspace* outDataspace, + uint8_t* outComponentMask) const override { if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE; Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -752,8 +747,8 @@ public: return error; } - virtual status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, - uint8_t componentMask, uint64_t maxFrames) { + status_t setDisplayContentSamplingEnabled(const sp& display, bool enable, + uint8_t componentMask, uint64_t maxFrames) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); @@ -766,9 +761,9 @@ public: return result; } - virtual status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, - uint64_t timestamp, - DisplayedFrameStats* outStats) const { + status_t getDisplayedContentSample(const sp& display, uint64_t maxFrames, + uint64_t timestamp, + DisplayedFrameStats* outStats) const override { if (!outStats) return BAD_VALUE; Parcel data, reply; @@ -805,7 +800,7 @@ public: return result; } - virtual status_t getProtectedContentSupport(bool* outSupported) const { + status_t getProtectedContentSupport(bool* outSupported) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t error = @@ -817,8 +812,8 @@ public: return error; } - virtual status_t isWideColorDisplay(const sp& token, - bool* outIsWideColorDisplay) const { + status_t isWideColorDisplay(const sp& token, + bool* outIsWideColorDisplay) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -837,9 +832,8 @@ public: return error; } - virtual status_t addRegionSamplingListener(const Rect& samplingArea, - const sp& stopLayerHandle, - const sp& listener) { + status_t addRegionSamplingListener(const Rect& samplingArea, const sp& stopLayerHandle, + const sp& listener) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -868,7 +862,7 @@ public: return error; } - virtual status_t removeRegionSamplingListener(const sp& listener) { + status_t removeRegionSamplingListener(const sp& listener) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -888,12 +882,11 @@ public: return error; } - virtual status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { + status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t defaultConfig, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { @@ -947,13 +940,12 @@ public: return reply.readInt32(); } - virtual status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) { + status_t getDesiredDisplayConfigSpecs(const sp& displayToken, + int32_t* outDefaultConfig, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override { if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { @@ -1011,8 +1003,8 @@ public: return reply.readInt32(); } - virtual status_t getDisplayBrightnessSupport(const sp& displayToken, - bool* outSupport) const { + status_t getDisplayBrightnessSupport(const sp& displayToken, + bool* outSupport) const override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1039,7 +1031,7 @@ public: return NO_ERROR; } - virtual status_t setDisplayBrightness(const sp& displayToken, float brightness) { + status_t setDisplayBrightness(const sp& displayToken, float brightness) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1064,7 +1056,7 @@ public: return NO_ERROR; } - virtual status_t notifyPowerBoost(int32_t boostId) { + status_t notifyPowerBoost(int32_t boostId) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1085,8 +1077,8 @@ public: return NO_ERROR; } - virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, - float lightPosY, float lightPosZ, float lightRadius) { + status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, + float lightPosY, float lightPosZ, float lightRadius) override { Parcel data, reply; status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (error != NO_ERROR) { @@ -1114,8 +1106,8 @@ public: return NO_ERROR; } - virtual status_t setFrameRate(const sp& surface, float frameRate, - int8_t compatibility, bool shouldBeSeamless) { + status_t setFrameRate(const sp& surface, float frameRate, + int8_t compatibility, bool shouldBeSeamless) override { Parcel data, reply; status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { @@ -1156,7 +1148,7 @@ public: return reply.readInt32(); } - virtual status_t acquireFrameRateFlexibilityToken(sp* outToken) { + status_t acquireFrameRateFlexibilityToken(sp* outToken) override { if (!outToken) return BAD_VALUE; Parcel data, reply; @@ -1191,40 +1183,34 @@ public: return NO_ERROR; } - virtual status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) { + status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) override { Parcel data, reply; status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err), - -err); + ALOGE("%s: failed writing interface token: %s (%d)", __func__, strerror(-err), -err); return err; } err = data.writeStrongBinder(IInterface::asBinder(surface)); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err), - -err); + ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err); return err; } - err = data.writeInt64(frameTimelineVsyncId); - if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err); - return err; - } + SAFE_PARCEL(frameTimelineInfo.write, data); - err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply); + err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err); + ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err); return err; } return reply.readInt32(); } - virtual status_t addTransactionTraceListener( - const sp& listener) { + status_t addTransactionTraceListener( + const sp& listener) override { Parcel data, reply; SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); @@ -1235,7 +1221,7 @@ public: /** * Get priority of the RenderEngine in surface flinger. */ - virtual int getGPUContextPriority() { + int getGPUContextPriority() override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); status_t err = @@ -1269,8 +1255,9 @@ status_t BnSurfaceComposer::onTransact( case SET_TRANSACTION_STATE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - int64_t frameTimelineVsyncId; - SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, data); + uint32_t count = 0; SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize()); Vector state; @@ -1324,10 +1311,10 @@ status_t BnSurfaceComposer::onTransact( uint64_t transactionId = -1; SAFE_PARCEL(data.readUint64, &transactionId); - return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags, - applyToken, inputWindowCommands, desiredPresentTime, - isAutoTimestamp, uncachedBuffer, hasListenerCallbacks, - listenerCallbacks, transactionId); + return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken, + inputWindowCommands, desiredPresentTime, isAutoTimestamp, + uncachedBuffer, hasListenerCallbacks, listenerCallbacks, + transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); @@ -2078,30 +2065,26 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case SET_FRAME_TIMELINE_VSYNC: { + case SET_FRAME_TIMELINE_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp binder; status_t err = data.readStrongBinder(&binder); if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)", - strerror(-err), -err); + ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err), + -err); return err; } sp surface = interface_cast(binder); if (!surface) { - ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)", + ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)", strerror(-err), -err); return err; } - int64_t frameTimelineVsyncId; - err = data.readInt64(&frameTimelineVsyncId); - if (err != NO_ERROR) { - ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err), - -err); - return err; - } - status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, data); + + status_t result = setFrameTimelineInfo(surface, frameTimelineInfo); reply->writeInt32(result); return NO_ERROR; } diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 180857185c..0ded9361bf 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -92,10 +92,8 @@ status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { return err; } -JankData::JankData() : - frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), - jankType(JankType::None) { -} +JankData::JankData() + : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {} status_t JankData::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeInt64, frameVsyncId); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2946aaed37..a4b054a5ff 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -63,7 +63,7 @@ layer_state_t::layer_state_t() shouldBeSeamless(true), fixedTransformHint(ui::Transform::ROT_INVALID), frameNumber(0), - frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID), + frameTimelineInfo(), autoRefresh(false) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; @@ -151,7 +151,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeBool, shouldBeSeamless); SAFE_PARCEL(output.writeUint32, fixedTransformHint); SAFE_PARCEL(output.writeUint64, frameNumber); - SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.write, output); SAFE_PARCEL(output.writeBool, autoRefresh); SAFE_PARCEL(output.writeUint32, blurRegions.size()); @@ -270,7 +270,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); SAFE_PARCEL(input.readUint64, &frameNumber); - SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId); + SAFE_PARCEL(frameTimelineInfo.read, input); SAFE_PARCEL(input.readBool, &autoRefresh); uint32_t numRegions = 0; @@ -537,15 +537,9 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameNumberChanged; frameNumber = other.frameNumber; } - if (other.what & eFrameTimelineVsyncChanged) { - // When merging vsync Ids we take the oldest valid one - if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && - other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId); - } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { - frameTimelineVsyncId = other.frameTimelineVsyncId; - } - what |= eFrameTimelineVsyncChanged; + if (other.what & eFrameTimelineInfoChanged) { + what |= eFrameTimelineInfoChanged; + frameTimelineInfo.merge(other.frameTimelineInfo); } if (other.what & eAutoRefreshChanged) { what |= eAutoRefreshChanged; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e82f0cc9e9..59ad8d28bd 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1496,8 +1496,8 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER: res = dispatchGetLastQueuedBuffer(args); break; - case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC: - res = dispatchSetFrameTimelineVsync(args); + case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO: + res = dispatchSetFrameTimelineInfo(args); break; default: res = NAME_NOT_FOUND; @@ -1806,12 +1806,13 @@ int Surface::dispatchGetLastQueuedBuffer(va_list args) { return result; } -int Surface::dispatchSetFrameTimelineVsync(va_list args) { +int Surface::dispatchSetFrameTimelineInfo(va_list args) { ATRACE_CALL(); auto frameTimelineVsyncId = static_cast(va_arg(args, int64_t)); + auto inputEventId = static_cast(va_arg(args, int32_t)); - ALOGV("Surface::dispatchSetFrameTimelineVsync"); - return setFrameTimelineVsync(frameTimelineVsyncId); + ALOGV("Surface::%s", __func__); + return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId}); } bool Surface::transformToDisplayInverse() { @@ -2579,9 +2580,8 @@ status_t Surface::setFrameRate(float frameRate, int8_t compatibility, bool shoul shouldBeSeamless); } -status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) { - return composerService()->setFrameTimelineVsync(mGraphicBufferProducer, - frameTimelineVsyncId); +status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) { + return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo); } }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 96c099be23..a1bdc033b0 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -396,7 +396,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime), mIsAutoTimestamp(other.mIsAutoTimestamp), - mFrameTimelineVsyncId(other.mFrameTimelineVsyncId), + mFrameTimelineInfo(other.mFrameTimelineInfo), mApplyToken(other.mApplyToken) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; @@ -427,7 +427,9 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const bool containsBuffer = parcel->readBool(); const int64_t desiredPresentTime = parcel->readInt64(); const bool isAutoTimestamp = parcel->readBool(); - const int64_t frameTimelineVsyncId = parcel->readInt64(); + FrameTimelineInfo frameTimelineInfo; + SAFE_PARCEL(frameTimelineInfo.read, *parcel); + sp applyToken; parcel->readNullableStrongBinder(&applyToken); size_t count = static_cast(parcel->readUint32()); @@ -502,7 +504,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mContainsBuffer = containsBuffer; mDesiredPresentTime = desiredPresentTime; mIsAutoTimestamp = isAutoTimestamp; - mFrameTimelineVsyncId = frameTimelineVsyncId; + mFrameTimelineInfo = frameTimelineInfo; mDisplayStates = displayStates; mListenerCallbacks = listenerCallbacks; mComposerStates = composerStates; @@ -534,7 +536,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeBool(mContainsBuffer); parcel->writeInt64(mDesiredPresentTime); parcel->writeBool(mIsAutoTimestamp); - parcel->writeInt64(mFrameTimelineVsyncId); + SAFE_PARCEL(mFrameTimelineInfo.write, *parcel); parcel->writeStrongBinder(mApplyToken); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { @@ -613,13 +615,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd; mApplyToken = other.mApplyToken; - // When merging vsync Ids we take the oldest one - if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID && - other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId); - } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) { - mFrameTimelineVsyncId = other.mFrameTimelineVsyncId; - } + mFrameTimelineInfo.merge(other.mFrameTimelineInfo); other.clear(); return *this; @@ -639,7 +635,7 @@ void SurfaceComposerClient::Transaction::clear() { mExplicitEarlyWakeupEnd = false; mDesiredPresentTime = 0; mIsAutoTimestamp = true; - mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mFrameTimelineInfo.clear(); mApplyToken = nullptr; } @@ -651,9 +647,8 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, - systemTime(), true, uncacheBuffer, false, {}, - 0 /* Undefined transactionId */); + sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true, + uncacheBuffer, false, {}, 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -773,7 +768,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { ? mApplyToken : IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, + sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken, mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, hasListenerCallbacks, listenerCallbacks, mId); @@ -1549,22 +1544,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixed return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( - int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( + const FrameTimelineInfo& frameTimelineInfo) { + mFrameTimelineInfo = frameTimelineInfo; return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync( - const sp& sc, int64_t frameTimelineVsyncId) { +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo( + const sp& sc, const FrameTimelineInfo& frameTimelineInfo) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->what |= layer_state_t::eFrameTimelineVsyncChanged; - s->frameTimelineVsyncId = frameTimelineVsyncId; + s->what |= layer_state_t::eFrameTimelineInfoChanged; + s->frameTimelineInfo = frameTimelineInfo; return *this; } diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 7f69bc4244..fa3efe15db 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -92,7 +92,7 @@ public: void flushShadowQueue() { mFlushShadowQueue = true; } status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); - status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); + status_t setFrameTimelineInfo(const FrameTimelineInfo& info); virtual ~BLASTBufferQueue(); @@ -156,7 +156,7 @@ private: // This is only relevant for shared buffer mode. bool mAutoRefresh GUARDED_BY(mMutex) = false; - std::queue mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex); + std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); // Last acquired buffer's scaling mode. This is used to check if we should update the blast // layer size immediately or wait until we get the next buffer. This will support scenarios diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 5587acf08f..f446dd88ed 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -25,7 +25,7 @@ struct VsyncEventData { // The Vsync Id corresponsing to this vsync event. This will be used to // populate ISurfaceComposer::setFrameTimelineVsync and // SurfaceComposerClient::setFrameTimelineVsync - int64_t id = ISurfaceComposer::INVALID_VSYNC_ID; + int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID; // The deadline in CLOCK_MONOTONIC that the app needs to complete its // frame by (both on the CPU and the GPU) diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h new file mode 100644 index 0000000000..3b4c009609 --- /dev/null +++ b/libs/gui/include/gui/FrameTimelineInfo.h @@ -0,0 +1,43 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace android { + +struct FrameTimelineInfo { + // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java + static constexpr int64_t INVALID_VSYNC_ID = -1; + + // The vsync id that was used to start the transaction + int64_t vsyncId = INVALID_VSYNC_ID; + + // The id of the input event that caused this buffer + int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + + status_t write(Parcel& output) const; + status_t read(const Parcel& input); + + void merge(const FrameTimelineInfo& other); + void clear(); +}; + +} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 86f3c605ab..81ff6b0d8d 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -117,9 +118,6 @@ public: using EventRegistrationFlags = Flags; - // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java - static constexpr int64_t INVALID_VSYNC_ID = -1; - /* * Create a connection with SurfaceFlinger. */ @@ -164,7 +162,7 @@ public: /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */ virtual status_t setTransactionState( - int64_t frameTimelineVsyncId, const Vector& state, + const FrameTimelineInfo& frameTimelineInfo, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, @@ -494,11 +492,11 @@ public: virtual status_t acquireFrameRateFlexibilityToken(sp* outToken) = 0; /* - * Sets the frame timeline vsync id received from choreographer that corresponds to next + * Sets the frame timeline vsync info received from choreographer that corresponds to next * buffer submitted on that surface. */ - virtual status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) = 0; + virtual status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) = 0; /* * Adds a TransactionTraceListener to listen for transaction tracing state updates. @@ -569,7 +567,7 @@ public: SET_GAME_CONTENT_TYPE, SET_FRAME_RATE, ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, - SET_FRAME_TIMELINE_VSYNC, + SET_FRAME_TIMELINE_INFO, ADD_TRANSACTION_TRACE_LISTENER, GET_GPU_CONTEXT_PRIORITY, // Always append new enum to the end. diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index b1305c6607..b3b074ad2f 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -132,7 +132,7 @@ struct layer_state_t { eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, eFrameNumberChanged = 0x400'00000000, - eFrameTimelineVsyncChanged = 0x800'00000000, + eFrameTimelineInfoChanged = 0x800'00000000, eBlurRegionsChanged = 0x1000'00000000, eAutoRefreshChanged = 0x2000'00000000, }; @@ -238,7 +238,7 @@ struct layer_state_t { // graphics producer. uint64_t frameNumber; - int64_t frameTimelineVsyncId; + FrameTimelineInfo frameTimelineInfo; // Indicates that the consumer should acquire the next frame as soon as it // can and not wait for a frame to become available. This is only relevant diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 43b5dcd60d..b6b5c7ca5e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -18,6 +18,7 @@ #define ANDROID_GUI_SURFACE_H #include +#include #include #include #include @@ -187,7 +188,7 @@ public: status_t getConsumerUsage(uint64_t* outUsage) const; virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); - virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId); + virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info); protected: virtual ~Surface(); @@ -273,7 +274,7 @@ private: int dispatchAddQueueInterceptor(va_list args); int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); - int dispatchSetFrameTimelineVsync(va_list args); + int dispatchSetFrameTimelineInfo(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 11db658de2..bed5c44110 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -385,8 +385,8 @@ public: int64_t mDesiredPresentTime = 0; bool mIsAutoTimestamp = true; - // The vsync Id provided by Choreographer.getVsyncId - int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + // The vsync id provided by Choreographer.getVsyncId and the input event id + FrameTimelineInfo mFrameTimelineInfo; // If not null, transactions will be queued up using this token otherwise a common token // per process will be used. @@ -546,11 +546,12 @@ public: Transaction& setFixedTransformHint(const sp& sc, int32_t transformHint); // Sets the frame timeline vsync id received from choreographer that corresponds - // to the transaction. - Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId); + // to the transaction, and the input event id that identifies the input event that caused + // the current frame. + Transaction& setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo); // Variant that only applies to a specific SurfaceControl. - Transaction& setFrameTimelineVsync(const sp& sc, - int64_t frameTimelineVsyncId); + Transaction& setFrameTimelineInfo(const sp& sc, + const FrameTimelineInfo& frameTimelineInfo); // Indicates that the consumer should acquire the next frame as soon as it // can and not wait for a frame to become available. This is only relevant diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 63db9a7b96..3f7a5b1785 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -695,7 +695,7 @@ public: void destroyDisplay(const sp& /*display */) override {} std::vector getPhysicalDisplayIds() const override { return {}; } sp getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; } - status_t setTransactionState(int64_t /*frameTimelineVsyncId*/, + status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/, const Vector& /*state*/, const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, @@ -877,8 +877,8 @@ public: return NO_ERROR; } - status_t setFrameTimelineVsync(const sp& /*surface*/, - int64_t /*frameTimelineVsyncId*/) override { + status_t setFrameTimelineInfo(const sp& /*surface*/, + const FrameTimelineInfo& /*frameTimelineInfo*/) override { return NO_ERROR; } diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl index 6316b59a57..bce0ec8367 100644 --- a/libs/input/android/os/IInputConstants.aidl +++ b/libs/input/android/os/IInputConstants.aidl @@ -28,4 +28,13 @@ interface IInputConstants * to identify apps that are using this flag. */ const long BLOCK_FLAG_SLIPPERY = 157929241; + + // Indicate invalid battery capacity + const int INVALID_BATTERY_CAPACITY = -1; + + /** + * Every input event has an id. This constant value is used when a valid input event id is not + * available. + */ + const int INVALID_INPUT_EVENT_ID = 0; } diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 82d2e661b4..ffe4412b72 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -255,7 +255,7 @@ enum { NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ - NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC = 48, /* private */ + NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */ // clang-format on }; @@ -1023,10 +1023,11 @@ static inline int native_window_set_frame_rate(struct ANativeWindow* window, flo (int)compatibility, (int)shouldBeSeamless); } -static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window, - int64_t frameTimelineVsyncId) { - return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC, - frameTimelineVsyncId); +static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window, + int64_t frameTimelineVsyncId, + int32_t inputEventId) { + return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO, + frameTimelineVsyncId, inputEventId); } // ------------------------------------------------------------------------------------------------ diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 32e6b1098f..52197873c5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -384,8 +384,8 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) { + mFrameTimelineInfo = frameTimelineInfo; } // ----------------------------------------------------------------------- @@ -445,9 +445,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, surfaceFrame}); @@ -485,9 +484,8 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 0e8fdbe092..41ff01262e 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -101,7 +101,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override; + void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override; sp createClone() override; @@ -145,10 +145,10 @@ private: sp mContentsChangedListener; - // The last vsync id received on this layer. This will be used when we get + // The last vsync info received on this layer. This will be used when we get // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. - std::optional mFrameTimelineVsyncId; + FrameTimelineInfo mFrameTimelineInfo; // Keeps track of the time SF latched the last buffer from this layer. // Used in buffer stuffing analysis in FrameTimeline. diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 17d1f3bff7..3743716876 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -275,13 +275,15 @@ int64_t TraceCookieCounter::getCookieForTracing() { return ++mTraceCookie; } -SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName, PredictionState predictionState, +SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, + uid_t ownerUid, std::string layerName, std::string debugName, + PredictionState predictionState, frametimeline::TimelineItem&& predictions, std::shared_ptr timeStats, JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter) - : mToken(token), + : mToken(frameTimelineInfo.vsyncId), + mInputEventId(frameTimelineInfo.inputEventId), mOwnerPid(ownerPid), mOwnerUid(ownerUid), mLayerName(std::move(layerName)), @@ -295,27 +297,27 @@ SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::s mTraceCookieCounter(*traceCookieCounter) {} void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActuals.startTime = actualStartTime; } void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActualQueueTime = actualQueueTime; } void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime); } void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mPresentState = presentState; mLastLatchTime = lastLatchTime; } std::optional SurfaceFrame::getJankType() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); if (mActuals.presentTime == 0) { return std::nullopt; } @@ -323,32 +325,32 @@ std::optional SurfaceFrame::getJankType() const { } nsecs_t SurfaceFrame::getBaseTime() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return getMinTime(mPredictionState, mPredictions, mActuals); } TimelineItem SurfaceFrame::getActuals() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mActuals; } SurfaceFrame::PresentState SurfaceFrame::getPresentState() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mPresentState; } FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mFramePresentMetadata; } FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); return mFrameReadyMetadata; } void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); StringAppendF(&result, "%s", indent.c_str()); StringAppendF(&result, "Layer - %s", mDebugName.c_str()); if (mJankType != JankType::None) { @@ -387,7 +389,7 @@ void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, nsecs_t vsyncPeriod) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); if (mPresentState != PresentState::Presented) { // No need to update dropped buffers return; @@ -479,6 +481,9 @@ void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType); } +/** + * TODO(b/178637512): add inputEventId to the perfetto trace. + */ void SurfaceFrame::trace(int64_t displayFrameToken) { using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource; @@ -486,12 +491,12 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { bool missingToken = false; // Expected timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); - if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) { + std::scoped_lock lock(mMutex); + if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str()); missingToken = true; return; - } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) { + } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken", mLayerName.c_str()); missingToken = true; @@ -521,7 +526,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { // Expected timeline end FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); packet->set_timestamp(static_cast(mPredictions.endTime)); @@ -535,7 +540,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing(); // Actual timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); // Actual start time is not yet available, so use expected start instead @@ -566,7 +571,7 @@ void SurfaceFrame::trace(int64_t displayFrameToken) { }); // Actual timeline end FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto packet = ctx.NewTracePacket(); packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC); packet->set_timestamp(static_cast(mActuals.endTime)); @@ -582,7 +587,7 @@ namespace impl { int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); const int64_t assignedToken = mCurrentToken++; mPredictions[assignedToken] = {systemTime(), predictions}; flushTokens(systemTime()); @@ -590,7 +595,7 @@ int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) { } std::optional TokenManager::getPredictionsForToken(int64_t token) const { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); auto predictionsIterator = mPredictions.find(token); if (predictionsIterator != mPredictions.end()) { return predictionsIterator->second.predictions; @@ -634,26 +639,28 @@ void FrameTimeline::registerDataSource() { } std::shared_ptr FrameTimeline::createSurfaceFrameForToken( - std::optional token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName) { + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) { ATRACE_CALL(); - if (!token) { - return std::make_shared(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid, - ownerUid, std::move(layerName), std::move(debugName), + if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) { + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), PredictionState::None, TimelineItem(), mTimeStats, mJankClassificationThresholds, &mTraceCookieCounter); } - std::optional predictions = mTokenManager.getPredictionsForToken(*token); + std::optional predictions = + mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId); if (predictions) { - return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), - std::move(debugName), PredictionState::Valid, - std::move(*predictions), mTimeStats, - mJankClassificationThresholds, &mTraceCookieCounter); - } - return std::make_shared(*token, ownerPid, ownerUid, std::move(layerName), - std::move(debugName), PredictionState::Expired, - TimelineItem(), mTimeStats, mJankClassificationThresholds, - &mTraceCookieCounter); + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), + PredictionState::Valid, std::move(*predictions), + mTimeStats, mJankClassificationThresholds, + &mTraceCookieCounter); + } + return std::make_shared(frameTimelineInfo, ownerPid, ownerUid, + std::move(layerName), std::move(debugName), + PredictionState::Expired, TimelineItem(), mTimeStats, + mJankClassificationThresholds, &mTraceCookieCounter); } FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr timeStats, @@ -669,13 +676,13 @@ FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr timeStats, void FrameTimeline::addSurfaceFrame(std::shared_ptr surfaceFrame) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame); } void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod, mTokenManager.getPredictionsForToken(token), wakeUpTime); } @@ -683,7 +690,7 @@ void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsync void FrameTimeline::setSfPresent(nsecs_t sfPresentTime, const std::shared_ptr& presentFence) { ATRACE_CALL(); - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); mCurrentDisplayFrame->setActualEndTime(sfPresentTime); mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame)); flushPendingPresentFences(); @@ -826,7 +833,7 @@ void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const { // Expected timeline start FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) { auto packet = ctx.NewTracePacket(); - if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) { + if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) { ALOGD("Cannot trace DisplayFrame with invalid token"); missingToken = true; return; @@ -999,7 +1006,7 @@ void FrameTimeline::DisplayFrame::dump(std::string& result, nsecs_t baseTime) co } void FrameTimeline::dumpAll(std::string& result) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size()); nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime(); for (size_t i = 0; i < mDisplayFrames.size(); i++) { @@ -1009,7 +1016,7 @@ void FrameTimeline::dumpAll(std::string& result) { } void FrameTimeline::dumpJank(std::string& result) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime(); for (size_t i = 0; i < mDisplayFrames.size(); i++) { mDisplayFrames[i]->dumpJank(result, baseTime, static_cast(i)); @@ -1031,7 +1038,7 @@ void FrameTimeline::parseArgs(const Vector& args, std::string& result) } void FrameTimeline::setMaxDisplayFrames(uint32_t size) { - std::lock_guard lock(mMutex); + std::scoped_lock lock(mMutex); // The size can either increase or decrease, clear everything, to be consistent mDisplayFrames.clear(); diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h index ed38cc6375..54e8efbc92 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h @@ -154,10 +154,10 @@ public: // Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through // TokenManager), Thresholds and TimeStats pointer. - SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName, - std::string debugName, PredictionState predictionState, TimelineItem&& predictions, - std::shared_ptr timeStats, JankClassificationThresholds thresholds, - TraceCookieCounter* traceCookieCounter); + SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName, PredictionState predictionState, + TimelineItem&& predictions, std::shared_ptr timeStats, + JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter); ~SurfaceFrame() = default; // Returns std::nullopt if the frame hasn't been classified yet. @@ -166,6 +166,7 @@ public: // Functions called by SF int64_t getToken() const { return mToken; }; + int32_t getInputEventId() const { return mInputEventId; }; TimelineItem getPredictions() const { return mPredictions; }; // Actual timestamps of the app are set individually at different functions. // Start time (if the app provides) and Queue time are accessible after queueing the frame, @@ -198,6 +199,7 @@ public: private: const int64_t mToken; + const int32_t mInputEventId; const pid_t mOwnerPid; const uid_t mOwnerUid; const std::string mLayerName; @@ -243,10 +245,9 @@ public: // Create a new surface frame, set the predictions based on a token and return it to the caller. // Debug name is the human-readable debugging string for dumpsys. - virtual std::shared_ptr createSurfaceFrameForToken(std::optional token, - pid_t ownerPid, uid_t ownerUid, - std::string layerName, - std::string debugName) = 0; + virtual std::shared_ptr createSurfaceFrameForToken( + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) = 0; // Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be // composited into one display frame. @@ -279,7 +280,7 @@ namespace impl { class TokenManager : public android::frametimeline::TokenManager { public: - TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {} + TokenManager() : mCurrentToken(FrameTimelineInfo::INVALID_VSYNC_ID + 1) {} ~TokenManager() = default; int64_t generateTokenForPredictions(TimelineItem&& predictions) override; @@ -353,7 +354,7 @@ public: private: void dump(std::string& result, nsecs_t baseTime) const; - int64_t mToken = ISurfaceComposer::INVALID_VSYNC_ID; + int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID; /* Usage of TimelineItem w.r.t SurfaceFlinger * startTime Time when SurfaceFlinger wakes up to handle transactions and buffer updates @@ -393,10 +394,9 @@ public: ~FrameTimeline() = default; frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; } - std::shared_ptr createSurfaceFrameForToken(std::optional token, - pid_t ownerPid, uid_t ownerUid, - std::string layerName, - std::string debugName) override; + std::shared_ptr createSurfaceFrameForToken( + const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid, + std::string layerName, std::string debugName) override; void addSurfaceFrame(std::shared_ptr surfaceFrame) override; void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override; void setSfPresent(nsecs_t sfPresentTime, diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 177a81a7bc..f6440d3843 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -129,7 +129,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.shadowRadius = 0.f; mCurrentState.treeHasFrameRateVote = false; mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; - mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + mCurrentState.frameTimelineInfo = {}; mCurrentState.postTime = -1; if (args.flags & ISurfaceComposerClient::eNoColorFill) { @@ -907,14 +907,10 @@ bool Layer::applyPendingStates(State* stateToCommit) { } if (stateUpdateAvailable) { - const auto vsyncId = - stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID - ? std::nullopt - : std::make_optional(stateToCommit->frameTimelineVsyncId); - mSurfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(vsyncId, mOwnerPid, mOwnerUid, - mName, mTransactionName); + mFlinger->mFrameTimeline + ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mTransactionName); mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); // For transactions we set the acquire fence time to the post time as we // don't have a buffer. For BufferStateLayer it is overridden in @@ -1491,8 +1487,8 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) { - mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId; +void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { + mCurrentState.frameTimelineInfo = info; mCurrentState.postTime = postTime; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 357c4a4dee..0660a4a998 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -304,8 +304,8 @@ public: // a fixed transform hint is not set. ui::Transform::RotationFlags fixedTransformHint; - // The vsync id that was used to start the transaction - int64_t frameTimelineVsyncId; + // The vsync info that was used to start the transaction + FrameTimelineInfo frameTimelineInfo; // When the transaction was posted nsecs_t postTime; @@ -869,8 +869,9 @@ public: bool setFrameRate(FrameRate); - virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {} - void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime); + virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} + void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo, + nsecs_t postTime); // Creates a new handle each time, so we only expect // this to be called once. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 27df232472..8d448e0910 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3287,7 +3287,7 @@ bool SurfaceFlinger::flushTransactionQueues() { break; } transactions.push_back(transaction); - applyTransactionState(transaction.frameTimelineVsyncId, transaction.states, + applyTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, mPendingInputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, transaction.buffer, @@ -3367,7 +3367,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t } status_t SurfaceFlinger::setTransactionState( - int64_t frameTimelineVsyncId, const Vector& states, + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, @@ -3420,7 +3420,7 @@ status_t SurfaceFlinger::setTransactionState( // if the transaction contains a buffer. if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) || pendingTransactions) { - mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, + mTransactionQueues[applyToken].emplace(frameTimelineInfo, states, displays, flags, desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, @@ -3429,7 +3429,7 @@ status_t SurfaceFlinger::setTransactionState( return NO_ERROR; } - applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, + applyTransactionState(frameTimelineInfo, states, displays, flags, inputWindowCommands, desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, transactionId, /*isMainThread*/ false); @@ -3437,7 +3437,7 @@ status_t SurfaceFlinger::setTransactionState( } void SurfaceFlinger::applyTransactionState( - int64_t frameTimelineVsyncId, const Vector& states, + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, @@ -3478,9 +3478,9 @@ void SurfaceFlinger::applyTransactionState( uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { clientStateFlags |= - setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, - isAutoTimestamp, postTime, privileged, - listenerCallbacksWithSurfaces, originPid, originUid); + setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, + postTime, privileged, listenerCallbacksWithSurfaces, originPid, + originUid); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), @@ -3658,7 +3658,7 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis } uint32_t SurfaceFlinger::setClientStateLocked( - int64_t frameTimelineVsyncId, const ComposerState& composerState, + const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks, int originPid, int originUid) { @@ -3916,10 +3916,10 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } - if (what & layer_state_t::eFrameTimelineVsyncChanged) { - layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime); - } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) { - layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime); + if (what & layer_state_t::eFrameTimelineInfoChanged) { + layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime); + } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { + layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime); } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { @@ -4255,7 +4255,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.width = 0; d.height = 0; displays.add(d); - setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr, + setTransactionState(FrameTimelineInfo{}, state, displays, 0, nullptr, mPendingInputWindowCommands, systemTime(), true, {}, false, {}, 0 /* Undefined transactionId */); @@ -5006,7 +5006,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_LAYERS: case CAPTURE_DISPLAY: case SET_DISPLAY_BRIGHTNESS: - case SET_FRAME_TIMELINE_VSYNC: + case SET_FRAME_TIMELINE_INFO: // This is not sensitive information, so should not require permission control. case GET_GPU_CONTEXT_PRIORITY: { return OK; @@ -6374,21 +6374,21 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { })); } -status_t SurfaceFlinger::setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) { +status_t SurfaceFlinger::setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) { Mutex::Autolock lock(mStateLock); if (!authenticateSurfaceTextureLocked(surface)) { - ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer"); + ALOGE("Attempt to set frame timeline info on an unrecognized IGraphicBufferProducer"); return BAD_VALUE; } sp layer = (static_cast(surface.get()))->getLayer(); if (layer == nullptr) { - ALOGE("Attempt to set frame timeline vsync on a layer that no longer exists"); + ALOGE("Attempt to set frame timeline info on a layer that no longer exists"); return BAD_VALUE; } - layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId); + layer->setFrameTimelineInfoForBuffer(frameTimelineInfo); return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 50d6099698..323ed40e36 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -343,7 +343,7 @@ protected: virtual ~SurfaceFlinger(); virtual uint32_t setClientStateLocked( - int64_t frameTimelineVsyncId, const ComposerState& composerState, + const FrameTimelineInfo& info, const ComposerState& composerState, int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks, int originPid, int originUid) REQUIRES(mStateLock); @@ -435,14 +435,15 @@ private: }; struct TransactionState { - TransactionState(int64_t frameTimelineVsyncId, const Vector& composerStates, + TransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, bool hasListenerCallbacks, std::vector listenerCallbacks, int originPid, int originUid, uint64_t transactionId) - : frameTimelineVsyncId(frameTimelineVsyncId), + : frameTimelineInfo(frameTimelineInfo), states(composerStates), displays(displayStates), flags(transactionFlags), @@ -457,7 +458,7 @@ private: originUid(originUid), id(transactionId) {} - int64_t frameTimelineVsyncId; + FrameTimelineInfo frameTimelineInfo; Vector states; Vector displays; uint32_t flags; @@ -522,7 +523,8 @@ private: void destroyDisplay(const sp& displayToken) override; std::vector getPhysicalDisplayIds() const override; sp getPhysicalDisplayToken(PhysicalDisplayId displayId) const override; - status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector& state, + status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo, + const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, @@ -608,8 +610,8 @@ private: int8_t compatibility, bool shouldBeSeamless) override; status_t acquireFrameRateFlexibilityToken(sp* outToken) override; - status_t setFrameTimelineVsync(const sp& surface, - int64_t frameTimelineVsyncId) override; + status_t setFrameTimelineInfo(const sp& surface, + const FrameTimelineInfo& frameTimelineInfo) override; status_t addTransactionTraceListener( const sp& listener) override; @@ -727,7 +729,7 @@ private: /* * Transactions */ - void applyTransactionState(int64_t frameTimelineVsyncId, const Vector& state, + void applyTransactionState(const FrameTimelineInfo& info, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp index 93d5f2f8ec..80dbd1b889 100644 --- a/services/surfaceflinger/tests/LayerState_test.cpp +++ b/services/surfaceflinger/tests/LayerState_test.cpp @@ -106,5 +106,34 @@ TEST(LayerStateTest, ParcellingScreenCaptureResults) { ASSERT_EQ(results.result, results2.result); } +/** + * Parcel a layer_state_t struct, and then unparcel. Ensure that the object that was parceled + * matches the object that's unparceled. + */ +TEST(LayerStateTest, ParcelUnparcelLayerStateT) { + layer_state_t input; + input.frameTimelineInfo.vsyncId = 1; + input.frameTimelineInfo.inputEventId = 2; + Parcel p; + input.write(p); + layer_state_t output; + p.setDataPosition(0); + output.read(p); + ASSERT_EQ(input.frameTimelineInfo.vsyncId, output.frameTimelineInfo.vsyncId); + ASSERT_EQ(input.frameTimelineInfo.inputEventId, output.frameTimelineInfo.inputEventId); +} + +TEST(LayerStateTest, LayerStateMerge_SelectsValidInputEvent) { + layer_state_t layer1; + layer1.frameTimelineInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID; + layer_state_t layer2; + layer2.frameTimelineInfo.inputEventId = 1; + layer2.what |= layer_state_t::eFrameTimelineInfoChanged; + + layer1.merge(layer2); + + ASSERT_EQ(1, layer1.frameTimelineInfo.inputEventId); +} + } // namespace test } // namespace android diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index e2584e266d..6e9f09bdaa 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -14,9 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wextra" #include "gmock/gmock-spec-builders.h" #include "mock/MockTimeStats.h" @@ -177,16 +174,17 @@ static const std::string sLayerNameTwo = "layer2"; static constexpr const uid_t sUidOne = 0; static constexpr pid_t sPidOne = 10; static constexpr pid_t sPidTwo = 20; +static constexpr int32_t sInputEventId = 5; TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0}); - EXPECT_EQ(getPredictions().size(), 1); + EXPECT_EQ(getPredictions().size(), 1u); flushTokens(systemTime() + maxTokenRetentionTime); int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30}); std::optional predictions = mTokenManager->getPredictionsForToken(token1); // token1 should have expired - EXPECT_EQ(getPredictions().size(), 1); + EXPECT_EQ(getPredictions().size(), 1u); EXPECT_EQ(predictions.has_value(), false); predictions = mTokenManager->getPredictionsForToken(token2); @@ -194,16 +192,16 @@ TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) { } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) { - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); - auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidTwo, sUidOne, + auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne); EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo); } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None); } @@ -211,21 +209,33 @@ TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) { TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) { int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0}); flushTokens(systemTime() + maxTokenRetentionTime); - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired); } TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid); EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true); } +TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) { + int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); + constexpr int32_t inputEventId = 1; + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); + + EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId()); +} + TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)); @@ -234,8 +244,9 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, 11); @@ -264,11 +275,11 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameTwo, sLayerNameTwo); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameTwo, sLayerNameTwo); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame1); @@ -288,8 +299,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) { // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame3 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped); mFrameTimeline->addSurfaceFrame(surfaceFrame3); @@ -320,8 +331,9 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { int64_t sfToken = mTokenManager->generateTokenForPredictions( {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, + sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -341,8 +353,8 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { int64_t sfToken = mTokenManager->generateTokenForPredictions( {22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -356,18 +368,18 @@ TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) { } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0, - "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(123); surfaceFrame->setAcquireFenceTime(456); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); } TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) { - auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0, - "acquireFenceAfterQueue", - "acquireFenceAfterQueue"); + auto surfaceFrame = + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue", + "acquireFenceAfterQueue"); surfaceFrame->setActualQueueTime(456); surfaceFrame->setAcquireFenceTime(123); EXPECT_EQ(surfaceFrame->getActuals().endTime, 456); @@ -383,8 +395,8 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Size shouldn't exceed maxDisplayFrames - 64 for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -395,15 +407,15 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Increase the size to 256 mFrameTimeline->setMaxDisplayFrames(256); - EXPECT_EQ(*maxDisplayFrames, 256); + EXPECT_EQ(*maxDisplayFrames, 256u); // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)) .Times(static_cast(*maxDisplayFrames + 10)); for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -414,15 +426,15 @@ TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) { // Shrink the size to 128 mFrameTimeline->setMaxDisplayFrames(128); - EXPECT_EQ(*maxDisplayFrames, 128); + EXPECT_EQ(*maxDisplayFrames, 128u); // Global increment EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)) .Times(static_cast(*maxDisplayFrames + 10)); for (size_t i = 0; i < *maxDisplayFrames + 10; i++) { auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, + sLayerNameOne); int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30}); mFrameTimeline->setSfWakeUp(sfToken, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); @@ -449,8 +461,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) { std::chrono::duration_cast(56ms).count(), std::chrono::duration_cast(60ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count(), 11); @@ -478,8 +490,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) { std::chrono::duration_cast(56ms).count(), std::chrono::duration_cast(60ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, std::chrono::duration_cast(52ms).count(), 30); @@ -507,8 +519,8 @@ TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) { std::chrono::duration_cast(86ms).count(), std::chrono::duration_cast(90ms).count()}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime( std::chrono::duration_cast(45ms).count()); mFrameTimeline->setSfWakeUp(sfToken1, @@ -542,8 +554,9 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token1, 20, 11); @@ -558,7 +571,7 @@ TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) { mFrameTimeline->setSfPresent(55, presentFence2); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 0); + EXPECT_EQ(packets.size(), 0u); } TEST_F(FrameTimelineTest, tracing_sanityTest) { @@ -573,8 +586,9 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { tracingSession->StartBlocking(); int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + auto surfaceFrame1 = + mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne, + sLayerNameOne, sLayerNameOne); // Set up the display frame mFrameTimeline->setSfWakeUp(token2, 20, 11); @@ -594,7 +608,7 @@ TEST_F(FrameTimelineTest, tracing_sanityTest) { auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); // Display Frame 1 has 8 packets - 4 from DisplayFrame and 4 from SurfaceFrame. - EXPECT_EQ(packets.size(), 8); + EXPECT_EQ(packets.size(), 8u); } TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) { @@ -622,7 +636,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 0); + EXPECT_EQ(packets.size(), 0u); } TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) { @@ -635,7 +649,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) tracingSession->StartBlocking(); int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); - auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne, + auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne, sLayerNameOne); // Set up the display frame @@ -657,7 +671,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); // Display Frame 1 has 4 packets (SurfaceFrame shouldn't be traced since it has an invalid // token). - EXPECT_EQ(packets.size(), 4); + EXPECT_EQ(packets.size(), 4u); } void validateTraceEvent(const ProtoExpectedDisplayFrameStart& received, @@ -791,12 +805,12 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 4); + EXPECT_EQ(packets.size(), 4u); // Packet - 0 : ExpectedDisplayFrameStart const auto& packet0 = packets[0]; ASSERT_TRUE(packet0.has_timestamp()); - EXPECT_EQ(packet0.timestamp(), 10); + EXPECT_EQ(packet0.timestamp(), 10u); ASSERT_TRUE(packet0.has_frame_timeline_event()); const auto& event0 = packet0.frame_timeline_event(); @@ -807,7 +821,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 1 : FrameEnd (ExpectedDisplayFrame) const auto& packet1 = packets[1]; ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), 25); + EXPECT_EQ(packet1.timestamp(), 25u); ASSERT_TRUE(packet1.has_frame_timeline_event()); const auto& event1 = packet1.frame_timeline_event(); @@ -818,7 +832,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 2 : ActualDisplayFrameStart const auto& packet2 = packets[2]; ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), 20); + EXPECT_EQ(packet2.timestamp(), 20u); ASSERT_TRUE(packet2.has_frame_timeline_event()); const auto& event2 = packet2.frame_timeline_event(); @@ -829,7 +843,7 @@ TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) { // Packet - 3 : FrameEnd (ActualDisplayFrame) const auto& packet3 = packets[3]; ASSERT_TRUE(packet3.has_timestamp()); - EXPECT_EQ(packet3.timestamp(), 26); + EXPECT_EQ(packet3.timestamp(), 26u); ASSERT_TRUE(packet3.has_frame_timeline_event()); const auto& event3 = packet3.frame_timeline_event(); @@ -853,8 +867,8 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setActualStartTime(0); surfaceFrame1->setActualQueueTime(15); surfaceFrame1->setAcquireFenceTime(20); @@ -904,12 +918,12 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { tracingSession->StopBlocking(); auto packets = readFrameTimelinePacketsBlocking(tracingSession.get()); - EXPECT_EQ(packets.size(), 8); + EXPECT_EQ(packets.size(), 8u); // Packet - 4 : ExpectedSurfaceFrameStart const auto& packet4 = packets[4]; ASSERT_TRUE(packet4.has_timestamp()); - EXPECT_EQ(packet4.timestamp(), 10); + EXPECT_EQ(packet4.timestamp(), 10u); ASSERT_TRUE(packet4.has_frame_timeline_event()); const auto& event4 = packet4.frame_timeline_event(); @@ -920,7 +934,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 5 : FrameEnd (ExpectedSurfaceFrame) const auto& packet5 = packets[5]; ASSERT_TRUE(packet5.has_timestamp()); - EXPECT_EQ(packet5.timestamp(), 25); + EXPECT_EQ(packet5.timestamp(), 25u); ASSERT_TRUE(packet5.has_frame_timeline_event()); const auto& event5 = packet5.frame_timeline_event(); @@ -931,7 +945,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 6 : ActualSurfaceFrameStart const auto& packet6 = packets[6]; ASSERT_TRUE(packet6.has_timestamp()); - EXPECT_EQ(packet6.timestamp(), 10); + EXPECT_EQ(packet6.timestamp(), 10u); ASSERT_TRUE(packet6.has_frame_timeline_event()); const auto& event6 = packet6.frame_timeline_event(); @@ -942,7 +956,7 @@ TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) { // Packet - 7 : FrameEnd (ActualSurfaceFrame) const auto& packet7 = packets[7]; ASSERT_TRUE(packet7.has_timestamp()); - EXPECT_EQ(packet7.timestamp(), 20); + EXPECT_EQ(packet7.timestamp(), 20u); ASSERT_TRUE(packet7.has_frame_timeline_event()); const auto& event7 = packet7.frame_timeline_event(); @@ -961,8 +975,8 @@ TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) { int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30}); int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30}); auto surfaceFrame = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented); mFrameTimeline->addSurfaceFrame(surfaceFrame); @@ -1126,8 +1140,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1145,8 +1159,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresen // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1199,8 +1213,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(16); mFrameTimeline->setSfWakeUp(sfToken1, 22, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1218,8 +1232,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(36); mFrameTimeline->setSfWakeUp(sfToken2, 52, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1270,8 +1284,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50}); int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken1, 42, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1316,8 +1330,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30}); int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(26); mFrameTimeline->setSfWakeUp(sfToken1, 32, 11); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1335,8 +1349,8 @@ TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishLatePresent) // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(40); mFrameTimeline->setSfWakeUp(sfToken2, 43, 11); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1390,8 +1404,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 56, 60}); int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120}); auto surfaceFrame1 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame1->setAcquireFenceTime(50); mFrameTimeline->setSfWakeUp(sfToken1, 52, 30); surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented); @@ -1409,8 +1423,8 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli // Trigger a flush by finalizing the next DisplayFrame auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); auto surfaceFrame2 = - mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne, - sLayerNameOne, sLayerNameOne); + mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne, + sUidOne, sLayerNameOne, sLayerNameOne); surfaceFrame2->setAcquireFenceTime(84); mFrameTimeline->setSfWakeUp(sfToken2, 112, 30); surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54); @@ -1456,6 +1470,3 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli JankType::AppDeadlineMissed | JankType::BufferStuffing); } } // namespace android::frametimeline - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 2701f472aa..8ca052f710 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -368,16 +368,14 @@ public: auto& getTransactionQueue() { return mFlinger->mTransactionQueues; } - auto setTransactionState(int64_t frameTimelineVsyncId, const Vector& states, - const Vector& displays, uint32_t flags, - const sp& applyToken, - const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, - std::vector& listenerCallbacks, - uint64_t transactionId) { - return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags, - applyToken, inputWindowCommands, desiredPresentTime, + auto setTransactionState( + const FrameTimelineInfo& frameTimelineInfo, const Vector& states, + const Vector& displays, uint32_t flags, const sp& applyToken, + const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + std::vector& listenerCallbacks, uint64_t transactionId) { + return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken, + inputWindowCommands, desiredPresentTime, isAutoTimestamp, uncacheBuffer, hasListenerCallbacks, listenerCallbacks, transactionId); } diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 06275c6b5b..6d2f672bce 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -14,10 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -100,43 +96,44 @@ public: InputWindowCommands inputWindowCommands; int64_t desiredPresentTime = 0; bool isAutoTimestamp = true; - int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; + FrameTimelineInfo frameTimelineInfo; client_cache_t uncacheBuffer; - int64_t id = -1; + uint64_t id = static_cast(-1); + static_assert(0xffffffffffffffff == static_cast(-1)); }; void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) { - EXPECT_EQ(0, info.states.size()); - EXPECT_EQ(0, state.states.size()); + EXPECT_EQ(0u, info.states.size()); + EXPECT_EQ(0u, state.states.size()); - EXPECT_EQ(0, info.displays.size()); - EXPECT_EQ(0, state.displays.size()); + EXPECT_EQ(0u, info.displays.size()); + EXPECT_EQ(0u, state.displays.size()); EXPECT_EQ(info.flags, state.flags); EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime); } void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t frameTimelineVsyncId) { + const FrameTimelineInfo& frameTimelineInfo) { mTransactionNumber++; transaction.flags |= flags; // ISurfaceComposer::eSynchronous; transaction.inputWindowCommands.syncInputWindows = syncInputWindows; transaction.desiredPresentTime = desiredPresentTime; transaction.isAutoTimestamp = isAutoTimestamp; - transaction.frameTimelineVsyncId = frameTimelineVsyncId; + transaction.frameTimelineInfo = frameTimelineInfo; } void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime())); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, - ISurfaceComposer::INVALID_VSYNC_ID); + FrameTimelineInfo{}); nsecs_t applicationTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, @@ -155,11 +152,11 @@ public: EXPECT_LE(returnedTime, applicationTime + s2ns(5)); } auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(0, transactionQueue.size()); + EXPECT_EQ(0u, transactionQueue.size()); } void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -170,10 +167,9 @@ public: .WillOnce(Return(time + nsecs_t(5 * 1e8))); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ time + s2ns(1), false, - ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, transaction.desiredPresentTime, transaction.isAutoTimestamp, @@ -184,11 +180,11 @@ public: EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); // This transaction should have been placed on the transaction queue auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(1, transactionQueue.size()); + EXPECT_EQ(1u, transactionQueue.size()); } void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction nsecs_t time = systemTime(); EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -197,18 +193,17 @@ public: // transaction that should go on the pending thread TransactionInfo transactionA; setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ time + s2ns(1), false, - ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{}); // transaction that would not have gone on the pending thread if not // blocked TransactionInfo transactionB; setupSingle(transactionB, flags, syncInputWindows, /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, - ISurfaceComposer::INVALID_VSYNC_ID); + FrameTimelineInfo{}); nsecs_t applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.isAutoTimestamp, @@ -221,7 +216,7 @@ public: EXPECT_LE(systemTime(), applicationSentTime + s2ns(5)); applicationSentTime = systemTime(); - mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states, + mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, transactionB.desiredPresentTime, transactionB.isAutoTimestamp, @@ -240,10 +235,10 @@ public: // check that there is one binder on the pending queue. auto transactionQueue = mFlinger.getTransactionQueue(); - EXPECT_EQ(1, transactionQueue.size()); + EXPECT_EQ(1u, transactionQueue.size()); auto& [applyToken, transactionStates] = *(transactionQueue.begin()); - EXPECT_EQ(2, transactionStates.size()); + EXPECT_EQ(2u, transactionStates.size()); auto& transactionStateA = transactionStates.front(); transactionStates.pop(); @@ -258,7 +253,7 @@ public: }; TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { - ASSERT_EQ(0, mFlinger.getTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); // called in SurfaceFlinger::signalTransaction EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); @@ -268,18 +263,18 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { .WillOnce(Return(s2ns(2))); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID); - mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, + /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{}); + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, transactionA.isAutoTimestamp, transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); - ASSERT_EQ(1, transactionQueue.size()); + ASSERT_EQ(1u, transactionQueue.size()); auto& [applyToken, transactionStates] = *(transactionQueue.begin()); - ASSERT_EQ(1, transactionStates.size()); + ASSERT_EQ(1u, transactionStates.size()); auto& transactionState = transactionStates.front(); checkEqual(transactionA, transactionState); @@ -289,8 +284,8 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // different process) to re-query and reset the cached expected present time TransactionInfo empty; empty.applyToken = sp(); - mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays, - empty.flags, empty.applyToken, empty.inputWindowCommands, + mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags, + empty.applyToken, empty.inputWindowCommands, empty.desiredPresentTime, empty.isAutoTimestamp, empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); @@ -298,7 +293,7 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { // passed mFlinger.flushTransactionQueues(); - EXPECT_EQ(0, transactionQueue.size()); + EXPECT_EQ(0u, transactionQueue.size()); } TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) { @@ -343,6 +338,3 @@ TEST_F(TransactionApplicationTest, FromHandle) { EXPECT_EQ(nullptr, ret.promote().get()); } } // namespace android - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" -- cgit v1.2.3-59-g8ed1b From a7fe3048aaaf8a45337c7355326f2c6b68b70fb0 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Fri, 29 Jan 2021 21:02:08 +0100 Subject: Rename DisplayConfig to DisplayMode This CL continues the raneming of display "configs" to display "modes". The goal of this is to have the same names as in the java code and the public display APIs. Additionally in this CL we move DisplayConfig (from libui) to the namespace android::ui. This is to prevent conflict with the SurfaceFlinger's internal android::DisplayMode. This is consistent with the neighboring classes which are also in the ui namespace. Also the type of the parameter defaultMode of {s,g}etDesiredDisplayModeSpecs is changed to size_t for consistency with the rest of the code. Appropriate error handling is added for this. Bug: 159590486 Bug: 179158858 Test: presubmit Change-Id: I31e5be1f2223a9ec9340789ce3dc5738eceaf40f --- cmds/flatland/GLHelper.cpp | 12 +- libs/gui/DisplayEventDispatcher.cpp | 6 +- libs/gui/ISurfaceComposer.cpp | 182 ++++++----- libs/gui/SurfaceComposerClient.cpp | 47 ++- libs/gui/include/gui/DisplayEventDispatcher.h | 4 +- libs/gui/include/gui/DisplayEventReceiver.h | 10 +- libs/gui/include/gui/ISurfaceComposer.h | 61 ++-- libs/gui/include/gui/SurfaceComposerClient.h | 37 +-- libs/gui/tests/BLASTBufferQueue_test.cpp | 8 +- libs/gui/tests/DisplayEventStructLayout_test.cpp | 6 +- libs/gui/tests/EndToEndNativeInputTest.cpp | 8 +- libs/gui/tests/Surface_test.cpp | 30 +- libs/nativedisplay/AChoreographer.cpp | 8 +- libs/nativedisplay/ADisplay.cpp | 34 +- libs/ui/include/ui/DisplayConfig.h | 41 --- libs/ui/include/ui/DisplayMode.h | 41 +++ libs/ui/include_vndk/ui/DisplayConfig.h | 1 - libs/ui/include_vndk/ui/DisplayMode.h | 1 + opengl/tests/lib/WindowSurface.cpp | 10 +- .../display/AutomotiveDisplayProxyService.cpp | 18 +- .../include/AutomotiveDisplayProxyService.h | 2 +- .../surfaceflinger/DisplayHardware/DisplayMode.h | 15 +- services/surfaceflinger/Scheduler/EventThread.cpp | 26 +- services/surfaceflinger/Scheduler/EventThread.h | 10 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 2 +- services/surfaceflinger/Scheduler/LayerHistory.h | 8 +- services/surfaceflinger/Scheduler/LayerInfo.cpp | 12 +- services/surfaceflinger/Scheduler/LayerInfo.h | 4 +- .../Scheduler/RefreshRateConfigs.cpp | 198 ++++++----- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 78 +++-- services/surfaceflinger/Scheduler/Scheduler.cpp | 116 ++++--- services/surfaceflinger/Scheduler/Scheduler.h | 28 +- services/surfaceflinger/SurfaceFlinger.cpp | 363 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 93 +++--- services/surfaceflinger/tests/Credentials_test.cpp | 43 ++- .../surfaceflinger/tests/DisplayConfigs_test.cpp | 94 +++--- services/surfaceflinger/tests/IPC_test.cpp | 10 +- .../surfaceflinger/tests/LayerTransactionTest.h | 10 +- services/surfaceflinger/tests/LayerUpdate_test.cpp | 6 +- .../tests/MultiDisplayLayerBounds_test.cpp | 10 +- .../surfaceflinger/tests/ScreenCapture_test.cpp | 6 +- .../tests/SurfaceInterceptor_test.cpp | 8 +- .../tests/TransactionTestHarnesses.h | 6 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 300 +++++++++-------- .../tests/unittests/EventThreadTest.cpp | 18 +- .../tests/unittests/LayerHistoryTest.cpp | 4 +- .../tests/unittests/LayerInfoTest.cpp | 18 +- .../tests/unittests/RefreshRateConfigsTest.cpp | 117 +++---- .../tests/unittests/RefreshRateStatsTest.cpp | 26 +- .../tests/unittests/SchedulerTest.cpp | 24 +- ...ceFlinger_SetupNewDisplayDeviceInternalTest.cpp | 2 +- .../tests/unittests/TestableScheduler.h | 13 +- .../tests/unittests/TestableSurfaceFlinger.h | 36 +- .../tests/unittests/mock/MockEventThread.h | 2 +- 54 files changed, 1127 insertions(+), 1146 deletions(-) delete mode 100644 libs/ui/include/ui/DisplayConfig.h create mode 100644 libs/ui/include/ui/DisplayMode.h delete mode 120000 libs/ui/include_vndk/ui/DisplayConfig.h create mode 120000 libs/ui/include_vndk/ui/DisplayMode.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp index 3a3df08534..01f7d30a42 100644 --- a/cmds/flatland/GLHelper.cpp +++ b/cmds/flatland/GLHelper.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace android { @@ -227,15 +227,15 @@ bool GLHelper::computeWindowScale(uint32_t w, uint32_t h, float* scale) { return false; } - DisplayConfig config; - status_t err = mSurfaceComposerClient->getActiveDisplayConfig(dpy, &config); + ui::DisplayMode mode; + status_t err = mSurfaceComposerClient->getActiveDisplayMode(dpy, &mode); if (err != NO_ERROR) { - fprintf(stderr, "SurfaceComposer::getActiveDisplayConfig failed: %#x\n", err); + fprintf(stderr, "SurfaceComposer::getActiveDisplayMode failed: %#x\n", err); return false; } - float scaleX = static_cast(config.resolution.getWidth()) / w; - float scaleY = static_cast(config.resolution.getHeight()) / h; + float scaleX = static_cast(mode.resolution.getWidth()) / w; + float scaleY = static_cast(mode.resolution.getHeight()) / h; *scale = scaleX < scaleY ? scaleX : scaleY; return true; diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 2ad484add3..5c9949b549 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -184,9 +184,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); break; - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: - dispatchConfigChanged(ev.header.timestamp, ev.header.displayId, - ev.config.configId, ev.config.vsyncPeriod); + case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: + dispatchModeChanged(ev.header.timestamp, ev.header.displayId, + ev.modeChange.modeId, ev.modeChange.vsyncPeriod); break; case DisplayEventReceiver::DISPLAY_EVENT_NULL: dispatchNullEvent(ev.header.timestamp, ev.header.displayId); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index f68f3e134e..10d48a35bf 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -36,8 +36,8 @@ #include -#include #include +#include #include #include #include @@ -333,20 +333,19 @@ public: return reply.read(*info); } - status_t getDisplayConfigs(const sp& display, - Vector* configs) override { + status_t getDisplayModes(const sp& display, Vector* modes) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply); + remote()->transact(BnSurfaceComposer::GET_DISPLAY_MODES, data, &reply); const status_t result = reply.readInt32(); if (result == NO_ERROR) { - const size_t numConfigs = reply.readUint32(); - configs->clear(); - configs->resize(numConfigs); - for (size_t c = 0; c < numConfigs; ++c) { - memcpy(&(configs->editItemAt(c)), reply.readInplace(sizeof(DisplayConfig)), - sizeof(DisplayConfig)); + const size_t numModes = reply.readUint32(); + modes->clear(); + modes->resize(numModes); + for (size_t i = 0; i < numModes; i++) { + memcpy(&(modes->editItemAt(i)), reply.readInplace(sizeof(ui::DisplayMode)), + sizeof(ui::DisplayMode)); } } return result; @@ -366,11 +365,11 @@ public: return result; } - int getActiveConfig(const sp& display) override { + int getActiveDisplayModeId(const sp& display) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_ACTIVE_CONFIG, data, &reply); + remote()->transact(BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE, data, &reply); return reply.readInt32(); } @@ -882,71 +881,70 @@ public: return error; } - status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t defaultConfig, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) override { + status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to writeInterfaceToken: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to writeInterfaceToken: %d", result); return result; } result = data.writeStrongBinder(displayToken); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to write display token: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to write display token: %d", result); return result; } - result = data.writeInt32(defaultConfig); + result = data.writeInt32(defaultMode); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write defaultMode: %d", result); return result; } result = data.writeBool(allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write allowGroupSwitching: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write allowGroupSwitching: %d", result); return result; } result = data.writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMin: %d", result); return result; } result = data.writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMax: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMax: %d", result); return result; } result = data.writeFloat(appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMin: %d", result); return result; } result = data.writeFloat(appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMax: %d", result); return result; } - result = remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_CONFIG_SPECS, data, - &reply); + result = + remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS, data, &reply); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs failed to transact: %d", result); + ALOGE("setDesiredDisplayModeSpecs failed to transact: %d", result); return result; } return reply.readInt32(); } - status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) override { - if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || + status_t getDesiredDisplayModeSpecs(const sp& displayToken, size_t* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override { + if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { return BAD_VALUE; @@ -954,50 +952,55 @@ public: Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to writeInterfaceToken: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to writeInterfaceToken: %d", result); return result; } result = data.writeStrongBinder(displayToken); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to writeStrongBinder: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to writeStrongBinder: %d", result); return result; } - result = remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_CONFIG_SPECS, data, - &reply); + result = + remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS, data, &reply); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to transact: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result); return result; } - result = reply.readInt32(outDefaultConfig); + int32_t defaultMode; + result = reply.readInt32(&defaultMode); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read defaultMode: %d", result); return result; } + if (defaultMode < 0) { + ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode); + return BAD_VALUE; + } + *outDefaultMode = static_cast(defaultMode); + result = reply.readBool(outAllowGroupSwitching); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read allowGroupSwitching: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read allowGroupSwitching: %d", result); return result; } result = reply.readFloat(outPrimaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMin: %d", result); return result; } result = reply.readFloat(outPrimaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMax: %d", result); + ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMax: %d", result); return result; } result = reply.readFloat(outAppRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMin: %d", - result); + ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMin: %d", result); return result; } result = reply.readFloat(outAppRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMax: %d", - result); + ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMax: %d", result); return result; } return reply.readInt32(); @@ -1430,17 +1433,17 @@ status_t BnSurfaceComposer::onTransact( if (result != NO_ERROR) return result; return reply->write(info); } - case GET_DISPLAY_CONFIGS: { + case GET_DISPLAY_MODES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector configs; + Vector modes; const sp display = data.readStrongBinder(); - const status_t result = getDisplayConfigs(display, &configs); + const status_t result = getDisplayModes(display, &modes); reply->writeInt32(result); if (result == NO_ERROR) { - reply->writeUint32(static_cast(configs.size())); - for (size_t c = 0; c < configs.size(); ++c) { - memcpy(reply->writeInplace(sizeof(DisplayConfig)), &configs[c], - sizeof(DisplayConfig)); + reply->writeUint32(static_cast(modes.size())); + for (size_t i = 0; i < modes.size(); i++) { + memcpy(reply->writeInplace(sizeof(ui::DisplayMode)), &modes[i], + sizeof(ui::DisplayMode)); } } return NO_ERROR; @@ -1457,10 +1460,10 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case GET_ACTIVE_CONFIG: { + case GET_ACTIVE_DISPLAY_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = data.readStrongBinder(); - int id = getActiveConfig(display); + int id = getActiveDisplayModeId(display); reply->writeInt32(id); return NO_ERROR; } @@ -1844,56 +1847,59 @@ status_t BnSurfaceComposer::onTransact( } return removeRegionSamplingListener(listener); } - case SET_DESIRED_DISPLAY_CONFIG_SPECS: { + case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - int32_t defaultConfig; - status_t result = data.readInt32(&defaultConfig); + int32_t defaultMode; + status_t result = data.readInt32(&defaultMode); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result); + ALOGE("setDesiredDisplayModeSpecs: failed to read defaultMode: %d", result); return result; } + if (defaultMode < 0) { + ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode); + return BAD_VALUE; + } bool allowGroupSwitching; result = data.readBool(&allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read allowGroupSwitching: %d", - result); + ALOGE("setDesiredDisplayModeSpecs: failed to read allowGroupSwitching: %d", result); return result; } float primaryRefreshRateMin; result = data.readFloat(&primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMin: %d", result); return result; } float primaryRefreshRateMax; result = data.readFloat(&primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMax: %d", result); return result; } float appRequestRefreshRateMin; result = data.readFloat(&appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMin: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMin: %d", result); return result; } float appRequestRefreshRateMax; result = data.readFloat(&appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMax: %d", + ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMax: %d", result); return result; } - result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching, - primaryRefreshRateMin, primaryRefreshRateMax, - appRequestRefreshRateMin, - appRequestRefreshRateMax); + result = setDesiredDisplayModeSpecs(displayToken, static_cast(defaultMode), + allowGroupSwitching, primaryRefreshRateMin, + primaryRefreshRateMax, appRequestRefreshRateMin, + appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: " + ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: " "%d", result); return result; @@ -1901,10 +1907,10 @@ status_t BnSurfaceComposer::onTransact( reply->writeInt32(result); return result; } - case GET_DESIRED_DISPLAY_CONFIG_SPECS: { + case GET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - int32_t defaultConfig; + size_t defaultMode; bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; @@ -1912,49 +1918,49 @@ status_t BnSurfaceComposer::onTransact( float appRequestRefreshRateMax; status_t result = - getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, &allowGroupSwitching, - &primaryRefreshRateMin, &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + getDesiredDisplayModeSpecs(displayToken, &defaultMode, &allowGroupSwitching, + &primaryRefreshRateMin, &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: " + ALOGE("getDesiredDisplayModeSpecs: failed to get getDesiredDisplayModeSpecs: " "%d", result); return result; } - result = reply->writeInt32(defaultConfig); + result = reply->writeInt32(static_cast(defaultMode)); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result); + ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result); return result; } result = reply->writeBool(allowGroupSwitching); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write allowGroupSwitching: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write allowGroupSwitching: %d", result); return result; } result = reply->writeFloat(primaryRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMin: %d", result); return result; } result = reply->writeFloat(primaryRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMax: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMax: %d", result); return result; } result = reply->writeFloat(appRequestRefreshRateMin); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMin: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMin: %d", result); return result; } result = reply->writeFloat(appRequestRefreshRateMax); if (result != NO_ERROR) { - ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMax: %d", + ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMax: %d", result); return result; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 550803d453..4493a21fc3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -39,7 +39,7 @@ #include #include #include -#include +#include #ifndef NO_INPUT #include @@ -1802,52 +1802,51 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp& display, Displ return ComposerService::getComposerService()->getDisplayInfo(display, info); } -status_t SurfaceComposerClient::getDisplayConfigs(const sp& display, - Vector* configs) { - return ComposerService::getComposerService()->getDisplayConfigs(display, configs); +status_t SurfaceComposerClient::getDisplayModes(const sp& display, + Vector* modes) { + return ComposerService::getComposerService()->getDisplayModes(display, modes); } -status_t SurfaceComposerClient::getActiveDisplayConfig(const sp& display, - DisplayConfig* config) { - Vector configs; - status_t result = getDisplayConfigs(display, &configs); +status_t SurfaceComposerClient::getActiveDisplayMode(const sp& display, + ui::DisplayMode* mode) { + Vector modes; + status_t result = getDisplayModes(display, &modes); if (result != NO_ERROR) { return result; } - int activeId = getActiveConfig(display); + int activeId = getActiveDisplayModeId(display); if (activeId < 0) { - ALOGE("No active configuration found"); + ALOGE("No active mode found"); return NAME_NOT_FOUND; } - *config = configs[static_cast(activeId)]; + *mode = modes[static_cast(activeId)]; return NO_ERROR; } -int SurfaceComposerClient::getActiveConfig(const sp& display) { - return ComposerService::getComposerService()->getActiveConfig(display); +int SurfaceComposerClient::getActiveDisplayModeId(const sp& display) { + return ComposerService::getComposerService()->getActiveDisplayModeId(display); } -status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs( - const sp& displayToken, int32_t defaultConfig, bool allowGroupSwitching, +status_t SurfaceComposerClient::setDesiredDisplayModeSpecs( + const sp& displayToken, size_t defaultMode, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, float appRequestRefreshRateMax) { return ComposerService::getComposerService() - ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching, - primaryRefreshRateMin, primaryRefreshRateMax, - appRequestRefreshRateMin, appRequestRefreshRateMax); + ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching, + primaryRefreshRateMin, primaryRefreshRateMax, + appRequestRefreshRateMin, appRequestRefreshRateMax); } -status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs( - const sp& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching, +status_t SurfaceComposerClient::getDesiredDisplayModeSpecs( + const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { return ComposerService::getComposerService() - ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outAllowGroupSwitching, - outPrimaryRefreshRateMin, outPrimaryRefreshRateMax, - outAppRequestRefreshRateMin, - outAppRequestRefreshRateMax); + ->getDesiredDisplayModeSpecs(displayToken, outDefaultMode, outAllowGroupSwitching, + outPrimaryRefreshRateMin, outPrimaryRefreshRateMax, + outAppRequestRefreshRateMin, outAppRequestRefreshRateMax); } status_t SurfaceComposerClient::getDisplayColorModes(const sp& display, diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 4175a49853..43b9feb295 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -73,8 +73,8 @@ private: VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; - virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, - int32_t configId, nsecs_t vsyncPeriod) = 0; + virtual void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, + nsecs_t vsyncPeriod) = 0; // AChoreographer-specific hook for processing null-events so that looper // can be properly poked. virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0; diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 3191fc9ab5..7179a20d22 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -52,7 +52,7 @@ public: enum { DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), - DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'), + DISPLAY_EVENT_MODE_CHANGE = fourcc('m', 'o', 'd', 'e'), DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'), DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'), DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'), @@ -82,8 +82,8 @@ public: bool connected; }; - struct Config { - int32_t configId; + struct ModeChange { + int32_t modeId; nsecs_t vsyncPeriod __attribute__((aligned(8))); }; @@ -96,7 +96,7 @@ public: union { VSync vsync; Hotplug hotplug; - Config config; + ModeChange modeChange; FrameRateOverride frameRateOverride; }; }; @@ -106,7 +106,7 @@ public: * DisplayEventReceiver creates and registers an event connection with * SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate * or requestNextVsync to receive them. - * To receive ConfigChanged and/or FrameRateOverrides events specify this in + * To receive ModeChanged and/or FrameRateOverrides events specify this in * the constructor. Other events start being delivered immediately. */ explicit DisplayEventReceiver( diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 81ff6b0d8d..6d1a3ab334 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -54,7 +54,6 @@ namespace android { struct client_cache_t; struct ComposerState; struct DisplayCaptureArgs; -struct DisplayConfig; struct DisplayInfo; struct DisplayStatInfo; struct DisplayState; @@ -73,6 +72,7 @@ using gui::IScreenCaptureListener; namespace ui { +struct DisplayMode; struct DisplayState; } // namespace ui @@ -112,7 +112,7 @@ public: }; enum class EventRegistration { - configChanged = 1 << 0, + modeChanged = 1 << 0, frameRateOverride = 1 << 1, }; @@ -207,15 +207,15 @@ public: virtual status_t getDisplayInfo(const sp& display, DisplayInfo*) = 0; /** - * Get configurations supported by given physical display. + * Get modes supported by given physical display. */ - virtual status_t getDisplayConfigs(const sp& display, Vector*) = 0; + virtual status_t getDisplayModes(const sp& display, Vector*) = 0; /** - * Get the index into configurations returned by getDisplayConfigs, - * corresponding to the active configuration. + * Get the index into modes returned by getDisplayModes, + * corresponding to the active mode. */ - virtual int getActiveConfig(const sp& display) = 0; + virtual int getActiveDisplayModeId(const sp& display) = 0; virtual status_t getDisplayColorModes(const sp& display, Vector* outColorModes) = 0; @@ -386,34 +386,31 @@ public: /* Sets the refresh rate boundaries for the display. * * The primary refresh rate range represents display manager's general guidance on the display - * configs we'll consider when switching refresh rates. Unless we get an explicit signal from an + * modes we'll consider when switching refresh rates. Unless we get an explicit signal from an * app, we should stay within this range. * - * The app request refresh rate range allows us to consider more display configs when switching + * The app request refresh rate range allows us to consider more display modes when switching * refresh rates. Although we should generally stay within the primary range, specific * considerations, such as layer frame rate settings specified via the setFrameRate() api, may * cause us to go outside the primary range. We never go outside the app request range. The app * request range will be greater than or equal to the primary refresh rate range, never smaller. * - * defaultConfig is used to narrow the list of display configs SurfaceFlinger will consider - * switching between. Only configs with a config group and resolution matching defaultConfig - * will be considered for switching. The defaultConfig index corresponds to the list of configs - * returned from getDisplayConfigs(). - */ - virtual status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) = 0; - - virtual status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) = 0; + * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider + * switching between. Only modes with a mode group and resolution matching defaultMode + * will be considered for switching. The defaultMode index corresponds to the list of modes + * returned from getDisplayModes(). + */ + virtual status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, + bool allowGroupSwitching, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) = 0; + + virtual status_t getDesiredDisplayModeSpecs( + const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) = 0; /* * Gets whether brightness operations are supported on a display. * @@ -527,8 +524,8 @@ public: SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, GET_SUPPORTED_FRAME_TIMESTAMPS, - GET_DISPLAY_CONFIGS, - GET_ACTIVE_CONFIG, + GET_DISPLAY_MODES, + GET_ACTIVE_DISPLAY_MODE, GET_DISPLAY_STATE, CAPTURE_DISPLAY, CAPTURE_LAYERS, @@ -554,8 +551,8 @@ public: GET_PHYSICAL_DISPLAY_IDS, ADD_REGION_SAMPLING_LISTENER, REMOVE_REGION_SAMPLING_LISTENER, - SET_DESIRED_DISPLAY_CONFIG_SPECS, - GET_DESIRED_DISPLAY_CONFIG_SPECS, + SET_DESIRED_DISPLAY_MODE_SPECS, + GET_DESIRED_DISPLAY_MODE_SPECS, GET_DISPLAY_BRIGHTNESS_SUPPORT, SET_DISPLAY_BRIGHTNESS, CAPTURE_DISPLAY_BY_ID, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e7abfe6172..bd9f066f96 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -110,30 +110,29 @@ public: // Get immutable information about given physical display. static status_t getDisplayInfo(const sp& display, DisplayInfo*); - // Get configurations supported by given physical display. - static status_t getDisplayConfigs(const sp& display, Vector*); + // Get modes supported by given physical display. + static status_t getDisplayModes(const sp& display, Vector*); - // Get the ID of the active DisplayConfig, as getDisplayConfigs index. - static int getActiveConfig(const sp& display); + // Get the ID of the active DisplayMode, as getDisplayModes index. + static int getActiveDisplayModeId(const sp& display); - // Shorthand for getDisplayConfigs element at getActiveConfig index. - static status_t getActiveDisplayConfig(const sp& display, DisplayConfig*); + // Shorthand for getDisplayModes element at getActiveDisplayModeId index. + static status_t getActiveDisplayMode(const sp& display, ui::DisplayMode*); // Sets the refresh rate boundaries for the display. - static status_t setDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t defaultConfig, bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax); + static status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, + bool allowGroupSwitching, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax); // Gets the refresh rate boundaries for the display. - static status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, - bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax); + static status_t getDesiredDisplayModeSpecs(const sp& displayToken, + size_t* outDefaultMode, bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax); // Gets the list of supported color modes for the given display static status_t getDisplayColorModes(const sp& display, diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 70e656da9b..5447b7659b 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -107,9 +107,9 @@ protected: t.apply(); t.clear(); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplayToken, &config)); - const ui::Size& resolution = config.resolution; + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &mode)); + const ui::Size& resolution = mode.resolution; mDisplayWidth = resolution.getWidth(); mDisplayHeight = resolution.getHeight(); diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp index c5093e2d88..7dbba31ba8 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -25,7 +25,7 @@ namespace android::test { TEST(DisplayEventStructLayoutTest, TestEventAlignment) { CHECK_OFFSET(DisplayEventReceiver::Event, vsync, 24); CHECK_OFFSET(DisplayEventReceiver::Event, hotplug, 24); - CHECK_OFFSET(DisplayEventReceiver::Event, config, 24); + CHECK_OFFSET(DisplayEventReceiver::Event, modeChange, 24); CHECK_OFFSET(DisplayEventReceiver::Event::Header, type, 0); CHECK_OFFSET(DisplayEventReceiver::Event::Header, displayId, 8); @@ -38,8 +38,8 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0); - CHECK_OFFSET(DisplayEventReceiver::Event::Config, configId, 0); - CHECK_OFFSET(DisplayEventReceiver::Event::Config, vsyncPeriod, 8); + CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, modeId, 0); + CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, vsyncPeriod, 8); CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, uid, 0); CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, frameRateHz, 8); diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 31cbbdc75c..d65a40baf6 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include @@ -272,13 +272,13 @@ public: const auto display = mComposerClient->getInternalDisplayToken(); ASSERT_NE(display, nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, mComposerClient->getActiveDisplayConfig(display, &config)); + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, mComposerClient->getActiveDisplayMode(display, &mode)); // After a new buffer is queued, SurfaceFlinger is notified and will // latch the new buffer on next vsync. Let's heuristically wait for 3 // vsyncs. - mBufferPostDelay = static_cast(1e6 / config.refreshRate) * 3; + mBufferPostDelay = static_cast(1e6 / mode.refreshRate) * 3; } void TearDown() { diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3f7a5b1785..80e4c770dc 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -737,7 +737,7 @@ public: status_t getDisplayInfo(const sp& /*display*/, DisplayInfo*) override { return NO_ERROR; } - status_t getDisplayConfigs(const sp& /*display*/, Vector*) override { + status_t getDisplayModes(const sp& /*display*/, Vector*) override { return NO_ERROR; } status_t getDisplayState(const sp& /*display*/, ui::DisplayState*) override { @@ -745,7 +745,7 @@ public: } status_t getDisplayStats(const sp& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } - int getActiveConfig(const sp& /*display*/) override { return 0; } + int getActiveDisplayModeId(const sp& /*display*/) override { return 0; } status_t getDisplayColorModes(const sp& /*display*/, Vector* /*outColorModes*/) override { return NO_ERROR; @@ -843,21 +843,21 @@ public: const sp& /*listener*/) override { return NO_ERROR; } - status_t setDesiredDisplayConfigSpecs(const sp& /*displayToken*/, - int32_t /*defaultConfig*/, bool /*allowGroupSwitching*/, - float /*primaryRefreshRateMin*/, - float /*primaryRefreshRateMax*/, - float /*appRequestRefreshRateMin*/, - float /*appRequestRefreshRateMax*/) { + status_t setDesiredDisplayModeSpecs(const sp& /*displayToken*/, size_t /*defaultMode*/, + bool /*allowGroupSwitching*/, + float /*primaryRefreshRateMin*/, + float /*primaryRefreshRateMax*/, + float /*appRequestRefreshRateMin*/, + float /*appRequestRefreshRateMax*/) { return NO_ERROR; } - status_t getDesiredDisplayConfigSpecs(const sp& /*displayToken*/, - int32_t* /*outDefaultConfig*/, - bool* /*outAllowGroupSwitching*/, - float* /*outPrimaryRefreshRateMin*/, - float* /*outPrimaryRefreshRateMax*/, - float* /*outAppRequestRefreshRateMin*/, - float* /*outAppRequestRefreshRateMax*/) override { + status_t getDesiredDisplayModeSpecs(const sp& /*displayToken*/, + size_t* /*outDefaultMode*/, + bool* /*outAllowGroupSwitching*/, + float* /*outPrimaryRefreshRateMin*/, + float* /*outPrimaryRefreshRateMax*/, + float* /*outAppRequestRefreshRateMin*/, + float* /*outAppRequestRefreshRateMax*/) override { return NO_ERROR; }; status_t notifyPowerBoost(int32_t /*boostId*/) override { return NO_ERROR; } diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp index 6b085a3292..dc2dd297c5 100644 --- a/libs/nativedisplay/AChoreographer.cpp +++ b/libs/nativedisplay/AChoreographer.cpp @@ -138,8 +138,8 @@ private: void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; - void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId, - nsecs_t vsyncPeriod) override; + void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, + nsecs_t vsyncPeriod) override; void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override; void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId, std::vector overrides) override; @@ -382,8 +382,8 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c this, to_string(displayId).c_str(), toString(connected)); } -void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) { - LOG_ALWAYS_FATAL("dispatchConfigChanged was called but was never registered"); +void Choreographer::dispatchModeChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) { + LOG_ALWAYS_FATAL("dispatchModeChanged was called but was never registered"); } void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId, diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp index 277635cd34..c595aa6309 100644 --- a/libs/nativedisplay/ADisplay.cpp +++ b/libs/nativedisplay/ADisplay.cpp @@ -16,8 +16,8 @@ #include #include -#include #include +#include #include #include @@ -134,8 +134,8 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { return NO_INIT; } - std::vector configsPerDisplay[size]; - int numConfigs = 0; + std::vector modesPerDisplay[size]; + int numModes = 0; for (int i = 0; i < size; ++i) { const sp token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]); @@ -145,23 +145,23 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { return status; } - Vector configs; - if (const status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs); + Vector modes; + if (const status_t status = SurfaceComposerClient::getDisplayModes(token, &modes); status != OK) { return status; } - if (configs.empty()) { + if (modes.empty()) { return NO_INIT; } - numConfigs += configs.size(); - configsPerDisplay[i].reserve(configs.size()); - for (int j = 0; j < configs.size(); ++j) { - const DisplayConfig& config = configs[j]; - configsPerDisplay[i].emplace_back( - DisplayConfigImpl{config.resolution.getWidth(), config.resolution.getHeight(), - info.density, config.refreshRate, config.sfVsyncOffset, - config.appVsyncOffset}); + numModes += modes.size(); + modesPerDisplay[i].reserve(modes.size()); + for (int j = 0; j < modes.size(); ++j) { + const ui::DisplayMode& mode = modes[j]; + modesPerDisplay[i].emplace_back( + DisplayConfigImpl{mode.resolution.getWidth(), mode.resolution.getHeight(), + info.density, mode.refreshRate, mode.sfVsyncOffset, + mode.appVsyncOffset}); } } @@ -192,7 +192,7 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { // contiguous block of DisplayConfigImpls specific to that display. DisplayImpl** const impls = reinterpret_cast( malloc((sizeof(DisplayImpl) + sizeof(DisplayImpl*)) * size + - sizeof(DisplayConfigImpl) * numConfigs)); + sizeof(DisplayConfigImpl) * numModes)); DisplayImpl* const displayData = reinterpret_cast(impls + size); DisplayConfigImpl* configData = reinterpret_cast(displayData + size); @@ -200,7 +200,7 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { const PhysicalDisplayId id = ids[i]; const ADisplayType type = (internalId == id) ? ADisplayType::DISPLAY_TYPE_INTERNAL : ADisplayType::DISPLAY_TYPE_EXTERNAL; - const std::vector& configs = configsPerDisplay[i]; + const std::vector& configs = modesPerDisplay[i]; memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size()); displayData[i] = DisplayImpl{id, @@ -257,7 +257,7 @@ int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) { CHECK_NOT_NULL(display); sp token = getToken(display); - const int index = SurfaceComposerClient::getActiveConfig(token); + const int index = SurfaceComposerClient::getActiveDisplayModeId(token); if (index < 0) { return index; } diff --git a/libs/ui/include/ui/DisplayConfig.h b/libs/ui/include/ui/DisplayConfig.h deleted file mode 100644 index d6fbaab387..0000000000 --- a/libs/ui/include/ui/DisplayConfig.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include -#include - -namespace android { - -// Configuration supported by physical display. -struct DisplayConfig { - ui::Size resolution; - float xDpi = 0; - float yDpi = 0; - - float refreshRate = 0; - nsecs_t appVsyncOffset = 0; - nsecs_t sfVsyncOffset = 0; - nsecs_t presentationDeadline = 0; - int configGroup = -1; -}; - -static_assert(std::is_trivially_copyable_v); - -} // namespace android diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h new file mode 100644 index 0000000000..145d7efd19 --- /dev/null +++ b/libs/ui/include/ui/DisplayMode.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace android::ui { + +// Mode supported by physical display. +struct DisplayMode { + ui::Size resolution; + float xDpi = 0; + float yDpi = 0; + + float refreshRate = 0; + nsecs_t appVsyncOffset = 0; + nsecs_t sfVsyncOffset = 0; + nsecs_t presentationDeadline = 0; + int group = -1; +}; + +static_assert(std::is_trivially_copyable_v); + +} // namespace android::ui diff --git a/libs/ui/include_vndk/ui/DisplayConfig.h b/libs/ui/include_vndk/ui/DisplayConfig.h deleted file mode 120000 index 1450319502..0000000000 --- a/libs/ui/include_vndk/ui/DisplayConfig.h +++ /dev/null @@ -1 +0,0 @@ -../../include/ui/DisplayConfig.h \ No newline at end of file diff --git a/libs/ui/include_vndk/ui/DisplayMode.h b/libs/ui/include_vndk/ui/DisplayMode.h new file mode 120000 index 0000000000..c87754a682 --- /dev/null +++ b/libs/ui/include_vndk/ui/DisplayMode.h @@ -0,0 +1 @@ +../../include/ui/DisplayMode.h \ No newline at end of file diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp index dfb9c92b5f..fd4522e757 100644 --- a/opengl/tests/lib/WindowSurface.cpp +++ b/opengl/tests/lib/WindowSurface.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include using namespace android; @@ -42,10 +42,10 @@ WindowSurface::WindowSurface() { return; } - DisplayConfig displayConfig; - err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); + ui::DisplayMode displayMode; + err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); if (err != NO_ERROR) { - fprintf(stderr, "ERROR: unable to get active display config\n"); + fprintf(stderr, "ERROR: unable to get active display mode\n"); return; } @@ -56,7 +56,7 @@ WindowSurface::WindowSurface() { return; } - const ui::Size& resolution = displayConfig.resolution; + const ui::Size& resolution = displayMode.resolution; auto width = resolution.getWidth(); auto height = resolution.getHeight(); diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp index 321bb8342d..d6fc69562b 100644 --- a/services/automotive/display/AutomotiveDisplayProxyService.cpp +++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp @@ -41,10 +41,10 @@ AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) { } // Get the resolution from stored display state. - DisplayConfig displayConfig = {}; - auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); + ui::DisplayMode displayMode = {}; + auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); if (err != NO_ERROR) { - ALOGE("Failed to get display configuration of %lX. " + ALOGE("Failed to get display mode of %lX. " "This display will be ignored.", (unsigned long)id); return nullptr; } @@ -57,8 +57,8 @@ AutomotiveDisplayProxyService::getIGraphicBufferProducer(uint64_t id) { return nullptr; } - auto displayWidth = displayConfig.resolution.getWidth(); - auto displayHeight = displayConfig.resolution.getHeight(); + auto displayWidth = displayMode.resolution.getWidth(); + auto displayHeight = displayMode.resolution.getHeight(); if ((displayState.orientation != ui::ROTATION_0) && (displayState.orientation != ui::ROTATION_180)) { std::swap(displayWidth, displayHeight); @@ -161,10 +161,10 @@ Return AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDispl if (displayToken == nullptr) { ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id); } else { - DisplayConfig displayConfig = {}; - auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); + ui::DisplayMode displayMode = {}; + auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); if (err != NO_ERROR) { - ALOGW("Failed to get display configuration of %lX. " + ALOGW("Failed to get display mode of %lX. " "This display will be ignored.", (unsigned long)id); } @@ -175,7 +175,7 @@ Return AutomotiveDisplayProxyService::getDisplayInfo(uint64_t id, getDispl "This display will be ignored.", (unsigned long)id); } - activeConfig.setToExternal((uint8_t*)&displayConfig, sizeof(DisplayConfig)); + activeConfig.setToExternal((uint8_t*)&displayMode, sizeof(ui::DisplayMode)); activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState)); } diff --git a/services/automotive/display/include/AutomotiveDisplayProxyService.h b/services/automotive/display/include/AutomotiveDisplayProxyService.h index e2fc0d2eec..4482b9beea 100644 --- a/services/automotive/display/include/AutomotiveDisplayProxyService.h +++ b/services/automotive/display/include/AutomotiveDisplayProxyService.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h index 31d1245ed0..1f0f3c3c33 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayMode.h +++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h @@ -86,8 +86,8 @@ public: return *this; } - Builder& setConfigGroup(int32_t configGroup) { - mDisplayMode->mConfigGroup = configGroup; + Builder& setGroup(int32_t group) { + mDisplayMode->mGroup = group; return *this; } @@ -119,7 +119,10 @@ public: nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); } float getDpiX() const { return mDpiX; } float getDpiY() const { return mDpiY; } - int32_t getConfigGroup() const { return mConfigGroup; } + + // Switches between modes in the same group are seamless, i.e. + // without visual interruptions such as a black screen. + int32_t getGroup() const { return mGroup; } private: explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {} @@ -132,15 +135,15 @@ private: Fps mFps; float mDpiX = -1; float mDpiY = -1; - int32_t mConfigGroup = -1; + int32_t mGroup = -1; }; inline std::string to_string(const DisplayMode& mode) { return base::StringPrintf("{id=%zu, hwcId=%d, width=%d, height=%d, refreshRate=%s, " - "dpiX=%.2f, dpiY=%.2f, configGroup=%d}", + "dpiX=%.2f, dpiY=%.2f, group=%d}", mode.getId().value(), mode.getHwcId(), mode.getWidth(), mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(), - mode.getDpiY(), mode.getConfigGroup()); + mode.getDpiY(), mode.getGroup()); } } // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index f90c130992..bfe9b4a3bb 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -90,9 +90,9 @@ std::string toString(const DisplayEventReceiver::Event& event) { return StringPrintf("VSync{displayId=%s, count=%u, expectedVSyncTimestamp=%" PRId64 "}", to_string(event.header.displayId).c_str(), event.vsync.count, event.vsync.expectedVSyncTimestamp); - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: - return StringPrintf("ConfigChanged{displayId=%s, configId=%u}", - to_string(event.header.displayId).c_str(), event.config.configId); + case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: + return StringPrintf("ModeChanged{displayId=%s, modeId=%u}", + to_string(event.header.displayId).c_str(), event.modeChange.modeId); default: return "Event{}"; } @@ -118,12 +118,12 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times return event; } -DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId, - nsecs_t vsyncPeriod) { +DisplayEventReceiver::Event makeModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, + nsecs_t vsyncPeriod) { DisplayEventReceiver::Event event; - event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()}; - event.config.configId = configId.value(); - event.config.vsyncPeriod = vsyncPeriod; + event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, displayId, systemTime()}; + event.modeChange.modeId = modeId.value(); + event.modeChange.vsyncPeriod = vsyncPeriod; return event; } @@ -373,11 +373,11 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) mCondition.notify_all(); } -void EventThread::onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId, - nsecs_t vsyncPeriod) { +void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, + nsecs_t vsyncPeriod) { std::lock_guard lock(mMutex); - mPendingEvents.push_back(makeConfigChanged(displayId, configId, vsyncPeriod)); + mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod)); mCondition.notify_all(); } @@ -518,9 +518,9 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event, case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: return true; - case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: { + case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: { return connection->mEventRegistration.test( - ISurfaceComposer::EventRegistration::configChanged); + ISurfaceComposer::EventRegistration::modeChanged); } case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 15efe219c0..35406041a8 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -123,9 +123,9 @@ public: virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; - // called when SF changes the active config and apps needs to be notified about the change - virtual void onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId, - nsecs_t vsyncPeriod) = 0; + // called when SF changes the active mode and apps needs to be notified about the change + virtual void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, + nsecs_t vsyncPeriod) = 0; // called when SF updates the Frame Rate Override list virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId, @@ -173,8 +173,8 @@ public: void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; - void onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId, - nsecs_t vsyncPeriod) override; + void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId, + nsecs_t vsyncPeriod) override; void onFrameRateOverridesChanged(PhysicalDisplayId displayId, std::vector overrides) override; diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 7ef531df63..ea92ad88bb 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -102,7 +102,7 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now, LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); const auto& info = it->second; - info->setLastPresentTime(presentTime, now, updateType, mConfigChangePending); + info->setLastPresentTime(presentTime, now, updateType, mModeChangePending); // Activate layer if inactive. if (const auto end = activeLayers().end(); it >= end) { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index bae9b5a41a..05ecc705cc 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -51,8 +51,8 @@ public: // Sets the display size. Client is responsible for synchronization. void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; } - // Sets whether a config change is pending to be applied - void setConfigChangePending(bool pending) { mConfigChangePending = pending; } + // Sets whether a mode change is pending to be applied + void setModeChangePending(bool pending) { mModeChangePending = pending; } // Represents which layer activity is recorded enum class LayerUpdateType { @@ -109,8 +109,8 @@ private: // Whether to use priority sent from WindowManager to determine the relevancy of the layer. const bool mUseFrameRatePriority; - // Whether a config change is in progress or not - std::atomic mConfigChangePending = false; + // Whether a mode change is in progress or not + std::atomic mModeChangePending = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 4324855b70..4b4cdaea09 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -44,7 +44,7 @@ LayerInfo::LayerInfo(const std::string& name, LayerHistory::LayerVoteType defaul mRefreshRateHistory(name) {} void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType, - bool pendingConfigChange) { + bool pendingModeChange) { lastPresentTime = std::max(lastPresentTime, static_cast(0)); mLastUpdatedTime = std::max(lastPresentTime, now); @@ -56,7 +56,7 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUp case LayerUpdateType::Buffer: FrameTimeData frameTime = {.presentTime = lastPresentTime, .queueTime = mLastUpdatedTime, - .pendingConfigChange = pendingConfigChange}; + .pendingModeChange = pendingModeChange}; mFrameTimes.push_back(frameTime); if (mFrameTimes.size() > HISTORY_SIZE) { mFrameTimes.pop_front(); @@ -124,11 +124,11 @@ bool LayerInfo::hasEnoughDataForHeuristic() const { } std::optional LayerInfo::calculateAverageFrameTime() const { - // Ignore frames captured during a config change - const bool isDuringConfigChange = + // Ignore frames captured during a mode change + const bool isDuringModeChange = std::any_of(mFrameTimes.begin(), mFrameTimes.end(), - [](auto frame) { return frame.pendingConfigChange; }); - if (isDuringConfigChange) { + [](const auto& frame) { return frame.pendingModeChange; }); + if (isDuringModeChange) { return std::nullopt; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index e32ba099f6..40c0214408 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -80,7 +80,7 @@ public: // the layer was last updated. If the present time is farther in the future than the // updated time, the updated time is the present time. void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType, - bool pendingConfigChange); + bool pendingModeChange); // Sets an explicit layer vote. This usually comes directly from the application via // ANativeWindow_setFrameRate API @@ -124,7 +124,7 @@ private: struct FrameTimeData { nsecs_t presentTime; // desiredPresentTime, if provided nsecs_t queueTime; // buffer queue time - bool pendingConfigChange; + bool pendingModeChange; }; // Holds information about the calculated and reported refresh rate diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 81ffe0f20e..e7a44a70d5 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -40,13 +40,13 @@ std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, f to_string(layer.desiredRefreshRate).c_str()); } -std::vector constructKnownFrameRates(const DisplayModes& configs) { +std::vector constructKnownFrameRates(const DisplayModes& modes) { std::vector knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; - knownFrameRates.reserve(knownFrameRates.size() + configs.size()); + knownFrameRates.reserve(knownFrameRates.size() + modes.size()); // Add all supported refresh rates to the set - for (const auto& config : configs) { - const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); + for (const auto& mode : modes) { + const auto refreshRate = Fps::fromPeriodNsecs(mode->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } @@ -65,8 +65,8 @@ using RefreshRate = RefreshRateConfigs::RefreshRate; std::string RefreshRate::toString() const { return base::StringPrintf("{id=%zu, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", - getConfigId().value(), hwcConfig->getHwcId(), getFps().getValue(), - hwcConfig->getWidth(), hwcConfig->getHeight(), getConfigGroup()); + getModeId().value(), mode->getHwcId(), getFps().getValue(), + mode->getWidth(), mode->getHeight(), getModeGroup()); } std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { @@ -89,9 +89,9 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { } std::string RefreshRateConfigs::Policy::toString() const { - return base::StringPrintf("default config ID: %zu, allowGroupSwitching = %d" + return base::StringPrintf("default mode ID: %zu, allowGroupSwitching = %d" ", primary range: %s, app request range: %s", - defaultConfig.value(), allowGroupSwitching, + defaultMode.value(), allowGroupSwitching, primaryRange.toString().c_str(), appRequestRange.toString().c_str()); } @@ -291,7 +291,7 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vectordefaultConfig); + const auto& defaultMode = mRefreshRates.at(policy->defaultMode); for (const auto& layer : layers) { ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(), @@ -303,11 +303,11 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vectorgetConfigGroup() == - mCurrentRefreshRate->getConfigGroup(); + const bool isSeamlessSwitch = + scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup(); if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) { - ALOGV("%s ignores %s to avoid non-seamless switch. Current config = %s", + ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s", formatLayerInfo(layer, weight).c_str(), scores[i].refreshRate->toString().c_str(), mCurrentRefreshRate->toString().c_str()); @@ -317,26 +317,25 @@ RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vectortoString().c_str(), mCurrentRefreshRate->toString().c_str()); continue; } - // Layers with default seamlessness vote for the current config group if + // Layers with default seamlessness vote for the current mode group if // there are layers with seamlessness=SeamedAndSeamless and for the default - // config group otherwise. In second case, if the current config group is different + // mode group otherwise. In second case, if the current mode group is different // from the default, this means a layer with seamlessness=SeamedAndSeamless has just // disappeared. const bool isInPolicyForDefault = seamedLayers > 0 - ? scores[i].refreshRate->getConfigGroup() == - mCurrentRefreshRate->getConfigGroup() - : scores[i].refreshRate->getConfigGroup() == defaultConfig->getConfigGroup(); + ? scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup() + : scores[i].refreshRate->getModeGroup() == defaultMode->getModeGroup(); if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault && !layer.focused) { - ALOGV("%s ignores %s. Current config = %s", formatLayerInfo(layer, weight).c_str(), + ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(), scores[i].refreshRate->toString().c_str(), mCurrentRefreshRate->toString().c_str()); continue; @@ -548,12 +547,12 @@ std::optional RefreshRateConfigs::onKernelTimerChanged( const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { for (auto refreshRate : mPrimaryRefreshRates) { - if (mCurrentRefreshRate->getConfigGroup() == refreshRate->getConfigGroup()) { + if (mCurrentRefreshRate->getModeGroup() == refreshRate->getModeGroup()) { return *refreshRate; } } - ALOGE("Can't find min refresh rate by policy with the same config group" - " as the current config %s", + ALOGE("Can't find min refresh rate by policy with the same mode group" + " as the current mode %s", mCurrentRefreshRate->toString().c_str()); // Defaulting to the lowest refresh rate return *mPrimaryRefreshRates.front(); @@ -567,12 +566,12 @@ RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const { const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); it++) { const auto& refreshRate = (**it); - if (mCurrentRefreshRate->getConfigGroup() == refreshRate.getConfigGroup()) { + if (mCurrentRefreshRate->getModeGroup() == refreshRate.getModeGroup()) { return refreshRate; } } - ALOGE("Can't find max refresh rate by policy with the same config group" - " as the current config %s", + ALOGE("Can't find max refresh rate by policy with the same mode group" + " as the current mode %s", mCurrentRefreshRate->toString().c_str()); // Defaulting to the highest refresh rate return *mPrimaryRefreshRates.back(); @@ -593,50 +592,50 @@ const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicyLocked() con mCurrentRefreshRate) != mAppRequestRefreshRates.end()) { return *mCurrentRefreshRate; } - return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig); + return *mRefreshRates.at(getCurrentPolicyLocked()->defaultMode); } -void RefreshRateConfigs::setCurrentConfigId(DisplayModeId configId) { +void RefreshRateConfigs::setCurrentModeId(DisplayModeId modeId) { std::lock_guard lock(mLock); - mCurrentRefreshRate = mRefreshRates.at(configId).get(); + mCurrentRefreshRate = mRefreshRates.at(modeId).get(); } -RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, +RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId, bool enableFrameRateOverride) - : mKnownFrameRates(constructKnownFrameRates(configs)), + : mKnownFrameRates(constructKnownFrameRates(modes)), mEnableFrameRateOverride(enableFrameRateOverride) { - updateDisplayConfigs(configs, currentConfigId); + updateDisplayModes(modes, currentModeId); } -void RefreshRateConfigs::updateDisplayConfigs(const DisplayModes& configs, - DisplayModeId currentConfigId) { +void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes, + DisplayModeId currentModeId) { std::lock_guard lock(mLock); - LOG_ALWAYS_FATAL_IF(configs.empty()); - LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); + LOG_ALWAYS_FATAL_IF(modes.empty()); + LOG_ALWAYS_FATAL_IF(currentModeId.value() >= modes.size()); mRefreshRates.clear(); - for (const auto& config : configs) { - const auto configId = config->getId(); - const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod()); - mRefreshRates.emplace(configId, - std::make_unique(configId, config, fps, + for (const auto& mode : modes) { + const auto modeId = mode->getId(); + const auto fps = Fps::fromPeriodNsecs(mode->getVsyncPeriod()); + mRefreshRates.emplace(modeId, + std::make_unique(modeId, mode, fps, RefreshRate::ConstructorTag(0))); - if (configId == currentConfigId) { - mCurrentRefreshRate = mRefreshRates.at(configId).get(); + if (modeId == currentModeId) { + mCurrentRefreshRate = mRefreshRates.at(modeId).get(); } } - std::vector sortedConfigs; - getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs); - mDisplayManagerPolicy.defaultConfig = currentConfigId; - mMinSupportedRefreshRate = sortedConfigs.front(); - mMaxSupportedRefreshRate = sortedConfigs.back(); + std::vector sortedModes; + getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes); + mDisplayManagerPolicy.defaultMode = currentModeId; + mMinSupportedRefreshRate = sortedModes.front(); + mMaxSupportedRefreshRate = sortedModes.back(); mSupportsFrameRateOverride = false; if (mEnableFrameRateOverride) { - for (const auto& config1 : sortedConfigs) { - for (const auto& config2 : sortedConfigs) { - if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) { + for (const auto& mode1 : sortedModes) { + for (const auto& mode2 : sortedModes) { + if (getFrameRateDivider(mode1->getFps(), mode2->getFps()) >= 2) { mSupportsFrameRateOverride = true; break; } @@ -648,15 +647,15 @@ void RefreshRateConfigs::updateDisplayConfigs(const DisplayModes& configs, } bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const { - // defaultConfig must be a valid config, and within the given refresh rate range. - auto iter = mRefreshRates.find(policy.defaultConfig); + // defaultMode must be a valid mode, and within the given refresh rate range. + auto iter = mRefreshRates.find(policy.defaultMode); if (iter == mRefreshRates.end()) { - ALOGE("Default config is not found."); + ALOGE("Default mode is not found."); return false; } const RefreshRate& refreshRate = *iter->second; if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) { - ALOGE("Default config is not in the primary range."); + ALOGE("Default mode is not in the primary range."); return false; } return policy.appRequestRange.min.lessThanOrEqualWithMargin(policy.primaryRange.min) && @@ -706,10 +705,10 @@ RefreshRateConfigs::Policy RefreshRateConfigs::getDisplayManagerPolicy() const { return mDisplayManagerPolicy; } -bool RefreshRateConfigs::isConfigAllowed(DisplayModeId config) const { +bool RefreshRateConfigs::isModeAllowed(DisplayModeId modeId) const { std::lock_guard lock(mLock); for (const RefreshRate* refreshRate : mAppRequestRefreshRates) { - if (refreshRate->configId == config) { + if (refreshRate->modeId == modeId) { return true; } } @@ -723,60 +722,59 @@ void RefreshRateConfigs::getSortedRefreshRateListLocked( outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { if (shouldAddRefreshRate(*refreshRate)) { - ALOGV("getSortedRefreshRateListLocked: config %zu added to list policy", - refreshRate->configId.value()); + ALOGV("getSortedRefreshRateListLocked: mode %zu added to list policy", + refreshRate->modeId.value()); outRefreshRates->push_back(refreshRate.get()); } } std::sort(outRefreshRates->begin(), outRefreshRates->end(), [](const auto refreshRate1, const auto refreshRate2) { - if (refreshRate1->hwcConfig->getVsyncPeriod() != - refreshRate2->hwcConfig->getVsyncPeriod()) { - return refreshRate1->hwcConfig->getVsyncPeriod() > - refreshRate2->hwcConfig->getVsyncPeriod(); + if (refreshRate1->mode->getVsyncPeriod() != + refreshRate2->mode->getVsyncPeriod()) { + return refreshRate1->mode->getVsyncPeriod() > + refreshRate2->mode->getVsyncPeriod(); } else { - return refreshRate1->hwcConfig->getConfigGroup() > - refreshRate2->hwcConfig->getConfigGroup(); + return refreshRate1->mode->getGroup() > refreshRate2->mode->getGroup(); } }); } void RefreshRateConfigs::constructAvailableRefreshRates() { - // Filter configs based on current policy and sort based on vsync period + // Filter modes based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); - const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; + const auto& defaultMode = mRefreshRates.at(policy->defaultMode)->mode; ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); - auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, - std::vector* - outRefreshRates) REQUIRES(mLock) { - getSortedRefreshRateListLocked( - [&](const RefreshRate& refreshRate) REQUIRES(mLock) { - const auto& hwcConfig = refreshRate.hwcConfig; - - return hwcConfig->getHeight() == defaultConfig->getHeight() && - hwcConfig->getWidth() == defaultConfig->getWidth() && - hwcConfig->getDpiX() == defaultConfig->getDpiX() && - hwcConfig->getDpiY() == defaultConfig->getDpiY() && - (policy->allowGroupSwitching || - hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) && - refreshRate.inPolicy(min, max); - }, - outRefreshRates); - - LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), - "No matching configs for %s range: min=%s max=%s", listName, - to_string(min).c_str(), to_string(max).c_str()); - auto stringifyRefreshRates = [&]() -> std::string { - std::string str; - for (auto refreshRate : *outRefreshRates) { - base::StringAppendF(&str, "%s ", refreshRate->getName().c_str()); - } - return str; - }; - ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str()); - }; + auto filterRefreshRates = + [&](Fps min, Fps max, const char* listName, + std::vector* outRefreshRates) REQUIRES(mLock) { + getSortedRefreshRateListLocked( + [&](const RefreshRate& refreshRate) REQUIRES(mLock) { + const auto& mode = refreshRate.mode; + + return mode->getHeight() == defaultMode->getHeight() && + mode->getWidth() == defaultMode->getWidth() && + mode->getDpiX() == defaultMode->getDpiX() && + mode->getDpiY() == defaultMode->getDpiY() && + (policy->allowGroupSwitching || + mode->getGroup() == defaultMode->getGroup()) && + refreshRate.inPolicy(min, max); + }, + outRefreshRates); + + LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), + "No matching modes for %s range: min=%s max=%s", listName, + to_string(min).c_str(), to_string(max).c_str()); + auto stringifyRefreshRates = [&]() -> std::string { + std::string str; + for (auto refreshRate : *outRefreshRates) { + base::StringAppendF(&str, "%s ", refreshRate->getName().c_str()); + } + return str; + }; + ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str()); + }; filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary", &mPrimaryRefreshRates); @@ -845,20 +843,20 @@ int RefreshRateConfigs::getRefreshRateDivider(Fps frameRate) const { void RefreshRateConfigs::dump(std::string& result) const { std::lock_guard lock(mLock); - base::StringAppendF(&result, "DesiredDisplayConfigSpecs (DisplayManager): %s\n\n", + base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n", mDisplayManagerPolicy.toString().c_str()); scheduler::RefreshRateConfigs::Policy currentPolicy = *getCurrentPolicyLocked(); if (mOverridePolicy && currentPolicy != mDisplayManagerPolicy) { - base::StringAppendF(&result, "DesiredDisplayConfigSpecs (Override): %s\n\n", + base::StringAppendF(&result, "DesiredDisplayModeSpecs (Override): %s\n\n", currentPolicy.toString().c_str()); } - auto config = mCurrentRefreshRate->hwcConfig; - base::StringAppendF(&result, "Current config: %s\n", mCurrentRefreshRate->toString().c_str()); + auto mode = mCurrentRefreshRate->mode; + base::StringAppendF(&result, "Current mode: %s\n", mCurrentRefreshRate->toString().c_str()); result.append("Refresh rates:\n"); for (const auto& [id, refreshRate] : mRefreshRates) { - config = refreshRate->hwcConfig; + mode = refreshRate->mode; base::StringAppendF(&result, "\t%s\n", refreshRate->toString().c_str()); } diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 0c7dc0515c..2bc22b43f7 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -64,12 +64,12 @@ public: }; public: - RefreshRate(DisplayModeId configId, DisplayModePtr config, Fps fps, ConstructorTag) - : configId(configId), hwcConfig(config), fps(std::move(fps)) {} + RefreshRate(DisplayModeId modeId, DisplayModePtr mode, Fps fps, ConstructorTag) + : modeId(modeId), mode(mode), fps(std::move(fps)) {} - DisplayModeId getConfigId() const { return configId; } - nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } - int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } + DisplayModeId getModeId() const { return modeId; } + nsecs_t getVsyncPeriod() const { return mode->getVsyncPeriod(); } + int32_t getModeGroup() const { return mode->getGroup(); } std::string getName() const { return to_string(fps); } Fps getFps() const { return fps; } @@ -81,7 +81,7 @@ public: } bool operator!=(const RefreshRate& other) const { - return configId != other.configId || hwcConfig != other.hwcConfig; + return modeId != other.modeId || mode != other.mode; } bool operator<(const RefreshRate& other) const { @@ -99,11 +99,8 @@ public: friend RefreshRateConfigs; friend class RefreshRateConfigsTest; - // This config ID corresponds to the position of the config in the vector that is stored - // on the device. - const DisplayModeId configId; - // The config itself - DisplayModePtr hwcConfig; + const DisplayModeId modeId; + DisplayModePtr mode; // Refresh rate in frames per second const Fps fps{0.0f}; }; @@ -131,16 +128,16 @@ public: static constexpr int kAllowGroupSwitchingDefault = false; public: - // The default config, used to ensure we only initiate display config switches within the - // same config group as defaultConfigId's group. - DisplayModeId defaultConfig; - // Whether or not we switch config groups to get the best frame rate. + // The default mode, used to ensure we only initiate display mode switches within the + // same mode group as defaultMode's group. + DisplayModeId defaultMode; + // Whether or not we switch mode groups to get the best frame rate. bool allowGroupSwitching = kAllowGroupSwitchingDefault; // The primary refresh rate range represents display manager's general guidance on the - // display configs we'll consider when switching refresh rates. Unless we get an explicit + // display modes we'll consider when switching refresh rates. Unless we get an explicit // signal from an app, we should stay within this range. FpsRange primaryRange; - // The app request refresh rate range allows us to consider more display configs when + // The app request refresh rate range allows us to consider more display modes when // switching refresh rates. Although we should generally stay within the primary range, // specific considerations, such as layer frame rate settings specified via the // setFrameRate() api, may cause us to go outside the primary range. We never go outside the @@ -150,25 +147,25 @@ public: Policy() = default; - Policy(DisplayModeId defaultConfig, const FpsRange& range) - : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {} + Policy(DisplayModeId defaultMode, const FpsRange& range) + : Policy(defaultMode, kAllowGroupSwitchingDefault, range, range) {} - Policy(DisplayModeId defaultConfig, bool allowGroupSwitching, const FpsRange& range) - : Policy(defaultConfig, allowGroupSwitching, range, range) {} + Policy(DisplayModeId defaultMode, bool allowGroupSwitching, const FpsRange& range) + : Policy(defaultMode, allowGroupSwitching, range, range) {} - Policy(DisplayModeId defaultConfig, const FpsRange& primaryRange, + Policy(DisplayModeId defaultMode, const FpsRange& primaryRange, const FpsRange& appRequestRange) - : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} + : Policy(defaultMode, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} - Policy(DisplayModeId defaultConfig, bool allowGroupSwitching, const FpsRange& primaryRange, + Policy(DisplayModeId defaultMode, bool allowGroupSwitching, const FpsRange& primaryRange, const FpsRange& appRequestRange) - : defaultConfig(defaultConfig), + : defaultMode(defaultMode), allowGroupSwitching(allowGroupSwitching), primaryRange(primaryRange), appRequestRange(appRequestRange) {} bool operator==(const Policy& other) const { - return defaultConfig == other.defaultConfig && primaryRange == other.primaryRange && + return defaultMode == other.defaultMode && primaryRange == other.primaryRange && appRequestRange == other.appRequestRange && allowGroupSwitching == other.allowGroupSwitching; } @@ -200,8 +197,8 @@ public: // Gets the display manager policy, regardless of whether an override policy is active. Policy getDisplayManagerPolicy() const EXCLUDES(mLock); - // Returns true if config is allowed by the current policy. - bool isConfigAllowed(DisplayModeId config) const EXCLUDES(mLock); + // Returns true if mode is allowed by the current policy. + bool isModeAllowed(DisplayModeId) const EXCLUDES(mLock); // Describes the different options the layer voted for refresh rate enum class LayerVoteType { @@ -270,7 +267,7 @@ public: return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()}; } - std::optional onKernelTimerChanged(std::optional desiredActiveConfigId, + std::optional onKernelTimerChanged(std::optional desiredActiveModeId, bool timerExpired) const EXCLUDES(mLock); // Returns the highest refresh rate according to the current policy. May change at runtime. Only @@ -286,14 +283,14 @@ public: // Returns the refresh rate that corresponds to a DisplayModeId. This may change at // runtime. - // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed. - RefreshRate getRefreshRateFromConfigId(DisplayModeId configId) const EXCLUDES(mLock) { + // TODO(b/159590486) An invalid mode id may be given here if the dipslay modes have changed. + RefreshRate getRefreshRateFromModeId(DisplayModeId modeId) const EXCLUDES(mLock) { std::lock_guard lock(mLock); - return *mRefreshRates.at(configId); + return *mRefreshRates.at(modeId); }; - // Stores the current configId the device operates at - void setCurrentConfigId(DisplayModeId configId) EXCLUDES(mLock); + // Stores the current modeId the device operates at + void setCurrentModeId(DisplayModeId) EXCLUDES(mLock); // Returns a string that represents the layer vote type static std::string layerVoteTypeString(LayerVoteType vote); @@ -301,14 +298,13 @@ public: // Returns a known frame rate that is the closest to frameRate Fps findClosestKnownFrameRate(Fps frameRate) const; - RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId, + RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId, bool enableFrameRateOverride = false); - void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig) - EXCLUDES(mLock); + void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock); - // Returns whether switching configs (refresh rate or resolution) is possible. - // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only + // Returns whether switching modes (refresh rate or resolution) is possible. + // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only // differ in resolution. bool canSwitch() const EXCLUDES(mLock) { std::lock_guard lock(mLock); @@ -387,7 +383,7 @@ private: float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&, bool isSeamlessSwitch) const REQUIRES(mLock); - // The list of refresh rates, indexed by display config ID. This may change after this + // The list of refresh rates, indexed by display modes ID. This may change after this // object is initialized. AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); @@ -399,7 +395,7 @@ private: // vsyncPeriod (the first element is the lowest refresh rate). std::vector mAppRequestRefreshRates GUARDED_BY(mLock); - // The current config. This will change at runtime. This is set by SurfaceFlinger on + // The current display mode. This will change at runtime. This is set by SurfaceFlinger on // the main thread, and read by the Scheduler (and other objects) on other threads. const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index d8612098ec..98132701d1 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -348,55 +348,53 @@ void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDis thread->onFrameRateOverridesChanged(displayId, std::move(overrides)); } -void Scheduler::onPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, - DisplayModeId configId, nsecs_t vsyncPeriod) { +void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, + DisplayModeId modeId, nsecs_t vsyncPeriod) { { std::lock_guard lock(mFeatureStateLock); - // Cache the last reported config for primary display. - mFeatures.cachedConfigChangedParams = {handle, displayId, configId, vsyncPeriod}; + // Cache the last reported modes for primary display. + mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod}; } - onNonPrimaryDisplayConfigChanged(handle, displayId, configId, vsyncPeriod); + onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod); } -void Scheduler::dispatchCachedReportedConfig() { +void Scheduler::dispatchCachedReportedMode() { // Check optional fields first. - if (!mFeatures.configId.has_value()) { - ALOGW("No config ID found, not dispatching cached config."); + if (!mFeatures.modeId.has_value()) { + ALOGW("No mode ID found, not dispatching cached mode."); return; } - if (!mFeatures.cachedConfigChangedParams.has_value()) { - ALOGW("No config changed params found, not dispatching cached config."); + if (!mFeatures.cachedModeChangedParams.has_value()) { + ALOGW("No mode changed params found, not dispatching cached mode."); return; } - const auto configId = *mFeatures.configId; - const auto vsyncPeriod = - mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getVsyncPeriod(); + const auto modeId = *mFeatures.modeId; + const auto vsyncPeriod = mRefreshRateConfigs.getRefreshRateFromModeId(modeId).getVsyncPeriod(); - // If there is no change from cached config, there is no need to dispatch an event - if (configId == mFeatures.cachedConfigChangedParams->configId && - vsyncPeriod == mFeatures.cachedConfigChangedParams->vsyncPeriod) { + // If there is no change from cached mode, there is no need to dispatch an event + if (modeId == mFeatures.cachedModeChangedParams->modeId && + vsyncPeriod == mFeatures.cachedModeChangedParams->vsyncPeriod) { return; } - mFeatures.cachedConfigChangedParams->configId = configId; - mFeatures.cachedConfigChangedParams->vsyncPeriod = vsyncPeriod; - onNonPrimaryDisplayConfigChanged(mFeatures.cachedConfigChangedParams->handle, - mFeatures.cachedConfigChangedParams->displayId, - mFeatures.cachedConfigChangedParams->configId, - mFeatures.cachedConfigChangedParams->vsyncPeriod); + mFeatures.cachedModeChangedParams->modeId = modeId; + mFeatures.cachedModeChangedParams->vsyncPeriod = vsyncPeriod; + onNonPrimaryDisplayModeChanged(mFeatures.cachedModeChangedParams->handle, + mFeatures.cachedModeChangedParams->displayId, + mFeatures.cachedModeChangedParams->modeId, + mFeatures.cachedModeChangedParams->vsyncPeriod); } -void Scheduler::onNonPrimaryDisplayConfigChanged(ConnectionHandle handle, - PhysicalDisplayId displayId, - DisplayModeId configId, nsecs_t vsyncPeriod) { +void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, + DisplayModeId modeId, nsecs_t vsyncPeriod) { android::EventThread* thread; { std::lock_guard lock(mConnectionsLock); RETURN_IF_INVALID_HANDLE(handle); thread = mConnections[handle].thread.get(); } - thread->onConfigChanged(displayId, configId, vsyncPeriod); + thread->onModeChanged(displayId, modeId, vsyncPeriod); } size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) { @@ -590,9 +588,9 @@ void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, } } -void Scheduler::setConfigChangePending(bool pending) { +void Scheduler::setModeChangePending(bool pending) { if (mLayerHistory) { - mLayerHistory->setConfigChangePending(pending); + mLayerHistory->setModeChangePending(pending); } } @@ -603,7 +601,7 @@ void Scheduler::chooseRefreshRateForContent() { scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime()); scheduler::RefreshRateConfigs::GlobalSignals consideredSignals; - DisplayModeId newConfigId; + DisplayModeId newModeId; bool frameRateChanged; bool frameRateOverridesChanged; { @@ -613,28 +611,28 @@ void Scheduler::chooseRefreshRateForContent() { } mFeatures.contentRequirements = summary; - newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals); - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + newModeId = calculateRefreshRateModeId(&consideredSignals); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); - if (mFeatures.configId == newConfigId) { - // We don't need to change the config, but we might need to send an event - // about a config change, since it was suppressed due to a previous idleConsidered + if (mFeatures.modeId == newModeId) { + // We don't need to change the display mode, but we might need to send an event + // about a mode change, since it was suppressed due to a previous idleConsidered if (!consideredSignals.idle) { - dispatchCachedReportedConfig(); + dispatchCachedReportedMode(); } frameRateChanged = false; } else { - mFeatures.configId = newConfigId; + mFeatures.modeId = newModeId; frameRateChanged = true; } } if (frameRateChanged) { - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); mSchedulerCallback.changeRefreshRate(newRefreshRate, - consideredSignals.idle ? ConfigEvent::None - : ConfigEvent::Changed); + consideredSignals.idle ? ModeEvent::None + : ModeEvent::Changed); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); @@ -783,7 +781,7 @@ bool Scheduler::updateFrameRateOverrides( template bool Scheduler::handleTimerStateChanged(T* currentState, T newState) { - DisplayModeId newConfigId; + DisplayModeId newModeId; bool refreshRateChanged = false; bool frameRateOverridesChanged; scheduler::RefreshRateConfigs::GlobalSignals consideredSignals; @@ -793,29 +791,27 @@ bool Scheduler::handleTimerStateChanged(T* currentState, T newState) { return false; } *currentState = newState; - newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals); - const RefreshRate& newRefreshRate = - mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + newModeId = calculateRefreshRateModeId(&consideredSignals); + const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); - if (mFeatures.configId == newConfigId) { - // We don't need to change the config, but we might need to send an event - // about a config change, since it was suppressed due to a previous idleConsidered + if (mFeatures.modeId == newModeId) { + // We don't need to change the display mode, but we might need to send an event + // about a mode change, since it was suppressed due to a previous idleConsidered if (!consideredSignals.idle) { - dispatchCachedReportedConfig(); + dispatchCachedReportedMode(); } } else { - mFeatures.configId = newConfigId; + mFeatures.modeId = newModeId; refreshRateChanged = true; } } if (refreshRateChanged) { - const RefreshRate& newRefreshRate = - mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId); mSchedulerCallback.changeRefreshRate(newRefreshRate, - consideredSignals.idle ? ConfigEvent::None - : ConfigEvent::Changed); + consideredSignals.idle ? ModeEvent::None + : ModeEvent::Changed); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); @@ -823,7 +819,7 @@ bool Scheduler::handleTimerStateChanged(T* currentState, T newState) { return consideredSignals.touch; } -DisplayModeId Scheduler::calculateRefreshRateConfigIndexType( +DisplayModeId Scheduler::calculateRefreshRateModeId( scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals) { ATRACE_CALL(); if (consideredSignals) *consideredSignals = {}; @@ -833,7 +829,7 @@ DisplayModeId Scheduler::calculateRefreshRateConfigIndexType( if (mDisplayPowerTimer && (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset)) { - return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId(); + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getModeId(); } const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active; @@ -842,16 +838,16 @@ DisplayModeId Scheduler::calculateRefreshRateConfigIndexType( return mRefreshRateConfigs .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle}, consideredSignals) - .getConfigId(); + .getModeId(); } -std::optional Scheduler::getPreferredConfigId() { +std::optional Scheduler::getPreferredModeId() { std::lock_guard lock(mFeatureStateLock); - // Make sure that the default config ID is first updated, before returned. - if (mFeatures.configId.has_value()) { - mFeatures.configId = calculateRefreshRateConfigIndexType(); + // Make sure that the default mode ID is first updated, before returned. + if (mFeatures.modeId.has_value()) { + mFeatures.modeId = calculateRefreshRateModeId(); } - return mFeatures.configId; + return mFeatures.modeId; } void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 340ca8e88d..5237516f17 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -70,7 +70,7 @@ protected: class Scheduler { public: using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; - using ConfigEvent = scheduler::RefreshRateConfigEvent; + using ModeEvent = scheduler::RefreshRateConfigEvent; Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&); ~Scheduler(); @@ -87,10 +87,10 @@ public: sp getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); - void onPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId configId, - nsecs_t vsyncPeriod) EXCLUDES(mFeatureStateLock); - void onNonPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId, - DisplayModeId configId, nsecs_t vsyncPeriod); + void onPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId, + nsecs_t vsyncPeriod) EXCLUDES(mFeatureStateLock); + void onNonPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId, + nsecs_t vsyncPeriod); void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); @@ -128,7 +128,7 @@ public: // Layers are registered on creation, and unregistered when the weak reference expires. void registerLayer(Layer*); void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType); - void setConfigChangePending(bool pending); + void setModeChangePending(bool pending); // Detects content using layer history, and selects a matching refresh rate. void chooseRefreshRateForContent(); @@ -153,7 +153,7 @@ public: void dumpVsync(std::string&) const; // Get the appropriate refresh for current conditions. - std::optional getPreferredConfigId(); + std::optional getPreferredModeId(); // Notifies the scheduler about a refresh rate timeline change. void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); @@ -227,11 +227,11 @@ private: // This function checks whether individual features that are affecting the refresh rate // selection were initialized, prioritizes them, and calculates the DisplayModeId // for the suggested refresh rate. - DisplayModeId calculateRefreshRateConfigIndexType( + DisplayModeId calculateRefreshRateModeId( scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) REQUIRES(mFeatureStateLock); - void dispatchCachedReportedConfig() REQUIRES(mFeatureStateLock); + void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock); bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, Fps displayRefreshRate) REQUIRES(mFeatureStateLock) EXCLUDES(mFrameRateOverridesMutex); @@ -283,20 +283,20 @@ private: TouchState touch = TouchState::Inactive; TimerState displayPowerTimer = TimerState::Expired; - std::optional configId; + std::optional modeId; LayerHistory::Summary contentRequirements; bool isDisplayPowerStateNormal = true; - // Used to cache the last parameters of onPrimaryDisplayConfigChanged - struct ConfigChangedParams { + // Used to cache the last parameters of onPrimaryDisplayModeChanged + struct ModeChangedParams { ConnectionHandle handle; PhysicalDisplayId displayId; - DisplayModeId configId; + DisplayModeId modeId; nsecs_t vsyncPeriod; }; - std::optional cachedConfigChangedParams; + std::optional cachedModeChangedParams; } mFeatures GUARDED_BY(mFeatureStateLock); const scheduler::RefreshRateConfigs& mRefreshRateConfigs; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9b587510a..39f9e9f1d7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -67,9 +67,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -887,9 +887,9 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& displayToken, Display return NO_ERROR; } -status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, - Vector* configs) { - if (!displayToken || !configs) { +status_t SurfaceFlinger::getDisplayModes(const sp& displayToken, + Vector* modes) { + if (!displayToken || !modes) { return BAD_VALUE; } @@ -900,16 +900,16 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, return NAME_NOT_FOUND; } - configs->clear(); + modes->clear(); - for (const auto& mode : display->getSupportedModes()) { - DisplayConfig config; + for (const auto& supportedMode : display->getSupportedModes()) { + ui::DisplayMode mode; - auto width = mode->getWidth(); - auto height = mode->getHeight(); + auto width = supportedMode->getWidth(); + auto height = supportedMode->getHeight(); - auto xDpi = mode->getDpiX(); - auto yDpi = mode->getDpiY(); + auto xDpi = supportedMode->getDpiX(); + auto yDpi = supportedMode->getDpiY(); if (display->isPrimary() && (internalDisplayOrientation == ui::ROTATION_90 || @@ -918,24 +918,24 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, std::swap(xDpi, yDpi); } - config.resolution = ui::Size(width, height); + mode.resolution = ui::Size(width, height); if (mEmulatedDisplayDensity) { - config.xDpi = mEmulatedDisplayDensity; - config.yDpi = mEmulatedDisplayDensity; + mode.xDpi = mEmulatedDisplayDensity; + mode.yDpi = mEmulatedDisplayDensity; } else { - config.xDpi = xDpi; - config.yDpi = yDpi; + mode.xDpi = xDpi; + mode.yDpi = yDpi; } - const nsecs_t period = mode->getVsyncPeriod(); - config.refreshRate = Fps::fromPeriodNsecs(period).getValue(); + const nsecs_t period = supportedMode->getVsyncPeriod(); + mode.refreshRate = Fps::fromPeriodNsecs(period).getValue(); const auto vsyncConfigSet = - mVsyncConfiguration->getConfigsForRefreshRate(Fps(config.refreshRate)); - config.appVsyncOffset = vsyncConfigSet.late.appOffset; - config.sfVsyncOffset = vsyncConfigSet.late.sfOffset; - config.configGroup = mode->getConfigGroup(); + mVsyncConfiguration->getConfigsForRefreshRate(Fps(mode.refreshRate)); + mode.appVsyncOffset = vsyncConfigSet.late.appOffset; + mode.sfVsyncOffset = vsyncConfigSet.late.sfOffset; + mode.group = supportedMode->getGroup(); // This is how far in advance a buffer must be queued for // presentation at a given time. If you want a buffer to appear @@ -949,9 +949,9 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, // // We add an additional 1ms to allow for processing time and // differences between the ideal and actual refresh rate. - config.presentationDeadline = period - config.sfVsyncOffset + 1000000; + mode.presentationDeadline = period - mode.sfVsyncOffset + 1000000; - configs->push_back(config); + modes->push_back(mode); } return NO_ERROR; @@ -966,15 +966,15 @@ status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* st return NO_ERROR; } -int SurfaceFlinger::getActiveConfig(const sp& displayToken) { - int activeConfig; +int SurfaceFlinger::getActiveDisplayModeId(const sp& displayToken) { + int activeMode; bool isPrimary; { Mutex::Autolock lock(mStateLock); if (const auto display = getDisplayDeviceLocked(displayToken)) { - activeConfig = display->getActiveMode()->getId().value(); + activeMode = display->getActiveMode()->getId().value(); isPrimary = display->isPrimary(); } else { ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get()); @@ -983,36 +983,35 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { } if (isPrimary) { - if (const auto config = getDesiredActiveConfig()) { - return config->configId.value(); + if (const auto mode = getDesiredActiveMode()) { + return mode->modeId.value(); } } - return activeConfig; + return activeMode; } -void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { +void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) { ATRACE_CALL(); - auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); - ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str()); - - std::lock_guard lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) { - // If a config change is pending, just cache the latest request in - // mDesiredActiveConfig - const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event; - mDesiredActiveConfig = info; - mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig; + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId); + ALOGV("%s(%s)", __func__, refreshRate.getName().c_str()); + + std::lock_guard lock(mActiveModeLock); + if (mDesiredActiveModeChanged) { + // If a mode change is pending, just cache the latest request in mDesiredActiveMode + const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event; + mDesiredActiveMode = info; + mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig; } else { - // Check if we are already at the desired config + // Check if we are already at the desired mode const auto display = getDefaultDisplayDeviceLocked(); - if (!display || display->getActiveMode()->getId() == refreshRate.getConfigId()) { + if (!display || display->getActiveMode()->getId() == refreshRate.getModeId()) { return; } - // Initiate a config change. - mDesiredActiveConfigChanged = true; - mDesiredActiveConfig = info; + // Initiate a mode change. + mDesiredActiveModeChanged = true; + mDesiredActiveMode = info; // This will trigger HWC refresh without resetting the idle timer. repaintEverythingForHWC(); @@ -1024,7 +1023,7 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated); updatePhaseConfiguration(refreshRate.getFps()); - mScheduler->setConfigChangePending(true); + mScheduler->setModeChangePending(true); } if (mRefreshRateOverlay) { @@ -1032,7 +1031,7 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { } } -status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int modeId) { +status_t SurfaceFlinger::setActiveMode(const sp& displayToken, int modeId) { ATRACE_CALL(); if (!displayToken) { @@ -1042,13 +1041,13 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo auto future = schedule([=]() -> status_t { const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { - ALOGE("Attempt to set allowed display configs for invalid display token %p", + ALOGE("Attempt to set allowed display modes for invalid display token %p", displayToken.get()); return NAME_NOT_FOUND; } if (display->isVirtual()) { - ALOGW("Attempt to set allowed display configs for virtual display"); + ALOGW("Attempt to set allowed display modes for virtual display"); return INVALID_OPERATION; } @@ -1067,13 +1066,13 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo {fps, fps}}; constexpr bool kOverridePolicy = false; - return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); + return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy); }); return future.get(); } -void SurfaceFlinger::setActiveConfigInternal() { +void SurfaceFlinger::setActiveModeInternal() { ATRACE_CALL(); const auto display = getDefaultDisplayDeviceLocked(); @@ -1081,21 +1080,21 @@ void SurfaceFlinger::setActiveConfigInternal() { return; } - const auto upcomingConfig = display->getMode(mUpcomingActiveConfig.configId); - if (!upcomingConfig) { - ALOGW("Upcoming active config is no longer supported. ConfigId = %zu", - mUpcomingActiveConfig.configId.value()); + const auto upcomingMode = display->getMode(mUpcomingActiveMode.modeId); + if (!upcomingMode) { + ALOGW("Upcoming active mode is no longer supported. Mode ID = %zu", + mUpcomingActiveMode.modeId.value()); // TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may - // have been already updated with the upcoming active config. + // have been already updated with the upcoming active mode. return; } const Fps oldRefreshRate = display->getActiveMode()->getFps(); - std::lock_guard lock(mActiveConfigLock); - mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId); - display->setActiveMode(mUpcomingActiveConfig.configId); + std::lock_guard lock(mActiveModeLock); + mRefreshRateConfigs->setCurrentModeId(mUpcomingActiveMode.modeId); + display->setActiveMode(mUpcomingActiveMode.modeId); - const Fps refreshRate = upcomingConfig->getFps(); + const Fps refreshRate = upcomingMode->getFps(); mRefreshRateStats->setRefreshRate(refreshRate); @@ -1105,71 +1104,71 @@ void SurfaceFlinger::setActiveConfigInternal() { updatePhaseConfiguration(refreshRate); ATRACE_INT("ActiveConfigFPS", refreshRate.getValue()); - if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { + if (mUpcomingActiveMode.event != Scheduler::ModeEvent::None) { const nsecs_t vsyncPeriod = refreshRate.getPeriodNsecs(); const auto physicalId = display->getPhysicalId(); - mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId, - mUpcomingActiveConfig.configId, vsyncPeriod); + mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId, + mUpcomingActiveMode.modeId, vsyncPeriod); } } -void SurfaceFlinger::clearDesiredActiveConfigState() { - std::lock_guard lock(mActiveConfigLock); - mDesiredActiveConfig.event = Scheduler::ConfigEvent::None; - mDesiredActiveConfigChanged = false; - mScheduler->setConfigChangePending(false); +void SurfaceFlinger::clearDesiredActiveModeState() { + std::lock_guard lock(mActiveModeLock); + mDesiredActiveMode.event = Scheduler::ModeEvent::None; + mDesiredActiveModeChanged = false; + mScheduler->setModeChangePending(false); } -void SurfaceFlinger::desiredActiveConfigChangeDone() { - const auto modeId = getDesiredActiveConfig()->configId; +void SurfaceFlinger::desiredActiveModeChangeDone() { + const auto modeId = getDesiredActiveMode()->modeId; - clearDesiredActiveConfigState(); + clearDesiredActiveModeState(); const auto refreshRate = getDefaultDisplayDeviceLocked()->getMode(modeId)->getFps(); mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs()); updatePhaseConfiguration(refreshRate); } -void SurfaceFlinger::performSetActiveConfig() { +void SurfaceFlinger::performSetActiveMode() { ATRACE_CALL(); ALOGV("%s", __FUNCTION__); // Store the local variable to release the lock. - const auto desiredActiveConfig = getDesiredActiveConfig(); - if (!desiredActiveConfig) { - // No desired active config pending to be applied + const auto desiredActiveMode = getDesiredActiveMode(); + if (!desiredActiveMode) { + // No desired active mode pending to be applied return; } const auto display = getDefaultDisplayDeviceLocked(); - const auto desiredConfig = display->getMode(desiredActiveConfig->configId); - if (!desiredConfig) { - ALOGW("Desired display config is no longer supported. Config ID = %zu", - desiredActiveConfig->configId.value()); - clearDesiredActiveConfigState(); + const auto desiredMode = display->getMode(desiredActiveMode->modeId); + if (!desiredMode) { + ALOGW("Desired display mode is no longer supported. Mode ID = %zu", + desiredActiveMode->modeId.value()); + clearDesiredActiveModeState(); return; } - const auto refreshRate = desiredConfig->getFps(); - ALOGV("performSetActiveConfig changing active config to %zu(%s)", - desiredConfig->getId().value(), to_string(refreshRate).c_str()); + const auto refreshRate = desiredMode->getFps(); + ALOGV("%s changing active mode to %zu(%s)", __FUNCTION__, desiredMode->getId().value(), + to_string(refreshRate).c_str()); - if (!display || display->getActiveMode()->getId() == desiredActiveConfig->configId) { + if (!display || display->getActiveMode()->getId() == desiredActiveMode->modeId) { // display is not valid or we are already in the requested mode // on both cases there is nothing left to do - desiredActiveConfigChangeDone(); + desiredActiveModeChangeDone(); return; } - // Desired active config was set, it is different than the config currently in use, however - // allowed configs might have changed by the time we process the refresh. - // Make sure the desired config is still allowed - if (!isDisplayConfigAllowed(desiredActiveConfig->configId)) { - desiredActiveConfigChangeDone(); + // Desired active mode was set, it is different than the mode currently in use, however + // allowed modes might have changed by the time we process the refresh. + // Make sure the desired mode is still allowed + if (!isDisplayModeAllowed(desiredActiveMode->modeId)) { + desiredActiveModeChangeDone(); return; } - mUpcomingActiveConfig = *desiredActiveConfig; + mUpcomingActiveMode = *desiredActiveMode; - ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getValue()); + ATRACE_INT("ActiveModeFPS_HWC", refreshRate.getValue()); // TODO(b/142753666) use constrains hal::VsyncPeriodChangeConstraints constraints; @@ -1178,7 +1177,7 @@ void SurfaceFlinger::performSetActiveConfig() { hal::VsyncPeriodChangeTimeline outTimeline; const auto status = - display->initiateModeChange(mUpcomingActiveConfig.configId, constraints, &outTimeline); + display->initiateModeChange(mUpcomingActiveMode.modeId, constraints, &outTimeline); if (status != NO_ERROR) { // initiateModeChange may fail if a hotplug event is just about // to be sent. We just log the error in this case. @@ -1188,7 +1187,7 @@ void SurfaceFlinger::performSetActiveConfig() { mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline); // Scheduler will submit an empty frame to HWC if needed. - mSetActiveConfigPending = true; + mSetActiveModePending = true; } status_t SurfaceFlinger::getDisplayColorModes(const sp& displayToken, @@ -1627,12 +1626,12 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -bool SurfaceFlinger::isDisplayConfigAllowed(DisplayModeId configId) const { - return mRefreshRateConfigs->isConfigAllowed(configId); +bool SurfaceFlinger::isDisplayModeAllowed(DisplayModeId modeId) const { + return mRefreshRateConfigs->isModeAllowed(modeId); } void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, - Scheduler::ConfigEvent event) { + Scheduler::ModeEvent event) { const auto display = getDefaultDisplayDeviceLocked(); if (!display || mBootStage != BootStage::FINISHED) { return; @@ -1640,13 +1639,13 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, ATRACE_CALL(); // Don't do any updating if the current fps is the same as the new one. - if (!isDisplayConfigAllowed(refreshRate.getConfigId())) { - ALOGV("Skipping config %zu as it is not part of allowed configs", - refreshRate.getConfigId().value()); + if (!isDisplayModeAllowed(refreshRate.getModeId())) { + ALOGV("Skipping mode %zu as it is not part of allowed modes", + refreshRate.getModeId().value()); return; } - setDesiredActiveConfig({refreshRate.getConfigId(), event}); + setDesiredActiveMode({refreshRate.getModeId(), event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId, @@ -1829,18 +1828,18 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT mGpuFrameMissedCount++; } - // If we are in the middle of a config change and the fence hasn't + // If we are in the middle of a mode change and the fence hasn't // fired yet just wait for the next invalidate - if (mSetActiveConfigPending) { + if (mSetActiveModePending) { if (framePending) { mEventQueue->invalidate(); return; } // We received the present fence from the HWC, so we assume it successfully updated - // the config, hence we update SF. - mSetActiveConfigPending = false; - ON_MAIN_THREAD(setActiveConfigInternal()); + // the mode, hence we update SF. + mSetActiveModePending = false; + ON_MAIN_THREAD(setActiveModeInternal()); } if (framePending) { @@ -1920,7 +1919,7 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT mScheduler->chooseRefreshRateForContent(); } - ON_MAIN_THREAD(performSetActiveConfig()); + ON_MAIN_THREAD(performSetActiveMode()); updateCursorAsync(); updateInputFlinger(); @@ -2370,7 +2369,7 @@ DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId display .setVsyncPeriod(hwcMode.vsyncPeriod) .setDpiX(hwcMode.dpiX) .setDpiY(hwcMode.dpiY) - .setConfigGroup(hwcMode.configGroup) + .setGroup(hwcMode.configGroup) .build()); } return modes; @@ -2391,7 +2390,7 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { if (event.connection == hal::Connection::CONNECTED) { auto supportedModes = loadSupportedDisplayModes(displayId); const auto activeModeHwcId = getHwComposer().getActiveMode(displayId); - LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active config"); + LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode"); const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(), [activeModeHwcId](const DisplayModePtr& mode) { @@ -2675,9 +2674,8 @@ void SurfaceFlinger::processDisplayChanged(const wp& displayToken, // TODO(b/175678251) Call a listener instead. if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) { - mRefreshRateConfigs - ->updateDisplayConfigs(currentState.physical->supportedModes, - currentState.physical->activeMode->getId()); + mRefreshRateConfigs->updateDisplayModes(currentState.physical->supportedModes, + currentState.physical->activeMode->getId()); mVsyncConfiguration->reset(); updatePhaseConfiguration(mRefreshRateConfigs->getCurrentRefreshRate().getFps()); if (mRefreshRateOverlay) { @@ -2935,8 +2933,7 @@ void SurfaceFlinger::updateCursorAsync() { mCompositionEngine->updateCursorAsync(refreshArgs); } -void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, - Scheduler::ConfigEvent event) { +void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ModeEvent event) { // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Scheduler::chooseRefreshRateForContent @@ -2996,16 +2993,16 @@ void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) { mRegionSamplingThread = new RegionSamplingThread(*this, *mScheduler, RegionSamplingThread::EnvironmentTimingTunables()); - // Dispatch a config change request for the primary display on scheduler + // Dispatch a mode change request for the primary display on scheduler // initialization, so that the EventThreads always contain a reference to a // prior configuration. // // This is a bit hacky, but this avoids a back-pointer into the main SF // classes from EventThread, and there should be no run-time binder cost // anyway since there are no connected apps at this point. - mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId, - displayState.physical->activeMode->getId(), - vsyncPeriod); + mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId, + displayState.physical->activeMode->getId(), + vsyncPeriod); static auto ignorePresentFences = base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false); mScheduler->setIgnorePresentFences( @@ -4532,8 +4529,8 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { mRefreshRateConfigs->dump(result); - StringAppendF(&result, "(config override by backdoor: %s)\n\n", - mDebugDisplayConfigSetByBackdoor ? "yes" : "no"); + StringAppendF(&result, "(mode override by backdoor: %s)\n\n", + mDebugDisplayModeSetByBackdoor ? "yes" : "no"); mScheduler->dump(mAppConnectionHandle, result); mScheduler->dumpVsync(result); @@ -4952,8 +4949,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case ENABLE_VSYNC_INJECTIONS: case GET_ANIMATION_FRAME_STATS: case GET_HDR_CAPABILITIES: - case SET_DESIRED_DISPLAY_CONFIG_SPECS: - case GET_DESIRED_DISPLAY_CONFIG_SPECS: + case SET_DESIRED_DISPLAY_MODE_SPECS: + case GET_DESIRED_DISPLAY_MODE_SPECS: case SET_ACTIVE_COLOR_MODE: case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: case SET_AUTO_LOW_LATENCY_MODE: @@ -4995,13 +4992,13 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // information, so it is OK to pass them. case AUTHENTICATE_SURFACE: case GET_ACTIVE_COLOR_MODE: - case GET_ACTIVE_CONFIG: + case GET_ACTIVE_DISPLAY_MODE: case GET_PHYSICAL_DISPLAY_IDS: case GET_PHYSICAL_DISPLAY_TOKEN: case GET_DISPLAY_COLOR_MODES: case GET_DISPLAY_NATIVE_PRIMARIES: case GET_DISPLAY_INFO: - case GET_DISPLAY_CONFIGS: + case GET_DISPLAY_MODES: case GET_DISPLAY_STATE: case GET_DISPLAY_STATS: case GET_SUPPORTED_FRAME_TIMESTAMPS: @@ -5375,7 +5372,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } case 1035: { const int modeId = data.readInt32(); - mDebugDisplayConfigSetByBackdoor = false; + mDebugDisplayModeSetByBackdoor = false; const auto displayId = getInternalDisplayId(); if (!displayId) { @@ -5383,12 +5380,12 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return NO_ERROR; } - status_t result = setActiveConfig(getPhysicalDisplayToken(*displayId), modeId); + status_t result = setActiveMode(getPhysicalDisplayToken(*displayId), modeId); if (result != NO_ERROR) { return result; } - mDebugDisplayConfigSetByBackdoor = true; + mDebugDisplayModeSetByBackdoor = true; return NO_ERROR; } @@ -5467,14 +5464,13 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getCurrentRefreshRate() static_cast(schedule([=] { - const auto desiredActiveConfig = getDesiredActiveConfig(); - const std::optional desiredConfigId = desiredActiveConfig - ? std::make_optional(desiredActiveConfig->configId) - : std::nullopt; + const auto desiredActiveMode = getDesiredActiveMode(); + const std::optional desiredModeId = + desiredActiveMode ? std::make_optional(desiredActiveMode->modeId) : std::nullopt; const bool timerExpired = mKernelIdleTimerEnabled && expired; const auto newRefreshRate = - mRefreshRateConfigs->onKernelTimerChanged(desiredConfigId, timerExpired); + mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired); if (newRefreshRate) { if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { mRefreshRateOverlay->changeRefreshRate(*newRefreshRate); @@ -6061,7 +6057,7 @@ void SurfaceFlinger::traverseLayersInLayerStack(ui::LayerStack layerStack, const } } -status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( +status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( const sp& display, const std::optional& policy, bool overridePolicy) { Mutex::Autolock lock(mStateLock); @@ -6071,10 +6067,10 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy"); if (!display->isPrimary()) { - // TODO(b/144711714): For non-primary displays we should be able to set an active config + // TODO(b/144711714): For non-primary displays we should be able to set an active mode // as well. For now, just call directly to initiateModeChange but ideally - // it should go thru setDesiredActiveConfig, similar to primary display. - ALOGV("setAllowedDisplayConfigsInternal for non-primary display"); + // it should go thru setDesiredActiveMode, similar to primary display. + ALOGV("%s for non-primary display", __func__); const auto displayId = display->getPhysicalId(); hal::VsyncPeriodChangeConstraints constraints; @@ -6082,23 +6078,22 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( constraints.seamlessRequired = false; hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0}; - if (display->initiateModeChange(policy->defaultConfig, constraints, &timeline) != - NO_ERROR) { + if (display->initiateModeChange(policy->defaultMode, constraints, &timeline) != NO_ERROR) { return BAD_VALUE; } if (timeline.refreshRequired) { repaintEverythingForHWC(); } - display->setActiveMode(policy->defaultConfig); - const nsecs_t vsyncPeriod = display->getMode(policy->defaultConfig)->getVsyncPeriod(); - mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId, - policy->defaultConfig, vsyncPeriod); + display->setActiveMode(policy->defaultMode); + const nsecs_t vsyncPeriod = display->getMode(policy->defaultMode)->getVsyncPeriod(); + mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, displayId, + policy->defaultMode, vsyncPeriod); return NO_ERROR; } - if (mDebugDisplayConfigSetByBackdoor) { - // ignore this request as config is overridden by backdoor + if (mDebugDisplayModeSetByBackdoor) { + // ignore this request as mode is overridden by backdoor return NO_ERROR; } @@ -6113,42 +6108,43 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( } scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); - ALOGV("Setting desired display config specs: %s", currentPolicy.toString().c_str()); + ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str()); // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might // be depending in this callback. - const auto activeConfig = display->getActiveMode(); - const nsecs_t vsyncPeriod = activeConfig->getVsyncPeriod(); + const auto activeMode = display->getActiveMode(); + const nsecs_t vsyncPeriod = activeMode->getVsyncPeriod(); const auto physicalId = display->getPhysicalId(); - mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId, - activeConfig->getId(), vsyncPeriod); + mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId, activeMode->getId(), + vsyncPeriod); toggleKernelIdleTimer(); - auto configId = mScheduler->getPreferredConfigId(); - auto preferredRefreshRate = configId - ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) - // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. - : mRefreshRateConfigs->getRefreshRateFromConfigId(currentPolicy.defaultConfig); - ALOGV("trying to switch to Scheduler preferred config %zu (%s)", - preferredRefreshRate.getConfigId().value(), preferredRefreshRate.getName().c_str()); - - if (isDisplayConfigAllowed(preferredRefreshRate.getConfigId())) { - ALOGV("switching to Scheduler preferred config %zu", - preferredRefreshRate.getConfigId().value()); - setDesiredActiveConfig( - {preferredRefreshRate.getConfigId(), Scheduler::ConfigEvent::Changed}); + auto modeId = mScheduler->getPreferredModeId(); + auto preferredRefreshRate = modeId + ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId) + // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind. + : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode); + ALOGV("trying to switch to Scheduler preferred mode %zu (%s)", + preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str()); + + if (isDisplayModeAllowed(preferredRefreshRate.getModeId())) { + ALOGV("switching to Scheduler preferred display mode %zu", + preferredRefreshRate.getModeId().value()); + setDesiredActiveMode({preferredRefreshRate.getModeId(), Scheduler::ModeEvent::Changed}); } else { - LOG_ALWAYS_FATAL("Desired config not allowed: %zu", - preferredRefreshRate.getConfigId().value()); + LOG_ALWAYS_FATAL("Desired display mode not allowed: %zu", + preferredRefreshRate.getModeId().value()); } return NO_ERROR; } -status_t SurfaceFlinger::setDesiredDisplayConfigSpecs( - const sp& displayToken, int32_t defaultConfig, bool allowGroupSwitching, - float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp& displayToken, + size_t defaultMode, bool allowGroupSwitching, + float primaryRefreshRateMin, + float primaryRefreshRateMax, + float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken) { @@ -6158,34 +6154,34 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs( auto future = schedule([=]() -> status_t { const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); if (!display) { - ALOGE("Attempt to set desired display configs for invalid display token %p", + ALOGE("Attempt to set desired display modes for invalid display token %p", displayToken.get()); return NAME_NOT_FOUND; } else if (display->isVirtual()) { - ALOGW("Attempt to set desired display configs for virtual display"); + ALOGW("Attempt to set desired display modes for virtual display"); return INVALID_OPERATION; } else { using Policy = scheduler::RefreshRateConfigs::Policy; - const Policy policy{DisplayModeId(defaultConfig), + const Policy policy{DisplayModeId(defaultMode), allowGroupSwitching, {Fps(primaryRefreshRateMin), Fps(primaryRefreshRateMax)}, {Fps(appRequestRefreshRateMin), Fps(appRequestRefreshRateMax)}}; constexpr bool kOverridePolicy = false; - return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); + return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy); } }); return future.get(); } -status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( - const sp& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching, +status_t SurfaceFlinger::getDesiredDisplayModeSpecs( + const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { ATRACE_CALL(); - if (!displayToken || !outDefaultConfig || !outPrimaryRefreshRateMin || + if (!displayToken || !outDefaultMode || !outPrimaryRefreshRateMin || !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) { return BAD_VALUE; } @@ -6199,7 +6195,7 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( if (display->isPrimary()) { scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy(); - *outDefaultConfig = policy.defaultConfig.value(); + *outDefaultMode = policy.defaultMode.value(); *outAllowGroupSwitching = policy.allowGroupSwitching; *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); @@ -6210,7 +6206,7 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( return INVALID_OPERATION; } else { const auto activeMode = display->getActiveMode(); - *outDefaultConfig = activeMode->getId().value(); + *outDefaultMode = activeMode->getId().value(); *outAllowGroupSwitching = false; auto vsyncPeriod = activeMode->getVsyncPeriod(); *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); @@ -6340,16 +6336,15 @@ status_t SurfaceFlinger::acquireFrameRateFlexibilityToken(sp* outToken) const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); // This is a little racy, but not in a way that hurts anything. As we grab the - // defaultConfig from the display manager policy, we could be setting a new display - // manager policy, leaving us using a stale defaultConfig. The defaultConfig doesn't + // defaultMode from the display manager policy, we could be setting a new display + // manager policy, leaving us using a stale defaultMode. The defaultMode doesn't // matter for the override policy though, since we set allowGroupSwitching to // true, so it's not a problem. scheduler::RefreshRateConfigs::Policy overridePolicy; - overridePolicy.defaultConfig = - mRefreshRateConfigs->getDisplayManagerPolicy().defaultConfig; + overridePolicy.defaultMode = mRefreshRateConfigs->getDisplayManagerPolicy().defaultMode; overridePolicy.allowGroupSwitching = true; constexpr bool kOverridePolicy = true; - result = setDesiredDisplayConfigSpecsInternal(display, overridePolicy, kOverridePolicy); + result = setDesiredDisplayModeSpecsInternal(display, overridePolicy, kOverridePolicy); } if (result == NO_ERROR) { @@ -6389,7 +6384,7 @@ void SurfaceFlinger::onFrameRateFlexibilityTokenReleased() { if (mFrameRateFlexibilityTokenCount == 0) { const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); constexpr bool kOverridePolicy = true; - status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy); + status_t result = setDesiredDisplayModeSpecsInternal(display, {}, kOverridePolicy); LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token"); } })); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 66fc4f0d18..4f00491c89 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -414,12 +414,12 @@ private: void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const; }; - struct ActiveConfigInfo { - DisplayModeId configId; - Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None; + struct ActiveModeInfo { + DisplayModeId modeId; + Scheduler::ModeEvent event = Scheduler::ModeEvent::None; - bool operator!=(const ActiveConfigInfo& other) const { - return configId != other.configId || event != other.event; + bool operator!=(const ActiveModeInfo& other) const { + return modeId != other.modeId || event != other.event; } }; @@ -554,8 +554,8 @@ private: status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats) override; status_t getDisplayState(const sp& displayToken, ui::DisplayState*) override; status_t getDisplayInfo(const sp& displayToken, DisplayInfo*) override; - status_t getDisplayConfigs(const sp& displayToken, Vector*) override; - int getActiveConfig(const sp& displayToken) override; + status_t getDisplayModes(const sp& displayToken, Vector*) override; + int getActiveDisplayModeId(const sp& displayToken) override; status_t getDisplayColorModes(const sp& displayToken, Vector*) override; status_t getDisplayNativePrimaries(const sp& displayToken, ui::DisplayPrimaries&) override; @@ -594,17 +594,16 @@ private: status_t addRegionSamplingListener(const Rect& samplingArea, const sp& stopLayerHandle, const sp& listener) override; status_t removeRegionSamplingListener(const sp& listener) override; - status_t setDesiredDisplayConfigSpecs(const sp& displayToken, int32_t displayModeId, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) override; - status_t getDesiredDisplayConfigSpecs(const sp& displayToken, - int32_t* outDefaultConfig, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, - float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, - float* outAppRequestRefreshRateMax) override; + status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t displayModeId, + bool allowGroupSwitching, float primaryRefreshRateMin, + float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) override; + status_t getDesiredDisplayModeSpecs(const sp& displayToken, size_t* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) override; status_t getDisplayBrightnessSupport(const sp& displayToken, bool* outSupport) const override; status_t setDisplayBrightness(const sp& displayToken, float brightness) override; @@ -649,7 +648,7 @@ private: // Toggles hardware VSYNC by calling into HWC. void setVsyncEnabled(bool) override; // Initiates a refresh rate change to be applied on invalidate. - void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override; + void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override; // Forces full composition on all displays without resetting the scheduler idle timer. void repaintEverythingForHWC() override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. @@ -677,24 +676,24 @@ private: // Called on the main thread in response to initializeDisplays() void onInitializeDisplays() REQUIRES(mStateLock); - // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig. - void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock); - status_t setActiveConfig(const sp& displayToken, int id); - // Once HWC has returned the present fence, this sets the active config and a new refresh + // Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode. + void setDesiredActiveMode(const ActiveModeInfo& info) REQUIRES(mStateLock); + status_t setActiveMode(const sp& displayToken, int id); + // Once HWC has returned the present fence, this sets the active mode and a new refresh // rate in SF. - void setActiveConfigInternal() REQUIRES(mStateLock); - // Calls to setActiveConfig on the main thread if there is a pending config + void setActiveModeInternal() REQUIRES(mStateLock); + // Calls to setActiveMode on the main thread if there is a pending mode change // that needs to be applied. - void performSetActiveConfig() REQUIRES(mStateLock); - void clearDesiredActiveConfigState() REQUIRES(mStateLock) EXCLUDES(mActiveConfigLock); - // Called when active config is no longer is progress - void desiredActiveConfigChangeDone() REQUIRES(mStateLock); + void performSetActiveMode() REQUIRES(mStateLock); + void clearDesiredActiveModeState() REQUIRES(mStateLock) EXCLUDES(mActiveModeLock); + // Called when active mode is no longer is progress + void desiredActiveModeChangeDone() REQUIRES(mStateLock); // Called on the main thread in response to setPowerMode() void setPowerModeInternal(const sp& display, hal::PowerMode mode) REQUIRES(mStateLock); - // Sets the desired display configs. - status_t setDesiredDisplayConfigSpecsInternal( + // Sets the desired display mode specs. + status_t setDesiredDisplayModeSpecsInternal( const sp& display, const std::optional& policy, bool overridePolicy) EXCLUDES(mStateLock); @@ -927,9 +926,9 @@ private: // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. - void changeRefreshRateLocked(const RefreshRate&, Scheduler::ConfigEvent) REQUIRES(mStateLock); + void changeRefreshRateLocked(const RefreshRate&, Scheduler::ModeEvent) REQUIRES(mStateLock); - bool isDisplayConfigAllowed(DisplayModeId configId) const REQUIRES(mStateLock); + bool isDisplayModeAllowed(DisplayModeId) const REQUIRES(mStateLock); // Gets the fence for the previous frame. // Must be called on the main thread. @@ -1045,9 +1044,9 @@ private: * Misc */ - std::optional getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) { - std::lock_guard lock(mActiveConfigLock); - if (mDesiredActiveConfigChanged) return mDesiredActiveConfig; + std::optional getDesiredActiveMode() EXCLUDES(mActiveModeLock) { + std::lock_guard lock(mActiveModeLock); + if (mDesiredActiveModeChanged) return mDesiredActiveMode; return std::nullopt; } @@ -1244,18 +1243,18 @@ private: nsecs_t mScheduledPresentTime = 0; hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE; - std::mutex mActiveConfigLock; - // This bit is set once we start setting the config. We read from this bit during the - // process. If at the end, this bit is different than mDesiredActiveConfig, we restart + std::mutex mActiveModeLock; + // This bit is set once we start setting the mode. We read from this bit during the + // process. If at the end, this bit is different than mDesiredActiveMode, we restart // the process. - ActiveConfigInfo mUpcomingActiveConfig; // Always read and written on the main thread. - // This bit can be set at any point in time when the system wants the new config. - ActiveConfigInfo mDesiredActiveConfig GUARDED_BY(mActiveConfigLock); + ActiveModeInfo mUpcomingActiveMode; // Always read and written on the main thread. + // This bit can be set at any point in time when the system wants the new mode. + ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock); // below flags are set by main thread only - TracedOrdinal mDesiredActiveConfigChanged - GUARDED_BY(mActiveConfigLock) = {"DesiredActiveConfigChanged", false}; - bool mSetActiveConfigPending = false; + TracedOrdinal mDesiredActiveModeChanged + GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false}; + bool mSetActiveModePending = false; bool mLumaSampling = true; sp mRegionSamplingThread; @@ -1279,8 +1278,8 @@ private: void enableRefreshRateOverlay(bool enable); std::unique_ptr mRefreshRateOverlay GUARDED_BY(mStateLock); - // Flag used to set override allowed display configs from backdoor - bool mDebugDisplayConfigSetByBackdoor = false; + // Flag used to set override desired display mode from backdoor + bool mDebugDisplayModeSetByBackdoor = false; // A set of layers that have no parent so they are not drawn on screen. // Should only be accessed by the main thread. diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 9302463190..53e37d874e 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include #include "utils/ScreenshotUtils.h" @@ -81,14 +81,13 @@ protected: mDisplay = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_FALSE(mDisplay == nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config)); + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode)); // Background surface - mBGSurfaceControl = - mComposerClient->createSurface(SURFACE_NAME, config.resolution.getWidth(), - config.resolution.getHeight(), - PIXEL_FORMAT_RGBA_8888, 0); + mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(), + mode.resolution.getHeight(), + PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(mBGSurfaceControl != nullptr); ASSERT_TRUE(mBGSurfaceControl->isValid()); @@ -185,13 +184,13 @@ TEST_F(CredentialsTest, AllowedGetterMethodsTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_TRUE(display != nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - Vector configs; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); + Vector modes; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); - ASSERT_TRUE(SurfaceComposerClient::getActiveConfig(display) >= 0); + ASSERT_TRUE(SurfaceComposerClient::getActiveDisplayModeId(display) >= 0); ASSERT_NE(static_cast(BAD_VALUE), SurfaceComposerClient::getActiveColorMode(display)); @@ -217,25 +216,23 @@ TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) { TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); - int32_t defaultConfig; + size_t defaultMode; bool allowGroupSwitching; float primaryFpsMin; float primaryFpsMax; float appRequestFpsMin; float appRequestFpsMax; status_t res = - SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig, - &allowGroupSwitching, - &primaryFpsMin, &primaryFpsMax, - &appRequestFpsMin, - &appRequestFpsMax); + SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &defaultMode, + &allowGroupSwitching, &primaryFpsMin, + &primaryFpsMax, &appRequestFpsMin, + &appRequestFpsMax); ASSERT_EQ(res, NO_ERROR); std::function condition = [=]() { - return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig, - allowGroupSwitching, - primaryFpsMin, primaryFpsMax, - appRequestFpsMin, - appRequestFpsMax); + return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, defaultMode, + allowGroupSwitching, primaryFpsMin, + primaryFpsMax, appRequestFpsMin, + appRequestFpsMax); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, PERMISSION_DENIED)); } diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 55b317382e..9f025a6aaa 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -38,7 +38,7 @@ namespace android { */ class RefreshRateRangeTest : public ::testing::Test { private: - int32_t initialDefaultConfig; + size_t initialDefaultMode; bool initialAllowGroupSwitching; float initialPrimaryMin; float initialPrimaryMax; @@ -49,25 +49,24 @@ protected: void SetUp() override { mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); status_t res = - SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, - &initialDefaultConfig, - &initialAllowGroupSwitching, - &initialPrimaryMin, - &initialPrimaryMax, - &initialAppRequestMin, - &initialAppRequestMax); + SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, + &initialDefaultMode, + &initialAllowGroupSwitching, + &initialPrimaryMin, + &initialPrimaryMax, + &initialAppRequestMin, + &initialAppRequestMax); ASSERT_EQ(res, NO_ERROR); } void TearDown() override { status_t res = - SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, - initialDefaultConfig, - initialAllowGroupSwitching, - initialPrimaryMin, - initialPrimaryMax, - initialAppRequestMin, - initialAppRequestMax); + SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, initialDefaultMode, + initialAllowGroupSwitching, + initialPrimaryMin, + initialPrimaryMax, + initialAppRequestMin, + initialAppRequestMax); ASSERT_EQ(res, NO_ERROR); } @@ -77,60 +76,59 @@ protected: }; TEST_F(RefreshRateRangeTest, setAllConfigs) { - Vector configs; - status_t res = SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &configs); + Vector modes; + status_t res = SurfaceComposerClient::getDisplayModes(mDisplayToken, &modes); ASSERT_EQ(res, NO_ERROR); - ASSERT_GT(configs.size(), 0); - - for (size_t i = 0; i < configs.size(); i++) { - res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, - static_cast(i), false, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate); + ASSERT_GT(modes.size(), 0); + + for (size_t i = 0; i < modes.size(); i++) { + res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, i, false, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate); ASSERT_EQ(res, NO_ERROR); - int defaultConfig; + size_t defaultConfig; bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; float appRequestRefreshRateMin; float appRequestRefreshRateMax; - res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, - &allowGroupSwitching, - &primaryRefreshRateMin, - &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig, + &allowGroupSwitching, + &primaryRefreshRateMin, + &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); ASSERT_EQ(res, NO_ERROR); ASSERT_EQ(defaultConfig, i); ASSERT_EQ(allowGroupSwitching, false); - ASSERT_EQ(primaryRefreshRateMin, configs[i].refreshRate); - ASSERT_EQ(primaryRefreshRateMax, configs[i].refreshRate); - ASSERT_EQ(appRequestRefreshRateMin, configs[i].refreshRate); - ASSERT_EQ(appRequestRefreshRateMax, configs[i].refreshRate); + ASSERT_EQ(primaryRefreshRateMin, modes[i].refreshRate); + ASSERT_EQ(primaryRefreshRateMax, modes[i].refreshRate); + ASSERT_EQ(appRequestRefreshRateMin, modes[i].refreshRate); + ASSERT_EQ(appRequestRefreshRateMax, modes[i].refreshRate); } } void RefreshRateRangeTest::testSetAllowGroupSwitching(bool allowGroupSwitching) { - status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 0, - allowGroupSwitching, 0.f, - 90.f, 0.f, 90.f); + status_t res = + SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, 0, allowGroupSwitching, + 0.f, 90.f, 0.f, 90.f); ASSERT_EQ(res, NO_ERROR); - int defaultConfig; + size_t defaultConfig; bool newAllowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; float appRequestRefreshRateMin; float appRequestRefreshRateMax; - res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig, - &newAllowGroupSwitching, - &primaryRefreshRateMin, - &primaryRefreshRateMax, - &appRequestRefreshRateMin, - &appRequestRefreshRateMax); + res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig, + &newAllowGroupSwitching, + &primaryRefreshRateMin, + &primaryRefreshRateMax, + &appRequestRefreshRateMin, + &appRequestRefreshRateMax); ASSERT_EQ(res, NO_ERROR); ASSERT_EQ(defaultConfig, 0); ASSERT_EQ(newAllowGroupSwitching, allowGroupSwitching); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 4023c66e52..a8647c3e50 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -227,10 +227,10 @@ public: ASSERT_EQ(NO_ERROR, mClient->initCheck()); mPrimaryDisplay = mClient->getInternalDisplayToken(); - DisplayConfig config; - mClient->getActiveDisplayConfig(mPrimaryDisplay, &config); - mDisplayWidth = config.resolution.getWidth(); - mDisplayHeight = config.resolution.getHeight(); + ui::DisplayMode mode; + mClient->getActiveDisplayMode(mPrimaryDisplay, &mode); + mDisplayWidth = mode.resolution.getWidth(); + mDisplayHeight = mode.resolution.getHeight(); Transaction setupTransaction; setupTransaction.setDisplayLayerStack(mPrimaryDisplay, 0); diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 67585185f9..eba2c250a5 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "BufferGenerator.h" #include "utils/ScreenshotUtils.h" @@ -265,16 +265,16 @@ private: mDisplay = mClient->getInternalDisplayToken(); ASSERT_FALSE(mDisplay == nullptr) << "failed to get display"; - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config)); - mDisplayRect = Rect(config.resolution); + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode)); + mDisplayRect = Rect(mode.resolution); mDisplayWidth = mDisplayRect.getWidth(); mDisplayHeight = mDisplayRect.getHeight(); // After a new buffer is queued, SurfaceFlinger is notified and will // latch the new buffer on next vsync. Let's heuristically wait for 3 // vsyncs. - mBufferPostDelay = static_cast(1e6 / config.refreshRate) * 3; + mBufferPostDelay = static_cast(1e6 / mode.refreshRate) * 3; mDisplayLayerStack = 0; diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index 6c56d209d4..ec826aed9c 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -36,9 +36,9 @@ protected: const auto display = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - const ui::Size& resolution = config.resolution; + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + const ui::Size& resolution = mode.resolution; // Background surface mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(), diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp index db0c56f6aa..eaf54e38ec 100644 --- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp +++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp @@ -37,13 +37,13 @@ protected: mMainDisplay = SurfaceComposerClient::getInternalDisplayToken(); SurfaceComposerClient::getDisplayState(mMainDisplay, &mMainDisplayState); - SurfaceComposerClient::getActiveDisplayConfig(mMainDisplay, &mMainDisplayConfig); + SurfaceComposerClient::getActiveDisplayMode(mMainDisplay, &mMainDisplayMode); sp consumer; BufferQueue::createBufferQueue(&mProducer, &consumer); consumer->setConsumerName(String8("Virtual disp consumer")); - consumer->setDefaultBufferSize(mMainDisplayConfig.resolution.getWidth(), - mMainDisplayConfig.resolution.getHeight()); + consumer->setDefaultBufferSize(mMainDisplayMode.resolution.getWidth(), + mMainDisplayMode.resolution.getHeight()); } virtual void TearDown() { @@ -59,7 +59,7 @@ protected: t.setDisplaySurface(mVirtualDisplay, mProducer); t.setDisplayLayerStack(mVirtualDisplay, layerStack); t.setDisplayProjection(mVirtualDisplay, mMainDisplayState.orientation, - Rect(layerStackSize), Rect(mMainDisplayConfig.resolution)); + Rect(layerStackSize), Rect(mMainDisplayMode.resolution)); }); } @@ -81,7 +81,7 @@ protected: } ui::DisplayState mMainDisplayState; - DisplayConfig mMainDisplayConfig; + ui::DisplayMode mMainDisplayMode; sp mMainDisplay; sp mVirtualDisplay; sp mProducer; diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 51ce1d3ff9..4598f9dc84 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -33,9 +33,9 @@ protected: const auto display = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - const ui::Size& resolution = config.resolution; + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + const ui::Size& resolution = mode.resolution; // Background surface mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(), diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index fa88ca5c57..a20d5c62d5 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include @@ -267,9 +267,9 @@ void SurfaceInterceptorTest::setupBackgroundSurface() { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - const ui::Size& resolution = config.resolution; + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + const ui::Size& resolution = mode.resolution; // Background surface mBGSurfaceControl = diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h index 33823d7057..89f608645d 100644 --- a/services/surfaceflinger/tests/TransactionTestHarnesses.h +++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h @@ -40,9 +40,9 @@ public: ui::DisplayState displayState; SurfaceComposerClient::getDisplayState(displayToken, &displayState); - DisplayConfig displayConfig; - SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig); - const ui::Size& resolution = displayConfig.resolution; + ui::DisplayMode displayMode; + SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode); + const ui::Size& resolution = displayMode.resolution; sp vDisplay; sp producer; diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index efa15f1f73..56e1ae90c3 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include @@ -243,9 +243,8 @@ protected: mComposerClient = new SurfaceComposerClient; ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); - mReceiver.reset( - new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp, - ISurfaceComposer::EventRegistration::configChanged)); + mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp, + ISurfaceComposer::EventRegistration::modeChanged)); mLooper = new Looper(false); mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this); } @@ -305,7 +304,7 @@ protected: return false; } - bool waitForConfigChangedEvent(Display display, int32_t configId) { + bool waitForModeChangedEvent(Display display, int32_t modeId) { PhysicalDisplayId displayId(display); int waitCount = 20; while (waitCount--) { @@ -313,12 +312,12 @@ protected: auto event = mReceivedDisplayEvents.front(); mReceivedDisplayEvents.pop_front(); - ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, - "event config: displayId %s, configId %d", - to_string(event.header.displayId).c_str(), event.config.configId); + ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, + "event mode: displayId %s, modeId %d", + to_string(event.header.displayId).c_str(), event.modeChange.modeId); - if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED && - event.header.displayId == displayId && event.config.configId == configId) { + if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE && + event.header.displayId == displayId && event.modeChange.modeId == modeId) { return true; } } @@ -348,11 +347,11 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); EXPECT_FALSE(display == nullptr); - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - const ui::Size& resolution = config.resolution; + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + const ui::Size& resolution = mode.resolution; EXPECT_EQ(ui::Size(200, 400), resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), @@ -380,8 +379,8 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); EXPECT_TRUE(display == nullptr); - DisplayConfig config; - EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + ui::DisplayMode mode; + EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); } } @@ -409,14 +408,14 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); EXPECT_FALSE(display == nullptr); - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(200, 400), config.resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(200, 400), mode.resolution); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -433,11 +432,11 @@ protected: } } - Vector configs; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); - EXPECT_EQ(configs.size(), 2); + Vector modes; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + EXPECT_EQ(modes.size(), 2); - // change active config + // change active mode if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 2, _, _)) @@ -447,28 +446,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < configs.size(); i++) { - const auto& config = configs[i]; - if (config.resolution.getWidth() == 800) { + for (int i = 0; i < modes.size(); i++) { + const auto& mode = modes[i]; + if (mode.resolution.getWidth() == 800) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, - config.refreshRate, - config.refreshRate, - config.refreshRate, - config.refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate)); waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); + EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -516,14 +515,14 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); EXPECT_FALSE(display == nullptr); - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -540,11 +539,11 @@ protected: } } - Vector configs; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); - EXPECT_EQ(configs.size(), 2); + Vector modes; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + EXPECT_EQ(modes.size(), 2); - // change active config + // change active mode if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -553,28 +552,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < configs.size(); i++) { - const auto& config = configs[i]; - if (config.refreshRate == 1e9f / 11'111'111) { + for (int i = 0; i < modes.size(); i++) { + const auto& mode = modes[i]; + if (mode.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, - config.refreshRate, - config.refreshRate, - config.refreshRate, - config.refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate)); waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); + EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -632,14 +631,14 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId); EXPECT_FALSE(display == nullptr); - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -656,11 +655,11 @@ protected: } } - Vector configs; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); - EXPECT_EQ(configs.size(), 4); + Vector modes; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + EXPECT_EQ(modes.size(), 4); - // change active config to 800x1600@90Hz + // change active mode to 800x1600@90Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -669,29 +668,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (size_t i = 0; i < configs.size(); i++) { - const auto& config = configs[i]; - if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) { + for (size_t i = 0; i < modes.size(); i++) { + const auto& mode = modes[i]; + if (mode.resolution.getWidth() == 800 && mode.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient:: - setDesiredDisplayConfigSpecs(display, i, false, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate)); waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); + EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -708,7 +706,7 @@ protected: } } - // change active config to 1600x3200@120Hz + // change active mode to 1600x3200@120Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 4, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -717,28 +715,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < configs.size(); i++) { - const auto& config = configs[i]; - if (config.refreshRate == 1e9f / 8'333'333) { + for (int i = 0; i < modes.size(); i++) { + const auto& mode = modes[i]; + if (mode.refreshRate == 1e9f / 8'333'333) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, - config.refreshRate, - config.refreshRate, - config.refreshRate, - config.refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate)); waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); + EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(1600, 3200), config.resolution); - EXPECT_EQ(1e9f / 8'333'333, config.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(1600, 3200), mode.resolution); + EXPECT_EQ(1e9f / 8'333'333, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -755,7 +753,7 @@ protected: } } - // change active config to 1600x3200@90Hz + // change active mode to 1600x3200@90Hz if (mIs2_4Client) { EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 5, _, _)) .WillOnce(Return(V2_4::Error::NONE)); @@ -764,28 +762,28 @@ protected: .WillOnce(Return(V2_1::Error::NONE)); } - for (int i = 0; i < configs.size(); i++) { - const auto& config = configs[i]; - if (config.resolution.getWidth() == 1600 && config.refreshRate == 1e9f / 11'111'111) { + for (int i = 0; i < modes.size(); i++) { + const auto& mode = modes[i]; + if (mode.resolution.getWidth() == 1600 && mode.refreshRate == 1e9f / 11'111'111) { EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, - config.refreshRate, - config.refreshRate, - config.refreshRate, - config.refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate, + mode.refreshRate)); waitForDisplayTransaction(EXTERNAL_DISPLAY); - EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i)); + EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i)); break; } } - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(1600, 3200), config.resolution); - EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(1600, 3200), mode.resolution); + EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); mFakeComposerClient->clearFrames(); { - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; auto surfaceControl = mComposerClient->createSurface(String8("Display Test Surface Foo"), resolution.getWidth(), resolution.getHeight(), @@ -822,8 +820,8 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); EXPECT_TRUE(display == nullptr); - DisplayConfig config; - auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config); + ui::DisplayMode mode; + auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode); EXPECT_NE(NO_ERROR, result); } @@ -848,11 +846,11 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); EXPECT_FALSE(display == nullptr); - DisplayConfig config; - auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config); + ui::DisplayMode mode; + auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode); EXPECT_EQ(NO_ERROR, result); - ASSERT_EQ(ui::Size(400, 200), config.resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + ASSERT_EQ(ui::Size(400, 200), mode.resolution); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); } } @@ -881,14 +879,14 @@ protected: // Verify that the active mode and the supported moded are updated { - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 11'111'111, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); - Vector configs; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); - EXPECT_EQ(configs.size(), 1); + Vector modes; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + EXPECT_EQ(modes.size(), 1); } // Send another hotplug connected event @@ -919,27 +917,27 @@ protected: // Verify that the active mode and the supported moded are updated { - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(1e9f / 16'666'666, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); } - Vector configs; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs)); - EXPECT_EQ(configs.size(), 3); + Vector modes; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + EXPECT_EQ(modes.size(), 3); - EXPECT_EQ(ui::Size(800, 1600), configs[0].resolution); - EXPECT_EQ(1e9f / 16'666'666, configs[0].refreshRate); + EXPECT_EQ(ui::Size(800, 1600), modes[0].resolution); + EXPECT_EQ(1e9f / 16'666'666, modes[0].refreshRate); - EXPECT_EQ(ui::Size(800, 1600), configs[1].resolution); - EXPECT_EQ(1e9f / 11'111'111, configs[1].refreshRate); + EXPECT_EQ(ui::Size(800, 1600), modes[1].resolution); + EXPECT_EQ(1e9f / 11'111'111, modes[1].refreshRate); - EXPECT_EQ(ui::Size(800, 1600), configs[2].resolution); - EXPECT_EQ(1e9f / 8'333'333, configs[2].refreshRate); + EXPECT_EQ(ui::Size(800, 1600), modes[2].resolution); + EXPECT_EQ(1e9f / 8'333'333, modes[2].refreshRate); // Verify that we are able to switch to any of the modes - for (int i = configs.size() - 1; i >= 0; i--) { + for (int i = modes.size() - 1; i >= 0; i--) { const auto hwcId = i + 1; // Set up HWC expectations for the mode change if (mIs2_4Client) { @@ -952,22 +950,22 @@ protected: } EXPECT_EQ(NO_ERROR, - SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate, - configs[i].refreshRate)); + SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate, + modes[i].refreshRate)); // We need to refresh twice - once to apply the pending mode change request, // and once to process the change. waitForDisplayTransaction(hwcDisplayId); waitForDisplayTransaction(hwcDisplayId); - EXPECT_TRUE(waitForConfigChangedEvent(hwcDisplayId, i)) + EXPECT_TRUE(waitForModeChangedEvent(hwcDisplayId, i)) << "Failure while switching to mode " << i; - DisplayConfig config; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); - EXPECT_EQ(ui::Size(800, 1600), config.resolution); - EXPECT_EQ(configs[i].refreshRate, config.refreshRate); + ui::DisplayMode mode; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); + EXPECT_EQ(ui::Size(800, 1600), mode.resolution); + EXPECT_EQ(modes[i].refreshRate, mode.refreshRate); } } @@ -1168,10 +1166,10 @@ protected: const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId); ASSERT_FALSE(display == nullptr); - DisplayConfig config; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config)); + ui::DisplayMode mode; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); - const ui::Size& resolution = config.resolution; + const ui::Size& resolution = mode.resolution; mDisplayWidth = resolution.getWidth(); mDisplayHeight = resolution.getHeight(); diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 45bc29cabb..7cc0032bc8 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -141,10 +141,10 @@ EventThreadTest::EventThreadTest() { createThread(std::move(vsyncSource)); mConnection = createConnection(mConnectionEventCallRecorder, - ISurfaceComposer::EventRegistration::configChanged | + ISurfaceComposer::EventRegistration::modeChanged | ISurfaceComposer::EventRegistration::frameRateOverride); mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder, - ISurfaceComposer::EventRegistration::configChanged, + ISurfaceComposer::EventRegistration::modeChanged, mThrottledConnectionUid); // A display must be connected for VSYNC events to be delivered. @@ -257,10 +257,10 @@ void EventThreadTest::expectConfigChangedEventReceivedByConnection( auto args = mConnectionEventCallRecorder.waitForCall(); ASSERT_TRUE(args.has_value()); const auto& event = std::get<0>(args.value()); - EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, event.header.type); + EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, event.header.type); EXPECT_EQ(expectedDisplayId, event.header.displayId); - EXPECT_EQ(expectedConfigId, event.config.configId); - EXPECT_EQ(expectedVsyncPeriod, event.config.vsyncPeriod); + EXPECT_EQ(expectedConfigId, event.modeChange.modeId); + EXPECT_EQ(expectedVsyncPeriod, event.modeChange.vsyncPeriod); } void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection( @@ -540,17 +540,17 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) { } TEST_F(EventThreadTest, postConfigChangedPrimary) { - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666); + mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666); } TEST_F(EventThreadTest, postConfigChangedExternal) { - mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666); + mThread->onModeChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666); expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666); } TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { - mThread->onConfigChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666); + mThread->onModeChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666); expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666); } @@ -559,7 +559,7 @@ TEST_F(EventThreadTest, suppressConfigChanged) { sp suppressConnection = createConnection(suppressConnectionEventRecorder); - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666); + mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666); auto args = suppressConnectionEventRecorder.waitForCall(); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 04cafbca72..fec590ee4c 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -113,12 +113,12 @@ protected: RefreshRateConfigs mConfigs{{DisplayMode::Builder(0) .setId(DisplayModeId(0)) .setVsyncPeriod(int32_t(LO_FPS_PERIOD)) - .setConfigGroup(0) + .setGroup(0) .build(), DisplayMode::Builder(1) .setId(DisplayModeId(1)) .setVsyncPeriod(int32_t(HI_FPS_PERIOD)) - .setConfigGroup(0) + .setGroup(0) .build()}, DisplayModeId(0)}; diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp index d5c9b57c6e..be76e8fd2f 100644 --- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp @@ -53,7 +53,7 @@ TEST_F(LayerInfoTest, prefersPresentTime) { for (int i = 1; i <= kNumFrames; i++) { frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i, .queueTime = 0, - .pendingConfigChange = false}); + .pendingModeChange = false}); } setFrameTimes(frameTimes); const auto averageFrameTime = calculateAverageFrameTime(); @@ -71,7 +71,7 @@ TEST_F(LayerInfoTest, fallbacksToQueueTimeIfNoPresentTime) { for (int i = 1; i <= kNumFrames; i++) { frameTimes.push_back(FrameTimeData{.presentTime = 0, .queueTime = kPeriod * i, - .pendingConfigChange = false}); + .pendingModeChange = false}); } setFrameTimes(frameTimes); setLastRefreshRate(Fps(20.0f)); // Set to some valid value @@ -89,7 +89,7 @@ TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) { for (int i = 1; i <= kNumFrames; i++) { frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i, .queueTime = period * i, - .pendingConfigChange = false}); + .pendingModeChange = false}); } setFrameTimes(frameTimesWithoutConfigChange); @@ -98,7 +98,7 @@ TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) { { // Config change in the first record auto frameTimes = frameTimesWithoutConfigChange; - frameTimes[0].pendingConfigChange = true; + frameTimes[0].pendingModeChange = true; setFrameTimes(frameTimes); ASSERT_FALSE(calculateAverageFrameTime().has_value()); } @@ -106,7 +106,7 @@ TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) { { // Config change in the last record auto frameTimes = frameTimesWithoutConfigChange; - frameTimes[frameTimes.size() - 1].pendingConfigChange = true; + frameTimes[frameTimes.size() - 1].pendingModeChange = true; setFrameTimes(frameTimes); ASSERT_FALSE(calculateAverageFrameTime().has_value()); } @@ -114,7 +114,7 @@ TEST_F(LayerInfoTest, returnsNulloptIfThereWasConfigChange) { { // Config change in the middle auto frameTimes = frameTimesWithoutConfigChange; - frameTimes[frameTimes.size() / 2].pendingConfigChange = true; + frameTimes[frameTimes.size() / 2].pendingModeChange = true; setFrameTimes(frameTimes); ASSERT_FALSE(calculateAverageFrameTime().has_value()); } @@ -131,12 +131,12 @@ TEST_F(LayerInfoTest, ignoresSmallPeriods) { for (int i = 1; i <= kNumIterations; i++) { frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i, .queueTime = 0, - .pendingConfigChange = false}); + .pendingModeChange = false}); // A duplicate frame frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod, .queueTime = 0, - .pendingConfigChange = false}); + .pendingModeChange = false}); } setFrameTimes(frameTimes); const auto averageFrameTime = calculateAverageFrameTime(); @@ -156,7 +156,7 @@ TEST_F(LayerInfoTest, ignoresLargePeriods) { auto record = [&](nsecs_t time) { frameTimes.push_back( - FrameTimeData{.presentTime = time, .queueTime = 0, .pendingConfigChange = false}); + FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false}); }; auto time = kExpectedPeriod; // Start with non-zero time. diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 738ded18ac..376995f79e 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -81,24 +81,25 @@ protected: static inline const DisplayModeId HWC_CONFIG_ID_50 = DisplayModeId(6); // Test configs - DisplayModePtr mConfig60 = createConfig(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs()); - DisplayModePtr mConfig90 = createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs()); + DisplayModePtr mConfig60 = createDisplayMode(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs()); + DisplayModePtr mConfig90 = createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs()); DisplayModePtr mConfig90DifferentGroup = - createConfig(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs()); DisplayModePtr mConfig90DifferentResolution = - createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), ui::Size(111, 222)); - DisplayModePtr mConfig72 = createConfig(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), ui::Size(111, 222)); + DisplayModePtr mConfig72 = createDisplayMode(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs()); DisplayModePtr mConfig72DifferentGroup = - createConfig(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs()); - DisplayModePtr mConfig120 = createConfig(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs()); + DisplayModePtr mConfig120 = + createDisplayMode(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs()); DisplayModePtr mConfig120DifferentGroup = - createConfig(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs()); - DisplayModePtr mConfig30 = createConfig(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs()); + DisplayModePtr mConfig30 = createDisplayMode(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs()); DisplayModePtr mConfig30DifferentGroup = - createConfig(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs()); DisplayModePtr mConfig25DifferentGroup = - createConfig(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs()); - DisplayModePtr mConfig50 = createConfig(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs()); + createDisplayMode(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs()); + DisplayModePtr mConfig50 = createDisplayMode(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs()); // Test device configurations // The positions of the configs in the arrays below MUST match their IDs. For example, @@ -128,8 +129,8 @@ protected: RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60), RefreshRate::ConstructorTag(0)}; RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60, - createConfig(HWC_CONFIG_ID_60, 0, 16666665), Fps(60), - RefreshRate::ConstructorTag(0)}; + createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665), + Fps(60), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, Fps(90), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup, @@ -144,8 +145,8 @@ protected: RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120), RefreshRate::ConstructorTag(0)}; private: - DisplayModePtr createConfig(DisplayModeId configId, int32_t configGroup, int64_t vsyncPeriod, - ui::Size resolution = ui::Size()); + DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod, + ui::Size resolution = ui::Size()); }; using Builder = DisplayMode::Builder; @@ -162,12 +163,12 @@ RefreshRateConfigsTest::~RefreshRateConfigsTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } -DisplayModePtr RefreshRateConfigsTest::createConfig(DisplayModeId configId, int32_t configGroup, - int64_t vsyncPeriod, ui::Size resolution) { - return DisplayMode::Builder(hal::HWConfigId(configId.value())) - .setId(configId) +DisplayModePtr RefreshRateConfigsTest::createDisplayMode(DisplayModeId modeId, int32_t group, + int64_t vsyncPeriod, ui::Size resolution) { + return DisplayMode::Builder(hal::HWConfigId(modeId.value())) + .setId(modeId) .setVsyncPeriod(int32_t(vsyncPeriod)) - .setConfigGroup(configGroup) + .setGroup(group) .setHeight(resolution.height) .setWidth(resolution.width) .build(); @@ -226,7 +227,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), 0); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -252,7 +253,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), 0); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -288,20 +289,20 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { /*currentConfigId=*/HWC_CONFIG_ID_60); { auto current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_60); + EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_60); } - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); { auto current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); + EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_90); } ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), 0); { auto current = refreshRateConfigs->getCurrentRefreshRate(); - EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); + EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_90); } } @@ -1196,30 +1197,30 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); RefreshRateConfigs::Policy policy; - policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; + policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode; policy.allowGroupSwitching = true; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); // Verify that we won't change the group if seamless switch is required. layer.seamlessness = Seamlessness::OnlySeamless; ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); // Verify that we won't do a seamless switch if we request the same mode as the default - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); layer.desiredRefreshRate = Fps(60.0f); layer.name = "60Hz ExplicitDefault"; layer.seamlessness = Seamlessness::OnlySeamless; ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); // Verify that if the current config is in another group and there are no layers with // seamlessness=SeamedAndSeamless we'll go back to the default group. @@ -1228,11 +1229,11 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { layer.seamlessness = Seamlessness::Default; ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); // If there's a layer with seamlessness=SeamedAndSeamless, another layer with - // seamlessness=OnlySeamless can't change the config group. - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + // seamlessness=OnlySeamless can't change the mode group. + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); layer.seamlessness = Seamlessness::OnlySeamless; layers.push_back(LayerRequirement{.weight = 0.5f}); @@ -1245,14 +1246,14 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); // If there's a layer with seamlessness=SeamedAndSeamless, another layer with - // seamlessness=Default can't change the config group. + // seamlessness=Default can't change the mode group. layers[0].seamlessness = Seamlessness::Default; ASSERT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); } TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { @@ -1262,7 +1263,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { // Allow group switching. RefreshRateConfigs::Policy policy; - policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; + policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode; policy.allowGroupSwitching = true; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); @@ -1276,12 +1277,12 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { ASSERT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_120); ASSERT_EQ(HWC_CONFIG_ID_120, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); } TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { @@ -1291,7 +1292,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { // Allow group switching. RefreshRateConfigs::Policy policy; - policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig; + policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode; policy.allowGroupSwitching = true; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0); @@ -1312,14 +1313,14 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { ASSERT_EQ(HWC_CONFIG_ID_50, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = Fps(30.0f); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_30); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_30); ASSERT_EQ(HWC_CONFIG_ID_25, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); } TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { @@ -1338,7 +1339,7 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { layers[0].desiredRefreshRate = fps; layers[0].focused = focused; return refreshRateConfigs->getBestRefreshRate(layers, {.touch = touchActive, .idle = false}) - .getConfigId(); + .getModeId(); }; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( @@ -1346,7 +1347,7 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { 0); EXPECT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false}) - .getConfigId()); + .getModeId()); EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f))); EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, Fps(90.f))); EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f))); @@ -1398,7 +1399,7 @@ TEST_F(RefreshRateConfigsTest, idle) { refreshRateConfigs ->getBestRefreshRate(layers, {.touch = touchActive, .idle = true}, &consideredSignals) - .getConfigId(); + .getModeId(); // Refresh rate will be chosen by either touch state or idle state EXPECT_EQ(!touchActive, consideredSignals.idle); return configId; @@ -1421,10 +1422,10 @@ TEST_F(RefreshRateConfigsTest, idle) { // With no layers, idle should still be lower priority than touch boost. EXPECT_EQ(HWC_CONFIG_ID_90, refreshRateConfigs->getBestRefreshRate({}, {.touch = true, .idle = true}) - .getConfigId()); + .getModeId()); // Idle should be higher precedence than other layer frame rate considerations. - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, /*touchActive=*/false)); EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, /*touchActive=*/false)); EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, /*touchActive=*/false)); @@ -1437,7 +1438,7 @@ TEST_F(RefreshRateConfigsTest, idle) { // Idle should be applied rather than the current config when there are no layers. EXPECT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = true}) - .getConfigId()); + .getModeId()); } TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) { @@ -1628,19 +1629,19 @@ TEST_F(RefreshRateConfigsTest, getRefreshRateDivider) { const auto frameRate = Fps(30.f); EXPECT_EQ(1, refreshRateConfigs->getRefreshRateDivider(frameRate)); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_60); EXPECT_EQ(2, refreshRateConfigs->getRefreshRateDivider(frameRate)); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_72); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_72); EXPECT_EQ(0, refreshRateConfigs->getRefreshRateDivider(frameRate)); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); EXPECT_EQ(3, refreshRateConfigs->getRefreshRateDivider(frameRate)); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_120); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(frameRate)); - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.5f))); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f))); } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index ceccd81f7a..bf07106afd 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -53,7 +53,7 @@ protected: mRefreshRateConfigs = std::make_unique(configs, /*currentConfig=*/CONFIG_ID_0); - const auto currFps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); + const auto currFps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps(); mRefreshRateStats = std::make_unique(mTimeStats, currFps, /*currentPowerMode=*/PowerMode::OFF); } @@ -62,7 +62,7 @@ protected: std::unique_ptr mRefreshRateConfigs; std::unique_ptr mRefreshRateStats; - DisplayModePtr createConfig(DisplayModeId configId, int32_t configGroup, int64_t vsyncPeriod); + DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod); }; RefreshRateStatsTest::RefreshRateStatsTest() { @@ -77,12 +77,12 @@ RefreshRateStatsTest::~RefreshRateStatsTest() { ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } -DisplayModePtr RefreshRateStatsTest::createConfig(DisplayModeId configId, int32_t configGroup, - int64_t vsyncPeriod) { - return DisplayMode::Builder(static_cast(configId.value())) - .setId(configId) +DisplayModePtr RefreshRateStatsTest::createDisplayMode(DisplayModeId modeId, int32_t group, + int64_t vsyncPeriod) { + return DisplayMode::Builder(static_cast(modeId.value())) + .setId(modeId) .setVsyncPeriod(static_cast(vsyncPeriod)) - .setConfigGroup(configGroup) + .setGroup(group) .build(); } @@ -91,7 +91,7 @@ namespace { * Test cases */ TEST_F(RefreshRateStatsTest, oneConfigTest) { - init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)}); + init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1)); @@ -110,7 +110,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(0u, times.count("90.00fps")); - const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); + const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps(); mRefreshRateStats->setRefreshRate(config0Fps); mRefreshRateStats->setPowerMode(PowerMode::ON); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; @@ -138,8 +138,8 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { } TEST_F(RefreshRateStatsTest, twoConfigsTest) { - init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90), - createConfig(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)}); + init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90), + createDisplayMode(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1)); @@ -158,8 +158,8 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps(); - const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_1).getFps(); + const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps(); + const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_1).getFps(); mRefreshRateStats->setRefreshRate(config0Fps); mRefreshRateStats->setPowerMode(PowerMode::ON); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index e688e10e14..694790f86a 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -52,7 +52,7 @@ protected: SchedulerTest(); const scheduler::RefreshRateConfigs - mConfigs{{DisplayMode::Builder(0).setVsyncPeriod(16'666'667).setConfigGroup(0).build()}, + mConfigs{{DisplayMode::Builder(0).setVsyncPeriod(16'666'667).setGroup(0).build()}, DisplayModeId(0)}; mock::SchedulerCallback mSchedulerCallback; @@ -166,25 +166,25 @@ TEST_F(SchedulerTest, noLayerHistory) { mScheduler.chooseRefreshRateForContent(); } -TEST_F(SchedulerTest, testDispatchCachedReportedConfig) { +TEST_F(SchedulerTest, testDispatchCachedReportedMode) { // If the optional fields are cleared, the function should return before - // onConfigChange is called. + // onModeChange is called. mScheduler.clearOptionalFieldsInFeatures(); - EXPECT_NO_FATAL_FAILURE(mScheduler.dispatchCachedReportedConfig()); - EXPECT_CALL(*mEventThread, onConfigChanged(_, _, _)).Times(0); + EXPECT_NO_FATAL_FAILURE(mScheduler.dispatchCachedReportedMode()); + EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0); } -TEST_F(SchedulerTest, onNonPrimaryDisplayConfigChanged_invalidParameters) { - DisplayModeId configId = DisplayModeId(111); +TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) { + DisplayModeId modeId = DisplayModeId(111); nsecs_t vsyncPeriod = 111111; // If the handle is incorrect, the function should return before - // onConfigChange is called. + // onModeChange is called. Scheduler::ConnectionHandle invalidHandle = {.id = 123}; - EXPECT_NO_FATAL_FAILURE(mScheduler.onNonPrimaryDisplayConfigChanged(invalidHandle, - PHYSICAL_DISPLAY_ID, - configId, vsyncPeriod)); - EXPECT_CALL(*mEventThread, onConfigChanged(_, _, _)).Times(0); + EXPECT_NO_FATAL_FAILURE(mScheduler.onNonPrimaryDisplayModeChanged(invalidHandle, + PHYSICAL_DISPLAY_ID, modeId, + vsyncPeriod)); + EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp index 2b5cb77b78..e32c4bf145 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp @@ -246,7 +246,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { .setVsyncPeriod(DEFAULT_VSYNC_PERIOD) .setDpiX(DEFAULT_DPI) .setDpiY(DEFAULT_DPI) - .setConfigGroup(0) + .setGroup(0) .build(); DisplayModes modes{activeMode}; state.physical = {.id = *displayId, diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index d3e90e39af..3f9dd01588 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -80,20 +80,19 @@ public: return mFeatures.touch == Scheduler::TouchState::Active; } - void dispatchCachedReportedConfig() { + void dispatchCachedReportedMode() { std::lock_guard lock(mFeatureStateLock); - return Scheduler::dispatchCachedReportedConfig(); + return Scheduler::dispatchCachedReportedMode(); } void clearOptionalFieldsInFeatures() { std::lock_guard lock(mFeatureStateLock); - mFeatures.cachedConfigChangedParams.reset(); + mFeatures.cachedModeChangedParams.reset(); } - void onNonPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, - DisplayModeId configId, nsecs_t vsyncPeriod) { - return Scheduler::onNonPrimaryDisplayConfigChanged(handle, displayId, configId, - vsyncPeriod); + void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId, + DisplayModeId modeId, nsecs_t vsyncPeriod) { + return Scheduler::onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod); } ~TestableScheduler() { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 3787c436a0..6aa6d3194d 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -210,26 +210,26 @@ public: std::unique_ptr vsyncTracker, std::unique_ptr appEventThread, std::unique_ptr sfEventThread, - ISchedulerCallback* callback = nullptr, bool hasMultipleConfigs = false) { - DisplayModes configs{DisplayMode::Builder(0) - .setId(DisplayModeId(0)) - .setVsyncPeriod(16'666'667) - .setConfigGroup(0) - .build()}; - - if (hasMultipleConfigs) { - configs.emplace_back(DisplayMode::Builder(1) - .setId(DisplayModeId(1)) - .setVsyncPeriod(11'111'111) - .setConfigGroup(0) - .build()); + ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) { + DisplayModes modes{DisplayMode::Builder(0) + .setId(DisplayModeId(0)) + .setVsyncPeriod(16'666'667) + .setGroup(0) + .build()}; + + if (hasMultipleModes) { + modes.emplace_back(DisplayMode::Builder(1) + .setId(DisplayModeId(1)) + .setVsyncPeriod(11'111'111) + .setGroup(0) + .build()); } - const auto currConfig = DisplayModeId(0); + const auto currMode = DisplayModeId(0); mFlinger->mRefreshRateConfigs = - std::make_unique(configs, currConfig); + std::make_unique(modes, currMode); const auto currFps = - mFlinger->mRefreshRateConfigs->getRefreshRateFromConfigId(currConfig).getFps(); + mFlinger->mRefreshRateConfigs->getRefreshRateFromModeId(currMode).getFps(); mFlinger->mRefreshRateStats = std::make_unique(*mFlinger->mTimeStats, currFps, /*powerMode=*/hal::PowerMode::OFF); @@ -643,7 +643,7 @@ public: .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD) .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI) .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI) - .setConfigGroup(0) + .setGroup(0) .build(); DisplayModes modes{activeMode}; @@ -756,7 +756,7 @@ public: private: void setVsyncEnabled(bool) override {} - void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override {} + void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {} void repaintEverythingForHWC() override {} void kernelTimerChanged(bool) override {} void triggerOnFrameRateOverridesChanged() {} diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index 40437bfe1d..485b4acdce 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,7 +33,7 @@ public: MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); - MOCK_METHOD3(onConfigChanged, void(PhysicalDisplayId, DisplayModeId, nsecs_t)); + MOCK_METHOD3(onModeChanged, void(PhysicalDisplayId, DisplayModeId, nsecs_t)); MOCK_METHOD2(onFrameRateOverridesChanged, void(PhysicalDisplayId, std::vector)); MOCK_CONST_METHOD1(dump, void(std::string&)); -- cgit v1.2.3-59-g8ed1b From cdb4ed7743f5abfa4e9a785b14a50ca25c906f3f Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 4 Feb 2021 13:39:33 -0500 Subject: Add plumbing for sending stretch effect to SF Bug: 179047472 Test: builds & boots, doesn't do anything yet Change-Id: Ib8cccdde518f0591c2f2ee3416684442f37a1e06 --- libs/gui/LayerState.cpp | 6 +++ libs/gui/SurfaceComposerClient.cpp | 17 +++++++ libs/gui/include/gui/LayerState.h | 5 ++ libs/gui/include/gui/SurfaceComposerClient.h | 4 ++ .../include/renderengine/LayerSettings.h | 3 ++ libs/renderengine/skia/SkiaGLRenderEngine.cpp | 3 ++ libs/ui/include/ui/StretchEffect.h | 57 ++++++++++++++++++++++ .../compositionengine/LayerFECompositionState.h | 3 ++ services/surfaceflinger/Layer.cpp | 19 +++++++- services/surfaceflinger/Layer.h | 6 +++ services/surfaceflinger/SurfaceFlinger.cpp | 5 ++ 11 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 libs/ui/include/ui/StretchEffect.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index fff33056e1..f053372cb0 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -167,6 +167,9 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeInt32, region.right); SAFE_PARCEL(output.writeInt32, region.bottom); } + + SAFE_PARCEL(output.write, stretchEffect); + return NO_ERROR; } @@ -290,6 +293,9 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readInt32, ®ion.bottom); blurRegions.push_back(region); } + + SAFE_PARCEL(input.read, stretchEffect); + return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 550803d453..73807c4bb6 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1569,6 +1569,23 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setApply return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setStretchEffect( + const sp& sc, float left, float top, float right, float bottom, float vecX, + float vecY, float maxAmount) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eStretchChanged; + s->stretchEffect = StretchEffect{.area = {left, top, right, bottom}, + .vectorX = vecX, + .vectorY = vecY, + .maxAmount = maxAmount}; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 2f9a0c01eb..b273805e25 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -135,6 +136,7 @@ struct layer_state_t { eFrameTimelineInfoChanged = 0x800'00000000, eBlurRegionsChanged = 0x1000'00000000, eAutoRefreshChanged = 0x2000'00000000, + eStretchChanged = 0x4000'00000000, }; layer_state_t(); @@ -244,6 +246,9 @@ struct layer_state_t { // can and not wait for a frame to become available. This is only relevant // in shared buffer mode. bool autoRefresh; + + // Stretch effect to be applied to this layer + StretchEffect stretchEffect; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e7abfe6172..61c0ab66a1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -551,6 +551,10 @@ public: // transactions from blocking each other. Transaction& setApplyToken(const sp& token); + Transaction& setStretchEffect(const sp& sc, float left, float top, + float right, float bottom, float vecX, float vecY, + float maxAmount); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 3a727c9caf..7661233967 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -28,6 +28,7 @@ #include #include #include +#include #include namespace android { @@ -155,6 +156,8 @@ struct LayerSettings { std::vector blurRegions; + StretchEffect stretchEffect; + // Name associated with the layer for debugging purposes. std::string name; }; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index dd26b17eb4..1eb8da9b25 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -491,6 +491,9 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp sh const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha) { + if (layer->stretchEffect.hasEffect()) { + // TODO: Implement + } if (mUseColorManagement && needsLinearEffect(layer->colorTransform, layer->sourceDataspace, display.outputDataspace)) { LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace, diff --git a/libs/ui/include/ui/StretchEffect.h b/libs/ui/include/ui/StretchEffect.h new file mode 100644 index 0000000000..1d2460ccfc --- /dev/null +++ b/libs/ui/include/ui/StretchEffect.h @@ -0,0 +1,57 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include "FloatRect.h" + +#include + +namespace android { + +struct StretchEffect : public LightFlattenablePod { + FloatRect area = {0, 0, 0, 0}; + float vectorX = 0; + float vectorY = 0; + float maxAmount = 0; + + bool operator==(const StretchEffect& other) const { + return area == other.area && vectorX == other.vectorX && vectorY == other.vectorY && + maxAmount == other.maxAmount; + } + + static bool isZero(float value) { + constexpr float NON_ZERO_EPSILON = 0.001f; + return fabsf(value) <= NON_ZERO_EPSILON; + } + + bool isNoOp() const { return isZero(vectorX) && isZero(vectorY); } + + bool hasEffect() const { return !isNoOp(); } + + void sanitize() { + // If the area is empty, or the max amount is zero, then reset back to defaults + if (area.bottom >= area.top || area.left >= area.right || isZero(maxAmount)) { + *this = StretchEffect{}; + } + } +}; + +static_assert(std::is_trivially_copyable::value, + "StretchEffect must be trivially copyable to be flattenable"); + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index c445d5b615..8402149c57 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -34,6 +34,7 @@ #include #include #include +#include #include "DisplayHardware/Hal.h" @@ -123,6 +124,8 @@ struct LayerFECompositionState { // List of regions that require blur std::vector blurRegions; + StretchEffect stretchEffect; + /* * Geometry state */ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index df14003c75..1fe0e2624b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -488,6 +488,7 @@ void Layer::prepareBasicGeometryCompositionState() { compositionState->alpha = alpha; compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius; compositionState->blurRegions = drawingState.blurRegions; + compositionState->stretchEffect = drawingState.stretchEffect; } void Layer::prepareGeometryCompositionState() { @@ -556,8 +557,8 @@ void Layer::preparePerFrameCompositionState() { isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - if (isHdrY410() || usesRoundedCorners || drawShadows() || - getDrawingState().blurRegions.size() > 0) { + if (isHdrY410() || usesRoundedCorners || drawShadows() || drawingState.blurRegions.size() > 0 || + drawingState.stretchEffect.hasEffect()) { compositionState->forceClientComposition = true; } } @@ -656,6 +657,7 @@ std::optional Layer::prepareClientCom layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); layerSettings.blurRegions = getBlurRegions(); } + layerSettings.stretchEffect = getDrawingState().stretchEffect; // Record the name of the layer for debugging further down the stack. layerSettings.name = getName(); return layerSettings; @@ -1423,6 +1425,19 @@ bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHin return true; } +bool Layer::setStretchEffect(const StretchEffect& effect) { + StretchEffect temp = effect; + temp.sanitize(); + if (mCurrentState.stretchEffect == temp) { + return false; + } + mCurrentState.sequence++; + mCurrentState.stretchEffect = temp; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + void Layer::updateTreeHasFrameRateVote() { const auto traverseTree = [&](const LayerVector::Visitor& visitor) { auto parent = getParent(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9cd15e8705..7d70d91bd3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -323,6 +324,9 @@ public: // An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to // trigger a warning if the number of SurfaceFrames crosses the threshold. static constexpr uint32_t kStateSurfaceFramesThreshold = 25; + + // Stretch effect to apply to this layer + StretchEffect stretchEffect; }; /* @@ -938,6 +942,8 @@ public: bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; } + bool setStretchEffect(const StretchEffect& effect); + protected: class SyncPoint { public: diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 689a3024a3..bbbb0034ce 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3953,6 +3953,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eAutoRefreshChanged) { layer->setAutoRefresh(s.autoRefresh); } + if (what & layer_state_t::eStretchChanged) { + if (layer->setStretchEffect(s.stretchEffect)) { + flags |= eTraversalNeeded; + } + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not -- cgit v1.2.3-59-g8ed1b From f51775dbb66ff8ee2254ec06d5d5668d8791d8dc Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 14 Jan 2021 23:44:15 +0100 Subject: Add GPU completion to FrameMetrics (2/3) - Add SurfaceStatsCallback to TransactionCompletedListener - Register a callback in RenderProxy to be called when we have surface stats from SF via the BLAST callback. - Instead of finishing a frame for frame metrics reporting immediately, wait until BLAST callback fires, note GPU completion time and finish frame. - Expose GPU_COMPLETION in FrameMetrics - Modify TOTAL_DURATION to also include GPU_COMPLETION Test: FrameMetricsListenerTest Fixes: 171046219 Change-Id: If4b63c6a4c49c9ce2f31410d7f33541b0e6bf594 --- Android.bp | 5 ++ include/private/surface_control_private.h | 71 ++++++++++++++++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 32 ++++++++++++- libs/gui/include/gui/SurfaceComposerClient.h | 21 ++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 include/private/surface_control_private.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/Android.bp b/Android.bp index 9829c7fbad..f714759732 100644 --- a/Android.bp +++ b/Android.bp @@ -43,3 +43,8 @@ filegroup { ":framework_native_aidl_gui", ], } + +cc_library_headers{ + name: "libandroid_headers_private", + export_include_dirs: ["include/private"], +} \ No newline at end of file diff --git a/include/private/surface_control_private.h b/include/private/surface_control_private.h new file mode 100644 index 0000000000..37a476e679 --- /dev/null +++ b/include/private/surface_control_private.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H +#define ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H + +#include + +__BEGIN_DECLS + +struct ASurfaceControl; +struct ASurfaceControlStats; + +typedef struct ASurfaceControlStats ASurfaceControlStats; + +/** + * Callback to be notified when surface stats for a specific surface control are available. + */ +typedef void (*ASurfaceControl_SurfaceStatsListener)(void* context, + ASurfaceControl* control, ASurfaceControlStats* stats); + +/** + * Registers a callback to be invoked when surface stats from a specific surface are available. + * + * \param context Optional context provided by the client that is passed into + * the callback. + * + * \param control The surface to retrieve callbacks for. + * + * \param func The callback to be invoked when surface stats are available. + */ +void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, void* context, + ASurfaceControl_SurfaceStatsListener func); + +/** + * Unregisters a callback to be invoked when surface stats from a specific surface are available. + * + * \param context The context passed into ASurfaceControl_registerSurfaceStatsListener + * + * \param func The callback passed into ASurfaceControl_registerSurfaceStatsListener + */ +void ASurfaceControl_unregisterSurfaceStatsListener(void* context, + ASurfaceControl_SurfaceStatsListener func); + +/** + * Returns the timestamp of when the buffer was acquired for a specific frame with frame number + * obtained from ASurfaceControlStats_getFrameNumber. + */ +int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats); + +/** + * Returns the frame number of the surface stats object passed into the callback. + */ +uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats); + +__END_DECLS + +#endif //ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 27fb2a8cd7..d41da9b308 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -194,6 +194,25 @@ void TransactionCompletedListener::removeJankListener(const sp } } +void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie, + sp surfaceControl, SurfaceStatsCallback listener) { + std::lock_guard lock(mMutex); + mSurfaceStatsListeners.insert({surfaceControl->getHandle(), + SurfaceStatsCallbackEntry(context, cookie, listener)}); +} + +void TransactionCompletedListener::removeSurfaceStatsListener(void* context, void* cookie) { + std::lock_guard lock(mMutex); + for (auto it = mSurfaceStatsListeners.begin(); it != mSurfaceStatsListeners.end();) { + auto [itContext, itCookie, itListener] = it->second; + if (itContext == context && itCookie == cookie) { + it = mSurfaceStatsListeners.erase(it); + } else { + it++; + } + } +} + void TransactionCompletedListener::addSurfaceControlToCallbacks( const sp& surfaceControl, const std::unordered_set& callbackIds) { @@ -210,6 +229,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks( void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) { std::unordered_map callbacksMap; std::multimap, sp> jankListenersMap; + std::multimap, SurfaceStatsCallbackEntry> surfaceListeners; { std::lock_guard lock(mMutex); @@ -226,6 +246,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener */ callbacksMap = mCallbacks; jankListenersMap = mJankListeners; + surfaceListeners = mSurfaceStatsListeners; for (const auto& transactionStats : listenerStats.transactionStats) { for (auto& callbackId : transactionStats.callbackIds) { mCallbacks.erase(callbackId); @@ -259,9 +280,16 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats); } for (const auto& surfaceStats : transactionStats.surfaceStats) { + auto listenerRange = surfaceListeners.equal_range(surfaceStats.surfaceControl); + for (auto it = listenerRange.first; it != listenerRange.second; it++) { + auto entry = it->second; + entry.callback(entry.context, transactionStats.latchTime, + transactionStats.presentFence, surfaceStats); + } + if (surfaceStats.jankData.empty()) continue; - for (auto it = jankListenersMap.find(surfaceStats.surfaceControl); - it != jankListenersMap.end(); it++) { + auto jankRange = jankListenersMap.equal_range(surfaceStats.surfaceControl); + for (auto it = jankRange.first; it != jankRange.second; it++) { it->second->onJankDataAvailable(surfaceStats.jankData); } } diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e89f3a7b44..8de7574fa7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -80,6 +80,10 @@ using TransactionCompletedCallbackTakesContext = using TransactionCompletedCallback = std::function& /*presentFence*/, const std::vector& /*stats*/)>; +using SurfaceStatsCallback = + std::function& /*presentFence*/, + const SurfaceStats& /*stats*/)>; // --------------------------------------------------------------------------- @@ -650,8 +654,21 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { surfaceControls; }; + struct SurfaceStatsCallbackEntry { + SurfaceStatsCallbackEntry(void* context, void* cookie, SurfaceStatsCallback callback) + : context(context), + cookie(cookie), + callback(callback) {} + + void* context; + void* cookie; + SurfaceStatsCallback callback; + }; + std::unordered_map mCallbacks GUARDED_BY(mMutex); std::multimap, sp> mJankListeners GUARDED_BY(mMutex); + std::multimap, SurfaceStatsCallbackEntry> + mSurfaceStatsListeners GUARDED_BY(mMutex); public: static sp getInstance(); @@ -679,6 +696,10 @@ public: */ void removeJankListener(const sp& listener); + void addSurfaceStatsListener(void* context, void* cookie, sp surfaceControl, + SurfaceStatsCallback listener); + void removeSurfaceStatsListener(void* context, void* cookie); + // Overrides BnTransactionCompletedListener's onTransactionCompleted void onTransactionCompleted(ListenerStats stats) override; }; -- cgit v1.2.3-59-g8ed1b From 228f46b5b9c3eac674aceb579a718cd459165f2e Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Thu, 28 Jan 2021 21:11:45 +0100 Subject: Introduce DynamicDisplayInfo In this CL we introduce the getDynamicDisplayInfo call on ISurfaceComposer which replaces the existing - getDisplayModes - getActiveDisplayMode - getColorModes - getActiveColorMode - getHdrCapabilities This way all display properties can be queried atomically. The current DisplayInfo class is moved to the androd::ui namespace and it's renamed to StaticDisplayInfo. ui::DisplayMode is now LightFlattenable and the mode ID is int32_t instead of size_t in order to prevent serialization problems. Additionally we add the ID field to ui::DisplayMode. This way we no longer need the supported display IDs to be from 0 to N-1. Bug: 159590486 Bug: 180539476 Test: presubmit, manually test that device boots Change-Id: I52b170913ce47cb5df2e8417e6cc95d395df1fda --- cmds/surfacereplayer/replayer/Replayer.cpp | 1 - include/input/TouchVideoFrame.h | 2 +- include/ui/DisplayInfo.h | 1 - include/ui/StaticDisplayInfo.h | 1 + libs/gui/ISurfaceComposer.cpp | 220 ++++----------------- libs/gui/Surface.cpp | 14 +- libs/gui/SurfaceComposerClient.cpp | 59 +++--- libs/gui/SurfaceControl.cpp | 2 +- libs/gui/include/gui/ISurfaceComposer.h | 70 +++---- libs/gui/include/gui/SurfaceComposerClient.h | 35 ++-- libs/gui/tests/Surface_test.cpp | 24 +-- libs/nativedisplay/ADisplay.cpp | 41 ++-- libs/nativedisplay/include/apex/display.h | 5 + libs/ui/Android.bp | 4 +- libs/ui/DisplayInfo.cpp | 54 ----- libs/ui/DisplayMode.cpp | 69 +++++++ libs/ui/DynamicDisplayInfo.cpp | 66 +++++++ libs/ui/HdrCapabilities.cpp | 4 - libs/ui/StaticDisplayInfo.cpp | 54 +++++ libs/ui/include/ui/DisplayInfo.h | 42 ---- libs/ui/include/ui/DisplayMode.h | 17 +- libs/ui/include/ui/DynamicDisplayInfo.h | 52 +++++ libs/ui/include/ui/HdrCapabilities.h | 6 - libs/ui/include/ui/StaticDisplayInfo.h | 41 ++++ libs/ui/include_vndk/ui/DisplayInfo.h | 1 - libs/ui/include_vndk/ui/StaticDisplayInfo.h | 1 + .../compositionengine/DisplayCreationArgs.h | 4 +- .../CompositionEngine/src/Display.cpp | 3 +- .../CompositionEngine/tests/DisplayTest.cpp | 10 +- .../CompositionEngine/tests/MockHWComposer.h | 2 +- services/surfaceflinger/DisplayDevice.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 10 +- .../surfaceflinger/DisplayHardware/DisplayMode.h | 5 +- services/surfaceflinger/DisplayHardware/HWC2.cpp | 7 +- services/surfaceflinger/DisplayHardware/HWC2.h | 6 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 10 +- .../surfaceflinger/DisplayHardware/HWComposer.h | 4 +- .../Scheduler/RefreshRateConfigs.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 202 +++++++------------ services/surfaceflinger/SurfaceFlinger.h | 27 +-- services/surfaceflinger/tests/Credentials_test.cpp | 26 +-- .../surfaceflinger/tests/DisplayConfigs_test.cpp | 14 +- .../tests/fakehwc/SFFakeHwc_test.cpp | 26 ++- .../tests/unittests/CompositionTest.cpp | 4 +- .../tests/unittests/DisplayTransactionTest.cpp | 8 +- .../unittests/DisplayTransactionTestHelpers.h | 13 +- .../tests/unittests/TestableSurfaceFlinger.h | 2 +- 47 files changed, 623 insertions(+), 656 deletions(-) delete mode 120000 include/ui/DisplayInfo.h create mode 120000 include/ui/StaticDisplayInfo.h delete mode 100644 libs/ui/DisplayInfo.cpp create mode 100644 libs/ui/DisplayMode.cpp create mode 100644 libs/ui/DynamicDisplayInfo.cpp create mode 100644 libs/ui/StaticDisplayInfo.cpp delete mode 100644 libs/ui/include/ui/DisplayInfo.h create mode 100644 libs/ui/include/ui/DynamicDisplayInfo.h create mode 100644 libs/ui/include/ui/StaticDisplayInfo.h delete mode 120000 libs/ui/include_vndk/ui/DisplayInfo.h create mode 120000 libs/ui/include_vndk/ui/StaticDisplayInfo.h (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 58d6582e0b..3c53c025ff 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h index 4fa2f86dc1..eda628e233 100644 --- a/include/input/TouchVideoFrame.h +++ b/include/input/TouchVideoFrame.h @@ -57,7 +57,7 @@ public: /** * Rotate the video frame. - * The rotation value is an enum from ui/DisplayInfo.h + * The rotation value is an enum from ui/Rotation.h */ void rotate(int32_t orientation); diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h deleted file mode 120000 index 9a195eaed4..0000000000 --- a/include/ui/DisplayInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../libs/ui/include/ui/DisplayInfo.h \ No newline at end of file diff --git a/include/ui/StaticDisplayInfo.h b/include/ui/StaticDisplayInfo.h new file mode 120000 index 0000000000..c58aae3020 --- /dev/null +++ b/include/ui/StaticDisplayInfo.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/StaticDisplayInfo.h \ No newline at end of file diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 762746c0ce..2e4f858a9d 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -36,11 +36,12 @@ #include -#include #include #include #include +#include #include +#include #include @@ -323,32 +324,26 @@ public: return result; } - status_t getDisplayInfo(const sp& display, DisplayInfo* info) override { + status_t getStaticDisplayInfo(const sp& display, + ui::StaticDisplayInfo* info) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply); + remote()->transact(BnSurfaceComposer::GET_STATIC_DISPLAY_INFO, data, &reply); const status_t result = reply.readInt32(); if (result != NO_ERROR) return result; return reply.read(*info); } - status_t getDisplayModes(const sp& display, Vector* modes) override { + status_t getDynamicDisplayInfo(const sp& display, + ui::DynamicDisplayInfo* info) override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_DISPLAY_MODES, data, &reply); + remote()->transact(BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO, data, &reply); const status_t result = reply.readInt32(); - if (result == NO_ERROR) { - const size_t numModes = reply.readUint32(); - modes->clear(); - modes->resize(numModes); - for (size_t i = 0; i < numModes; i++) { - memcpy(&(modes->editItemAt(i)), reply.readInplace(sizeof(ui::DisplayMode)), - sizeof(ui::DisplayMode)); - } - } - return result; + if (result != NO_ERROR) return result; + return reply.read(*info); } status_t getDisplayStats(const sp& display, DisplayStatInfo* stats) override { @@ -365,44 +360,6 @@ public: return result; } - int getActiveDisplayModeId(const sp& display) override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - data.writeStrongBinder(display); - remote()->transact(BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE, data, &reply); - return reply.readInt32(); - } - - status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) override { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result); - return result; - } - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply); - if (result != NO_ERROR) { - ALOGE("getDisplayColorModes failed to transact: %d", result); - return result; - } - result = static_cast(reply.readInt32()); - if (result == NO_ERROR) { - size_t numModes = reply.readUint32(); - outColorModes->clear(); - outColorModes->resize(numModes); - for (size_t i = 0; i < numModes; ++i) { - outColorModes->replaceAt(static_cast(reply.readInt32()), i); - } - } - return result; - } - status_t getDisplayNativePrimaries(const sp& display, ui::DisplayPrimaries& primaries) override { Parcel data, reply; @@ -429,26 +386,6 @@ public: return result; } - ColorMode getActiveColorMode(const sp& display) override { - Parcel data, reply; - status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - if (result != NO_ERROR) { - ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result); - return static_cast(result); - } - result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result); - return static_cast(result); - } - result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply); - if (result != NO_ERROR) { - ALOGE("getActiveColorMode failed to transact: %d", result); - return static_cast(result); - } - return static_cast(reply.readInt32()); - } - status_t setActiveColorMode(const sp& display, ColorMode colorMode) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -580,28 +517,6 @@ public: return reply.readInt32(); } - status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getHdrCapabilities failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_HDR_CAPABILITIES, - data, &reply); - if (result != NO_ERROR) { - ALOGE("getHdrCapabilities failed to transact: %d", result); - return result; - } - result = reply.readInt32(); - if (result == NO_ERROR) { - result = reply.read(*outCapabilities); - } - return result; - } - status_t enableVSyncInjections(bool enable) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -881,9 +796,10 @@ public: return error; } - status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, float appRequestRefreshRateMin, + status_t setDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId defaultMode, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, float appRequestRefreshRateMax) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -938,7 +854,8 @@ public: return reply.readInt32(); } - status_t getDesiredDisplayModeSpecs(const sp& displayToken, size_t* outDefaultMode, + status_t getDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId* outDefaultMode, bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, @@ -966,17 +883,16 @@ public: ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result); return result; } - int32_t defaultMode; - result = reply.readInt32(&defaultMode); + + result = reply.readInt32(outDefaultMode); if (result != NO_ERROR) { ALOGE("getDesiredDisplayModeSpecs failed to read defaultMode: %d", result); return result; } - if (defaultMode < 0) { - ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode); + if (*outDefaultMode < 0) { + ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, *outDefaultMode); return BAD_VALUE; } - *outDefaultMode = static_cast(defaultMode); result = reply.readBool(outAllowGroupSwitching); if (result != NO_ERROR) { @@ -1436,28 +1352,24 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case GET_DISPLAY_INFO: { + case GET_STATIC_DISPLAY_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - DisplayInfo info; + ui::StaticDisplayInfo info; const sp display = data.readStrongBinder(); - const status_t result = getDisplayInfo(display, &info); - reply->writeInt32(result); + const status_t result = getStaticDisplayInfo(display, &info); + SAFE_PARCEL(reply->writeInt32, result); if (result != NO_ERROR) return result; - return reply->write(info); + SAFE_PARCEL(reply->write, info); + return NO_ERROR; } - case GET_DISPLAY_MODES: { + case GET_DYNAMIC_DISPLAY_INFO: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector modes; + ui::DynamicDisplayInfo info; const sp display = data.readStrongBinder(); - const status_t result = getDisplayModes(display, &modes); - reply->writeInt32(result); - if (result == NO_ERROR) { - reply->writeUint32(static_cast(modes.size())); - for (size_t i = 0; i < modes.size(); i++) { - memcpy(reply->writeInplace(sizeof(ui::DisplayMode)), &modes[i], - sizeof(ui::DisplayMode)); - } - } + const status_t result = getDynamicDisplayInfo(display, &info); + SAFE_PARCEL(reply->writeInt32, result); + if (result != NO_ERROR) return result; + SAFE_PARCEL(reply->write, info); return NO_ERROR; } case GET_DISPLAY_STATS: { @@ -1472,32 +1384,6 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } - case GET_ACTIVE_DISPLAY_MODE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = data.readStrongBinder(); - int id = getActiveDisplayModeId(display); - reply->writeInt32(id); - return NO_ERROR; - } - case GET_DISPLAY_COLOR_MODES: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - Vector colorModes; - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result); - return result; - } - result = getDisplayColorModes(display, &colorModes); - reply->writeInt32(result); - if (result == NO_ERROR) { - reply->writeUint32(static_cast(colorModes.size())); - for (size_t i = 0; i < colorModes.size(); ++i) { - reply->writeInt32(static_cast(colorModes[i])); - } - } - return NO_ERROR; - } case GET_DISPLAY_NATIVE_PRIMARIES: { CHECK_INTERFACE(ISurfaceComposer, data, reply); ui::DisplayPrimaries primaries; @@ -1518,18 +1404,6 @@ status_t BnSurfaceComposer::onTransact( return NO_ERROR; } - case GET_ACTIVE_COLOR_MODE: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getActiveColorMode failed to readStrongBinder: %d", result); - return result; - } - ColorMode colorMode = getActiveColorMode(display); - result = reply->writeInt32(static_cast(colorMode)); - return result; - } case SET_ACTIVE_COLOR_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = nullptr; @@ -1639,23 +1513,6 @@ status_t BnSurfaceComposer::onTransact( setPowerMode(display, mode); return NO_ERROR; } - case GET_HDR_CAPABILITIES: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getHdrCapabilities failed to readStrongBinder: %d", - result); - return result; - } - HdrCapabilities capabilities; - result = getHdrCapabilities(display, &capabilities); - reply->writeInt32(result); - if (result == NO_ERROR) { - reply->write(capabilities); - } - return NO_ERROR; - } case ENABLE_VSYNC_INJECTIONS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); bool enable = false; @@ -1862,7 +1719,7 @@ status_t BnSurfaceComposer::onTransact( case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - int32_t defaultMode; + ui::DisplayModeId defaultMode; status_t result = data.readInt32(&defaultMode); if (result != NO_ERROR) { ALOGE("setDesiredDisplayModeSpecs: failed to read defaultMode: %d", result); @@ -1906,10 +1763,9 @@ status_t BnSurfaceComposer::onTransact( result); return result; } - result = setDesiredDisplayModeSpecs(displayToken, static_cast(defaultMode), - allowGroupSwitching, primaryRefreshRateMin, - primaryRefreshRateMax, appRequestRefreshRateMin, - appRequestRefreshRateMax); + result = setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching, + primaryRefreshRateMin, primaryRefreshRateMax, + appRequestRefreshRateMin, appRequestRefreshRateMax); if (result != NO_ERROR) { ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: " "%d", @@ -1922,7 +1778,7 @@ status_t BnSurfaceComposer::onTransact( case GET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); - size_t defaultMode; + ui::DisplayModeId defaultMode; bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; @@ -1941,7 +1797,7 @@ status_t BnSurfaceComposer::onTransact( return result; } - result = reply->writeInt32(static_cast(defaultMode)); + result = reply->writeInt32(defaultMode); if (result != NO_ERROR) { ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result); return result; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 07fc0694d6..6de3e971b2 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -34,9 +34,9 @@ #include #include +#include #include #include -#include #include #include @@ -48,7 +48,6 @@ namespace android { -using ui::ColorMode; using ui::Dataspace; namespace { @@ -361,15 +360,12 @@ status_t Surface::getHdrSupport(bool* supported) { return NAME_NOT_FOUND; } - HdrCapabilities hdrCapabilities; - status_t err = - composerService()->getHdrCapabilities(display, &hdrCapabilities); - - if (err) + ui::DynamicDisplayInfo info; + if (status_t err = composerService()->getDynamicDisplayInfo(display, &info); err != NO_ERROR) { return err; + } - *supported = !hdrCapabilities.getSupportedHdrTypes().empty(); - + *supported = !info.hdrCapabilities.getSupportedHdrTypes().empty(); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 27fb2a8cd7..0bd2c8811b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #ifndef NO_INPUT #include @@ -1815,39 +1816,35 @@ status_t SurfaceComposerClient::getDisplayState(const sp& display, return ComposerService::getComposerService()->getDisplayState(display, state); } -status_t SurfaceComposerClient::getDisplayInfo(const sp& display, DisplayInfo* info) { - return ComposerService::getComposerService()->getDisplayInfo(display, info); +status_t SurfaceComposerClient::getStaticDisplayInfo(const sp& display, + ui::StaticDisplayInfo* info) { + return ComposerService::getComposerService()->getStaticDisplayInfo(display, info); } -status_t SurfaceComposerClient::getDisplayModes(const sp& display, - Vector* modes) { - return ComposerService::getComposerService()->getDisplayModes(display, modes); +status_t SurfaceComposerClient::getDynamicDisplayInfo(const sp& display, + ui::DynamicDisplayInfo* info) { + return ComposerService::getComposerService()->getDynamicDisplayInfo(display, info); } status_t SurfaceComposerClient::getActiveDisplayMode(const sp& display, ui::DisplayMode* mode) { - Vector modes; - status_t result = getDisplayModes(display, &modes); + ui::DynamicDisplayInfo info; + status_t result = getDynamicDisplayInfo(display, &info); if (result != NO_ERROR) { return result; } - int activeId = getActiveDisplayModeId(display); - if (activeId < 0) { - ALOGE("No active mode found"); - return NAME_NOT_FOUND; + if (const auto activeMode = info.getActiveDisplayMode()) { + *mode = *activeMode; + return NO_ERROR; } - *mode = modes[static_cast(activeId)]; - return NO_ERROR; -} - -int SurfaceComposerClient::getActiveDisplayModeId(const sp& display) { - return ComposerService::getComposerService()->getActiveDisplayModeId(display); + ALOGE("Active display mode not found."); + return NAME_NOT_FOUND; } status_t SurfaceComposerClient::setDesiredDisplayModeSpecs( - const sp& displayToken, size_t defaultMode, bool allowGroupSwitching, + const sp& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, float appRequestRefreshRateMax) { return ComposerService::getComposerService() @@ -1856,30 +1853,24 @@ status_t SurfaceComposerClient::setDesiredDisplayModeSpecs( appRequestRefreshRateMin, appRequestRefreshRateMax); } -status_t SurfaceComposerClient::getDesiredDisplayModeSpecs( - const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { +status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) { return ComposerService::getComposerService() ->getDesiredDisplayModeSpecs(displayToken, outDefaultMode, outAllowGroupSwitching, outPrimaryRefreshRateMin, outPrimaryRefreshRateMax, outAppRequestRefreshRateMin, outAppRequestRefreshRateMax); } -status_t SurfaceComposerClient::getDisplayColorModes(const sp& display, - Vector* outColorModes) { - return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes); -} - status_t SurfaceComposerClient::getDisplayNativePrimaries(const sp& display, ui::DisplayPrimaries& outPrimaries) { return ComposerService::getComposerService()->getDisplayNativePrimaries(display, outPrimaries); } -ColorMode SurfaceComposerClient::getActiveColorMode(const sp& display) { - return ComposerService::getComposerService()->getActiveColorMode(display); -} - status_t SurfaceComposerClient::setActiveColorMode(const sp& display, ColorMode colorMode) { return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); @@ -1932,12 +1923,6 @@ status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) { return ComposerService::getComposerService()->getAnimationFrameStats(outStats); } -status_t SurfaceComposerClient::getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) { - return ComposerService::getComposerService()->getHdrCapabilities(display, - outCapabilities); -} - status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index e842382ded..1dcfe2e804 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -30,9 +30,9 @@ #include -#include #include #include +#include #include #include diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 292838e9ae..d0ab4802e1 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -54,7 +55,6 @@ namespace android { struct client_cache_t; struct ComposerState; struct DisplayCaptureArgs; -struct DisplayInfo; struct DisplayStatInfo; struct DisplayState; struct InputWindowCommands; @@ -74,6 +74,8 @@ namespace ui { struct DisplayMode; struct DisplayState; +struct DynamicDisplayInfo; +struct StaticDisplayInfo; } // namespace ui @@ -202,26 +204,17 @@ public: virtual status_t getDisplayState(const sp& display, ui::DisplayState*) = 0; /** - * Get immutable information about given physical display. + * Gets immutable information about given physical display. */ - virtual status_t getDisplayInfo(const sp& display, DisplayInfo*) = 0; + virtual status_t getStaticDisplayInfo(const sp& display, ui::StaticDisplayInfo*) = 0; /** - * Get modes supported by given physical display. + * Gets dynamic information about given physical display. */ - virtual status_t getDisplayModes(const sp& display, Vector*) = 0; + virtual status_t getDynamicDisplayInfo(const sp& display, ui::DynamicDisplayInfo*) = 0; - /** - * Get the index into modes returned by getDisplayModes, - * corresponding to the active mode. - */ - virtual int getActiveDisplayModeId(const sp& display) = 0; - - virtual status_t getDisplayColorModes(const sp& display, - Vector* outColorModes) = 0; virtual status_t getDisplayNativePrimaries(const sp& display, ui::DisplayPrimaries& primaries) = 0; - virtual ui::ColorMode getActiveColorMode(const sp& display) = 0; virtual status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode) = 0; @@ -296,13 +289,6 @@ public: */ virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0; - /* Gets the supported HDR capabilities of the given display. - * - * Requires the ACCESS_SURFACE_FLINGER permission. - */ - virtual status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities) const = 0; - virtual status_t enableVSyncInjections(bool enable) = 0; virtual status_t injectVSync(nsecs_t when) = 0; @@ -397,20 +383,21 @@ public: * * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider * switching between. Only modes with a mode group and resolution matching defaultMode - * will be considered for switching. The defaultMode index corresponds to the list of modes - * returned from getDisplayModes(). - */ - virtual status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, - bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) = 0; - - virtual status_t getDesiredDisplayModeSpecs( - const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) = 0; + * will be considered for switching. The defaultMode corresponds to an ID of mode in the list + * of supported modes returned from getDynamicDisplayInfo(). + */ + virtual status_t setDesiredDisplayModeSpecs( + const sp& displayToken, ui::DisplayModeId defaultMode, + bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, float appRequestRefreshRateMax) = 0; + + virtual status_t getDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) = 0; /* * Gets whether brightness operations are supported on a display. * @@ -534,7 +521,7 @@ public: // Java by ActivityManagerService. BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION, CREATE_CONNECTION, - GET_DISPLAY_INFO, + GET_STATIC_DISPLAY_INFO, CREATE_DISPLAY_EVENT_CONNECTION, CREATE_DISPLAY, DESTROY_DISPLAY, @@ -542,8 +529,8 @@ public: SET_TRANSACTION_STATE, AUTHENTICATE_SURFACE, GET_SUPPORTED_FRAME_TIMESTAMPS, - GET_DISPLAY_MODES, - GET_ACTIVE_DISPLAY_MODE, + GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. + GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. GET_DISPLAY_STATE, CAPTURE_DISPLAY, CAPTURE_LAYERS, @@ -551,9 +538,9 @@ public: GET_ANIMATION_FRAME_STATS, SET_POWER_MODE, GET_DISPLAY_STATS, - GET_HDR_CAPABILITIES, - GET_DISPLAY_COLOR_MODES, - GET_ACTIVE_COLOR_MODE, + GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. + GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. + GET_ACTIVE_COLOR_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_ACTIVE_COLOR_MODE, ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, @@ -586,6 +573,7 @@ public: ADD_TRANSACTION_TRACE_LISTENER, GET_GPU_CONTEXT_PRIORITY, GET_EXTRA_BUFFER_COUNT, + GET_DYNAMIC_DISPLAY_INFO, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e89f3a7b44..2b72b73d96 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -108,43 +108,33 @@ public: static status_t getDisplayState(const sp& display, ui::DisplayState*); // Get immutable information about given physical display. - static status_t getDisplayInfo(const sp& display, DisplayInfo*); + static status_t getStaticDisplayInfo(const sp& display, ui::StaticDisplayInfo*); - // Get modes supported by given physical display. - static status_t getDisplayModes(const sp& display, Vector*); + // Get dynamic information about given physical display. + static status_t getDynamicDisplayInfo(const sp& display, ui::DynamicDisplayInfo*); - // Get the ID of the active DisplayMode, as getDisplayModes index. - static int getActiveDisplayModeId(const sp& display); - - // Shorthand for getDisplayModes element at getActiveDisplayModeId index. + // Shorthand for the active display mode from getDynamicDisplayInfo(). + // TODO(b/180391891): Update clients to use getDynamicDisplayInfo and remove this function. static status_t getActiveDisplayMode(const sp& display, ui::DisplayMode*); // Sets the refresh rate boundaries for the display. - static status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t defaultMode, - bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax); + static status_t setDesiredDisplayModeSpecs( + const sp& displayToken, ui::DisplayModeId defaultMode, + bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, float appRequestRefreshRateMax); // Gets the refresh rate boundaries for the display. static status_t getDesiredDisplayModeSpecs(const sp& displayToken, - size_t* outDefaultMode, bool* outAllowGroupSwitching, + ui::DisplayModeId* outDefaultMode, + bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax); - // Gets the list of supported color modes for the given display - static status_t getDisplayColorModes(const sp& display, - Vector* outColorModes); - // Get the coordinates of the display's native color primaries static status_t getDisplayNativePrimaries(const sp& display, ui::DisplayPrimaries& outPrimaries); - // Gets the active color mode for the given display - static ui::ColorMode getActiveColorMode(const sp& display); - // Sets the active color mode for the given display static status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode); @@ -583,9 +573,6 @@ public: static status_t clearAnimationFrameStats(); static status_t getAnimationFrameStats(FrameStats* outStats); - static status_t getHdrCapabilities(const sp& display, - HdrCapabilities* outCapabilities); - static void setDisplayProjection(const sp& token, ui::Rotation orientation, const Rect& layerStackRect, const Rect& displayRect); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 43909ac00d..3397198fa0 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -734,10 +735,11 @@ public: } void setPowerMode(const sp& /*display*/, int /*mode*/) override {} - status_t getDisplayInfo(const sp& /*display*/, DisplayInfo*) override { + status_t getStaticDisplayInfo(const sp& /*display*/, ui::StaticDisplayInfo*) override { return NO_ERROR; } - status_t getDisplayModes(const sp& /*display*/, Vector*) override { + status_t getDynamicDisplayInfo(const sp& /*display*/, + ui::DynamicDisplayInfo*) override { return NO_ERROR; } status_t getDisplayState(const sp& /*display*/, ui::DisplayState*) override { @@ -745,19 +747,10 @@ public: } status_t getDisplayStats(const sp& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } - int getActiveDisplayModeId(const sp& /*display*/) override { return 0; } - status_t getDisplayColorModes(const sp& /*display*/, - Vector* /*outColorModes*/) override { - return NO_ERROR; - } status_t getDisplayNativePrimaries(const sp& /*display*/, ui::DisplayPrimaries& /*primaries*/) override { return NO_ERROR; } - ColorMode getActiveColorMode(const sp& /*display*/) - override { - return ColorMode::NATIVE; - } status_t setActiveColorMode(const sp& /*display*/, ColorMode /*colorMode*/) override { return NO_ERROR; } status_t captureDisplay(const DisplayCaptureArgs& /* captureArgs */, @@ -787,10 +780,6 @@ public: status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override { return NO_ERROR; } - status_t getHdrCapabilities(const sp& /*display*/, - HdrCapabilities* /*outCapabilities*/) const override { - return NO_ERROR; - } status_t enableVSyncInjections(bool /*enable*/) override { return NO_ERROR; } @@ -843,7 +832,8 @@ public: const sp& /*listener*/) override { return NO_ERROR; } - status_t setDesiredDisplayModeSpecs(const sp& /*displayToken*/, size_t /*defaultMode*/, + status_t setDesiredDisplayModeSpecs(const sp& /*displayToken*/, + ui::DisplayModeId /*defaultMode*/, bool /*allowGroupSwitching*/, float /*primaryRefreshRateMin*/, float /*primaryRefreshRateMax*/, @@ -852,7 +842,7 @@ public: return NO_ERROR; } status_t getDesiredDisplayModeSpecs(const sp& /*displayToken*/, - size_t* /*outDefaultMode*/, + ui::DisplayModeId* /*outDefaultMode*/, bool* /*outAllowGroupSwitching*/, float* /*outPrimaryRefreshRateMin*/, float* /*outPrimaryRefreshRateMax*/, diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp index c595aa6309..6288194714 100644 --- a/libs/nativedisplay/ADisplay.cpp +++ b/libs/nativedisplay/ADisplay.cpp @@ -16,10 +16,11 @@ #include #include -#include #include +#include #include #include +#include #include #include @@ -32,6 +33,11 @@ namespace android::display::impl { * Implementation of ADisplayConfig */ struct DisplayConfigImpl { + /** + * The ID of the display configuration. + */ + size_t id; + /** * The width in pixels of the display configuration. */ @@ -139,17 +145,19 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { for (int i = 0; i < size; ++i) { const sp token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]); - DisplayInfo info; - if (const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info); + ui::StaticDisplayInfo staticInfo; + if (const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &staticInfo); status != OK) { return status; } - Vector modes; - if (const status_t status = SurfaceComposerClient::getDisplayModes(token, &modes); + ui::DynamicDisplayInfo dynamicInfo; + if (const status_t status = + SurfaceComposerClient::getDynamicDisplayInfo(token, &dynamicInfo); status != OK) { return status; } + const auto& modes = dynamicInfo.supportedDisplayModes; if (modes.empty()) { return NO_INIT; } @@ -159,9 +167,9 @@ int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { for (int j = 0; j < modes.size(); ++j) { const ui::DisplayMode& mode = modes[j]; modesPerDisplay[i].emplace_back( - DisplayConfigImpl{mode.resolution.getWidth(), mode.resolution.getHeight(), - info.density, mode.refreshRate, mode.sfVsyncOffset, - mode.appVsyncOffset}); + DisplayConfigImpl{static_cast(mode.id), mode.resolution.getWidth(), + mode.resolution.getHeight(), staticInfo.density, + mode.refreshRate, mode.sfVsyncOffset, mode.appVsyncOffset}); } } @@ -257,15 +265,22 @@ int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) { CHECK_NOT_NULL(display); sp token = getToken(display); - const int index = SurfaceComposerClient::getActiveDisplayModeId(token); - if (index < 0) { - return index; + ui::DynamicDisplayInfo info; + if (const auto status = SurfaceComposerClient::getDynamicDisplayInfo(token, &info); + status != OK) { + return status; } DisplayImpl* impl = reinterpret_cast(display); + for (size_t i = 0; i < impl->numConfigs; i++) { + auto* config = impl->configs + i; + if (config->id == info.activeDisplayModeId) { + *outConfig = reinterpret_cast(config); + return OK; + } + } - *outConfig = reinterpret_cast(impl->configs + index); - return OK; + return NAME_NOT_FOUND; } float ADisplayConfig_getDensity(ADisplayConfig* config) { diff --git a/libs/nativedisplay/include/apex/display.h b/libs/nativedisplay/include/apex/display.h index a7eaf87b9e..bd94b5523e 100644 --- a/libs/nativedisplay/include/apex/display.h +++ b/libs/nativedisplay/include/apex/display.h @@ -97,6 +97,11 @@ void ADisplay_getPreferredWideColorFormat(ADisplay* display, ADataSpace* outData * such an update is observed, then this method should be recalled to get the * new current configuration. * + * After a subsequent hotplug "connected" event the supported display configs + * may change. Then the preloaded display configs will be stale and the + * call for current config may return NAME_NOT_FOUND. In this case the client + * should release and re-acquire the display handle. + * * Returns OK on success, -errno on failure. */ int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig); diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp index 714ee3e909..f160c298b6 100644 --- a/libs/ui/Android.bp +++ b/libs/ui/Android.bp @@ -105,7 +105,8 @@ cc_library_shared { srcs: [ "DebugUtils.cpp", "DeviceProductInfo.cpp", - "DisplayInfo.cpp", + "DisplayMode.cpp", + "DynamicDisplayInfo.cpp", "Fence.cpp", "FenceTime.cpp", "FrameStats.cpp", @@ -120,6 +121,7 @@ cc_library_shared { "PixelFormat.cpp", "PublicFormat.cpp", "Size.cpp", + "StaticDisplayInfo.cpp", ], include_dirs: [ diff --git a/libs/ui/DisplayInfo.cpp b/libs/ui/DisplayInfo.cpp deleted file mode 100644 index 73a78af186..0000000000 --- a/libs/ui/DisplayInfo.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include - -#include - -#define RETURN_IF_ERROR(op) \ - if (const status_t status = (op); status != OK) return status; - -namespace android { - -size_t DisplayInfo::getFlattenedSize() const { - return FlattenableHelpers::getFlattenedSize(connectionType) + - FlattenableHelpers::getFlattenedSize(density) + - FlattenableHelpers::getFlattenedSize(secure) + - FlattenableHelpers::getFlattenedSize(deviceProductInfo); -} - -status_t DisplayInfo::flatten(void* buffer, size_t size) const { - if (size < getFlattenedSize()) { - return NO_MEMORY; - } - RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, connectionType)); - RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, density)); - RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, secure)); - RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, deviceProductInfo)); - return OK; -} - -status_t DisplayInfo::unflatten(void const* buffer, size_t size) { - RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &connectionType)); - RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &density)); - RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &secure)); - RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &deviceProductInfo)); - return OK; -} - -} // namespace android diff --git a/libs/ui/DisplayMode.cpp b/libs/ui/DisplayMode.cpp new file mode 100644 index 0000000000..cf05dbfb05 --- /dev/null +++ b/libs/ui/DisplayMode.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +#define RETURN_IF_ERROR(op) \ + if (const status_t status = (op); status != OK) return status; + +namespace android::ui { + +size_t DisplayMode::getFlattenedSize() const { + return FlattenableHelpers::getFlattenedSize(id) + + FlattenableHelpers::getFlattenedSize(resolution) + + FlattenableHelpers::getFlattenedSize(xDpi) + + FlattenableHelpers::getFlattenedSize(yDpi) + + FlattenableHelpers::getFlattenedSize(refreshRate) + + FlattenableHelpers::getFlattenedSize(appVsyncOffset) + + FlattenableHelpers::getFlattenedSize(sfVsyncOffset) + + FlattenableHelpers::getFlattenedSize(presentationDeadline) + + FlattenableHelpers::getFlattenedSize(group); +} + +status_t DisplayMode::flatten(void* buffer, size_t size) const { + if (size < getFlattenedSize()) { + return NO_MEMORY; + } + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, id)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, resolution)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, xDpi)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, yDpi)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, refreshRate)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, appVsyncOffset)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, sfVsyncOffset)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, presentationDeadline)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, group)); + return OK; +} + +status_t DisplayMode::unflatten(const void* buffer, size_t size) { + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &id)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &resolution)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &xDpi)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &yDpi)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &refreshRate)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &appVsyncOffset)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &sfVsyncOffset)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &presentationDeadline)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &group)); + return OK; +} + +} // namespace android::ui diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp new file mode 100644 index 0000000000..11acdae921 --- /dev/null +++ b/libs/ui/DynamicDisplayInfo.cpp @@ -0,0 +1,66 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +#define RETURN_IF_ERROR(op) \ + if (const status_t status = (op); status != OK) return status; + +namespace android::ui { + +std::optional DynamicDisplayInfo::getActiveDisplayMode() const { + for (const auto& currMode : supportedDisplayModes) { + if (currMode.id == activeDisplayModeId) { + return currMode; + } + } + return {}; +} + +size_t DynamicDisplayInfo::getFlattenedSize() const { + return FlattenableHelpers::getFlattenedSize(supportedDisplayModes) + + FlattenableHelpers::getFlattenedSize(activeDisplayModeId) + + FlattenableHelpers::getFlattenedSize(supportedColorModes) + + FlattenableHelpers::getFlattenedSize(activeColorMode) + + FlattenableHelpers::getFlattenedSize(hdrCapabilities); +} + +status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const { + if (size < getFlattenedSize()) { + return NO_MEMORY; + } + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedDisplayModes)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeDisplayModeId)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities)); + return OK; +} + +status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) { + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedDisplayModes)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeDisplayModeId)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities)); + return OK; +} + +} // namespace android::ui diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp index a5b3e89314..aec2fac780 100644 --- a/libs/ui/HdrCapabilities.cpp +++ b/libs/ui/HdrCapabilities.cpp @@ -23,10 +23,6 @@ namespace android { #pragma clang diagnostic ignored "-Wundefined-reinterpret-cast" #endif -HdrCapabilities::~HdrCapabilities() = default; -HdrCapabilities::HdrCapabilities(HdrCapabilities&& other) noexcept = default; -HdrCapabilities& HdrCapabilities::operator=(HdrCapabilities&& other) noexcept = default; - size_t HdrCapabilities::getFlattenedSize() const { return sizeof(mMaxLuminance) + sizeof(mMaxAverageLuminance) + diff --git a/libs/ui/StaticDisplayInfo.cpp b/libs/ui/StaticDisplayInfo.cpp new file mode 100644 index 0000000000..b66b281394 --- /dev/null +++ b/libs/ui/StaticDisplayInfo.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include + +#define RETURN_IF_ERROR(op) \ + if (const status_t status = (op); status != OK) return status; + +namespace android::ui { + +size_t StaticDisplayInfo::getFlattenedSize() const { + return FlattenableHelpers::getFlattenedSize(connectionType) + + FlattenableHelpers::getFlattenedSize(density) + + FlattenableHelpers::getFlattenedSize(secure) + + FlattenableHelpers::getFlattenedSize(deviceProductInfo); +} + +status_t StaticDisplayInfo::flatten(void* buffer, size_t size) const { + if (size < getFlattenedSize()) { + return NO_MEMORY; + } + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, connectionType)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, density)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, secure)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, deviceProductInfo)); + return OK; +} + +status_t StaticDisplayInfo::unflatten(void const* buffer, size_t size) { + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &connectionType)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &density)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &secure)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &deviceProductInfo)); + return OK; +} + +} // namespace android::ui diff --git a/libs/ui/include/ui/DisplayInfo.h b/libs/ui/include/ui/DisplayInfo.h deleted file mode 100644 index 03e0a3886e..0000000000 --- a/libs/ui/include/ui/DisplayInfo.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#include -#include - -namespace android { - -enum class DisplayConnectionType { Internal, External }; - -// Immutable information about physical display. -struct DisplayInfo : LightFlattenable { - DisplayConnectionType connectionType = DisplayConnectionType::Internal; - float density = 0.f; - bool secure = false; - std::optional deviceProductInfo; - - bool isFixedSize() const { return false; } - size_t getFlattenedSize() const; - status_t flatten(void* buffer, size_t size) const; - status_t unflatten(void const* buffer, size_t size); -}; - -} // namespace android diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h index 145d7efd19..56f68e7bb2 100644 --- a/libs/ui/include/ui/DisplayMode.h +++ b/libs/ui/include/ui/DisplayMode.h @@ -16,15 +16,21 @@ #pragma once +#include #include #include +#include #include namespace android::ui { +// This value is going to be serialized over binder so we prefer a fixed width type. +using DisplayModeId = int32_t; + // Mode supported by physical display. -struct DisplayMode { +struct DisplayMode : LightFlattenable { + DisplayModeId id; ui::Size resolution; float xDpi = 0; float yDpi = 0; @@ -33,9 +39,12 @@ struct DisplayMode { nsecs_t appVsyncOffset = 0; nsecs_t sfVsyncOffset = 0; nsecs_t presentationDeadline = 0; - int group = -1; -}; + int32_t group = -1; -static_assert(std::is_trivially_copyable_v); + bool isFixedSize() const { return false; } + size_t getFlattenedSize() const; + status_t flatten(void* buffer, size_t size) const; + status_t unflatten(const void* buffer, size_t size); +}; } // namespace android::ui diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h new file mode 100644 index 0000000000..6c349b749d --- /dev/null +++ b/libs/ui/include/ui/DynamicDisplayInfo.h @@ -0,0 +1,52 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "DisplayMode.h" + +#include +#include +#include + +#include +#include +#include + +namespace android::ui { + +// Information about a physical display which may change on hotplug reconnect. +struct DynamicDisplayInfo : LightFlattenable { + std::vector supportedDisplayModes; + + // This struct is going to be serialized over binder, so + // we can't use size_t because it may have different width + // in the client process. + int32_t activeDisplayModeId; + + std::vector supportedColorModes; + ui::ColorMode activeColorMode; + HdrCapabilities hdrCapabilities; + + std::optional getActiveDisplayMode() const; + + bool isFixedSize() const { return false; } + size_t getFlattenedSize() const; + status_t flatten(void* buffer, size_t size) const; + status_t unflatten(const void* buffer, size_t size); +}; + +} // namespace android::ui diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h index 65ac26cf7e..813addeca6 100644 --- a/libs/ui/include/ui/HdrCapabilities.h +++ b/libs/ui/include/ui/HdrCapabilities.h @@ -36,18 +36,12 @@ public: mMaxAverageLuminance(maxAverageLuminance), mMinLuminance(minLuminance) {} - // Make this move-constructable and move-assignable - HdrCapabilities(HdrCapabilities&& other) noexcept; - HdrCapabilities& operator=(HdrCapabilities&& other) noexcept; - HdrCapabilities() : mSupportedHdrTypes(), mMaxLuminance(-1.0f), mMaxAverageLuminance(-1.0f), mMinLuminance(-1.0f) {} - ~HdrCapabilities(); - const std::vector& getSupportedHdrTypes() const { return mSupportedHdrTypes; } diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h new file mode 100644 index 0000000000..e86ca29a2a --- /dev/null +++ b/libs/ui/include/ui/StaticDisplayInfo.h @@ -0,0 +1,41 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +namespace android::ui { + +enum class DisplayConnectionType { Internal, External }; + +// Immutable information about physical display. +struct StaticDisplayInfo : LightFlattenable { + DisplayConnectionType connectionType = DisplayConnectionType::Internal; + float density = 0.f; + bool secure = false; + std::optional deviceProductInfo; + + bool isFixedSize() const { return false; } + size_t getFlattenedSize() const; + status_t flatten(void* buffer, size_t size) const; + status_t unflatten(void const* buffer, size_t size); +}; + +} // namespace android::ui diff --git a/libs/ui/include_vndk/ui/DisplayInfo.h b/libs/ui/include_vndk/ui/DisplayInfo.h deleted file mode 120000 index 75f14cf66d..0000000000 --- a/libs/ui/include_vndk/ui/DisplayInfo.h +++ /dev/null @@ -1 +0,0 @@ -../../include/ui/DisplayInfo.h \ No newline at end of file diff --git a/libs/ui/include_vndk/ui/StaticDisplayInfo.h b/libs/ui/include_vndk/ui/StaticDisplayInfo.h new file mode 120000 index 0000000000..541a7a37b9 --- /dev/null +++ b/libs/ui/include_vndk/ui/StaticDisplayInfo.h @@ -0,0 +1 @@ +../../include/ui/StaticDisplayInfo.h \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 95ba9f0429..633668e1c2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -21,9 +21,9 @@ #include #include -#include #include #include +#include #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/PowerAdvisor.h" @@ -39,7 +39,7 @@ class CompositionEngine; struct DisplayCreationArgs { struct Physical { DisplayId id; - DisplayConnectionType type; + ui::DisplayConnectionType type; }; // Required for physical displays. Gives the HWC display id for the existing diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 0b0b8d5e9c..a605fe1dc3 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -55,7 +55,8 @@ void Display::setConfiguration(const compositionengine::DisplayCreationArgs& arg editState().isSecure = args.isSecure; editState().displaySpace.bounds = Rect(args.pixels); setLayerStackFilter(args.layerStackId, - args.physical && args.physical->type == DisplayConnectionType::Internal); + args.physical && + args.physical->type == ui::DisplayConnectionType::Internal); setName(args.name); mGpuVirtualDisplayIdGenerator = args.gpuVirtualDisplayIdGenerator; diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 348ec398ae..8a83639ce5 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -35,8 +35,8 @@ #include #include #include -#include #include +#include #include "MockHWC2.h" #include "MockHWComposer.h" @@ -169,7 +169,7 @@ struct DisplayTestCommon : public testing::Test { DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() { return DisplayCreationArgsBuilder() - .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal}) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setPixelFormat(static_cast(PIXEL_FORMAT_RGBA_8888)) .setIsSecure(true) @@ -265,7 +265,7 @@ TEST_F(DisplaySetConfigurationTest, configuresInternalSecurePhysicalDisplay) { mDisplay->setConfiguration( DisplayCreationArgsBuilder() .setUseHwcVirtualDisplays(true) - .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal}) .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) .setPixelFormat(static_cast(PIXEL_FORMAT_RGBA_8888)) .setIsSecure(true) @@ -286,7 +286,7 @@ TEST_F(DisplaySetConfigurationTest, configuresExternalInsecurePhysicalDisplay) { mDisplay->setConfiguration( DisplayCreationArgsBuilder() .setUseHwcVirtualDisplays(true) - .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::External}) + .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::External}) .setPixels(ui::Size(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_WIDTH)) .setPixelFormat(static_cast(PIXEL_FORMAT_RGBA_8888)) .setIsSecure(false) @@ -1018,7 +1018,7 @@ struct DisplayFunctionalTest : public testing::Test { std::shared_ptr mDisplay = impl::createDisplayTemplated< Display>(mCompositionEngine, DisplayCreationArgsBuilder() - .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal}) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setPixelFormat(static_cast(PIXEL_FORMAT_RGBA_8888)) .setIsSecure(true) diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index ab003852de..bac894a6dc 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -91,7 +91,7 @@ public: MOCK_CONST_METHOD1(getColorModes, std::vector(PhysicalDisplayId)); MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent)); MOCK_CONST_METHOD0(isUsingVrComposer, bool()); - MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId)); + MOCK_CONST_METHOD1(getDisplayConnectionType, ui::DisplayConnectionType(PhysicalDisplayId)); MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId)); MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*)); MOCK_METHOD4(setActiveModeWithConstraints, diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index c751f22c97..36c4c4d5ba 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -173,7 +173,7 @@ const DisplayModes& DisplayDevice::getSupportedModes() const { DisplayModePtr DisplayDevice::getMode(DisplayModeId modeId) const { const auto id = modeId.value(); - if (id < mSupportedModes.size()) { + if (static_cast(id) < mSupportedModes.size()) { return mSupportedModes[id]; } return nullptr; @@ -254,7 +254,7 @@ ui::Transform::RotationFlags DisplayDevice::getPrimaryDisplayRotationFlags() { std::string DisplayDevice::getDebugName() const { const char* type = "virtual"; if (mConnectionType) { - type = *mConnectionType == DisplayConnectionType::Internal ? "internal" : "external"; + type = *mConnectionType == ui::DisplayConnectionType::Internal ? "internal" : "external"; } return base::StringPrintf("DisplayDevice{%s, %s%s, \"%s\"}", to_string(getId()).c_str(), type, diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index b4db933e19..a94bfa269d 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -28,11 +28,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -74,7 +74,7 @@ public: return mCompositionDisplay; } - std::optional getConnectionType() const { return mConnectionType; } + std::optional getConnectionType() const { return mConnectionType; } bool isVirtual() const { return !mConnectionType; } bool isPrimary() const { return mIsPrimary; } @@ -195,7 +195,7 @@ private: HWComposer& mHwComposer; const wp mDisplayToken; const int32_t mSequenceId; - const std::optional mConnectionType; + const std::optional mConnectionType; const std::shared_ptr mCompositionDisplay; @@ -222,7 +222,7 @@ private: struct DisplayDeviceState { struct Physical { PhysicalDisplayId id; - DisplayConnectionType type; + ui::DisplayConnectionType type; hardware::graphics::composer::hal::HWDisplayId hwcDisplayId; std::optional deviceProductInfo; DisplayModes supportedModes; @@ -263,7 +263,7 @@ struct DisplayDeviceCreationArgs { const std::shared_ptr compositionDisplay; int32_t sequenceId{0}; - std::optional connectionType; + std::optional connectionType; bool isSecure{false}; sp nativeWindow; sp displaySurface; diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h index 1f0f3c3c33..853c05b244 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayMode.h +++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -36,7 +37,7 @@ namespace hal = android::hardware::graphics::composer::hal; class DisplayMode; using DisplayModePtr = std::shared_ptr; using DisplayModes = std::vector; -using DisplayModeId = StrongTyping; +using DisplayModeId = StrongTyping; class DisplayMode { public: @@ -139,7 +140,7 @@ private: }; inline std::string to_string(const DisplayMode& mode) { - return base::StringPrintf("{id=%zu, hwcId=%d, width=%d, height=%d, refreshRate=%s, " + return base::StringPrintf("{id=%d, hwcId=%d, width=%d, height=%d, refreshRate=%s, " "dpiX=%.2f, dpiY=%.2f, group=%d}", mode.getId().value(), mode.getHwcId(), mode.getWidth(), mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(), diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 71a3276d1b..d04b5f7316 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -264,7 +264,7 @@ Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests, return Error::NONE; } -Error Display::getConnectionType(android::DisplayConnectionType* outType) const { +Error Display::getConnectionType(ui::DisplayConnectionType* outType) const { if (mType != DisplayType::PHYSICAL) return Error::BAD_DISPLAY; using ConnectionType = Hwc2::IComposerClient::DisplayConnectionType; @@ -274,9 +274,8 @@ Error Display::getConnectionType(android::DisplayConnectionType* outType) const return error; } - *outType = connectionType == ConnectionType::INTERNAL - ? android::DisplayConnectionType::Internal - : android::DisplayConnectionType::External; + *outType = connectionType == ConnectionType::INTERNAL ? ui::DisplayConnectionType::Internal + : ui::DisplayConnectionType::External; return Error::NONE; } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 4c7f28412d..e7bf286d08 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -18,9 +18,9 @@ #include #include -#include #include #include +#include #include #include #include @@ -104,7 +104,7 @@ public: hal::DisplayRequest* outDisplayRequests, std::unordered_map* outLayerRequests) = 0; [[clang::warn_unused_result]] virtual hal::Error getConnectionType( - android::DisplayConnectionType*) const = 0; + ui::DisplayConnectionType*) const = 0; [[clang::warn_unused_result]] virtual hal::Error supportsDoze(bool* outSupport) const = 0; [[clang::warn_unused_result]] virtual hal::Error getHdrCapabilities( android::HdrCapabilities* outCapabilities) const = 0; @@ -175,7 +175,7 @@ public: hal::Error getRequests( hal::DisplayRequest* outDisplayRequests, std::unordered_map* outLayerRequests) override; - hal::Error getConnectionType(android::DisplayConnectionType*) const override; + hal::Error getConnectionType(ui::DisplayConnectionType*) const override; hal::Error supportsDoze(bool* outSupport) const override; hal::Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override; hal::Error getDisplayedContentSamplingAttributes(hal::PixelFormat* outFormat, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index b9a8e4be37..ccfaa76374 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -369,16 +369,16 @@ std::optional HWComposer::getActiveMode(PhysicalDisplayId displ // Composer 2.4 -DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const { - RETURN_IF_INVALID_DISPLAY(displayId, DisplayConnectionType::Internal); +ui::DisplayConnectionType HWComposer::getDisplayConnectionType(PhysicalDisplayId displayId) const { + RETURN_IF_INVALID_DISPLAY(displayId, ui::DisplayConnectionType::Internal); const auto& hwcDisplay = mDisplayData.at(displayId).hwcDisplay; - DisplayConnectionType type; + ui::DisplayConnectionType type; const auto error = hwcDisplay->getConnectionType(&type); const auto FALLBACK_TYPE = hwcDisplay->getId() == mInternalHwcDisplayId - ? DisplayConnectionType::Internal - : DisplayConnectionType::External; + ? ui::DisplayConnectionType::Internal + : ui::DisplayConnectionType::External; RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE); return type; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index f9c8e2efef..cf6bc68897 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -204,7 +204,7 @@ public: ui::RenderIntent) = 0; // Composer 2.4 - virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0; + virtual ui::DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0; virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0; virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId, nsecs_t* outVsyncPeriod) const = 0; @@ -335,7 +335,7 @@ public: status_t setActiveColorMode(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent) override; // Composer 2.4 - DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override; + ui::DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override; bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override; status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId, nsecs_t* outVsyncPeriod) const override; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index a03f79384e..de11c16f64 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -64,7 +64,7 @@ using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; std::string RefreshRate::toString() const { - return base::StringPrintf("{id=%zu, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", + return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", getModeId().value(), mode->getHwcId(), getFps().getValue(), mode->getWidth(), mode->getHeight(), getModeGroup()); } @@ -89,7 +89,7 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { } std::string RefreshRateConfigs::Policy::toString() const { - return base::StringPrintf("default mode ID: %zu, allowGroupSwitching = %d" + return base::StringPrintf("default mode ID: %d, allowGroupSwitching = %d" ", primary range: %s, app request range: %s", defaultMode.value(), allowGroupSwitching, primaryRange.toString().c_str(), appRequestRange.toString().c_str()); @@ -724,7 +724,7 @@ void RefreshRateConfigs::getSortedRefreshRateListLocked( outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { if (shouldAddRefreshRate(*refreshRate)) { - ALOGV("getSortedRefreshRateListLocked: mode %zu added to list policy", + ALOGV("getSortedRefreshRateListLocked: mode %d added to list policy", refreshRate->modeId.value()); outRefreshRates->push_back(refreshRate.get()); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7fada820e4..ecf535835a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -68,12 +68,13 @@ #include #include #include -#include #include #include #include +#include #include #include +#include #include #include #include @@ -854,7 +855,8 @@ status_t SurfaceFlinger::getDisplayState(const sp& displayToken, ui::Di return NO_ERROR; } -status_t SurfaceFlinger::getDisplayInfo(const sp& displayToken, DisplayInfo* info) { +status_t SurfaceFlinger::getStaticDisplayInfo(const sp& displayToken, + ui::StaticDisplayInfo* info) { if (!displayToken || !info) { return BAD_VALUE; } @@ -875,7 +877,7 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& displayToken, Display if (mEmulatedDisplayDensity) { info->density = mEmulatedDisplayDensity; } else { - info->density = info->connectionType == DisplayConnectionType::Internal + info->density = info->connectionType == ui::DisplayConnectionType::Internal ? mInternalDisplayDensity : FALLBACK_DENSITY; } @@ -887,9 +889,9 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& displayToken, Display return NO_ERROR; } -status_t SurfaceFlinger::getDisplayModes(const sp& displayToken, - Vector* modes) { - if (!displayToken || !modes) { +status_t SurfaceFlinger::getDynamicDisplayInfo(const sp& displayToken, + ui::DynamicDisplayInfo* info) { + if (!displayToken || !info) { return BAD_VALUE; } @@ -900,16 +902,25 @@ status_t SurfaceFlinger::getDisplayModes(const sp& displayToken, return NAME_NOT_FOUND; } - modes->clear(); + info->activeDisplayModeId = static_cast(display->getActiveMode()->getId().value()); + if (display->isPrimary()) { + if (const auto mode = getDesiredActiveMode()) { + info->activeDisplayModeId = static_cast(mode->modeId.value()); + } + } - for (const auto& supportedMode : display->getSupportedModes()) { - ui::DisplayMode mode; + const auto& supportedModes = display->getSupportedModes(); + info->supportedDisplayModes.clear(); + info->supportedDisplayModes.reserve(supportedModes.size()); + for (const auto& mode : supportedModes) { + ui::DisplayMode outMode; + outMode.id = static_cast(mode->getId().value()); - auto width = supportedMode->getWidth(); - auto height = supportedMode->getHeight(); + auto width = mode->getWidth(); + auto height = mode->getHeight(); - auto xDpi = supportedMode->getDpiX(); - auto yDpi = supportedMode->getDpiY(); + auto xDpi = mode->getDpiX(); + auto yDpi = mode->getDpiY(); if (display->isPrimary() && (internalDisplayOrientation == ui::ROTATION_90 || @@ -918,24 +929,24 @@ status_t SurfaceFlinger::getDisplayModes(const sp& displayToken, std::swap(xDpi, yDpi); } - mode.resolution = ui::Size(width, height); + outMode.resolution = ui::Size(width, height); if (mEmulatedDisplayDensity) { - mode.xDpi = mEmulatedDisplayDensity; - mode.yDpi = mEmulatedDisplayDensity; + outMode.xDpi = mEmulatedDisplayDensity; + outMode.yDpi = mEmulatedDisplayDensity; } else { - mode.xDpi = xDpi; - mode.yDpi = yDpi; + outMode.xDpi = xDpi; + outMode.yDpi = yDpi; } - const nsecs_t period = supportedMode->getVsyncPeriod(); - mode.refreshRate = Fps::fromPeriodNsecs(period).getValue(); + const nsecs_t period = mode->getVsyncPeriod(); + outMode.refreshRate = Fps::fromPeriodNsecs(period).getValue(); const auto vsyncConfigSet = - mVsyncConfiguration->getConfigsForRefreshRate(Fps(mode.refreshRate)); - mode.appVsyncOffset = vsyncConfigSet.late.appOffset; - mode.sfVsyncOffset = vsyncConfigSet.late.sfOffset; - mode.group = supportedMode->getGroup(); + mVsyncConfiguration->getConfigsForRefreshRate(Fps(outMode.refreshRate)); + outMode.appVsyncOffset = vsyncConfigSet.late.appOffset; + outMode.sfVsyncOffset = vsyncConfigSet.late.sfOffset; + outMode.group = mode->getGroup(); // This is how far in advance a buffer must be queued for // presentation at a given time. If you want a buffer to appear @@ -949,11 +960,15 @@ status_t SurfaceFlinger::getDisplayModes(const sp& displayToken, // // We add an additional 1ms to allow for processing time and // differences between the ideal and actual refresh rate. - mode.presentationDeadline = period - mode.sfVsyncOffset + 1000000; + outMode.presentationDeadline = period - outMode.sfVsyncOffset + 1000000; - modes->push_back(mode); + info->supportedDisplayModes.push_back(outMode); } + info->activeColorMode = display->getCompositionDisplay()->getState().colorMode; + info->supportedColorModes = getDisplayColorModes(display->getPhysicalId()); + + info->hdrCapabilities = display->getHdrCapabilities(); return NO_ERROR; } @@ -966,31 +981,6 @@ status_t SurfaceFlinger::getDisplayStats(const sp&, DisplayStatInfo* st return NO_ERROR; } -int SurfaceFlinger::getActiveDisplayModeId(const sp& displayToken) { - int activeMode; - bool isPrimary; - - { - Mutex::Autolock lock(mStateLock); - - if (const auto display = getDisplayDeviceLocked(displayToken)) { - activeMode = display->getActiveMode()->getId().value(); - isPrimary = display->isPrimary(); - } else { - ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get()); - return NAME_NOT_FOUND; - } - } - - if (isPrimary) { - if (const auto mode = getDesiredActiveMode()) { - return mode->modeId.value(); - } - } - - return activeMode; -} - void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) { ATRACE_CALL(); auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId); @@ -1082,7 +1072,7 @@ void SurfaceFlinger::setActiveModeInternal() { const auto upcomingMode = display->getMode(mUpcomingActiveMode.modeId); if (!upcomingMode) { - ALOGW("Upcoming active mode is no longer supported. Mode ID = %zu", + ALOGW("Upcoming active mode is no longer supported. Mode ID = %d", mUpcomingActiveMode.modeId.value()); // TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may // have been already updated with the upcoming active mode. @@ -1142,13 +1132,13 @@ void SurfaceFlinger::performSetActiveMode() { const auto display = getDefaultDisplayDeviceLocked(); const auto desiredMode = display->getMode(desiredActiveMode->modeId); if (!desiredMode) { - ALOGW("Desired display mode is no longer supported. Mode ID = %zu", + ALOGW("Desired display mode is no longer supported. Mode ID = %d", desiredActiveMode->modeId.value()); clearDesiredActiveModeState(); return; } const auto refreshRate = desiredMode->getFps(); - ALOGV("%s changing active mode to %zu(%s)", __FUNCTION__, desiredMode->getId().value(), + ALOGV("%s changing active mode to %d(%s)", __FUNCTION__, desiredMode->getId().value(), to_string(refreshRate).c_str()); if (!display || display->getActiveMode()->getId() == desiredActiveMode->modeId) { @@ -1190,39 +1180,20 @@ void SurfaceFlinger::performSetActiveMode() { mSetActiveModePending = true; } -status_t SurfaceFlinger::getDisplayColorModes(const sp& displayToken, - Vector* outColorModes) { - if (!displayToken || !outColorModes) { - return BAD_VALUE; - } - - std::vector modes; - bool isInternalDisplay = false; - { - ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - - const auto displayId = getPhysicalDisplayIdLocked(displayToken); - if (!displayId) { - return NAME_NOT_FOUND; - } - - modes = getHwComposer().getColorModes(*displayId); - isInternalDisplay = displayId == getInternalDisplayIdLocked(); - } - outColorModes->clear(); +std::vector SurfaceFlinger::getDisplayColorModes(PhysicalDisplayId displayId) { + auto modes = getHwComposer().getColorModes(displayId); + bool isInternalDisplay = displayId == getInternalDisplayIdLocked(); // If it's built-in display and the configuration claims it's not wide color capable, // filter out all wide color modes. The typical reason why this happens is that the // hardware is not good enough to support GPU composition of wide color, and thus the // OEMs choose to disable this capability. if (isInternalDisplay && !hasWideColorDisplay) { - std::remove_copy_if(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes), - isWideColorMode); - } else { - std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes)); + const auto newEnd = std::remove_if(modes.begin(), modes.end(), isWideColorMode); + modes.erase(newEnd, modes.end()); } - return NO_ERROR; + return modes; } status_t SurfaceFlinger::getDisplayNativePrimaries(const sp& displayToken, @@ -1240,19 +1211,14 @@ status_t SurfaceFlinger::getDisplayNativePrimaries(const sp& displayTok return NO_ERROR; } -ColorMode SurfaceFlinger::getActiveColorMode(const sp& displayToken) { - Mutex::Autolock lock(mStateLock); - - if (const auto display = getDisplayDeviceLocked(displayToken)) { - return display->getCompositionDisplay()->getState().colorMode; - } - return static_cast(BAD_VALUE); -} - status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, ColorMode mode) { schedule([=]() MAIN_THREAD { - Vector modes; - getDisplayColorModes(displayToken, &modes); + const auto displayId = getPhysicalDisplayIdLocked(displayToken); + if (!displayId) { + ALOGE("Invalid display token %p", displayToken.get()); + return; + } + const auto modes = getDisplayColorModes(*displayId); bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes); if (mode < ColorMode::NATIVE || !exists) { ALOGE("Attempt to set invalid active color mode %s (%d) for display token %p", @@ -1349,28 +1315,6 @@ status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const { return NO_ERROR; } -status_t SurfaceFlinger::getHdrCapabilities(const sp& displayToken, - HdrCapabilities* outCapabilities) const { - Mutex::Autolock lock(mStateLock); - - const auto display = getDisplayDeviceLocked(displayToken); - if (!display) { - ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get()); - return NAME_NOT_FOUND; - } - - // At this point the DisplayDevice should already be set up, - // meaning the luminance information is already queried from - // hardware composer and stored properly. - const HdrCapabilities& capabilities = display->getHdrCapabilities(); - *outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(), - capabilities.getDesiredMaxLuminance(), - capabilities.getDesiredMaxAverageLuminance(), - capabilities.getDesiredMinLuminance()); - - return NO_ERROR; -} - status_t SurfaceFlinger::getDisplayedContentSamplingAttributes(const sp& displayToken, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace, @@ -1640,7 +1584,7 @@ void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, // Don't do any updating if the current fps is the same as the new one. if (!isDisplayModeAllowed(refreshRate.getModeId())) { - ALOGV("Skipping mode %zu as it is not part of allowed modes", + ALOGV("Skipping mode %d as it is not part of allowed modes", refreshRate.getModeId().value()); return; } @@ -2360,7 +2304,7 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) { DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const { const auto hwcModes = getHwComposer().getModes(displayId); DisplayModes modes; - size_t nextModeId = 0; + int32_t nextModeId = 0; for (const auto& hwcMode : hwcModes) { modes.push_back(DisplayMode::Builder(hwcMode.hwcId) .setId(DisplayModeId{nextModeId++}) @@ -5013,7 +4957,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case GET_PHYSICAL_DISPLAY_TOKEN: case GET_DISPLAY_COLOR_MODES: case GET_DISPLAY_NATIVE_PRIMARIES: - case GET_DISPLAY_INFO: + case GET_STATIC_DISPLAY_INFO: + case GET_DYNAMIC_DISPLAY_INFO: case GET_DISPLAY_MODES: case GET_DISPLAY_STATE: case GET_DISPLAY_STATS: @@ -6141,27 +6086,25 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId) // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode); - ALOGV("trying to switch to Scheduler preferred mode %zu (%s)", + ALOGV("trying to switch to Scheduler preferred mode %d (%s)", preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str()); if (isDisplayModeAllowed(preferredRefreshRate.getModeId())) { - ALOGV("switching to Scheduler preferred display mode %zu", + ALOGV("switching to Scheduler preferred display mode %d", preferredRefreshRate.getModeId().value()); setDesiredActiveMode({preferredRefreshRate.getModeId(), Scheduler::ModeEvent::Changed}); } else { - LOG_ALWAYS_FATAL("Desired display mode not allowed: %zu", + LOG_ALWAYS_FATAL("Desired display mode not allowed: %d", preferredRefreshRate.getModeId().value()); } return NO_ERROR; } -status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp& displayToken, - size_t defaultMode, bool allowGroupSwitching, - float primaryRefreshRateMin, - float primaryRefreshRateMax, - float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { +status_t SurfaceFlinger::setDesiredDisplayModeSpecs( + const sp& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin, + float appRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken) { @@ -6192,10 +6135,13 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp& displayTo return future.get(); } -status_t SurfaceFlinger::getDesiredDisplayModeSpecs( - const sp& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching, - float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, - float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) { +status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId* outDefaultMode, + bool* outAllowGroupSwitching, + float* outPrimaryRefreshRateMin, + float* outPrimaryRefreshRateMax, + float* outAppRequestRefreshRateMin, + float* outAppRequestRefreshRateMax) { ATRACE_CALL(); if (!displayToken || !outDefaultMode || !outPrimaryRefreshRateMin || diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a62d0b9a95..21cd2a5682 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -552,14 +552,14 @@ private: const sp& captureListener) override; status_t getDisplayStats(const sp& displayToken, DisplayStatInfo* stats) override; - status_t getDisplayState(const sp& displayToken, ui::DisplayState*) override; - status_t getDisplayInfo(const sp& displayToken, DisplayInfo*) override; - status_t getDisplayModes(const sp& displayToken, Vector*) override; - int getActiveDisplayModeId(const sp& displayToken) override; - status_t getDisplayColorModes(const sp& displayToken, Vector*) override; + status_t getDisplayState(const sp& displayToken, ui::DisplayState*) + EXCLUDES(mStateLock) override; + status_t getStaticDisplayInfo(const sp& displayToken, ui::StaticDisplayInfo*) + EXCLUDES(mStateLock) override; + status_t getDynamicDisplayInfo(const sp& displayToken, ui::DynamicDisplayInfo*) + EXCLUDES(mStateLock) override; status_t getDisplayNativePrimaries(const sp& displayToken, ui::DisplayPrimaries&) override; - ui::ColorMode getActiveColorMode(const sp& displayToken) override; status_t setActiveColorMode(const sp& displayToken, ui::ColorMode colorMode) override; status_t getAutoLowLatencyModeSupport(const sp& displayToken, bool* outSupported) const override; @@ -570,8 +570,6 @@ private: void setPowerMode(const sp& displayToken, int mode) override; status_t clearAnimationFrameStats() override; status_t getAnimationFrameStats(FrameStats* outStats) const override; - status_t getHdrCapabilities(const sp& displayToken, - HdrCapabilities* outCapabilities) const override; status_t enableVSyncInjections(bool enable) override; status_t injectVSync(nsecs_t when) override; status_t getLayerDebugInfo(std::vector* outLayers) override; @@ -594,11 +592,13 @@ private: status_t addRegionSamplingListener(const Rect& samplingArea, const sp& stopLayerHandle, const sp& listener) override; status_t removeRegionSamplingListener(const sp& listener) override; - status_t setDesiredDisplayModeSpecs(const sp& displayToken, size_t displayModeId, - bool allowGroupSwitching, float primaryRefreshRateMin, - float primaryRefreshRateMax, float appRequestRefreshRateMin, + status_t setDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId displayModeId, bool allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, float appRequestRefreshRateMax) override; - status_t getDesiredDisplayModeSpecs(const sp& displayToken, size_t* outDefaultMode, + status_t getDesiredDisplayModeSpecs(const sp& displayToken, + ui::DisplayModeId* outDefaultMode, bool* outAllowGroupSwitching, float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax, @@ -1054,6 +1054,9 @@ private: return std::nullopt; } + std::vector getDisplayColorModes(PhysicalDisplayId displayId) + REQUIRES(mStateLock); + static int calculateExtraBufferCount(Fps maxSupportedRefreshRate, std::chrono::nanoseconds presentLatency); diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index 53e37d874e..6246321fab 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include "utils/ScreenshotUtils.h" @@ -188,19 +189,15 @@ TEST_F(CredentialsTest, AllowedGetterMethodsTest) { ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode)); Vector modes; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); - - ASSERT_TRUE(SurfaceComposerClient::getActiveDisplayModeId(display) >= 0); - - ASSERT_NE(static_cast(BAD_VALUE), - SurfaceComposerClient::getActiveColorMode(display)); + ui::DynamicDisplayInfo info; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); } -TEST_F(CredentialsTest, GetDisplayColorModesTest) { +TEST_F(CredentialsTest, GetDynamicDisplayInfoTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); std::function condition = [=]() { - Vector outColorModes; - return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes); + ui::DynamicDisplayInfo info; + return SurfaceComposerClient::getDynamicDisplayInfo(display, &info); }; ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, NO_ERROR, NO_ERROR)); } @@ -216,7 +213,7 @@ TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) { TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); - size_t defaultMode; + ui::DisplayModeId defaultMode; bool allowGroupSwitching; float primaryFpsMin; float primaryFpsMax; @@ -355,8 +352,9 @@ TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) { status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result); ASSERT_EQ(NO_ERROR, error); bool hasWideColorMode = false; - Vector colorModes; - SurfaceComposerClient::getDisplayColorModes(display, &colorModes); + ui::DynamicDisplayInfo info; + SurfaceComposerClient::getDynamicDisplayInfo(display, &info); + const auto& colorModes = info.supportedColorModes; for (ColorMode colorMode : colorModes) { switch (colorMode) { case ColorMode::DISPLAY_P3: @@ -384,7 +382,9 @@ TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) { TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ASSERT_FALSE(display == nullptr); - ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display); + ui::DynamicDisplayInfo info; + SurfaceComposerClient::getDynamicDisplayInfo(display, &info); + ColorMode colorMode = info.activeColorMode; ASSERT_NE(static_cast(BAD_VALUE), colorMode); } diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 9f025a6aaa..2dc96b8511 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,7 @@ namespace android { */ class RefreshRateRangeTest : public ::testing::Test { private: - size_t initialDefaultMode; + ui::DisplayModeId initialDefaultMode; bool initialAllowGroupSwitching; float initialPrimaryMin; float initialPrimaryMax; @@ -76,20 +77,21 @@ protected: }; TEST_F(RefreshRateRangeTest, setAllConfigs) { - Vector modes; - status_t res = SurfaceComposerClient::getDisplayModes(mDisplayToken, &modes); + ui::DynamicDisplayInfo info; + status_t res = SurfaceComposerClient::getDynamicDisplayInfo(mDisplayToken, &info); + const auto& modes = info.supportedDisplayModes; ASSERT_EQ(res, NO_ERROR); ASSERT_GT(modes.size(), 0); for (size_t i = 0; i < modes.size(); i++) { - res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, i, false, + res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, modes[i].id, false, modes[i].refreshRate, modes[i].refreshRate, modes[i].refreshRate, modes[i].refreshRate); ASSERT_EQ(res, NO_ERROR); - size_t defaultConfig; + ui::DisplayModeId defaultConfig; bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; @@ -116,7 +118,7 @@ void RefreshRateRangeTest::testSetAllowGroupSwitching(bool allowGroupSwitching) SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, 0, allowGroupSwitching, 0.f, 90.f, 0.f, 90.f); ASSERT_EQ(res, NO_ERROR); - size_t defaultConfig; + ui::DisplayModeId defaultConfig; bool newAllowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 56e1ae90c3..11bd9ebbb8 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -432,8 +433,9 @@ protected: } } - Vector modes; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + ui::DynamicDisplayInfo info; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); + const auto& modes = info.supportedDisplayModes; EXPECT_EQ(modes.size(), 2); // change active mode @@ -539,8 +541,9 @@ protected: } } - Vector modes; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + ui::DynamicDisplayInfo info; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); + const auto& modes = info.supportedDisplayModes; EXPECT_EQ(modes.size(), 2); // change active mode @@ -655,8 +658,9 @@ protected: } } - Vector modes; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + ui::DynamicDisplayInfo info; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); + const auto& modes = info.supportedDisplayModes; EXPECT_EQ(modes.size(), 4); // change active mode to 800x1600@90Hz @@ -884,8 +888,9 @@ protected: EXPECT_EQ(ui::Size(800, 1600), mode.resolution); EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate); - Vector modes; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + ui::DynamicDisplayInfo info; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); + const auto& modes = info.supportedDisplayModes; EXPECT_EQ(modes.size(), 1); } @@ -923,8 +928,9 @@ protected: EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate); } - Vector modes; - EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes)); + ui::DynamicDisplayInfo info; + EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDynamicDisplayInfo(display, &info)); + const auto& modes = info.supportedDisplayModes; EXPECT_EQ(modes.size(), 3); EXPECT_EQ(ui::Size(800, 1600), modes[0].resolution); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index b696a6d51b..256be27b2d 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -286,7 +286,7 @@ struct BaseDisplayVariant { auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder() - .setPhysical({DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + .setPhysical({DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal}) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setIsSecure(Derived::IS_SECURE) .setLayerStackId(DEFAULT_LAYER_STACK) @@ -300,7 +300,7 @@ struct BaseDisplayVariant { ceDisplayArgs); test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay, - DisplayConnectionType::Internal, HWC_DISPLAY, + ui::DisplayConnectionType::Internal, HWC_DISPLAY, true /* isPrimary */) .setDisplaySurface(test->mDisplaySurface) .setNativeWindow(test->mNativeWindow) diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 90692003ef..a3e810871c 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -139,14 +139,14 @@ sp DisplayTransactionTest::injectDefaultInternalDisplay( createDisplay(mFlinger.getCompositionEngine(), compositionengine::DisplayCreationArgsBuilder() .setPhysical( - {DEFAULT_DISPLAY_ID, DisplayConnectionType::Internal}) + {DEFAULT_DISPLAY_ID, ui::DisplayConnectionType::Internal}) .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT}) .setPowerAdvisor(&mPowerAdvisor) .build()); - auto injector = - FakeDisplayDeviceInjector(mFlinger, compositionDisplay, DisplayConnectionType::Internal, - DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */); + auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay, + ui::DisplayConnectionType::Internal, + DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */); injector.setNativeWindow(mNativeWindow); if (injectExtra) { diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 166430193d..d68fff6345 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -202,12 +202,13 @@ struct DisplayIdGetter { template struct DisplayConnectionTypeGetter { - static constexpr std::optional value; + static constexpr std::optional value; }; template struct DisplayConnectionTypeGetter> { - static constexpr std::optional value = PhysicalDisplay::CONNECTION_TYPE; + static constexpr std::optional value = + PhysicalDisplay::CONNECTION_TYPE; }; template @@ -263,7 +264,7 @@ struct DisplayVariant { static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { auto ceDisplayArgs = compositionengine::DisplayCreationArgsBuilder(); if (auto displayId = PhysicalDisplayId::tryCast(DISPLAY_ID::get())) { - ceDisplayArgs.setPhysical({*displayId, DisplayConnectionType::Internal}); + ceDisplayArgs.setPhysical({*displayId, ui::DisplayConnectionType::Internal}); } else { // We turn off the use of HwcVirtualDisplays, to prevent Composition Engine // from calling into HWComposer. This way all virtual displays will get @@ -457,7 +458,7 @@ struct HwcDisplayVariant { static void setupHwcHotplugCallExpectations(DisplayTransactionTest* test) { constexpr auto CONNECTION_TYPE = - PhysicalDisplay::CONNECTION_TYPE == DisplayConnectionType::Internal + PhysicalDisplay::CONNECTION_TYPE == ui::DisplayConnectionType::Internal ? IComposerClient::DisplayConnectionType::INTERNAL : IComposerClient::DisplayConnectionType::EXTERNAL; @@ -504,7 +505,7 @@ struct PhysicalDisplayVariant template struct PrimaryDisplay { - static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal; + static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::Internal; static constexpr Primary PRIMARY = Primary::TRUE; static constexpr uint8_t PORT = 255; static constexpr HWDisplayId HWC_DISPLAY_ID = 1001; @@ -514,7 +515,7 @@ struct PrimaryDisplay { template struct ExternalDisplay { - static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External; + static constexpr auto CONNECTION_TYPE = ui::DisplayConnectionType::External; static constexpr Primary PRIMARY = Primary::FALSE; static constexpr uint8_t PORT = 254; static constexpr HWDisplayId HWC_DISPLAY_ID = 1002; diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index dee13d6e8d..2ba6490cd7 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -634,7 +634,7 @@ public: public: FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, std::shared_ptr compositionDisplay, - std::optional connectionType, + std::optional connectionType, std::optional hwcDisplayId, bool isPrimary) : mFlinger(flinger), mCreationArgs(flinger.mFlinger.get(), flinger.mFlinger->getHwComposer(), -- cgit v1.2.3-59-g8ed1b From b173f7599a8f93786342d27167facf7eae02845e Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Tue, 16 Feb 2021 19:38:36 +0100 Subject: SF: Move ALLM and GameContentType to DynamicDisplayInfo ALLM and Game content type support may change after a hotplug, for that reason we move them to DynamicDisplayInfo. Bug: 180108954 Test: flash a device and manually test that the values are properly piped to DisplayManager Change-Id: I05810c620b241e204d2c01618bb8a4069c41d32d --- libs/gui/ISurfaceComposer.cpp | 70 ---------------------------- libs/gui/SurfaceComposerClient.cpp | 12 ----- libs/gui/include/gui/ISurfaceComposer.h | 27 +++-------- libs/gui/include/gui/SurfaceComposerClient.h | 6 --- libs/gui/tests/Surface_test.cpp | 8 ---- libs/ui/DynamicDisplayInfo.cpp | 8 +++- libs/ui/include/ui/DynamicDisplayInfo.h | 8 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 50 ++++---------------- services/surfaceflinger/SurfaceFlinger.h | 4 -- 9 files changed, 31 insertions(+), 162 deletions(-) (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2e4f858a9d..eba7b3c9fd 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -411,24 +411,6 @@ public: return static_cast(reply.readInt32()); } - status_t getAutoLowLatencyModeSupport(const sp& display, - bool* outSupport) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_AUTO_LOW_LATENCY_MODE_SUPPORT, data, - &reply); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to transact: %d", result); - return result; - } - return reply.readBool(outSupport); - } - void setAutoLowLatencyMode(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -454,23 +436,6 @@ public: } } - status_t getGameContentTypeSupport(const sp& display, - bool* outSupport) const override { - Parcel data, reply; - data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t result = data.writeStrongBinder(display); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to writeStrongBinder: %d", result); - return result; - } - result = remote()->transact(BnSurfaceComposer::GET_GAME_CONTENT_TYPE_SUPPORT, data, &reply); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to transact: %d", result); - return result; - } - return reply.readBool(outSupport); - } - void setGameContentType(const sp& display, bool on) override { Parcel data, reply; status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); @@ -1423,23 +1388,6 @@ status_t BnSurfaceComposer::onTransact( result = reply->writeInt32(result); return result; } - - case GET_AUTO_LOW_LATENCY_MODE_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getAutoLowLatencyModeSupport failed to readStrongBinder: %d", result); - return result; - } - bool supported = false; - result = getAutoLowLatencyModeSupport(display, &supported); - if (result == NO_ERROR) { - result = reply->writeBool(supported); - } - return result; - } - case SET_AUTO_LOW_LATENCY_MODE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = nullptr; @@ -1457,23 +1405,6 @@ status_t BnSurfaceComposer::onTransact( setAutoLowLatencyMode(display, setAllm); return result; } - - case GET_GAME_CONTENT_TYPE_SUPPORT: { - CHECK_INTERFACE(ISurfaceComposer, data, reply); - sp display = nullptr; - status_t result = data.readStrongBinder(&display); - if (result != NO_ERROR) { - ALOGE("getGameContentTypeSupport failed to readStrongBinder: %d", result); - return result; - } - bool supported = false; - result = getGameContentTypeSupport(display, &supported); - if (result == NO_ERROR) { - result = reply->writeBool(supported); - } - return result; - } - case SET_GAME_CONTENT_TYPE: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp display = nullptr; @@ -1491,7 +1422,6 @@ status_t BnSurfaceComposer::onTransact( setGameContentType(display, setGameContentTypeOn); return result; } - case CLEAR_ANIMATION_FRAME_STATS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); status_t result = clearAnimationFrameStats(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0bd2c8811b..f78c12e61e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1876,22 +1876,10 @@ status_t SurfaceComposerClient::setActiveColorMode(const sp& display, return ComposerService::getComposerService()->setActiveColorMode(display, colorMode); } -bool SurfaceComposerClient::getAutoLowLatencyModeSupport(const sp& display) { - bool supported = false; - ComposerService::getComposerService()->getAutoLowLatencyModeSupport(display, &supported); - return supported; -} - void SurfaceComposerClient::setAutoLowLatencyMode(const sp& display, bool on) { ComposerService::getComposerService()->setAutoLowLatencyMode(display, on); } -bool SurfaceComposerClient::getGameContentTypeSupport(const sp& display) { - bool supported = false; - ComposerService::getComposerService()->getGameContentTypeSupport(display, &supported); - return supported; -} - void SurfaceComposerClient::setGameContentType(const sp& display, bool on) { ComposerService::getComposerService()->setGameContentType(display, on); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index d0ab4802e1..6289e5a5d0 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -218,33 +218,18 @@ public: virtual status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode) = 0; - /** - * Returns true if the connected display reports support for HDMI 2.1 Auto - * Low Latency Mode. - * For more information, see the HDMI 2.1 specification. - */ - virtual status_t getAutoLowLatencyModeSupport(const sp& display, - bool* outSupport) const = 0; - /** * Switches Auto Low Latency Mode on/off on the connected display, if it is - * available. This should only be called if #getAutoLowLatencyMode returns - * true. + * available. This should only be called if the display supports Auto Low + * Latency Mode as reported in #getDynamicDisplayInfo. * For more information, see the HDMI 2.1 specification. */ virtual void setAutoLowLatencyMode(const sp& display, bool on) = 0; - /** - * Returns true if the connected display reports support for Game Content Type. - * For more information, see the HDMI 1.4 specification. - */ - virtual status_t getGameContentTypeSupport(const sp& display, - bool* outSupport) const = 0; - /** * This will start sending infoframes to the connected display with - * ContentType=Game (if on=true). This will switch the disply to Game mode. - * This should only be called if #getGameContentTypeSupport returns true. + * ContentType=Game (if on=true). This should only be called if the display + * Game Content Type as reported in #getDynamicDisplayInfo. * For more information, see the HDMI 1.4 specification. */ virtual void setGameContentType(const sp& display, bool on) = 0; @@ -563,9 +548,9 @@ public: CAPTURE_DISPLAY_BY_ID, NOTIFY_POWER_BOOST, SET_GLOBAL_SHADOW_SETTINGS, - GET_AUTO_LOW_LATENCY_MODE_SUPPORT, + GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_AUTO_LOW_LATENCY_MODE, - GET_GAME_CONTENT_TYPE_SUPPORT, + GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead. SET_GAME_CONTENT_TYPE, SET_FRAME_RATE, ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2b72b73d96..2553d40136 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -139,17 +139,11 @@ public: static status_t setActiveColorMode(const sp& display, ui::ColorMode colorMode); - // Reports whether the connected display supports Auto Low Latency Mode - static bool getAutoLowLatencyModeSupport(const sp& display); - // Switches on/off Auto Low Latency Mode on the connected display. This should only be // called if the connected display supports Auto Low Latency Mode as reported by // #getAutoLowLatencyModeSupport static void setAutoLowLatencyMode(const sp& display, bool on); - // Reports whether the connected display supports Game content type - static bool getGameContentTypeSupport(const sp& display); - // Turns Game mode on/off on the connected display. This should only be called // if the display supports Game content type, as reported by #getGameContentTypeSupport static void setGameContentType(const sp& display, bool on); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 3397198fa0..69bb86649c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -757,15 +757,7 @@ public: const sp& /* captureListener */) override { return NO_ERROR; } - status_t getAutoLowLatencyModeSupport(const sp& /*display*/, - bool* /*outSupport*/) const override { - return NO_ERROR; - } void setAutoLowLatencyMode(const sp& /*display*/, bool /*on*/) override {} - status_t getGameContentTypeSupport(const sp& /*display*/, - bool* /*outSupport*/) const override { - return NO_ERROR; - } void setGameContentType(const sp& /*display*/, bool /*on*/) override {} status_t captureDisplay(uint64_t /*displayOrLayerStack*/, const sp& /* captureListener */) override { diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp index 11acdae921..d5c4ef0c17 100644 --- a/libs/ui/DynamicDisplayInfo.cpp +++ b/libs/ui/DynamicDisplayInfo.cpp @@ -39,7 +39,9 @@ size_t DynamicDisplayInfo::getFlattenedSize() const { FlattenableHelpers::getFlattenedSize(activeDisplayModeId) + FlattenableHelpers::getFlattenedSize(supportedColorModes) + FlattenableHelpers::getFlattenedSize(activeColorMode) + - FlattenableHelpers::getFlattenedSize(hdrCapabilities); + FlattenableHelpers::getFlattenedSize(hdrCapabilities) + + FlattenableHelpers::getFlattenedSize(autoLowLatencyModeSupported) + + FlattenableHelpers::getFlattenedSize(gameContentTypeSupported); } status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const { @@ -51,6 +53,8 @@ status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const { RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes)); RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode)); RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, autoLowLatencyModeSupported)); + RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, gameContentTypeSupported)); return OK; } @@ -60,6 +64,8 @@ status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) { RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes)); RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode)); RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &autoLowLatencyModeSupported)); + RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &gameContentTypeSupported)); return OK; } diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h index 6c349b749d..a4c2f71a4c 100644 --- a/libs/ui/include/ui/DynamicDisplayInfo.h +++ b/libs/ui/include/ui/DynamicDisplayInfo.h @@ -41,6 +41,14 @@ struct DynamicDisplayInfo : LightFlattenable { ui::ColorMode activeColorMode; HdrCapabilities hdrCapabilities; + // True if the display reports support for HDMI 2.1 Auto Low Latency Mode. + // For more information, see the HDMI 2.1 specification. + bool autoLowLatencyModeSupported; + + // True if the display reports support for Game Content Type. + // For more information, see the HDMI 1.4 specification. + bool gameContentTypeSupported; + std::optional getActiveDisplayMode() const; bool isFixedSize() const { return false; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ecf535835a..549c123cde 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -966,9 +966,18 @@ status_t SurfaceFlinger::getDynamicDisplayInfo(const sp& displayToken, } info->activeColorMode = display->getCompositionDisplay()->getState().colorMode; - info->supportedColorModes = getDisplayColorModes(display->getPhysicalId()); + const auto displayId = display->getPhysicalId(); + info->supportedColorModes = getDisplayColorModes(displayId); info->hdrCapabilities = display->getHdrCapabilities(); + info->autoLowLatencyModeSupported = + getHwComposer().hasDisplayCapability(displayId, + hal::DisplayCapability::AUTO_LOW_LATENCY_MODE); + std::vector types; + getHwComposer().getSupportedContentTypes(displayId, &types); + info->gameContentTypeSupported = std::any_of(types.begin(), types.end(), [](auto type) { + return type == hal::ContentType::GAME; + }); return NO_ERROR; } @@ -1243,24 +1252,6 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, Col return NO_ERROR; } -status_t SurfaceFlinger::getAutoLowLatencyModeSupport(const sp& displayToken, - bool* outSupport) const { - if (!displayToken) { - return BAD_VALUE; - } - - Mutex::Autolock lock(mStateLock); - - const auto displayId = getPhysicalDisplayIdLocked(displayToken); - if (!displayId) { - return NAME_NOT_FOUND; - } - *outSupport = - getHwComposer().hasDisplayCapability(*displayId, - hal::DisplayCapability::AUTO_LOW_LATENCY_MODE); - return NO_ERROR; -} - void SurfaceFlinger::setAutoLowLatencyMode(const sp& displayToken, bool on) { static_cast(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { @@ -1271,27 +1262,6 @@ void SurfaceFlinger::setAutoLowLatencyMode(const sp& displayToken, bool })); } -status_t SurfaceFlinger::getGameContentTypeSupport(const sp& displayToken, - bool* outSupport) const { - if (!displayToken) { - return BAD_VALUE; - } - - Mutex::Autolock lock(mStateLock); - - const auto displayId = getPhysicalDisplayIdLocked(displayToken); - if (!displayId) { - return NAME_NOT_FOUND; - } - - std::vector types; - getHwComposer().getSupportedContentTypes(*displayId, &types); - - *outSupport = std::any_of(types.begin(), types.end(), - [](auto type) { return type == hal::ContentType::GAME; }); - return NO_ERROR; -} - void SurfaceFlinger::setGameContentType(const sp& displayToken, bool on) { static_cast(schedule([=]() MAIN_THREAD { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 21cd2a5682..d9af7509a1 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -561,11 +561,7 @@ private: status_t getDisplayNativePrimaries(const sp& displayToken, ui::DisplayPrimaries&) override; status_t setActiveColorMode(const sp& displayToken, ui::ColorMode colorMode) override; - status_t getAutoLowLatencyModeSupport(const sp& displayToken, - bool* outSupported) const override; void setAutoLowLatencyMode(const sp& displayToken, bool on) override; - status_t getGameContentTypeSupport(const sp& displayToken, - bool* outSupported) const override; void setGameContentType(const sp& displayToken, bool on) override; void setPowerMode(const sp& displayToken, int mode) override; status_t clearAnimationFrameStats() override; -- cgit v1.2.3-59-g8ed1b From adebf5c63121f7986b2ee609ed4b6904e5290285 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 5 Jan 2021 12:57:36 -0800 Subject: Support streaming fps updates for a layer subtree to sysui via listener. The supported flow is: * A binder listener is registered with SurfaceFlinger that is associated with a task's SurfaceControl. * Every frame, for every listener that is registered, the fps for each layer subtree is computed and reported back to each listener via onFpsUpdated. * Fps for the layer subtree is computed via FrameTimeline: the layer IDs for the subtree are gathered into a set, and FrameTimeline internally finds all DisplayFrames containing at least one layer, then obtains the present time for each of those frames, then computes the aggregated fps from those frames. Pragmatically, this should correspond with the last half second of activity for high refresh rate devices. No heuristics are used to select the "correct" layer from the layer subtree. If a game is rendering to two layers at a cadence of 30fps but offset by one 60hz vsync, then the reported fps will be 60fps because both layers will be counted on the same linear timeline. No rate limiting is applied in this patch either. The caller is able to hack in rate-limiting by immediately unregistering the listener after a FPS callback is dispatched, and then reregistered. Architecturally, it is not hard to add in rate-limiting at the SurfaceFlinger level, but that can be added in a follow-up patch since this patch is already large. Bug: 174956756 Test: libsurfaceflinger_unittest Test: E2E verification with custom listener outputting to logcat Change-Id: I792bc19cad18b6aee6c6e644bca9da40a0f15099 --- libs/gui/ISurfaceComposer.cpp | 65 ++++- libs/gui/SurfaceComposerClient.cpp | 9 + libs/gui/aidl/android/gui/IFpsListener.aidl | 24 ++ libs/gui/include/gui/ISurfaceComposer.h | 34 ++- libs/gui/include/gui/SurfaceComposerClient.h | 3 + libs/gui/tests/Surface_test.cpp | 5 + services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/FpsReporter.cpp | 74 ++++++ services/surfaceflinger/FpsReporter.h | 65 +++++ .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 85 ++++++- .../surfaceflinger/FrameTimeline/FrameTimeline.h | 19 +- services/surfaceflinger/Layer.cpp | 7 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 30 +++ services/surfaceflinger/SurfaceFlinger.h | 5 + services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/FpsReporterTest.cpp | 184 ++++++++++++++ .../tests/unittests/FrameTimelineTest.cpp | 277 +++++++++++++++++---- .../tests/unittests/mock/MockFrameTimeline.h | 1 + 19 files changed, 805 insertions(+), 87 deletions(-) create mode 100644 libs/gui/aidl/android/gui/IFpsListener.aidl create mode 100644 services/surfaceflinger/FpsReporter.cpp create mode 100644 services/surfaceflinger/FpsReporter.h create mode 100644 services/surfaceflinger/tests/unittests/FpsReporterTest.cpp (limited to 'libs/gui/SurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 2e4f858a9d..45d210f4b9 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -17,15 +17,10 @@ // tag as surfaceflinger #define LOG_TAG "SurfaceFlinger" -#include -#include - #include - -#include #include #include - +#include #include #include #include @@ -33,16 +28,15 @@ #include #include #include - +#include +#include #include - #include #include #include #include #include #include - #include // --------------------------------------------------------------------------- @@ -796,6 +790,33 @@ public: return error; } + virtual status_t addFpsListener(const sp& layerHandle, + const sp& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, layerHandle); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + const status_t error = + remote()->transact(BnSurfaceComposer::ADD_FPS_LISTENER, data, &reply); + if (error != OK) { + ALOGE("addFpsListener: Failed to transact"); + } + return error; + } + + virtual status_t removeFpsListener(const sp& listener) { + Parcel data, reply; + SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor()); + SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener)); + + const status_t error = + remote()->transact(BnSurfaceComposer::REMOVE_FPS_LISTENER, data, &reply); + if (error != OK) { + ALOGE("removeFpsListener: Failed to transact"); + } + return error; + } + status_t setDesiredDisplayModeSpecs(const sp& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax, @@ -1716,6 +1737,32 @@ status_t BnSurfaceComposer::onTransact( } return removeRegionSamplingListener(listener); } + case ADD_FPS_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp layerHandle; + status_t result = data.readNullableStrongBinder(&layerHandle); + if (result != NO_ERROR) { + ALOGE("addFpsListener: Failed to read layer handle"); + return result; + } + sp listener; + result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("addFpsListener: Failed to read listener"); + return result; + } + return addFpsListener(layerHandle, listener); + } + case REMOVE_FPS_LISTENER: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + sp listener; + status_t result = data.readNullableStrongBinder(&listener); + if (result != NO_ERROR) { + ALOGE("removeFpsListener: Failed to read listener"); + return result; + } + return removeFpsListener(listener); + } case SET_DESIRED_DISPLAY_MODE_SPECS: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp displayToken = data.readStrongBinder(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 1a643c2409..b97eeec465 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1994,6 +1994,15 @@ status_t SurfaceComposerClient::removeRegionSamplingListener( return ComposerService::getComposerService()->removeRegionSamplingListener(listener); } +status_t SurfaceComposerClient::addFpsListener(const sp& layerHandle, + const sp& listener) { + return ComposerService::getComposerService()->addFpsListener(layerHandle, listener); +} + +status_t SurfaceComposerClient::removeFpsListener(const sp& listener) { + return ComposerService::getComposerService()->removeFpsListener(listener); +} + bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp& displayToken) { bool support = false; ComposerService::getComposerService()->getDisplayBrightnessSupport(displayToken, &support); diff --git a/libs/gui/aidl/android/gui/IFpsListener.aidl b/libs/gui/aidl/android/gui/IFpsListener.aidl new file mode 100644 index 0000000000..63d333c940 --- /dev/null +++ b/libs/gui/aidl/android/gui/IFpsListener.aidl @@ -0,0 +1,24 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gui; + +/** @hide */ +oneway interface IFpsListener { + + // Reports the most recent recorded fps for the tree rooted at this layer + void onFpsReported(float fps); +} \ No newline at end of file diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index d0ab4802e1..9c6dfd1876 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -16,21 +16,17 @@ #pragma once -#include -#include - -#include -#include - +#include #include #include +#include +#include #include #include - #include