Loading libs/gui/LayerState.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #define LOG_TAG "LayerState" #define LOG_TAG "LayerState" #include <apex/window.h> #include <inttypes.h> #include <inttypes.h> #include <binder/Parcel.h> #include <binder/Parcel.h> Loading Loading @@ -620,7 +621,8 @@ status_t InputWindowCommands::read(const Parcel& input) { return NO_ERROR; 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"; const char* functionName = inFunctionName != nullptr ? inFunctionName : "call"; int floatClassification = std::fpclassify(frameRate); int floatClassification = std::fpclassify(frameRate); if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { Loading @@ -629,8 +631,10 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc } } if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) { compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility); (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, compatibility, privileged ? "yes" : "no"); return false; return false; } } Loading libs/gui/SurfaceComposerClient.cpp +4 −1 Original line number Original line Diff line number Diff line Loading @@ -1518,7 +1518,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame mStatus = BAD_INDEX; mStatus = BAD_INDEX; return *this; 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; mStatus = BAD_VALUE; return *this; return *this; } } Loading libs/gui/include/gui/LayerState.h +8 −5 Original line number Original line Diff line number Diff line Loading @@ -309,11 +309,14 @@ static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) return compare_type(lhs.token, rhs.token); return compare_type(lhs.token, rhs.token); } } // Returns true if the frameRate and compatibility are valid values, false // Returns true if the frameRate is valid. // 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. // @param frameRate the frame rate in Hz // functionName can be null. // @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName); // @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 { struct CaptureArgs { const static int32_t UNSET_UID = -1; const static int32_t UNSET_UID = -1; Loading libs/nativewindow/include/apex/window.h +13 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,19 @@ enum ANativeWindowPerform { // clang-format on // 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 * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. * when ANativeWindow_cancelBuffer is called. Loading services/surfaceflinger/Layer.cpp +29 −14 Original line number Original line Diff line number Diff line Loading @@ -1432,21 +1432,28 @@ void Layer::updateTreeHasFrameRateVote() { }; }; // update parents and children about the vote // update parents and children about the vote // First traverse the tree and count how many layers has votes // First traverse the tree and count how many layers has votes. In addition // activate the layers in Scheduler's LayerHistory for it to check for changes int layersWithVote = 0; int layersWithVote = 0; traverseTree([&layersWithVote](Layer* layer) { traverseTree([&layersWithVote, this](Layer* layer) { const auto layerVotedWithDefaultCompatibility = const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; 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 do not count layers that are ExactOrMultiple for the same reason // we are allowing touch boost for those layers. See // we are allowing touch boost for those layers. See // RefreshRateConfigs::getBestRefreshRate for more details. // RefreshRateConfigs::getBestRefreshRate for more details. if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) { if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote || layerVotedWithExactCompatibility) { layersWithVote++; layersWithVote++; } } mFlinger->mScheduler->recordLayerHistory(layer, systemTime(), LayerHistory::LayerUpdateType::SetFrameRate); }); }); // Now update the other layers // Now update the other layers Loading Loading @@ -1474,10 +1481,6 @@ bool Layer::setFrameRate(FrameRate frameRate) { return false; return false; } } // Activate the layer in Scheduler's LayerHistory mFlinger->mScheduler->recordLayerHistory(this, systemTime(), LayerHistory::LayerUpdateType::SetFrameRate); mCurrentState.sequence++; mCurrentState.sequence++; mCurrentState.frameRate = frameRate; mCurrentState.frameRate = frameRate; mCurrentState.modified = true; mCurrentState.modified = true; Loading @@ -1501,8 +1504,16 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { return frameRate; return frameRate; } } // This layer doesn't have a frame rate. If one of its ancestors or successors // This layer doesn't have a frame rate. Check if its ancestors have a vote // have a vote, return a NoVote for ancestors/successors to set the vote if (sp<Layer> parent = getParent(); parent) { if (const auto parentFrameRate = parent->getFrameRateForLayerTree(); parentFrameRate.rate.isValid()) { return parentFrameRate; } } // This layer and its ancestors don't have a frame rate. If one of successors // has a vote, return a NoVote for successors to set the vote if (getDrawingState().treeHasFrameRateVote) { if (getDrawingState().treeHasFrameRateVote) { return {Fps(0.0f), FrameRateCompatibility::NoVote}; return {Fps(0.0f), FrameRateCompatibility::NoVote}; } } Loading Loading @@ -1654,6 +1665,8 @@ std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility co return "ExactOrMultiple"; return "ExactOrMultiple"; case FrameRateCompatibility::NoVote: case FrameRateCompatibility::NoVote: return "NoVote"; return "NoVote"; case FrameRateCompatibility::Exact: return "Exact"; } } } } Loading Loading @@ -1692,11 +1705,11 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { const FloatRect& crop = outputLayerState.sourceCrop; const FloatRect& crop = outputLayerState.sourceCrop; StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); crop.bottom); if (layerState.frameRate.rate.isValid() || const auto frameRate = getFrameRateForLayerTree(); layerState.frameRate.type != FrameRateCompatibility::Default) { if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { StringAppendF(&result, "%s %15s %17s", to_string(layerState.frameRate.rate).c_str(), StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), frameRateCompatibilityString(layerState.frameRate.type).c_str(), frameRateCompatibilityString(frameRate.type).c_str(), toString(layerState.frameRate.seamlessness).c_str()); toString(frameRate.seamlessness).c_str()); } else { } else { result.append(41, ' '); result.append(41, ' '); } } Loading Loading @@ -2755,6 +2768,8 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::Default; return FrameRateCompatibility::Default; case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: return FrameRateCompatibility::ExactOrMultiple; return FrameRateCompatibility::ExactOrMultiple; case ANATIVEWINDOW_FRAME_RATE_EXACT: return FrameRateCompatibility::Exact; default: default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; return FrameRateCompatibility::Default; Loading Loading
libs/gui/LayerState.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ #define LOG_TAG "LayerState" #define LOG_TAG "LayerState" #include <apex/window.h> #include <inttypes.h> #include <inttypes.h> #include <binder/Parcel.h> #include <binder/Parcel.h> Loading Loading @@ -620,7 +621,8 @@ status_t InputWindowCommands::read(const Parcel& input) { return NO_ERROR; 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"; const char* functionName = inFunctionName != nullptr ? inFunctionName : "call"; int floatClassification = std::fpclassify(frameRate); int floatClassification = std::fpclassify(frameRate); if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) { Loading @@ -629,8 +631,10 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc } } if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT && compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) { compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE && ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility); (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) { ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName, compatibility, privileged ? "yes" : "no"); return false; return false; } } Loading
libs/gui/SurfaceComposerClient.cpp +4 −1 Original line number Original line Diff line number Diff line Loading @@ -1518,7 +1518,10 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame mStatus = BAD_INDEX; mStatus = BAD_INDEX; return *this; 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; mStatus = BAD_VALUE; return *this; return *this; } } Loading
libs/gui/include/gui/LayerState.h +8 −5 Original line number Original line Diff line number Diff line Loading @@ -309,11 +309,14 @@ static inline int compare_type(const DisplayState& lhs, const DisplayState& rhs) return compare_type(lhs.token, rhs.token); return compare_type(lhs.token, rhs.token); } } // Returns true if the frameRate and compatibility are valid values, false // Returns true if the frameRate is valid. // 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. // @param frameRate the frame rate in Hz // functionName can be null. // @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName); // @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 { struct CaptureArgs { const static int32_t UNSET_UID = -1; const static int32_t UNSET_UID = -1; Loading
libs/nativewindow/include/apex/window.h +13 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,19 @@ enum ANativeWindowPerform { // clang-format on // 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 * Prototype of the function that an ANativeWindow implementation would call * when ANativeWindow_cancelBuffer is called. * when ANativeWindow_cancelBuffer is called. Loading
services/surfaceflinger/Layer.cpp +29 −14 Original line number Original line Diff line number Diff line Loading @@ -1432,21 +1432,28 @@ void Layer::updateTreeHasFrameRateVote() { }; }; // update parents and children about the vote // update parents and children about the vote // First traverse the tree and count how many layers has votes // First traverse the tree and count how many layers has votes. In addition // activate the layers in Scheduler's LayerHistory for it to check for changes int layersWithVote = 0; int layersWithVote = 0; traverseTree([&layersWithVote](Layer* layer) { traverseTree([&layersWithVote, this](Layer* layer) { const auto layerVotedWithDefaultCompatibility = const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; 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 do not count layers that are ExactOrMultiple for the same reason // we are allowing touch boost for those layers. See // we are allowing touch boost for those layers. See // RefreshRateConfigs::getBestRefreshRate for more details. // RefreshRateConfigs::getBestRefreshRate for more details. if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) { if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote || layerVotedWithExactCompatibility) { layersWithVote++; layersWithVote++; } } mFlinger->mScheduler->recordLayerHistory(layer, systemTime(), LayerHistory::LayerUpdateType::SetFrameRate); }); }); // Now update the other layers // Now update the other layers Loading Loading @@ -1474,10 +1481,6 @@ bool Layer::setFrameRate(FrameRate frameRate) { return false; return false; } } // Activate the layer in Scheduler's LayerHistory mFlinger->mScheduler->recordLayerHistory(this, systemTime(), LayerHistory::LayerUpdateType::SetFrameRate); mCurrentState.sequence++; mCurrentState.sequence++; mCurrentState.frameRate = frameRate; mCurrentState.frameRate = frameRate; mCurrentState.modified = true; mCurrentState.modified = true; Loading @@ -1501,8 +1504,16 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { return frameRate; return frameRate; } } // This layer doesn't have a frame rate. If one of its ancestors or successors // This layer doesn't have a frame rate. Check if its ancestors have a vote // have a vote, return a NoVote for ancestors/successors to set the vote if (sp<Layer> parent = getParent(); parent) { if (const auto parentFrameRate = parent->getFrameRateForLayerTree(); parentFrameRate.rate.isValid()) { return parentFrameRate; } } // This layer and its ancestors don't have a frame rate. If one of successors // has a vote, return a NoVote for successors to set the vote if (getDrawingState().treeHasFrameRateVote) { if (getDrawingState().treeHasFrameRateVote) { return {Fps(0.0f), FrameRateCompatibility::NoVote}; return {Fps(0.0f), FrameRateCompatibility::NoVote}; } } Loading Loading @@ -1654,6 +1665,8 @@ std::string Layer::frameRateCompatibilityString(Layer::FrameRateCompatibility co return "ExactOrMultiple"; return "ExactOrMultiple"; case FrameRateCompatibility::NoVote: case FrameRateCompatibility::NoVote: return "NoVote"; return "NoVote"; case FrameRateCompatibility::Exact: return "Exact"; } } } } Loading Loading @@ -1692,11 +1705,11 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { const FloatRect& crop = outputLayerState.sourceCrop; const FloatRect& crop = outputLayerState.sourceCrop; StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); crop.bottom); if (layerState.frameRate.rate.isValid() || const auto frameRate = getFrameRateForLayerTree(); layerState.frameRate.type != FrameRateCompatibility::Default) { if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) { StringAppendF(&result, "%s %15s %17s", to_string(layerState.frameRate.rate).c_str(), StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(), frameRateCompatibilityString(layerState.frameRate.type).c_str(), frameRateCompatibilityString(frameRate.type).c_str(), toString(layerState.frameRate.seamlessness).c_str()); toString(frameRate.seamlessness).c_str()); } else { } else { result.append(41, ' '); result.append(41, ' '); } } Loading Loading @@ -2755,6 +2768,8 @@ Layer::FrameRateCompatibility Layer::FrameRate::convertCompatibility(int8_t comp return FrameRateCompatibility::Default; return FrameRateCompatibility::Default; case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE: return FrameRateCompatibility::ExactOrMultiple; return FrameRateCompatibility::ExactOrMultiple; case ANATIVEWINDOW_FRAME_RATE_EXACT: return FrameRateCompatibility::Exact; default: default: LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility); return FrameRateCompatibility::Default; return FrameRateCompatibility::Default; Loading