@@ -489,6 +489,20 @@ auto RefreshRateSelector::getRankedFrameRates(const std::vector<LayerRequirement
489489 return mGetRankedFrameRatesCache ->result ;
490490}
491491
492+ using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
493+ using PerUidLayerRequirements = std::unordered_map<uid_t , LayerRequirementPtrs>;
494+
495+ PerUidLayerRequirements groupLayersByUid (
496+ const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
497+ PerUidLayerRequirements layersByUid;
498+ for (const auto & layer : layers) {
499+ const auto it = layersByUid.emplace (layer.ownerUid , LayerRequirementPtrs ()).first ;
500+ auto & layersWithSameUid = it->second ;
501+ layersWithSameUid.push_back (&layer);
502+ }
503+ return layersByUid;
504+ }
505+
492506auto RefreshRateSelector::getRankedFrameRatesLocked (const std::vector<LayerRequirement>& layers,
493507 GlobalSignals signals, Fps pacesetterFps) const
494508 -> RankedFrameRates {
@@ -525,6 +539,43 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
525539 return {ranking, GlobalSignals{.powerOnImminent = true }};
526540 }
527541
542+ // A method for UI Toolkit to send the touch signal via "HighHint" category vote,
543+ // which will touch boost when there are no ExplicitDefault layer votes on the app.
544+ // At most one app can have the "HighHint" touch boost vote at a time.
545+ // This accounts for cases such as games that use `setFrameRate`
546+ // with Default compatibility to limit the frame rate and disabling touch boost.
547+ bool isAppTouchBoost = false ;
548+ const auto layersByUid = groupLayersByUid (layers);
549+ for (const auto & [uid, layersWithSameUid] : layersByUid) {
550+ bool hasHighHint = false ;
551+ bool hasExplicitDefault = false ;
552+ for (const auto & layer : layersWithSameUid) {
553+ switch (layer->vote ) {
554+ case LayerVoteType::ExplicitDefault:
555+ hasExplicitDefault = true ;
556+ break ;
557+ case LayerVoteType::ExplicitCategory:
558+ if (layer->frameRateCategory == FrameRateCategory::HighHint) {
559+ hasHighHint = true ;
560+ }
561+ break ;
562+ default :
563+ // No action
564+ break ;
565+ }
566+ if (hasHighHint && hasExplicitDefault) {
567+ break ;
568+ }
569+ }
570+
571+ if (hasHighHint && !hasExplicitDefault) {
572+ // Focused app has touch signal (HighHint) and no frame rate ExplicitDefault votes
573+ // (which prevents touch boost due to games use case).
574+ isAppTouchBoost = true ;
575+ break ;
576+ }
577+ }
578+
528579 int noVoteLayers = 0 ;
529580 // Layers that prefer the same mode ("no-op").
530581 int noPreferenceLayers = 0 ;
@@ -535,7 +586,6 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
535586 int explicitExact = 0 ;
536587 int explicitGteLayers = 0 ;
537588 int explicitCategoryVoteLayers = 0 ;
538- int interactiveLayers = 0 ;
539589 int seamedFocusedLayers = 0 ;
540590 int categorySmoothSwitchOnlyLayers = 0 ;
541591
@@ -563,11 +613,9 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
563613 explicitGteLayers++;
564614 break ;
565615 case LayerVoteType::ExplicitCategory:
566- if (layer.frameRateCategory == FrameRateCategory::HighHint) {
567- // HighHint does not count as an explicit signal from an app. It may be
568- // be a touch signal.
569- interactiveLayers++;
570- } else {
616+ // HighHint does not count as an explicit signal from an app. It is a touch signal
617+ // sent from UI Toolkit.
618+ if (layer.frameRateCategory != FrameRateCategory::HighHint) {
571619 explicitCategoryVoteLayers++;
572620 }
573621 if (layer.frameRateCategory == FrameRateCategory::NoPreference) {
@@ -882,14 +930,11 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
882930 return explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size ();
883931 };
884932
885- // A method for UI Toolkit to send the touch signal via "HighHint" category vote,
886- // which will touch boost when there are no ExplicitDefault layer votes. This is an
887- // incomplete solution but accounts for cases such as games that use `setFrameRate` with default
933+ // This accounts for cases such as games that use `setFrameRate` with Default
888934 // compatibility to limit the frame rate, which should not have touch boost.
889- const bool hasInteraction = signals.touch || interactiveLayers > 0 ;
890-
891- if (hasInteraction && explicitDefaultVoteLayers == 0 && isTouchBoostForExplicitExact () &&
892- isTouchBoostForCategory ()) {
935+ const bool isLateGlobalTouchBoost = signals.touch && explicitDefaultVoteLayers == 0 ;
936+ const bool isLateTouchBoost = isLateGlobalTouchBoost || isAppTouchBoost;
937+ if (isLateTouchBoost && isTouchBoostForExplicitExact () && isTouchBoostForCategory ()) {
893938 const auto touchRefreshRates = rankFrameRates (anchorGroup, RefreshRateOrder::Descending);
894939 using fps_approx_ops::operator <;
895940
@@ -917,42 +962,6 @@ auto RefreshRateSelector::getRankedFrameRatesLocked(const std::vector<LayerRequi
917962 return {ranking, kNoSignals };
918963}
919964
920- using LayerRequirementPtrs = std::vector<const RefreshRateSelector::LayerRequirement*>;
921- using PerUidLayerRequirements = std::unordered_map<uid_t , LayerRequirementPtrs>;
922-
923- PerUidLayerRequirements groupLayersByUid (
924- const std::vector<RefreshRateSelector::LayerRequirement>& layers) {
925- PerUidLayerRequirements layersByUid;
926- for (const auto & layer : layers) {
927- const auto it = layersByUid.emplace (layer.ownerUid , LayerRequirementPtrs ()).first ;
928- auto & layersWithSameUid = it->second ;
929- layersWithSameUid.push_back (&layer);
930- }
931-
932- // Remove uids that can't have a frame rate override
933- for (auto it = layersByUid.begin (); it != layersByUid.end ();) {
934- const auto & layersWithSameUid = it->second ;
935- bool skipUid = false ;
936- for (const auto & layer : layersWithSameUid) {
937- using LayerVoteType = RefreshRateSelector::LayerVoteType;
938-
939- if (layer->vote == LayerVoteType::Max || layer->vote == LayerVoteType::Heuristic) {
940- ALOGV (" %s: %s skips uid=%d due to the vote" , __func__,
941- formatLayerInfo (*layer, layer->weight ).c_str (), layer->ownerUid );
942- skipUid = true ;
943- break ;
944- }
945- }
946- if (skipUid) {
947- it = layersByUid.erase (it);
948- } else {
949- ++it;
950- }
951- }
952-
953- return layersByUid;
954- }
955-
956965auto RefreshRateSelector::getFrameRateOverrides (const std::vector<LayerRequirement>& layers,
957966 Fps displayRefreshRate,
958967 GlobalSignals globalSignals) const
@@ -997,6 +1006,7 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme
9971006 bool hasExplicitExactOrMultiple = false ;
9981007 bool hasExplicitDefault = false ;
9991008 bool hasHighHint = false ;
1009+ bool hasSkipOverrideLayer = false ;
10001010 for (const auto & layer : layersWithSameUid) {
10011011 switch (layer->vote ) {
10021012 case LayerVoteType::ExplicitExactOrMultiple:
@@ -1010,15 +1020,25 @@ auto RefreshRateSelector::getFrameRateOverrides(const std::vector<LayerRequireme
10101020 hasHighHint = true ;
10111021 }
10121022 break ;
1023+ case LayerVoteType::Max:
1024+ case LayerVoteType::Heuristic:
1025+ hasSkipOverrideLayer = true ;
1026+ break ;
10131027 default :
10141028 // No action
10151029 break ;
10161030 }
1017- if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint) {
1031+ if (hasExplicitExactOrMultiple && hasExplicitDefault && hasHighHint &&
1032+ hasSkipOverrideLayer) {
10181033 break ;
10191034 }
10201035 }
10211036
1037+ if (hasSkipOverrideLayer) {
1038+ ALOGV (" %s: Skipping due to vote(s): uid=%d" , __func__, uid);
1039+ continue ;
1040+ }
1041+
10221042 // Layers with ExplicitExactOrMultiple expect touch boost
10231043 if (globalSignals.touch && hasExplicitExactOrMultiple) {
10241044 ALOGV (" %s: Skipping for touch (input signal): uid=%d" , __func__, uid);
0 commit comments