0

[Jank] Create wrapper for requestLayout() with trace event

In jank investigations, there are traces with lots of re-layouts but we
don't know where these layouts are coming from. Adding a trace event to
every call to requestLayout() will help us understand these traces.

Bug: 1354176
Change-Id: I027b83d2c50390a8623e1ab47e5d1c178a7510c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3999988
Reviewed-by: Ted Choc <tedchoc@chromium.org>
Reviewed-by: Mugdha Lakhani <nator@chromium.org>
Reviewed-by: Yaron Friedman <yfriedman@chromium.org>
Commit-Queue: Peilin Wang <peilinwang@google.com>
Cr-Commit-Position: refs/heads/main@{#1069805}
This commit is contained in:
Peilin Wang
2022-11-10 16:33:57 +00:00
committed by Chromium LUCI CQ
parent 377a4524e3
commit bba4a865e3
49 changed files with 204 additions and 72 deletions
PRESUBMIT.py
android_webview/java/src/org/chromium/android_webview
chrome
android
browser
commerce
merchant_viewer
android
java
src
org
chromium
chrome
content_creation
notes
internal
android
java
src
org
chromium
chrome
browser
content_creation
feed
android
java
src
org
chromium
chrome
browser
history_clusters
share
android
java
src
org
touch_to_fill
android
internal
java
src
org
chromium
chrome
browser
ui
android
omnibox
java
toolbar
java
src
org
chromium
chrome
browser
components
autofill_assistant
android
java
src
org
chromium
components
browser_ui
bottomsheet
android
internal
java
src
org
chromium
components
browser_ui
bottomsheet
photo_picker
android
java
src
org
chromium
components
site_settings
android
java
src
org
chromium
components
browser_ui
widget
android
java
src
org
chromium
webapps
browser
android
java
src
org
chromium
content/public/android/java/src/org/chromium/content/browser
ui/android/java/src/org/chromium/ui/base
weblayer/browser/java/org/chromium/weblayer_private

@ -238,6 +238,18 @@ _BANNED_JAVA_FUNCTIONS : Sequence[BanRule] = (
'primitives.',
),
),
BanRule(
'requestLayout()',
(
'Layouts can be expensive. Prefer using ViewUtils.requestLayout(), '
'which emits a trace event with additional information to help with '
'scroll jank investigations. See http://crbug.com/1354176.',
),
False,
excluded_paths=(
'ui/android/java/src/org/chromium/ui/base/ViewUtils.java',
),
),
)
_BANNED_OBJC_FUNCTIONS : Sequence[BanRule] = (

@ -121,6 +121,7 @@ import org.chromium.ui.base.Clipboard;
import org.chromium.ui.base.IntentRequestTracker;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.display.DisplayAndroid.DisplayAndroidObserver;
import org.chromium.url.GURL;
@ -710,7 +711,8 @@ public class AwContents implements SmartClipProvider {
private class AwLayoutSizerDelegate implements AwLayoutSizer.Delegate {
@Override
public void requestLayout() {
mContainerView.requestLayout();
ViewUtils.requestLayout(
mContainerView, "AwContents.AwLayoutSizerDelegate.requestLayout");
}
@Override
@ -1331,7 +1333,7 @@ public class AwContents implements SmartClipProvider {
}
awViewMethodsImpl.onWindowFocusChanged(mContainerView.hasWindowFocus());
awViewMethodsImpl.onFocusChanged(mContainerView.hasFocus(), 0, null);
mContainerView.requestLayout();
ViewUtils.requestLayout(mContainerView, "AwContents.onContainerViewChanged");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (mAutofillProvider != null) mAutofillProvider.onContainerViewChanged(mContainerView);
}

@ -28,6 +28,7 @@ import org.chromium.base.annotations.NativeMethods;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListenerWithScroll;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.display.DisplayAndroid.DisplayAndroidObserver;
import org.chromium.ui.resources.HandleViewResources;
@ -273,7 +274,10 @@ public class PopupTouchHandleDrawable extends View implements DisplayAndroidObse
if (mDrawable != null) mDrawable.setAlpha((int) (255 * mAlpha));
if (!isInLayout()) requestLayout();
if (!isInLayout()) {
ViewUtils.requestLayout(
this, "PopupTouchHandleDrawable.updateDrawableAndRequestLayout");
}
}
private void updateParentPosition(int parentPositionX, int parentPositionY) {

@ -68,6 +68,7 @@ import org.chromium.components.browser_ui.widget.InsetObserverViewSupplier;
import org.chromium.components.browser_ui.widget.gesture.BackPressHandler;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.DropdownPopupWindow;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
@ -472,7 +473,8 @@ class ManualFillingMediator
if (compositorViewHolderSupplier.hasValue()) {
// The CompositorViewHolder is null when the activity is in the process of being
// destroyed which also renders relayouting pointless.
compositorViewHolderSupplier.get().requestLayout();
ViewUtils.requestLayout(compositorViewHolderSupplier.get(),
"ManualFillingMediator.enforceStateProperties");
}
}
TraceEvent.end("ManualFillingMediator#enforceStateProperties");

@ -37,6 +37,7 @@ import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
@ -77,7 +78,7 @@ class TabGridPanelViewBinder {
} else if (CONTENT_TOP_MARGIN == propertyKey) {
((FrameLayout.LayoutParams) viewHolder.contentView.getLayoutParams()).topMargin =
model.get(CONTENT_TOP_MARGIN);
viewHolder.contentView.requestLayout();
ViewUtils.requestLayout(viewHolder.contentView, "TabGridPanelViewBinder.bind");
} else if (PRIMARY_COLOR == propertyKey) {
viewHolder.toolbarView.setPrimaryColor(model.get(PRIMARY_COLOR));
viewHolder.contentView.setBackgroundColor(model.get(PRIMARY_COLOR));

@ -19,6 +19,7 @@ import android.widget.FrameLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
@ -55,11 +56,11 @@ class TabListContainerViewBinder {
if (newTopMargin == params.topMargin) return;
params.topMargin = newTopMargin;
view.requestLayout();
ViewUtils.requestLayout(view, "TabListContainerViewBinder.bind TOP_MARGIN");
} else if (BOTTOM_CONTROLS_HEIGHT == propertyKey) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
params.bottomMargin = model.get(BOTTOM_CONTROLS_HEIGHT);
view.requestLayout();
ViewUtils.requestLayout(view, "TabListContainerViewBinder.bind BOTTOM_CONTROLS_HEIGHT");
} else if (SHADOW_TOP_OFFSET == propertyKey) {
view.setShadowTopOffset(model.get(SHADOW_TOP_OFFSET));
} else if (BOTTOM_PADDING == propertyKey) {

@ -39,6 +39,7 @@ import org.chromium.base.Log;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.tab_ui.R;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
@ -217,7 +218,8 @@ class TabListRecyclerView
}
// TODO(crbug.com/972157): remove this band-aid after we know why GTS is invisible.
if (TabUiFeatureUtilities.isTabToGtsAnimationEnabled()) {
requestLayout();
ViewUtils.requestLayout(TabListRecyclerView.this,
"TabListRecyclerView.startShowing.AnimatorListenerAdapter.onAnimationEnd");
}
}
});

@ -79,6 +79,7 @@ import org.chromium.ui.UiUtils;
import org.chromium.ui.base.ApplicationViewportInsetSupplier;
import org.chromium.ui.base.EventForwarder;
import org.chromium.ui.base.EventOffsetHandler;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.mojom.VirtualKeyboardMode;
import org.chromium.ui.resources.ResourceManager;
@ -1164,7 +1165,8 @@ public class CompositorViewHolder extends FrameLayout
|| layoutParams.bottomMargin != (int) bottomMargin)) {
layoutParams.topMargin = (int) topMargin;
layoutParams.bottomMargin = (int) bottomMargin;
child.requestLayout();
ViewUtils.requestLayout(
child, "CompositorViewHolder.applyMarginToFullscreenChildViews");
TraceEvent.instant("FullscreenManager:child.requestLayout()");
}
}

@ -28,6 +28,7 @@ import org.chromium.chrome.browser.layouts.animation.CompositorAnimator;
import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
import org.chromium.components.browser_ui.settings.SettingsLauncher;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
@ -400,7 +401,7 @@ public class ContextualSearchPromoControl extends OverlayPanelInflater {
// NOTE(pedrosimonetti): We need to call requestLayout, otherwise
// the Promo View will not become visible.
view.requestLayout();
ViewUtils.requestLayout(view, "ContextualSearchPromoControl.showPromoView");
mIsShowingView = true;
mPromoViewY = y;

@ -27,6 +27,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.browser_ui.widget.chips.ChipProperties;
import org.chromium.components.browser_ui.widget.chips.ChipsCoordinator;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.modelutil.PropertyModel;
@ -410,7 +411,7 @@ public class RelatedSearchesControl {
view.setVisibility(View.VISIBLE);
// NOTE: We need to call requestLayout, otherwise the View will not become visible.
view.requestLayout();
ViewUtils.requestLayout(view, "RelatedSearchesControl.showView");
mIsShowingView = true;
mViewY = y;

@ -36,6 +36,7 @@ import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.content_public.browser.RenderCoordinates;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.IntentRequestTracker;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.url.GURL;
@ -168,7 +169,7 @@ public class EphemeralTabSheetContent implements BottomSheetContent {
// We scale it by |FULL_HEIGHT_RATIO| to make the size equal to that of
// ThinWebView and so it can leave a portion of the page below it visible.
layoutParams.height = (int) (maxViewHeight * FULL_HEIGHT_RATIO) - mToolbarHeightPx;
mSheetContentView.requestLayout();
ViewUtils.requestLayout(mSheetContentView, "EphemeralTabSheetContent.updateContentHeight");
}
/** Method to be called to start the favicon anmiation. */

@ -56,6 +56,7 @@ import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.util.ColorUtils;
import java.lang.annotation.Retention;
@ -570,7 +571,8 @@ public class PartialCustomTabHeightStrategy extends CustomTabHeightStrategy
R.dimen.custom_tabs_shadow_offset);
}
setTopMargins(mShadowOffset, getHandleHeight() + mShadowOffset);
mToolbarCoordinator.requestLayout();
ViewUtils.requestLayout(
mToolbarCoordinator, "PartialCustomTabHeightStrategy.updateShadowOffet");
}
private void setTopMargins(int shadowOffset, int handleOffset) {

@ -18,6 +18,7 @@ import androidx.annotation.DrawableRes;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.toolbar.ToolbarFeatures;
import org.chromium.components.omnibox.SecurityButtonAnimationDelegate;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
/**
@ -99,7 +100,7 @@ class CustomTabToolbarAnimationDelegate {
final int[] oldLoc = new int[2];
mUrlBar.getLocationInWindow(oldLoc);
mUrlBar.requestLayout();
ViewUtils.requestLayout(mUrlBar, "CustomTabToolbarAnimationDelegate.startTitleAnimation");
mUrlBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override

@ -44,6 +44,7 @@ import org.chromium.chrome.browser.toolbar.ToolbarFeatures;
import org.chromium.chrome.browser.vr.VrModuleProvider;
import org.chromium.components.browser_ui.util.BrowserControlsVisibilityDelegate;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.util.TokenHolder;
import org.chromium.ui.vr.VrModeObserver;
@ -148,7 +149,8 @@ public class BrowserControlsManager
// may be less expensive. The overlay trimming optimization only works
// pre-Android N (see https://crbug.com/725453), so this call should be removed
// entirely once it's confirmed to be safe.
mControlContainer.getView().requestLayout();
ViewUtils.requestLayout(mControlContainer.getView(),
"BrowserControlsManager.mUpdateVisibilityRunnable Runnable");
}
for (BrowserControlsStateProvider.Observer observer : mControlsObservers) {

@ -52,6 +52,7 @@ import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.NavigationHandle;
import org.chromium.content_public.browser.SelectionPopupController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ViewUtils;
import java.lang.ref.WeakReference;
@ -202,7 +203,8 @@ public class FullscreenHtmlApiHandler implements ActivityStateListener, WindowFo
}
});
contentView.requestLayout();
ViewUtils.requestLayout(contentView,
"FullscreenHtmlApiHandler.FullscreenHandler.handleMessage");
break;
}
case MSG_ID_CLEAR_LAYOUT_FULLSCREEN_FLAG: {
@ -603,7 +605,7 @@ public class FullscreenHtmlApiHandler implements ActivityStateListener, WindowFo
// Request a layout so the updated system visibility takes affect.
// The flow will continue in the handler of MSG_ID_SET_FULLSCREEN_SYSTEM_UI_FLAGS message.
contentView.requestLayout();
ViewUtils.requestLayout(contentView, "FullscreenHtmlApiHandler.enterFullScreen");
mWebContentsInFullscreen = webContents;
mContentViewInFullscreen = contentView;

@ -28,6 +28,7 @@ import androidx.appcompat.widget.SwitchCompat;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.components.content_settings.CookieControlsEnforcement;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.widget.ChromeBulletSpan;
@ -258,7 +259,7 @@ public class LegacyIncognitoDescriptionView
LinearLayout.LayoutParams params = (LayoutParams) mLearnMore.getLayoutParams();
params.setMargins(0, learnMoreSpacingTop, 0, learnMoreSpacingBottom);
mLearnMore.requestLayout();
ViewUtils.requestLayout(mLearnMore, "LegacyIncognitoDescriptionView.adjustLayout");
((LinearLayout.LayoutParams) mHeader.getLayoutParams())
.setMargins(0, totalSpaceBetweenViews, 0, 0);

@ -159,7 +159,7 @@ public class RecentTabsPage
// Work around a bug on Samsung devices where the recent tabs page does not appear after
// toggling the Sync quick setting. For some reason, the layout is being dropped on the
// flow and we need to force a root level layout to get the UI to appear.
view.getRootView().requestLayout();
ViewUtils.requestLayout(view.getRootView(), "RecentTabsPage.onViewAttachedToWindow");
}
@Override

@ -44,6 +44,7 @@ import org.chromium.components.browser_ui.widget.TintedDrawable;
import org.chromium.components.browser_ui.widget.animation.Interpolators;
import org.chromium.ui.HorizontalListDividerDrawable;
import org.chromium.ui.UiUtils;
import org.chromium.ui.base.ViewUtils;
import java.util.ArrayList;
import java.util.List;
@ -501,7 +502,7 @@ public abstract class PaymentRequestSection extends LinearLayout implements View
if (oldMargin != newMargin) {
((ViewGroup.MarginLayoutParams) mTitleView.getLayoutParams()).bottomMargin =
newMargin;
requestLayout();
ViewUtils.requestLayout(this, "PaymentRequestSection.UpdateControlLayout");
}
}
@ -1267,7 +1268,8 @@ public abstract class PaymentRequestSection extends LinearLayout implements View
params.height = LayoutParams.WRAP_CONTENT;
params.bottomMargin = getContext().getResources().getDimensionPixelSize(
R.dimen.payments_section_checking_spacing);
mCheckingProgress.requestLayout();
ViewUtils.requestLayout(
mCheckingProgress, "PaymentRequestSection.OptionRow.setSpinnerVisibility");
} else {
if (mCheckingProgress.getParent() == null) return;

@ -55,6 +55,7 @@ import org.chromium.components.payments.PaymentFeatureList;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.identitymanager.ConsentLevel;
import org.chromium.components.signin.identitymanager.IdentityManager;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.text.NoUnderlineClickableSpan;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.text.SpanApplier.SpanInfo;
@ -700,7 +701,8 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
mPaymentContainerLayout.addView(mShippingOptionSection, addressSectionIndex + 2,
new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
mPaymentContainerLayout.requestLayout();
ViewUtils.requestLayout(
mPaymentContainerLayout, "PaymentRequestUI.addShippingOptionSectionIfNecessary");
}
/**
@ -760,7 +762,8 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
mPaymentContainerLayout.getChildAt(contactSectionIndex - 1).setVisibility(View.GONE);
}
mPaymentContainerLayout.requestLayout();
ViewUtils.requestLayout(
mPaymentContainerLayout, "PaymentRequestUI.selectedPaymentMethodUpdated");
}
@Override
@ -979,7 +982,7 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
// TODO(dfalcantara): Animate this: https://crbug.com/621955
((FrameLayout.LayoutParams) mRequestView.getLayoutParams()).height =
LayoutParams.WRAP_CONTENT;
mRequestView.requestLayout();
ViewUtils.requestLayout(mRequestView, "PaymentRequestUI.changeSpinnerVisibility show");
} else {
mPaymentContainer.setVisibility(View.VISIBLE);
mBottomBar.setVisibility(View.VISIBLE);
@ -989,7 +992,8 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
if (mIsExpandedToFullHeight) {
((FrameLayout.LayoutParams) mRequestView.getLayoutParams()).height =
LayoutParams.MATCH_PARENT;
mRequestView.requestLayout();
ViewUtils.requestLayout(mRequestView,
"PaymentRequestUI.changeSpinnerVisibility expanded to full height");
}
}
}
@ -1052,7 +1056,7 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
// Expand all the dividers.
for (int i = 0; i < mSectionSeparators.size(); i++) mSectionSeparators.get(i).expand();
mPaymentContainerLayout.requestLayout();
ViewUtils.requestLayout(mPaymentContainerLayout, "PaymentRequestUI.expand");
// Switch the 'edit' button to a 'cancel' button.
mEditButton.setText(mContext.getString(R.string.cancel));
@ -1357,7 +1361,8 @@ public class PaymentRequestUI implements DimmingDialog.OnDismissListener, View.O
// Reset the layout so that everything is in the expected place.
mRequestView.setTranslationY(0);
mBottomBar.setTranslationY(0);
mRequestView.requestLayout();
ViewUtils.requestLayout(
mRequestView, "PaymentRequestUI.SheetEnlargingAnimator.onAnimationEnd");
// Indicate that the dialog is ready to use.
mSheetAnimator = null;

@ -19,6 +19,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
import org.chromium.chrome.browser.tab.TabObscuringHandler;
import org.chromium.components.browser_ui.widget.ViewResourceFrameLayout;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
import org.chromium.ui.resources.ResourceManager;
@ -189,7 +190,9 @@ public class StatusIndicatorCoordinator {
new StatusIndicatorViewBinder.ViewHolder(root, mSceneLayer),
StatusIndicatorViewBinder::bind);
mMediator.initialize(model, this::registerResource, this::unregisterResource,
invalidateCompositorView, root::requestLayout);
invalidateCompositorView, () -> {
ViewUtils.requestLayout(root, "StatusIndicatorCoordinator.initialize Runnable");
});
root.addOnLayoutChangeListener(mMediator);
mRemoveOnLayoutChangeListener = () -> root.removeOnLayoutChangeListener(mMediator);

@ -26,6 +26,7 @@ import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSitesMetadataUtils;
import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
import org.chromium.components.search_engines.TemplateUrlService.TemplateUrlServiceObserver;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.PropertyModel;
import java.io.IOException;
@ -255,7 +256,8 @@ public class MostVisitedTilesMediator implements TileGroup.Observer, TemplateUrl
if (!mIsScrollableMVTEnabled) {
((MostVisitedTilesGridLayout) mMvTilesLayout)
.setSearchProviderHasLogo(mSearchProviderHasLogo);
mMvTilesLayout.requestLayout();
ViewUtils.requestLayout(
mMvTilesLayout, "MostVisitedTilesMediator.onSearchEngineHasLogoChanged");
}
}

@ -27,6 +27,7 @@ import org.chromium.components.thinwebview.ThinWebView;
import org.chromium.components.thinwebview.ThinWebViewConstraints;
import org.chromium.components.thinwebview.ThinWebViewFactory;
import org.chromium.ui.base.IntentRequestTracker;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
@ -214,7 +215,8 @@ public class MerchantTrustBottomSheetCoordinator implements View.OnLayoutChangeL
layoutParams.height =
(int) (maxViewHeight * MerchantTrustBottomSheetContent.FULL_HEIGHT_RATIO)
- mToolbarView.getToolbarHeightPx();
mThinWebView.getView().requestLayout();
ViewUtils.requestLayout(
mThinWebView.getView(), "MerchantTrustBottomSheetCoordinator.onLayoutChange");
mCurrentMaxViewHeight = maxViewHeight;
}

@ -296,7 +296,6 @@ public class NoteCreationDialog extends DialogFragment {
params.setMarginStart(paddingLeft);
params.setMarginEnd(paddingRight);
itemView.setLayoutParams(params);
itemView.requestLayout();
}
private void maybeShowToast() {
@ -368,7 +367,6 @@ public class NoteCreationDialog extends DialogFragment {
(MarginLayoutParams) carouselView.getLayoutParams();
params.topMargin = (int) ((viewHeight - templateWidth) / 2);
carouselView.setLayoutParams(params);
carouselView.requestLayout();
}
});
return;
@ -378,7 +376,6 @@ public class NoteCreationDialog extends DialogFragment {
MarginLayoutParams params = (MarginLayoutParams) firstView.getLayoutParams();
params.topMargin = (int) (minTopMargin + (screenHeight - topMarginOffset) * 0.15f);
firstView.setLayoutParams(params);
firstView.requestLayout();
}
private void addScrollView() {

@ -16,6 +16,7 @@ import androidx.annotation.Nullable;
import org.chromium.chrome.browser.feed.R;
import org.chromium.components.browser_ui.widget.chips.ChipView;
import org.chromium.ui.base.ViewUtils;
/**
* View class representing an expandable/collapsible view holding option chips for the feed.
@ -79,7 +80,8 @@ public class FeedOptionsView extends LinearLayout {
height = (int) (targetHeight * interpolatedTime);
}
getLayoutParams().height = height;
requestLayout();
ViewUtils.requestLayout(FeedOptionsView.this,
"FeedOptionsView.expand.Animation.applyTransformation");
}
@Override
@ -104,7 +106,8 @@ public class FeedOptionsView extends LinearLayout {
} else {
getLayoutParams().height =
initialHeight - (int) (initialHeight * interpolatedTime);
requestLayout();
ViewUtils.requestLayout(FeedOptionsView.this,
"FeedOptionsView.collapse.Animation.applyTransformation");
}
}

@ -14,6 +14,8 @@ import android.widget.FrameLayout.LayoutParams;
import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;
import org.chromium.ui.base.ViewUtils;
/**
* A horizontal divider view with a fixed height that spans the width of its parent along the
* bottom. Initially hidden.
@ -41,6 +43,6 @@ class DividerView extends View {
} else {
layoutParams.height = getResources().getDimensionPixelSize(R.dimen.divider_height);
}
requestLayout();
ViewUtils.requestLayout(this, "DividerView.setIsThickDivider");
}
}

@ -20,6 +20,7 @@ import androidx.annotation.Nullable;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.components.browser_ui.styles.SemanticColorUtils;
import org.chromium.components.browser_ui.widget.selectable_list.SelectableItemView;
import org.chromium.ui.base.ViewUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -121,7 +122,7 @@ class HistoryClusterView extends SelectableItemView<HistoryCluster> {
layoutParams.bottomMargin = 0;
}
requestLayout();
ViewUtils.requestLayout(this, "HistoryClusterView.setHasThickDivider");
}
void setIconDrawableVisibility(int visibility) {

@ -15,6 +15,7 @@ import androidx.appcompat.content.res.AppCompatResources;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.components.browser_ui.widget.selectable_list.SelectableItemView;
import org.chromium.components.browser_ui.widget.selectable_list.SelectableListUtils;
import org.chromium.ui.base.ViewUtils;
class HistoryClustersItemView extends SelectableItemView<ClusterVisit> {
private DividerView mDividerView;
@ -80,7 +81,7 @@ class HistoryClustersItemView extends SelectableItemView<ClusterVisit> {
layoutParams.bottomMargin = 0;
}
requestLayout();
ViewUtils.requestLayout(this, "HistoryClustersItemView.setHasThickDivider");
}
void setEndButtonVisibility(boolean visible) {

@ -14,6 +14,7 @@ import androidx.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.components.browser_ui.widget.chips.ChipProperties;
import org.chromium.components.browser_ui.widget.chips.ChipsCoordinator;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
@ -73,6 +74,7 @@ class HistoryClustersRelatedSearchesChipLayout extends FrameLayout {
layoutParams.bottomMargin = 0;
}
requestLayout();
ViewUtils.requestLayout(
this, "HistoryClustersRelatedSearchesChipLayout.setHasThickDivider");
}
}

@ -52,6 +52,7 @@ import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.components.feature_engagement.FeatureConstants;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.LayoutViewBuilder;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
@ -226,7 +227,7 @@ class ShareSheetBottomSheetContent implements BottomSheetContent, OnItemClickLis
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = iconSize;
params.width = iconSize;
view.requestLayout();
ViewUtils.requestLayout(view, "ShareSheetBottomSheetContent.bind3PShareItem");
layout.setPadding(0, paddingTop, 0, 0);
}
}

@ -44,6 +44,7 @@ import org.chromium.components.favicon.LargeIconBridge;
import org.chromium.components.feature_engagement.EventConstants;
import org.chromium.components.feature_engagement.Tracker;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.base.WindowAndroid.ActivityStateObserver;
import org.chromium.ui.modelutil.PropertyModel;
@ -444,8 +445,10 @@ public class ShareSheetCoordinator implements ActivityStateObserver, ChromeOptio
return;
}
mBottomSheet.getFirstPartyView().invalidate();
mBottomSheet.getFirstPartyView().requestLayout();
ViewUtils.requestLayout(mBottomSheet.getFirstPartyView(),
"ShareSheetCoordinator.onLayoutChange first party view");
mBottomSheet.getThirdPartyView().invalidate();
mBottomSheet.getThirdPartyView().requestLayout();
ViewUtils.requestLayout(mBottomSheet.getThirdPartyView(),
"ShareSheetCoordinator.onLayoutChange third party view");
}
}

@ -30,6 +30,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.base.ViewUtils;
/**
* This class is responsible for rendering the bottom sheet which displays the touch to fill
@ -336,7 +337,7 @@ class TouchToFillView implements BottomSheetContent {
}
// If the footer would move off-screen, make it sticky and update the layout.
remeasure(true);
mContentView.requestLayout();
ViewUtils.requestLayout(mContentView, "TouchToFillView.getMaximumSheetHeight");
return getHeightWhenFullyExtended();
}
@ -349,7 +350,7 @@ class TouchToFillView implements BottomSheetContent {
// This can happen when bottom sheet container layout changes, apparently causing
// the footer layout to be invalidated. Measure the content view again.
remeasure(true);
footer.requestLayout();
ViewUtils.requestLayout(footer, "TouchToFillView.getHeightWhenFullyExtended");
}
height += getHeightWithMargins(footer, false);
return height;

@ -33,6 +33,7 @@ import org.chromium.components.browser_ui.widget.ChromeTransitionDrawable;
import org.chromium.components.browser_ui.widget.CompositeTouchDelegate;
import org.chromium.components.browser_ui.widget.animation.Interpolators;
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.util.TokenHolder;
import org.chromium.ui.widget.Toast;
@ -348,7 +349,8 @@ public class StatusView extends LinearLayout {
// due to a stale measurement cache. Post a task to request layout to force this visibility
// change (crbug.com/1345552).
if (wasLayoutPreviouslyRequested && getHandler() != null) {
getHandler().post(() -> requestLayout());
getHandler().post(
() -> ViewUtils.requestLayout(this, "StatusView.setStatusIconShown Runnable"));
}
}

@ -457,7 +457,7 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
mInitialResizeState = InitialResizeState.IGNORING_SHRINKING;
PostTask.postDelayedTask(UiThreadTaskTraits.USER_BLOCKING, () -> {
if (mInitialResizeState != InitialResizeState.IGNORING_SHRINKING) return;
requestLayout();
ViewUtils.requestLayout(this, "OmniboxSuggestionsDropdown.onMeasure");
mInitialResizeState = InitialResizeState.HANDLED_INITIAL_SIZING;
}, DEFERRED_INITIAL_SHRINKING_LAYOUT_FROM_IME_DURATION_MS);
return;
@ -593,7 +593,8 @@ public class OmniboxSuggestionsDropdown extends RecyclerView {
@Override
public void onGlobalLayout() {
if (offsetInWindowChanged() || insetsHaveChanged()) {
requestLayout();
ViewUtils.requestLayout(OmniboxSuggestionsDropdown.this,
"OmniboxSuggestionsDropdown.setEmbedder.OnGlobalLayoutListener.onGlobalLayout");
}
}

@ -18,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
import org.chromium.chrome.browser.omnibox.R;
import org.chromium.chrome.browser.omnibox.suggestions.header.HeaderView;
import org.chromium.chrome.browser.util.KeyNavigationUtil;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
/**
@ -134,7 +135,7 @@ public class BaseCarouselSuggestionView extends LinearLayout {
*/
public void setItemSpacingPx(int itemSpacingPx) {
mItemSpacingPx = itemSpacingPx;
mRecyclerView.requestLayout();
ViewUtils.requestLayout(mRecyclerView, "BaseCarouselSuggestionView.setItemSpacingPx");
}
/**

@ -6,6 +6,8 @@ package org.chromium.chrome.browser.omnibox.suggestions.tail;
import android.view.View;
import org.chromium.ui.base.ViewUtils;
import java.util.ArrayList;
import java.util.List;
@ -87,7 +89,7 @@ class AlignmentManager {
for (int index = 0; index < count; ++index) {
final View view = mVisibleTailSuggestions.get(index);
if (view == excluded) continue;
view.requestLayout();
ViewUtils.requestLayout(view, "AlignmentManger.relayoutAllViewsExcept");
}
}
}

@ -1799,7 +1799,7 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
// The width of location bar depends on mTabSwitcherState so layout request is needed. See
// crbug.com/974745.
requestLayout();
ViewUtils.requestLayout(this, "ToolbarPhone.setTabSwitcherMode");
mLocationBar.setUrlBarFocusable(false);
@ -1894,7 +1894,7 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
// The width of location bar depends on mTabSwitcherState so layout request is needed. See
// crbug.com/974745.
requestLayout();
ViewUtils.requestLayout(this, "ToolbarPhone.onTabSwitcherTransitionFinished");
finishAnimations();
updateVisualsForLocationBarState();
updateViewsForTabSwitcherMode();
@ -2064,7 +2064,8 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
mDisableLocationBarRelayout = true;
} else {
mLayoutLocationBarInFocusedMode = true;
requestLayout();
ViewUtils.requestLayout(ToolbarPhone.this,
"ToolbarPhone.triggerUrlFocusAnimation.CancelAwareAnimatorListener.onStart");
}
}
@ -2080,7 +2081,8 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
if (!hasFocus) {
mDisableLocationBarRelayout = false;
mLayoutLocationBarInFocusedMode = false;
requestLayout();
ViewUtils.requestLayout(ToolbarPhone.this,
"ToolbarPhone.triggerUrlFocusAnimation.CancelAwareAnimatorListener.onEnd");
}
mLocationBar.finishUrlFocusChange(hasFocus, shouldShowKeyboard,
getToolbarDataProvider().shouldShowLocationBarInOverviewMode());
@ -2214,7 +2216,8 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
ntpDelegate.setSearchBoxScrollListener(this::onNtpScrollChanged);
if (ntpDelegate.isLocationBarShown()) {
updateToNtpBackground();
requestLayout();
ViewUtils.requestLayout(
this, "ToolbarPhone.updateNtpAnimationState showing LocationBar");
} else if (wasShowingNtp) {
// Convert the previous NTP scroll progress to URL focus progress because that
// will give a nicer transition animation from the expanded NTP omnibox to the
@ -2224,7 +2227,7 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
Math.max(previousNtpScrollFraction, mUrlFocusChangeFraction);
triggerUrlFocusAnimation(false);
}
requestLayout();
ViewUtils.requestLayout(this, "ToolbarPhone.updateNtpAnimationState showing ntp");
}
}
@ -2475,7 +2478,8 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
case TransitionType.COLLAPSING_ACTION_CHIP:
case TransitionType.HIDING:
mLayoutLocationBarWithoutExtraButton = true;
requestLayout();
ViewUtils.requestLayout(this,
"ToolbarPhone.initializeOptionalButton.mOptionalButton.setTransitionStartedCallback");
break;
case TransitionType.EXPANDING_ACTION_CHIP:
case TransitionType.SHOWING:
@ -2495,7 +2499,8 @@ public class ToolbarPhone extends ToolbarLayout implements OnClickListener, TabC
mOptionalButtonAnimationRunning = false;
allowBrowserControlsHide();
if (mLayoutUpdater != null) mLayoutUpdater.run();
requestLayout();
ViewUtils.requestLayout(this,
"ToolbarPhone.initializeOptionalButton.mOptionalButton.setTransitionFinishedCallback");
});
}
}

@ -44,6 +44,7 @@ import org.chromium.components.image_fetcher.ImageFetcher;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ApplicationViewportInsetSupplier;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.util.AccessibilityUtil;
@ -300,7 +301,10 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
mAccessibilityObserver = (talkbackEnabled) -> {
setViewportMode(talkbackEnabled ? AssistantViewportMode.RESIZE_VISUAL_VIEWPORT
: mTargetViewportMode);
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, mRootViewContainer::requestLayout);
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
ViewUtils.requestLayout(mRootViewContainer,
"AssistantBottomBarCoordinator.<init>.mAccessibilityObserver Runnable");
});
};
mAccessibilityUtil.addObserver(mAccessibilityObserver);
}

@ -34,6 +34,7 @@ import org.chromium.components.browser_ui.bottomsheet.internal.R;
import org.chromium.components.browser_ui.widget.animation.CancelAwareAnimatorListener;
import org.chromium.ui.KeyboardVisibilityDelegate;
import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.util.AccessibilityUtil;
/**
@ -430,7 +431,9 @@ class BottomSheet extends FrameLayout
// Trigger a relayout on window focus to correct any positioning issues when leaving Chrome
// previously. This is required as a layout is not triggered when coming back to Chrome
// with the keyboard previously shown.
if (hasWindowFocus) requestLayout();
if (hasWindowFocus) {
ViewUtils.requestLayout(this, "BottomSheet.onWindowFocusChagned");
}
}
@Override
@ -1076,7 +1079,7 @@ class BottomSheet extends FrameLayout
getLayoutParams().width = maxSheetWidth;
setTranslationX((LocalizationUtils.isLayoutRtl() ? -1 : 1)
* (mContainerWidth - maxSheetWidth) / 2f);
requestLayout();
ViewUtils.requestLayout(this, "BottomSheet.sizeAndPositionSheetInParent");
}
private void ensureContentDesiredHeightIsComputed() {

@ -37,6 +37,7 @@ import org.chromium.components.browser_ui.widget.selectable_list.SelectableListL
import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
import org.chromium.net.MimeTypeFilter;
import org.chromium.ui.base.PhotoPickerListener;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid;
import java.util.ArrayList;
@ -257,7 +258,7 @@ public class PickerCategoryView extends RelativeLayout
// list becomes ready.
if (mPickerBitmaps != null) {
mPickerAdapter.notifyDataSetChanged();
mRecyclerView.requestLayout();
ViewUtils.requestLayout(mRecyclerView, "PickerCategoryView.onConfigurationChanged");
}
}
@ -453,7 +454,7 @@ public class PickerCategoryView extends RelativeLayout
mLayoutManager.setSpanCount(mColumns);
mPickerAdapter.notifyDataSetChanged();
mRecyclerView.requestLayout();
ViewUtils.requestLayout(mRecyclerView, "PickerCategoryView.flipZoomMode");
}
// Simple accessors:

@ -36,6 +36,7 @@ import androidx.core.view.GestureDetectorCompat;
import org.chromium.base.task.PostTask;
import org.chromium.content_public.browser.UiThreadTaskTraits;
import org.chromium.ui.UiUtils;
import org.chromium.ui.base.ViewUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -403,9 +404,11 @@ public class PickerVideoPlayer
}
mVideoView.setLayoutParams(layoutParams);
mVideoView.requestLayout();
ViewUtils.requestLayout(
mVideoView, "PickerVideoPlayer.adjustVideoLayoutParamsToOrientation mVideoView");
mVideoControls.setLayoutParams(layoutParams);
mVideoControls.requestLayout();
ViewUtils.requestLayout(mVideoControls,
"PickerVideoPlayer.adjustVideoLayoutParamsToOrientation mVideoControls");
}
private boolean onSingleTapVideo() {

@ -13,6 +13,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceDialogFragmentCompat;
import org.chromium.base.Callback;
import org.chromium.ui.base.ViewUtils;
/**
* The fragment used to display the clear website storage confirmation dialog.
@ -54,7 +55,10 @@ public class ClearWebsiteStorageDialog extends PreferenceDialogFragmentCompat {
// When the device switches to multi-window in landscape mode, the height of the
// offlineTextView is not calculated correctly (its height gets truncated) and a layout
// pass is needed to fix it. See https://crbug.com/1072922.
mDialogView.getHandler().post(mDialogView::requestLayout);
mDialogView.getHandler().post(() -> {
ViewUtils.requestLayout(
mDialogView, "ClearWebsiteStorageDialog.onConfigurationChanged Runnable");
});
}
}

@ -11,6 +11,8 @@ import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.widget.LinearLayout;
import org.chromium.ui.base.ViewUtils;
/**
* A LinearLayout that can be constrained to a maximum size or percentage of the screen size.
*
@ -63,7 +65,7 @@ public class BoundedLinearLayout extends LinearLayout {
boolean ignoreWidthConstraints, boolean ignoreHeightConstraint) {
mIgnoreWidthConstraints = ignoreWidthConstraints;
mIgnoreHeightConstraints = ignoreHeightConstraint;
requestLayout();
ViewUtils.requestLayout(this, "BoundedLinearLayout.setIgnoreConstraints");
}
@Override

@ -16,6 +16,8 @@ import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import org.chromium.ui.base.ViewUtils;
import java.util.ArrayList;
/** Animates children of a vertical {@link LinearLayout} expanding/collapsing when focused. */
@ -146,7 +148,8 @@ public class FocusAnimator {
finishAnimation(callback);
// Request a layout to put everything in the right final place.
mLayout.requestLayout();
ViewUtils.requestLayout(mLayout,
"FocusAnimator.startAnimator.AnimatorListenerAdapter.onAnimationEnd");
}
});
animator.start();

@ -19,6 +19,8 @@ import android.widget.ImageView;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
import org.chromium.ui.base.ViewUtils;
/**
* A helper class to simulate {@link View#getForeground()} on older versions of Android. This class
* requires specific setup to work properly. The following methods must be overridden and forwarded
@ -125,7 +127,7 @@ public class ForegroundDrawableCompat
}
mDrawable.setCallback(mView);
}
mView.requestLayout();
ViewUtils.requestLayout(mView, "ForegroundDrawableCompat.setDrawable");
mView.invalidate();
}

@ -24,6 +24,7 @@ import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.components.browser_ui.styles.SemanticColorUtils;
import org.chromium.components.browser_ui.widget.R;
import org.chromium.components.browser_ui.widget.TintedDrawable;
import org.chromium.ui.base.ViewUtils;
/**
* Default implementation of SelectableItemViewBase. Contains a start icon, title, description, and
@ -158,7 +159,8 @@ public abstract class SelectableItemView<E> extends SelectableItemViewBase<E> {
mCustomContentContainer = findViewById(R.id.custom_content_container);
mStartIconView.getLayoutParams().width = mStartIconViewSize;
mStartIconView.getLayoutParams().height = mStartIconViewSize;
mStartIconView.requestLayout();
ViewUtils.requestLayout(
mStartIconView, "SelectableItemView.inflateAndPopulateViewVariables");
}
}

@ -24,6 +24,7 @@ import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.ContextUtils;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
@ -95,7 +96,8 @@ public class AddToHomescreenDialogView
mShortcutTitleInput.getLayoutParams().height =
mProgressBarView.getMeasuredHeight()
+ mShortcutTitleInput.getPaddingBottom();
v.requestLayout();
ViewUtils.requestLayout(v,
"AddToHomescreenDialogView.<init>.OnLayoutChangeListener.onLayoutChange");
v.removeOnLayoutChangeListener(this);
}
}

@ -13,6 +13,7 @@ import org.chromium.content.browser.webcontents.WebContentsImpl.UserDataFactory;
import org.chromium.content_public.browser.ViewEventSink;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.ViewAndroidDelegate;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.base.WindowAndroid.ActivityStateObserver;
/**
@ -103,7 +104,10 @@ public final class ViewEventSinkImpl implements ViewEventSink, ActivityStateObse
// To request layout has side effect, but it seems OK as it only happen in
// onConfigurationChange and layout has to be changed in most case.
ViewAndroidDelegate delegate = mWebContents.getViewAndroidDelegate();
if (delegate != null) delegate.getContainerView().requestLayout();
if (delegate != null) {
ViewUtils.requestLayout(
delegate.getContainerView(), "ViewEventSinkImpl.onConfigurationChanged");
}
} finally {
TraceEvent.end("ViewEventSink.onConfigurationChanged");
}

@ -17,6 +17,8 @@ import android.view.ViewGroup;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import org.chromium.base.TraceEvent;
/**
* A utility class that has helper methods for Android view.
*/
@ -215,4 +217,30 @@ public final class ViewUtils {
to = (View) to.getParent();
}
}
/**
* A wrapper that calls android.view.requestLayout() immediately after emitting an instant trace
* event with information about the caller. This helps jank investigations, as there are traces
* with lots of re-layouts, but we don't know where these layouts are coming from.
*
* Do not include any identifying information in {@code caller}! Only constant string literals
* about code execution should be included.
*
* Examples of useful {@code caller} values:
* "MyClass.myMethod" when requestLayout is called in myMethod in MyClass.
* "MyClass.MyInnerClass.myMethod" when requestLayout is called in an inner class.
* "MyClass.myMethod.MyInnerClass.innerMethod" when requestLayout is called in an inner class
* defined in a method.
* "MyClass.myMethod other_helpful_information" when requestLayout is called more than once in
* the same method.
* "MyClass.myMethod Runnable" when requestLayout is posted somewhere to be executed later.
*
* @param view The view to call requestLayout on.
* @param caller Some queryable information about the caller.
*/
public static void requestLayout(View view, String caller) {
assert view != null;
TraceEvent.instant("requestLayout", "caller: " + caller);
view.requestLayout();
}
}

@ -22,6 +22,7 @@ import org.chromium.base.annotations.NativeMethods;
import org.chromium.cc.input.BrowserControlsState;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.EventOffsetHandler;
import org.chromium.ui.base.ViewUtils;
import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
/**
@ -337,7 +338,7 @@ class BrowserControlsContainerView extends FrameLayout {
reportHeightChange();
// Request a layout so onLayout can update the saved dimensions now that the
// layer has finished animating.
requestLayout();
ViewUtils.requestLayout(this, "BrowserControlsContainerView.onOffestsChanged");
}
if (mIsFullscreen) return;