[Signin][Android] Implement Drawable class for AI tier status ring [chromium/src : main]

1 view
Skip to first unread message

gwsq (Gerrit)

unread,
Jul 10, 2026, 4:36:03 AM (9 days ago) Jul 10
to Lucia Giorgi, Chrome Signin Android Reviews, Tanmoy Mollik, Chromium LUCI CQ, chromium...@chromium.org
Attention needed from Tanmoy Mollik

Message from gwsq

Reviewer source(s):
triplo...@chromium.org is from context(googleclient/chrome/chromium_gwsq/chrome/browser/signin/android/config.gwsq)

Open in Gerrit

Related details

Attention is currently required from:
  • Tanmoy Mollik
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
Gerrit-Change-Number: 8037810
Gerrit-PatchSet: 11
Gerrit-Owner: Lucia Giorgi <quac...@google.com>
Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
Gerrit-CC: gwsq
Gerrit-Attention: Tanmoy Mollik <triplo...@google.com>
Gerrit-Comment-Date: Fri, 10 Jul 2026 08:35:52 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Lucia Giorgi (Gerrit)

unread,
Jul 10, 2026, 4:57:01 AM (9 days ago) Jul 10
to Chrome Signin Android Reviews, Tanmoy Mollik, Chromium LUCI CQ, chromium...@chromium.org
Attention needed from Tanmoy Mollik

Lucia Giorgi added 1 comment

Patchset-level comments
File-level comment, Patchset 11 (Latest):
Lucia Giorgi . resolved

Hey @triplo...@google.com, if you need some context you can take a look at the DD linked in the bug but please feel free to reach out to me as well :)

Gerrit-Comment-Date: Fri, 10 Jul 2026 08:56:43 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Tanmoy Mollik (Gerrit)

unread,
Jul 10, 2026, 7:34:33 AM (9 days ago) Jul 10
to Lucia Giorgi, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org
Attention needed from Lucia Giorgi

Tanmoy Mollik added 6 comments

Patchset-level comments
Tanmoy Mollik . unresolved

I think these changes need to be reviewed by someone by the clank team. Not sure if this is the rigth ui pattern to use.

File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
Line 63, Patchset 11 (Latest): // The ring is drawn outside the bounds.
Tanmoy Mollik . unresolved

Please fix this WARNING reported by autoreview issue finding: Drawing outside the `Drawable`'s bounds is highly prone to clipping. Because `getIntrinsicWidth()` and `getIntrinsicHeight()` only return the inner drawable's size, an `ImageView` using `wrap_content` will be sized exactly to the inner drawable, and the ring will likely be clipped by the view's boundaries.

It is safer to include the padding in the intrinsic size, and then inset the inner drawable here:
```java
@Override
public int getIntrinsicWidth() {
return mInnerDrawable.getIntrinsicWidth() + (mRingThicknessPx + mRingSpacingPx) * 2;
}
@Override
public int getIntrinsicHeight() {
return mInnerDrawable.getIntrinsicHeight() + (mRingThicknessPx + mRingSpacingPx) * 2;
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
    int padding = mRingThicknessPx + mRingSpacingPx;

// Inset the bounds for the inner drawable
Rect innerBounds = new Rect(bounds);
innerBounds.inset(padding, padding);
mInnerDrawable.setBounds(innerBounds);
    // Use the outer bounds for the ring
mBounds.set(bounds);
float strokeInset = mRingThicknessPx / 2f;
mBounds.inset(strokeInset, strokeInset);
...
}
```
Line 75, Patchset 11 (Latest): mPaint.setShader(null);
Tanmoy Mollik . unresolved

Please fix this WARNING reported by autoreview issue finding: The javadoc in `SubscriptionTierBrandingDelegate` mentions returning `null` if no ring should be drawn. However, setting the shader to `null` here will cause `mPaint` to fall back to the default solid blue color (set in the constructor), and `drawArc` will still be called.

If the intention is to completely skip drawing the ring when `getRingShader` returns `null`, we should store a boolean flag to skip the `drawArc` call in `draw()`, or set the color to `Color.TRANSPARENT`.

File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGenerator.java
Line 232, Patchset 11 (Latest): android.content.Context context, @Nullable Drawable avatar, @Px int ringThicknessPx) {
Tanmoy Mollik . unresolved

please import this.

File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGeneratorTest.java
Line 234, Patchset 11 (Latest): public void testgetAvatarWithAiTierRing() {
Tanmoy Mollik . unresolved

Please fix this WARNING reported by autoreview issue finding: Typo: should be `testGetAvatarWithAiTierRing` (capital `G`).

Line 246, Patchset 11 (Latest): assertEquals(avatarDrawable.getIntrinsicWidth(), wrappedDrawable.getIntrinsicWidth());
Tanmoy Mollik . unresolved

Please fix this WARNING reported by autoreview issue finding: If `AiTierRingDrawable` is updated to include the ring in its intrinsic size, remember to update these assertions to account for the extra padding.

Open in Gerrit

Related details

Attention is currently required from:
  • Lucia Giorgi
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
    Gerrit-Change-Number: 8037810
    Gerrit-PatchSet: 11
    Gerrit-Owner: Lucia Giorgi <quac...@google.com>
    Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
    Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
    Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
    Gerrit-CC: gwsq
    Gerrit-Attention: Lucia Giorgi <quac...@google.com>
    Gerrit-Comment-Date: Fri, 10 Jul 2026 11:34:15 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Lucia Giorgi (Gerrit)

    unread,
    Jul 14, 2026, 4:30:22 AM (5 days ago) Jul 14
    to Chrome Signin Android Reviews, Tanmoy Mollik, Chromium LUCI CQ, chromium...@chromium.org
    Attention needed from Tanmoy Mollik

    Lucia Giorgi added 4 comments

    File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
    Line 63, Patchset 11: // The ring is drawn outside the bounds.
    Tanmoy Mollik . unresolved

    Please fix this WARNING reported by autoreview issue finding: Drawing outside the `Drawable`'s bounds is highly prone to clipping. Because `getIntrinsicWidth()` and `getIntrinsicHeight()` only return the inner drawable's size, an `ImageView` using `wrap_content` will be sized exactly to the inner drawable, and the ring will likely be clipped by the view's boundaries.

    It is safer to include the padding in the intrinsic size, and then inset the inner drawable here:
    ```java
    @Override
    public int getIntrinsicWidth() {
    return mInnerDrawable.getIntrinsicWidth() + (mRingThicknessPx + mRingSpacingPx) * 2;
    }
    @Override
    public int getIntrinsicHeight() {
    return mInnerDrawable.getIntrinsicHeight() + (mRingThicknessPx + mRingSpacingPx) * 2;
    }
    @Override
    protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
        int padding = mRingThicknessPx + mRingSpacingPx;

    // Inset the bounds for the inner drawable
    Rect innerBounds = new Rect(bounds);
    innerBounds.inset(padding, padding);
    mInnerDrawable.setBounds(innerBounds);
        // Use the outer bounds for the ring
    mBounds.set(bounds);
    float strokeInset = mRingThicknessPx / 2f;
    mBounds.inset(strokeInset, strokeInset);
    ...
    }
    ```
    Lucia Giorgi

    I went with this solution because otherwise I would've needed to add logic to `OptionalButtonView` to accommodate for the bigger footprint of avatar + circle, and I was advised to avoid changing that class because it's widely used. Menghan approved my solution of drawing outside the bounds. Also, here no clipping occurs, and when this feature will be extended to `AccountManagementFragment` and `CentralAccountCardPreference` the fix for the clipping is really easy (literally two lines in the xml file to tell it not to clip it).

    Line 75, Patchset 11: mPaint.setShader(null);
    Tanmoy Mollik . resolved

    Please fix this WARNING reported by autoreview issue finding: The javadoc in `SubscriptionTierBrandingDelegate` mentions returning `null` if no ring should be drawn. However, setting the shader to `null` here will cause `mPaint` to fall back to the default solid blue color (set in the constructor), and `drawArc` will still be called.

    If the intention is to completely skip drawing the ring when `getRingShader` returns `null`, we should store a boolean flag to skip the `drawArc` call in `draw()`, or set the color to `Color.TRANSPARENT`.

    Lucia Giorgi

    Right, I forgot to update the javadoc. The intended behavior is to draw a simple blue circle.

    File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGenerator.java
    Line 232, Patchset 11: android.content.Context context, @Nullable Drawable avatar, @Px int ringThicknessPx) {
    Tanmoy Mollik . resolved

    please import this.

    Lucia Giorgi

    right, thanks!

    File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGeneratorTest.java
    Line 234, Patchset 11: public void testgetAvatarWithAiTierRing() {
    Tanmoy Mollik . resolved

    Please fix this WARNING reported by autoreview issue finding: Typo: should be `testGetAvatarWithAiTierRing` (capital `G`).

    Lucia Giorgi

    Thanks!

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Tanmoy Mollik
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
    Gerrit-Change-Number: 8037810
    Gerrit-PatchSet: 12
    Gerrit-Owner: Lucia Giorgi <quac...@google.com>
    Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
    Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
    Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
    Gerrit-CC: gwsq
    Gerrit-Attention: Tanmoy Mollik <triplo...@google.com>
    Gerrit-Comment-Date: Tue, 14 Jul 2026 08:30:04 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Tanmoy Mollik <triplo...@google.com>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Tanmoy Mollik (Gerrit)

    unread,
    Jul 15, 2026, 3:13:11 AM (4 days ago) Jul 15
    to Lucia Giorgi, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org
    Attention needed from Lucia Giorgi

    Tanmoy Mollik voted and added 3 comments

    Votes added by Tanmoy Mollik

    Code-Review+1

    3 comments

    Patchset-level comments
    File-level comment, Patchset 13 (Latest):
    Tanmoy Mollik . resolved

    overall it looks okay to me. But I am not an owner and you should ask someone from the clank team to take a look as well.

    File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
    Line 63, Patchset 11: // The ring is drawn outside the bounds.
    Tanmoy Mollik . resolved

    Please fix this WARNING reported by autoreview issue finding: Drawing outside the `Drawable`'s bounds is highly prone to clipping. Because `getIntrinsicWidth()` and `getIntrinsicHeight()` only return the inner drawable's size, an `ImageView` using `wrap_content` will be sized exactly to the inner drawable, and the ring will likely be clipped by the view's boundaries.

    It is safer to include the padding in the intrinsic size, and then inset the inner drawable here:
    ```java
    @Override
    public int getIntrinsicWidth() {
    return mInnerDrawable.getIntrinsicWidth() + (mRingThicknessPx + mRingSpacingPx) * 2;
    }
    @Override
    public int getIntrinsicHeight() {
    return mInnerDrawable.getIntrinsicHeight() + (mRingThicknessPx + mRingSpacingPx) * 2;
    }
    @Override
    protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
        int padding = mRingThicknessPx + mRingSpacingPx;

    // Inset the bounds for the inner drawable
    Rect innerBounds = new Rect(bounds);
    innerBounds.inset(padding, padding);
    mInnerDrawable.setBounds(innerBounds);
        // Use the outer bounds for the ring
    mBounds.set(bounds);
    float strokeInset = mRingThicknessPx / 2f;
    mBounds.inset(strokeInset, strokeInset);
    ...
    }
    ```
    Lucia Giorgi

    I went with this solution because otherwise I would've needed to add logic to `OptionalButtonView` to accommodate for the bigger footprint of avatar + circle, and I was advised to avoid changing that class because it's widely used. Menghan approved my solution of drawing outside the bounds. Also, here no clipping occurs, and when this feature will be extended to `AccountManagementFragment` and `CentralAccountCardPreference` the fix for the clipping is really easy (literally two lines in the xml file to tell it not to clip it).

    Tanmoy Mollik

    Acknowledged

    File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGeneratorTest.java
    Line 246, Patchset 11: assertEquals(avatarDrawable.getIntrinsicWidth(), wrappedDrawable.getIntrinsicWidth());
    Tanmoy Mollik . resolved

    Please fix this WARNING reported by autoreview issue finding: If `AiTierRingDrawable` is updated to include the ring in its intrinsic size, remember to update these assertions to account for the extra padding.

    Tanmoy Mollik

    Acknowledged

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Lucia Giorgi
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
      Gerrit-Change-Number: 8037810
      Gerrit-PatchSet: 13
      Gerrit-Owner: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
      Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
      Gerrit-CC: gwsq
      Gerrit-Attention: Lucia Giorgi <quac...@google.com>
      Gerrit-Comment-Date: Wed, 15 Jul 2026 07:12:47 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Comment-In-Reply-To: Lucia Giorgi <quac...@google.com>
      Comment-In-Reply-To: Tanmoy Mollik <triplo...@google.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Wenyu Fu (Gerrit)

      unread,
      Jul 15, 2026, 2:29:17 PM (4 days ago) Jul 15
      to Lucia Giorgi, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org
      Attention needed from Lucia Giorgi

      Wenyu Fu added 7 comments

      Patchset-level comments
      Wenyu Fu . resolved

      Just FYI I have moved to a different team within Chrome, no longer with Clank, so response for Android reviews will be slow :)

      File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
      Line 5, Patchset 13 (Latest):package org.chromium.components.browser_ui.util;
      Wenyu Fu . unresolved

      nit: Can this live in //components/browser_ui/widgets?

      Line 32, Patchset 13 (Latest): public AiTierRingDrawable(Context context, Drawable innerDrawable, @Px int ringThicknessPx) {
      Wenyu Fu . unresolved

      nit: javadoc

      Line 44, Patchset 13 (Latest): mBrandingDelegate = ServiceLoaderUtil.maybeCreate(SubscriptionTierBrandingDelegate.class);
      Wenyu Fu . unresolved

      nit: Can we pass this in from the ctor? It'd be nice to keep this as a pure drawable class without adding this server loader DEPS

      Line 53, Patchset 13 (Latest): canvas.drawArc(mBounds, 0, 360, false, mPaint);
      Wenyu Fu . unresolved

      For drawing a full 360-degree circle, `canvas.drawOval(mBounds, mPaint)` is more concise and slightly more efficient than `drawArc`.

      Line 63, Patchset 13 (Latest): // The ring is drawn outside the bounds.
      Wenyu Fu . unresolved

      This drawable draws the ring outside the `bounds` passed to `onBoundsChange`. Even for static images, this is problematic because most Views (like `ImageView`) will clip the drawing to their own bounds.

      A better approach is to treat the `bounds` as the total area for both the avatar and the ring. You should inset the `mInnerDrawable` bounds so it fits inside the ring.

      Example:
      ```java

      @Override
      protected void onBoundsChange(Rect bounds) {
      super.onBoundsChange(bounds);
          int totalPadding = mRingThicknessPx + mRingSpacingPx;

      // Inset the inner avatar so it fits inside the ring + spacing.

      Rect innerBounds = new Rect(bounds);
          innerBounds.inset(totalPadding, totalPadding);
      mInnerDrawable.setBounds(innerBounds);
          // Set ring bounds so the stroke stays within the allocated area.

      mBounds.set(bounds);
      float strokeInset = mRingThicknessPx / 2f;
      mBounds.inset(strokeInset, strokeInset);
      ...
      }
      ```
      Line 98, Patchset 13 (Latest): return mInnerDrawable.getIntrinsicWidth();
      Wenyu Fu . unresolved

      This should return the total width including the ring and the spacing. If it only returns the inner width, parent views using `wrap_content` will not allocate enough space for the ring.

      ```java
      @Override
      public int getIntrinsicWidth() {
          int innerWidth = mInnerDrawable.getIntrinsicWidth();
      if (innerWidth <= 0) return innerWidth;
      return innerWidth + 2 * (mRingThicknessPx + mRingSpacingPx);
      }
      ```
      Open in Gerrit

      Related details

      Attention is currently required from:
      • Lucia Giorgi
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
      Gerrit-Change-Number: 8037810
      Gerrit-PatchSet: 13
      Gerrit-Owner: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
      Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
      Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
      Gerrit-CC: gwsq
      Gerrit-Attention: Lucia Giorgi <quac...@google.com>
      Gerrit-Comment-Date: Wed, 15 Jul 2026 18:29:03 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Lucia Giorgi (Gerrit)

      unread,
      Jul 15, 2026, 2:42:05 PM (4 days ago) Jul 15
      to Wenyu Fu, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org
      Attention needed from Wenyu Fu

      Lucia Giorgi added 2 comments

      Patchset-level comments
      Lucia Giorgi . resolved

      Thank you @wen...@chromium.org for the review! Just one quick question before I start addressing your comments in the implementation

      File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
      Line 63, Patchset 11: // The ring is drawn outside the bounds.
      Tanmoy Mollik . unresolved

      Please fix this WARNING reported by autoreview issue finding: Drawing outside the `Drawable`'s bounds is highly prone to clipping. Because `getIntrinsicWidth()` and `getIntrinsicHeight()` only return the inner drawable's size, an `ImageView` using `wrap_content` will be sized exactly to the inner drawable, and the ring will likely be clipped by the view's boundaries.

      It is safer to include the padding in the intrinsic size, and then inset the inner drawable here:
      ```java
      @Override
      public int getIntrinsicWidth() {
          return mInnerDrawable.getIntrinsicWidth() + (mRingThicknessPx + mRingSpacingPx) * 2;
      }
      @Override
      public int getIntrinsicHeight() {
      return mInnerDrawable.getIntrinsicHeight() + (mRingThicknessPx + mRingSpacingPx) * 2;
      }
      @Override

      protected void onBoundsChange(Rect bounds) {
      super.onBoundsChange(bounds);
          int padding = mRingThicknessPx + mRingSpacingPx;


      // Inset the bounds for the inner drawable
          Rect innerBounds = new Rect(bounds);
          innerBounds.inset(padding, padding);
      mInnerDrawable.setBounds(innerBounds);
          // Use the outer bounds for the ring
          mBounds.set(bounds);
      float strokeInset = mRingThicknessPx / 2f;
      mBounds.inset(strokeInset, strokeInset);
      ...
      }
      ```
      Lucia Giorgi

      I went with this solution because otherwise I would've needed to add logic to `OptionalButtonView` to accommodate for the bigger footprint of avatar + circle, and I was advised to avoid changing that class because it's widely used. Menghan approved my solution of drawing outside the bounds. Also, here no clipping occurs, and when this feature will be extended to `AccountManagementFragment` and `CentralAccountCardPreference` the fix for the clipping is really easy (literally two lines in the xml file to tell it not to clip it).

      Tanmoy Mollik

      Acknowledged

      Lucia Giorgi

      @wen...@chromium.org
      This was the motivation behind drawing outside of the bounds since we don't want to shrink the avatar size. Can you confirm that I can make changes to `OptionalButtonView` if I go with your solution?

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Wenyu Fu
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
      Gerrit-Change-Number: 8037810
      Gerrit-PatchSet: 13
      Gerrit-Owner: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
      Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
      Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
      Gerrit-CC: gwsq
      Gerrit-Attention: Wenyu Fu <wen...@chromium.org>
      Gerrit-Comment-Date: Wed, 15 Jul 2026 18:41:44 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Tanmoy Mollik <triplo...@google.com>
      Comment-In-Reply-To: Lucia Giorgi <quac...@google.com>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Wenyu Fu (Gerrit)

      unread,
      Jul 15, 2026, 6:38:49 PM (4 days ago) Jul 15
      to Lucia Giorgi, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org
      Attention needed from Lucia Giorgi

      Wenyu Fu added 1 comment

      File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
      Wenyu Fu

      The current CL that this is implemented as a drawable makes me hesitate - it can be put into any view which the parent will have the ability to clip / scale the drawable within.

      If wthis is a case exception for a specific view, it might make sense to do this exception at the view level. We have prior cases that need to draw outer rings that goes beyond the view bounds e.g. [OutlineViewHelper](https://source.chromium.org/chromium/chromium/src/+/main:ui/android/java/src/org/chromium/ui/widget/OutlineOverlayHelper.java;l=54;bpv=0;bpt=1) but I don't know if this is directly applicable here.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Lucia Giorgi
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
      Gerrit-Change-Number: 8037810
      Gerrit-PatchSet: 13
      Gerrit-Owner: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
      Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
      Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
      Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
      Gerrit-CC: gwsq
      Gerrit-Attention: Lucia Giorgi <quac...@google.com>
      Gerrit-Comment-Date: Wed, 15 Jul 2026 22:38:36 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Lucia Giorgi (Gerrit)

      unread,
      Jul 17, 2026, 7:47:50 AM (2 days ago) Jul 17
      to android-bu...@system.gserviceaccount.com, Wenyu Fu, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org, hanxi...@chromium.org, peilinwa...@google.com
      Attention needed from Tanmoy Mollik and Wenyu Fu

      Lucia Giorgi added 10 comments

      Patchset-level comments
      File-level comment, Patchset 15 (Latest):
      Lucia Giorgi . unresolved

      I've completely changed the approach to ensure no drawing occurs outside the bounds of the drawable.

      To prevent the avatar image from being shrunk, I had to adjust the surrounding paddings in the UI instead. To do that, I added a boolean to `DisplayableProfileData` so the views know when to accommodate the extra spacing for the ring.

      Wdyt?

      File chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCache.java
      Line 373, Patchset 15 (Latest): /* hasAiTierRing= */ false);
      Lucia Giorgi . unresolved

      Setting to `false` for now, the proper logic will be added in a follow up CL.

      File chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
      Line 412, Patchset 15 (Latest): int paddingBottom =
      Lucia Giorgi . unresolved

      added padding logic to accommodate for the bigger footprint of avatar + ring

      File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
      Line 5, Patchset 13:package org.chromium.components.browser_ui.util;
      Wenyu Fu . unresolved

      nit: Can this live in //components/browser_ui/widgets?

      Lucia Giorgi
      Taking a look at `components/browser_ui/widget/android/BUILD.gn`, we can see that `//components/browser_ui/widgets` [depends](https://source.chromium.org/chromium/chromium/src/+/main:components/browser_ui/widget/android/BUILD.gn;l=156;drc=e90d6417232c42a007ecb0f8ec1cd148351fe2c5) on `//components/browser_ui/util`.
      This drawable is used by `AvatarGenerator` which is in `util`, so this would create a circular dependency.
      Line 32, Patchset 13: public AiTierRingDrawable(Context context, Drawable innerDrawable, @Px int ringThicknessPx) {
      Wenyu Fu . resolved

      nit: javadoc

      Lucia Giorgi

      Done

      Line 44, Patchset 13: mBrandingDelegate = ServiceLoaderUtil.maybeCreate(SubscriptionTierBrandingDelegate.class);
      Wenyu Fu . unresolved

      nit: Can we pass this in from the ctor? It'd be nice to keep this as a pure drawable class without adding this server loader DEPS

      Lucia Giorgi

      Sure, is it ok now?

      Line 53, Patchset 13: canvas.drawArc(mBounds, 0, 360, false, mPaint);
      Wenyu Fu . resolved

      For drawing a full 360-degree circle, `canvas.drawOval(mBounds, mPaint)` is more concise and slightly more efficient than `drawArc`.

      Lucia Giorgi

      oh thanks, done!

      Lucia Giorgi

      Ok, got it. I changed approach and now the ring is no longer drawn outside the bounds.

      Line 63, Patchset 13: // The ring is drawn outside the bounds.
      Wenyu Fu . unresolved

      This drawable draws the ring outside the `bounds` passed to `onBoundsChange`. Even for static images, this is problematic because most Views (like `ImageView`) will clip the drawing to their own bounds.

      A better approach is to treat the `bounds` as the total area for both the avatar and the ring. You should inset the `mInnerDrawable` bounds so it fits inside the ring.

      Example:
      ```java

      @Override
      protected void onBoundsChange(Rect bounds) {
      super.onBoundsChange(bounds);
          int totalPadding = mRingThicknessPx + mRingSpacingPx;

      // Inset the inner avatar so it fits inside the ring + spacing.
          Rect innerBounds = new Rect(bounds);
          innerBounds.inset(totalPadding, totalPadding);
      mInnerDrawable.setBounds(innerBounds);
          // Set ring bounds so the stroke stays within the allocated area.
          mBounds.set(bounds);
      float strokeInset = mRingThicknessPx / 2f;
      mBounds.inset(strokeInset, strokeInset);
      ...
      }
      ```
      Lucia Giorgi

      Thank you, I implemented this solution!

      Line 98, Patchset 13: return mInnerDrawable.getIntrinsicWidth();
      Wenyu Fu . resolved

      This should return the total width including the ring and the spacing. If it only returns the inner width, parent views using `wrap_content` will not allocate enough space for the ring.

      ```java
      @Override
      public int getIntrinsicWidth() {

      int innerWidth = mInnerDrawable.getIntrinsicWidth();
      if (innerWidth <= 0) return innerWidth;
      return innerWidth + 2 * (mRingThicknessPx + mRingSpacingPx);
      }
      ```
      Lucia Giorgi

      Thanks!

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Tanmoy Mollik
      • Wenyu Fu
      Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement is not satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement is not satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
        Gerrit-Change-Number: 8037810
        Gerrit-PatchSet: 15
        Gerrit-Owner: Lucia Giorgi <quac...@google.com>
        Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
        Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
        Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
        Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
        Gerrit-CC: gwsq
        Gerrit-Attention: Tanmoy Mollik <triplo...@google.com>
        Gerrit-Attention: Wenyu Fu <wen...@chromium.org>
        Gerrit-Comment-Date: Fri, 17 Jul 2026 11:47:31 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Lucia Giorgi <quac...@google.com>
        Comment-In-Reply-To: Tanmoy Mollik <triplo...@google.com>
        Comment-In-Reply-To: Wenyu Fu <wen...@chromium.org>
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Wenyu Fu (Gerrit)

        unread,
        Jul 17, 2026, 4:28:14 PM (2 days ago) Jul 17
        to Lucia Giorgi, android-bu...@system.gserviceaccount.com, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org, hanxi...@chromium.org, peilinwa...@google.com
        Attention needed from Lucia Giorgi and Tanmoy Mollik

        Wenyu Fu voted and added 9 comments

        Votes added by Wenyu Fu

        Code-Review+1

        9 comments

        Patchset-level comments
        Wenyu Fu . resolved

        Thanks!

        File chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java
        Line 285, Patchset 15 (Latest): public Builder setHasAiTierRing(boolean hasAiTierRing) {
        Wenyu Fu . unresolved

        Just thoughts: I wonder if it make sense to group this with `setIsIdentityDisk` so this is limited to avatar for now. Unsure if it will be useful for other buttons?

        File chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
        Line 417, Patchset 15 (Latest): : buttonSpec.hasAiTierRing()
        Wenyu Fu . unresolved

        nit: The indentation of using inline if else is quite bad... can we use if blocks to improve this?

        Line 439, Patchset 15 (Latest): mButton.setPaddingRelative(paddingStart, paddingTop, paddingEnd, paddingBottom);
        Wenyu Fu . unresolved

        Can you please test if this padding changes the toolbar height / space between the buttons? I think they should be fine, but just want to make sure

        File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AiTierRingDrawable.java
        Line 5, Patchset 13:package org.chromium.components.browser_ui.util;
        Wenyu Fu . resolved

        nit: Can this live in //components/browser_ui/widgets?

        Lucia Giorgi
        Taking a look at `components/browser_ui/widget/android/BUILD.gn`, we can see that `//components/browser_ui/widgets` [depends](https://source.chromium.org/chromium/chromium/src/+/main:components/browser_ui/widget/android/BUILD.gn;l=156;drc=e90d6417232c42a007ecb0f8ec1cd148351fe2c5) on `//components/browser_ui/util`.
        This drawable is used by `AvatarGenerator` which is in `util`, so this would create a circular dependency.
        Wenyu Fu

        Make sense, thanks!

        Line 44, Patchset 13: mBrandingDelegate = ServiceLoaderUtil.maybeCreate(SubscriptionTierBrandingDelegate.class);
        Wenyu Fu . resolved

        nit: Can we pass this in from the ctor? It'd be nice to keep this as a pure drawable class without adding this server loader DEPS

        Lucia Giorgi

        Sure, is it ok now?

        Wenyu Fu

        Thanks!

        Line 63, Patchset 13: // The ring is drawn outside the bounds.
        Wenyu Fu . resolved

        This drawable draws the ring outside the `bounds` passed to `onBoundsChange`. Even for static images, this is problematic because most Views (like `ImageView`) will clip the drawing to their own bounds.

        A better approach is to treat the `bounds` as the total area for both the avatar and the ring. You should inset the `mInnerDrawable` bounds so it fits inside the ring.

        Example:
        ```java
        @Override
        protected void onBoundsChange(Rect bounds) {
        super.onBoundsChange(bounds);
        int totalPadding = mRingThicknessPx + mRingSpacingPx;

        // Inset the inner avatar so it fits inside the ring + spacing.
        Rect innerBounds = new Rect(bounds);
        innerBounds.inset(totalPadding, totalPadding);
        mInnerDrawable.setBounds(innerBounds);
            // Set ring bounds so the stroke stays within the allocated area.
        mBounds.set(bounds);
        float strokeInset = mRingThicknessPx / 2f;
        mBounds.inset(strokeInset, strokeInset);
        ...
        }
        ```
        Lucia Giorgi

        Thank you, I implemented this solution!

        Wenyu Fu

        Acknowledged

        File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGenerator.java
        Line 234, Patchset 15 (Latest): Context context, @Nullable Drawable avatar, @Px int ringThicknessPx) {
        Wenyu Fu . unresolved

        optional nit: The contract here is if we pass a null avatar you get a null return value - seems we can just avoid the @Nullable altogether by ensure the `avatar` is not null

        File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/SubscriptionTierBrandingDelegate.java
        Line 23, Patchset 15 (Latest): * @return The Shader to use for drawing the ring, or null to fall back to the default solid
        * blue color.
        Wenyu Fu . unresolved

        nit: This is a implementation detail for AiTierRingDrawable, not this interface. Let's move it

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Lucia Giorgi
        • Tanmoy Mollik
        Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement is not satisfiedCode-Owners
          • requirement satisfiedCode-Review
          • requirement is not satisfiedNo-Unresolved-Comments
          • requirement satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
          Gerrit-Change-Number: 8037810
          Gerrit-PatchSet: 15
          Gerrit-Owner: Lucia Giorgi <quac...@google.com>
          Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
          Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
          Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
          Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
          Gerrit-CC: gwsq
          Gerrit-Attention: Lucia Giorgi <quac...@google.com>
          Gerrit-Attention: Tanmoy Mollik <triplo...@google.com>
          Gerrit-Comment-Date: Fri, 17 Jul 2026 20:28:02 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          Comment-In-Reply-To: Lucia Giorgi <quac...@google.com>
          Comment-In-Reply-To: Wenyu Fu <wen...@chromium.org>
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Lucia Giorgi (Gerrit)

          unread,
          Jul 18, 2026, 3:16:59 PM (16 hours ago) Jul 18
          to Wenyu Fu, android-bu...@system.gserviceaccount.com, Tanmoy Mollik, Chrome Signin Android Reviews, Chromium LUCI CQ, chromium...@chromium.org, hanxi...@chromium.org, peilinwa...@google.com
          Attention needed from Tanmoy Mollik and Wenyu Fu

          Lucia Giorgi added 5 comments

          File chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/ButtonData.java
          Line 285, Patchset 15: public Builder setHasAiTierRing(boolean hasAiTierRing) {
          Wenyu Fu . unresolved

          Just thoughts: I wonder if it make sense to group this with `setIsIdentityDisk` so this is limited to avatar for now. Unsure if it will be useful for other buttons?

          Lucia Giorgi

          Yeah, it makes sense as it won't be used for other buttons. I renamed the method to `setIdentityDiscConfig` and grouped both booleans together.

          File chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/optional_button/OptionalButtonView.java
          Line 417, Patchset 15: : buttonSpec.hasAiTierRing()
          Wenyu Fu . unresolved

          nit: The indentation of using inline if else is quite bad... can we use if blocks to improve this?

          Lucia Giorgi
          Sure, is it better now? Or should I group them like this?
          ```
          if (buttonSpec.hasErrorBadge()) {
          paddingBottomRes = ...
          paddingTopRes = ...
          paddingStartRes = ...
          } else if (buttonSpec.hasAiTierRing()) {
          paddingBottomRes = ...
          paddingTopRes = ...
          paddingStartRes = ...
          } else {
          paddingBottomRes = ...
          paddingTopRes = ...
          paddingStartRes = ...
          }

          ```
          Line 439, Patchset 15: mButton.setPaddingRelative(paddingStart, paddingTop, paddingEnd, paddingBottom);
          Wenyu Fu . unresolved

          Can you please test if this padding changes the toolbar height / space between the buttons? I think they should be fine, but just want to make sure

          Lucia Giorgi

          Sure, I double checked and everything looks fine!

          File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/AvatarGenerator.java
          Line 234, Patchset 15: Context context, @Nullable Drawable avatar, @Px int ringThicknessPx) {
          Wenyu Fu . resolved

          optional nit: The contract here is if we pass a null avatar you get a null return value - seems we can just avoid the @Nullable altogether by ensure the `avatar` is not null

          Lucia Giorgi

          Thank you for pointing that out, I removed the `@Nullable`!

          File components/browser_ui/util/android/java/src/org/chromium/components/browser_ui/util/SubscriptionTierBrandingDelegate.java
          Line 23, Patchset 15: * @return The Shader to use for drawing the ring, or null to fall back to the default solid
          * blue color.
          Wenyu Fu . resolved

          nit: This is a implementation detail for AiTierRingDrawable, not this interface. Let's move it

          Lucia Giorgi

          Done

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Tanmoy Mollik
          • Wenyu Fu
          Submit Requirements:
            • requirement satisfiedCode-Coverage
            • requirement is not satisfiedCode-Owners
            • requirement is not satisfiedCode-Review
            • requirement is not satisfiedNo-Unresolved-Comments
            • requirement is not satisfiedReview-Enforcement
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: comment
            Gerrit-Project: chromium/src
            Gerrit-Branch: main
            Gerrit-Change-Id: I7b628c868bde5f6b14351c267711cc076eddb1fb
            Gerrit-Change-Number: 8037810
            Gerrit-PatchSet: 17
            Gerrit-Owner: Lucia Giorgi <quac...@google.com>
            Gerrit-Reviewer: Lucia Giorgi <quac...@google.com>
            Gerrit-Reviewer: Tanmoy Mollik <triplo...@google.com>
            Gerrit-Reviewer: Wenyu Fu <wen...@chromium.org>
            Gerrit-CC: Chrome Signin Android Reviews <chrome-signin-...@google.com>
            Gerrit-CC: gwsq
            Gerrit-Attention: Tanmoy Mollik <triplo...@google.com>
            Gerrit-Attention: Wenyu Fu <wen...@chromium.org>
            Gerrit-Comment-Date: Sat, 18 Jul 2026 19:16:35 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: No
            Comment-In-Reply-To: Wenyu Fu <wen...@chromium.org>
            satisfied_requirement
            unsatisfied_requirement
            open
            diffy
            Reply all
            Reply to author
            Forward
            0 new messages