From b676ca3a62878fdcd01ac7c55fc67621a2ce9f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Fri, 16 Aug 2024 15:15:00 +0200 Subject: [PATCH] Fix several issues related to CircularIconsPreference * Sometimes would cause an unending stream of accessibility events (particularly if starting off-screen). This would break TalkBack and anything that depends on UiAutomator (although the system itself took it like a champ). * Sometimes would not load images (because the ViewTreeObserver would never fire onGlobalLayout after being added because measured width was 0, even though a new width was calculated later). * Would not recalculate the number of icons that fit if the width changes after the first layout. Combining ViewHolders with waiting for measuring and/or ViewTreeObservers was always a wonky approach, even though it should've worked in theory. This should be more robust. Also fixes the unwanted animation on mode screen load related to the absence of the header name being applied a tad too late. Fixes: 359948417 Fixes: 360072876 Fixes: 360328804 Test: atest SettingsRoboTests + manual + adb shell uiautomator events Flag: android.app.modes_ui Change-Id: I7e5dfbdab220d1ebc1c68e5e87ce544ee86b6a65 --- res/layout/preference_circular_icons.xml | 4 +- .../AbstractZenModeHeaderController.java | 15 +- .../modes/CircularIconsPreference.java | 202 ++------------- .../notification/modes/CircularIconsView.java | 232 ++++++++++++++++++ .../settings/notification/modes/IconUtil.java | 20 +- .../ZenModeAppsLinkPreferenceController.java | 4 +- .../ZenModeOtherLinkPreferenceController.java | 2 +- ...ZenModePeopleLinkPreferenceController.java | 2 +- .../modes/CircularIconsPreferenceTest.java | 182 ++++++++------ .../TestableCircularIconsPreference.java | 4 +- ...nModeAppsLinkPreferenceControllerTest.java | 17 +- ...ModeOtherLinkPreferenceControllerTest.java | 4 +- ...odePeopleLinkPreferenceControllerTest.java | 25 +- 13 files changed, 414 insertions(+), 299 deletions(-) create mode 100644 src/com/android/settings/notification/modes/CircularIconsView.java diff --git a/res/layout/preference_circular_icons.xml b/res/layout/preference_circular_icons.xml index 863d2288513..e1d7cfeb470 100644 --- a/res/layout/preference_circular_icons.xml +++ b/res/layout/preference_circular_icons.xml @@ -58,8 +58,8 @@ android:lineBreakWordStyle="phrase" android:maxLines="10"/> - - + icons, int extraItems) { - static final LoadedIcons EMPTY = new LoadedIcons(ImmutableList.of(), 0); - } - - private Executor mUiExecutor; - - // Chronologically, fields will be set top-to-bottom. - @Nullable private CircularIconSet mIconSet; - @Nullable private ListenableFuture> mPendingLoadIconsFuture; - @Nullable private LoadedIcons mLoadedIcons; + private CircularIconSet mIconSet = CircularIconSet.EMPTY; public CircularIconsPreference(Context context) { super(context); - init(context); - } - - @VisibleForTesting(otherwise = VisibleForTesting.NONE) - public CircularIconsPreference(Context context, Executor uiExecutor) { - this(context); - mUiExecutor = uiExecutor; + init(); } public CircularIconsPreference(Context context, AttributeSet attrs) { super(context, attrs); - init(context); + init(); } public CircularIconsPreference(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(context); + init(); } public CircularIconsPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - init(context); + init(); } - private void init(Context context) { - mUiExecutor = context.getMainExecutor(); + private void init() { setLayoutResource(R.layout.preference_circular_icons); } - void displayIcons(CircularIconSet iconSet) { - displayIcons(iconSet, null); + void setIcons(CircularIconSet iconSet) { + setIcons(iconSet, null); } - void displayIcons(CircularIconSet iconSet, @Nullable Equivalence itemEquivalence) { - if (mIconSet != null && mIconSet.hasSameItemsAs(iconSet, itemEquivalence)) { + void setIcons(CircularIconSet iconSet, @Nullable Equivalence itemEquivalence) { + if (mIconSet.hasSameItemsAs(iconSet, itemEquivalence)) { return; } + mIconSet = iconSet; - - mLoadedIcons = null; - if (mPendingLoadIconsFuture != null) { - mPendingLoadIconsFuture.cancel(true); - mPendingLoadIconsFuture = null; - } - notifyChanged(); } @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); + CircularIconsView iconContainer = checkNotNull( + (CircularIconsView) holder.findViewById(R.id.circles_container)); - LinearLayout iconContainer = checkNotNull( - (LinearLayout) holder.findViewById(R.id.circles_container)); - bindIconContainer(iconContainer); - } - - private void bindIconContainer(LinearLayout container) { - if (mLoadedIcons != null) { - // We have the icons ready to display already, show them. - setDrawables(container, mLoadedIcons); - } else if (mIconSet != null) { - // We know what icons we want, but haven't yet loaded them. - if (mIconSet.size() == 0) { - container.setVisibility(View.GONE); - mLoadedIcons = LoadedIcons.EMPTY; - return; - } - container.setVisibility(View.VISIBLE); - if (container.getMeasuredWidth() != 0) { - startLoadingIcons(container, mIconSet); - } else { - container.getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - container.getViewTreeObserver().removeOnGlobalLayoutListener(this); - notifyChanged(); - } - } - ); - } - } - } - - private void startLoadingIcons(LinearLayout container, CircularIconSet iconSet) { - Resources res = getContext().getResources(); - int availableSpace = container.getMeasuredWidth(); - int iconHorizontalSpace = res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_diameter) - + res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_margin_between); - int numIconsThatFit = availableSpace / iconHorizontalSpace; - - List> iconFutures; - int extraItems; - if (iconSet.size() > numIconsThatFit) { - // Reserve one space for the (+xx) textview. - int numIconsToShow = numIconsThatFit - 1; - if (numIconsToShow < 0) { - numIconsToShow = 0; - } - iconFutures = iconSet.getIcons(numIconsToShow); - extraItems = iconSet.size() - numIconsToShow; - } else { - // Fit exactly or with remaining space. - iconFutures = iconSet.getIcons(); - extraItems = 0; - } - - // Display icons when all are ready (more consistent than randomly loading). - mPendingLoadIconsFuture = Futures.allAsList(iconFutures); - FutureUtil.whenDone( - mPendingLoadIconsFuture, - icons -> { - mLoadedIcons = new LoadedIcons(ImmutableList.copyOf(icons), extraItems); - notifyChanged(); // So that view is rebound and icons actually shown. - }, - mUiExecutor); - } - - private void setDrawables(LinearLayout container, LoadedIcons loadedIcons) { - // Rearrange child views until we have ImageViews... - LayoutInflater inflater = LayoutInflater.from(getContext()); - int numImages = loadedIcons.icons.size(); - int numImageViews = getChildCount(container, ImageView.class); - if (numImages > numImageViews) { - for (int i = 0; i < numImages - numImageViews; i++) { - ImageView imageView = (ImageView) inflater.inflate( - R.layout.preference_circular_icons_item, container, false); - container.addView(imageView, 0); - } - } else if (numImageViews > numImages) { - for (int i = 0; i < numImageViews - numImages; i++) { - container.removeViewAt(0); - } - } - // ... plus 0/1 TextViews at the end. - if (loadedIcons.extraItems > 0 && !(getLastChild(container) instanceof TextView)) { - TextView plusView = (TextView) inflater.inflate( - R.layout.preference_circular_icons_plus_item, container, false); - container.addView(plusView); - } else if (loadedIcons.extraItems == 0 && (getLastChild(container) instanceof TextView)) { - container.removeViewAt(container.getChildCount() - 1); - } - - // Show images (and +n if needed). - for (int i = 0; i < numImages; i++) { - ImageView imageView = (ImageView) container.getChildAt(i); - imageView.setImageDrawable(loadedIcons.icons.get(i)); - } - if (loadedIcons.extraItems > 0) { - TextView textView = (TextView) checkNotNull(getLastChild(container)); - textView.setText(getContext().getString(R.string.zen_mode_plus_n_items, - loadedIcons.extraItems)); - } - - // Apply enabled/disabled style. - for (int i = 0; i < container.getChildCount(); i++) { - View child = container.getChildAt(i); - child.setAlpha(isEnabled() ? 1.0f : DISABLED_ITEM_ALPHA); - } - } - - private static int getChildCount(ViewGroup parent, Class childClass) { - int count = 0; - for (int i = 0; i < parent.getChildCount(); i++) { - if (childClass.isInstance(parent.getChildAt(i))) { - count++; - } - } - return count; - } - - @Nullable - private static View getLastChild(ViewGroup parent) { - if (parent.getChildCount() == 0) { - return null; - } - return parent.getChildAt(parent.getChildCount() - 1); - } - - @VisibleForTesting(otherwise = VisibleForTesting.NONE) - @Nullable - LoadedIcons getLoadedIcons() { - return mLoadedIcons; + iconContainer.setVisibility(mIconSet != null && mIconSet.size() == 0 ? GONE : VISIBLE); + iconContainer.setEnabled(isEnabled()); + iconContainer.setIcons(mIconSet); } } diff --git a/src/com/android/settings/notification/modes/CircularIconsView.java b/src/com/android/settings/notification/modes/CircularIconsView.java new file mode 100644 index 00000000000..b0e4280129b --- /dev/null +++ b/src/com/android/settings/notification/modes/CircularIconsView.java @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification.modes; + +import static com.google.common.base.Preconditions.checkNotNull; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import com.android.settings.R; + +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import java.util.List; +import java.util.concurrent.Executor; + +public class CircularIconsView extends LinearLayout { + + private static final float DISABLED_ITEM_ALPHA = 0.3f; + + record Icons(ImmutableList icons, int extraItems) { } + + private Executor mUiExecutor; + private int mNumberOfCirclesThatFit; + + // Chronologically, fields will be set top-to-bottom. + @Nullable private CircularIconSet mIconSet; + @Nullable private ListenableFuture> mPendingLoadIconsFuture; + @Nullable private Icons mDisplayedIcons; + + public CircularIconsView(Context context) { + super(context); + setUiExecutor(context.getMainExecutor()); + } + + public CircularIconsView(Context context, AttributeSet attrs) { + super(context, attrs); + setUiExecutor(context.getMainExecutor()); + } + + public CircularIconsView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + setUiExecutor(context.getMainExecutor()); + } + + public CircularIconsView(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setUiExecutor(context.getMainExecutor()); + } + + @VisibleForTesting + void setUiExecutor(Executor uiExecutor) { + mUiExecutor = uiExecutor; + } + + void setIcons(CircularIconSet iconSet) { + if (mIconSet != null && mIconSet.equals(iconSet)) { + return; + } + + mIconSet = checkNotNull(iconSet); + cancelPendingTasks(); + if (getMeasuredWidth() != 0) { + startLoadingIcons(iconSet); + } + } + + private void cancelPendingTasks() { + mDisplayedIcons = null; + if (mPendingLoadIconsFuture != null) { + mPendingLoadIconsFuture.cancel(true); + mPendingLoadIconsFuture = null; + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + int numFitting = getNumberOfCirclesThatFit(); + if (mNumberOfCirclesThatFit != numFitting) { + // View has been measured for the first time OR its dimensions have changed since then. + // Keep track, because we want to reload stuff if more (or less) items fit. + mNumberOfCirclesThatFit = numFitting; + + if (mIconSet != null) { + cancelPendingTasks(); + startLoadingIcons(mIconSet); + } + } + } + + private int getNumberOfCirclesThatFit() { + Resources res = getContext().getResources(); + int availableSpace = getMeasuredWidth(); + int iconHorizontalSpace = res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_diameter) + + res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_margin_between); + return availableSpace / iconHorizontalSpace; + } + + private void startLoadingIcons(CircularIconSet iconSet) { + int numCirclesThatFit = getNumberOfCirclesThatFit(); + + List> iconFutures; + int extraItems; + if (iconSet.size() > numCirclesThatFit) { + // Reserve one space for the (+xx) textview. + int numIconsToShow = numCirclesThatFit - 1; + if (numIconsToShow < 0) { + numIconsToShow = 0; + } + iconFutures = iconSet.getIcons(numIconsToShow); + extraItems = iconSet.size() - numIconsToShow; + } else { + // Fit exactly or with remaining space. + iconFutures = iconSet.getIcons(); + extraItems = 0; + } + + // Display icons when all are ready (more consistent than randomly loading). + mPendingLoadIconsFuture = Futures.allAsList(iconFutures); + FutureUtil.whenDone( + mPendingLoadIconsFuture, + icons -> setDrawables(new Icons(ImmutableList.copyOf(icons), extraItems)), + mUiExecutor); + } + + private void setDrawables(Icons icons) { + mDisplayedIcons = icons; + + // Rearrange child views until we have ImageViews... + LayoutInflater inflater = LayoutInflater.from(getContext()); + int numImages = icons.icons.size(); + int numImageViews = getChildCount(ImageView.class); + if (numImages > numImageViews) { + for (int i = 0; i < numImages - numImageViews; i++) { + ImageView imageView = (ImageView) inflater.inflate( + R.layout.preference_circular_icons_item, this, false); + addView(imageView, 0); + } + } else if (numImageViews > numImages) { + for (int i = 0; i < numImageViews - numImages; i++) { + removeViewAt(0); + } + } + // ... plus 0/1 TextViews at the end. + if (icons.extraItems > 0 && !(getLastChild() instanceof TextView)) { + TextView plusView = (TextView) inflater.inflate( + R.layout.preference_circular_icons_plus_item, this, false); + this.addView(plusView); + } else if (icons.extraItems == 0 && (getLastChild() instanceof TextView)) { + removeViewAt(getChildCount() - 1); + } + + // Show images (and +n if needed). + for (int i = 0; i < numImages; i++) { + ImageView imageView = (ImageView) getChildAt(i); + imageView.setImageDrawable(icons.icons.get(i)); + } + if (icons.extraItems > 0) { + TextView textView = (TextView) checkNotNull(getLastChild()); + textView.setText(getContext().getString(R.string.zen_mode_plus_n_items, + icons.extraItems)); + } + + applyEnabledDisabledAppearance(isEnabled()); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + applyEnabledDisabledAppearance(isEnabled()); + } + + private void applyEnabledDisabledAppearance(boolean enabled) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.setAlpha(enabled ? 1.0f : DISABLED_ITEM_ALPHA); + } + } + + private int getChildCount(Class childClass) { + int count = 0; + for (int i = 0; i < getChildCount(); i++) { + if (childClass.isInstance(getChildAt(i))) { + count++; + } + } + return count; + } + + @Nullable + private View getLastChild() { + if (getChildCount() == 0) { + return null; + } + return getChildAt(getChildCount() - 1); + } + + @VisibleForTesting(otherwise = VisibleForTesting.NONE) + @Nullable + Icons getDisplayedIcons() { + return mDisplayedIcons; + } +} diff --git a/src/com/android/settings/notification/modes/IconUtil.java b/src/com/android/settings/notification/modes/IconUtil.java index dc4d875869e..33d0d961698 100644 --- a/src/com/android/settings/notification/modes/IconUtil.java +++ b/src/com/android/settings/notification/modes/IconUtil.java @@ -79,6 +79,7 @@ class IconUtil { @Px int innerSizePx = res.getDimensionPixelSize(R.dimen.zen_mode_header_inner_icon_size); Drawable base = composeIcons( + context.getResources(), background, Utils.getColorAttr(context, com.android.internal.R.attr.materialColorSecondaryContainer), @@ -89,6 +90,7 @@ class IconUtil { innerSizePx); Drawable selected = composeIcons( + context.getResources(), background, Utils.getColorAttr(context, com.android.internal.R.attr.materialColorPrimary), outerSizePx, @@ -111,6 +113,7 @@ class IconUtil { */ static Drawable makeIconPickerHeader(@NonNull Context context, Drawable icon) { return composeIconCircle( + context.getResources(), Utils.getColorAttr(context, com.android.internal.R.attr.materialColorSecondaryContainer), context.getResources().getDimensionPixelSize( @@ -129,6 +132,7 @@ class IconUtil { */ static Drawable makeIconPickerItem(@NonNull Context context, @DrawableRes int iconResId) { return composeIconCircle( + context.getResources(), context.getColorStateList(R.color.modes_icon_selectable_background), context.getResources().getDimensionPixelSize( R.dimen.zen_mode_icon_list_item_circle_diameter), @@ -146,6 +150,7 @@ class IconUtil { static Drawable makeCircularIconPreferenceItem(@NonNull Context context, @DrawableRes int iconResId) { return composeIconCircle( + context.getResources(), Utils.getColorAttr(context, com.android.internal.R.attr.materialColorSecondaryContainer), context.getResources().getDimensionPixelSize( @@ -166,6 +171,7 @@ class IconUtil { Resources res = context.getResources(); if (Strings.isNullOrEmpty(displayName)) { return composeIconCircle( + context.getResources(), Utils.getColorAttr(context, com.android.internal.R.attr.materialColorTertiaryContainer), res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_diameter), @@ -204,17 +210,17 @@ class IconUtil { return new BitmapDrawable(context.getResources(), bitmap); } - private static Drawable composeIconCircle(ColorStateList circleColor, @Px int circleDiameterPx, - Drawable icon, ColorStateList iconColor, @Px int iconSizePx) { - return composeIcons(new ShapeDrawable(new OvalShape()), circleColor, circleDiameterPx, icon, - iconColor, iconSizePx); + private static Drawable composeIconCircle(Resources res, ColorStateList circleColor, + @Px int circleDiameterPx, Drawable icon, ColorStateList iconColor, @Px int iconSizePx) { + return composeIcons(res, new ShapeDrawable(new OvalShape()), circleColor, circleDiameterPx, + icon, iconColor, iconSizePx); } - private static Drawable composeIcons(Drawable outer, ColorStateList outerColor, + private static Drawable composeIcons(Resources res, Drawable outer, ColorStateList outerColor, @Px int outerSizePx, Drawable icon, ColorStateList iconColor, @Px int iconSizePx) { - Drawable background = checkNotNull(outer.getConstantState()).newDrawable().mutate(); + Drawable background = checkNotNull(outer.getConstantState()).newDrawable(res).mutate(); background.setTintList(outerColor); - Drawable foreground = checkNotNull(icon.getConstantState()).newDrawable().mutate(); + Drawable foreground = checkNotNull(icon.getConstantState()).newDrawable(res).mutate(); foreground.setTintList(iconColor); LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { background, foreground }); diff --git a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java index a3cb30d5657..3f95028f0c4 100644 --- a/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceController.java @@ -109,7 +109,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr if (zenMode.getPolicy().getAllowedChannels() == ZenPolicy.CHANNEL_POLICY_NONE) { mPreference.setSummary(R.string.zen_mode_apps_none_apps); - mPreference.displayIcons(CircularIconSet.EMPTY); + mPreference.setIcons(CircularIconSet.EMPTY); if (mAppSession != null) { mAppSession.deactivateSession(); } @@ -151,7 +151,7 @@ class ZenModeAppsLinkPreferenceController extends AbstractZenModePreferenceContr ImmutableList apps = getAppsBypassingDndSortedByName(allApps); mPreference.setSummary(mSummaryHelper.getAppsSummary(mZenMode, apps)); - mPreference.displayIcons(new CircularIconSet<>(apps, + mPreference.setIcons(new CircularIconSet<>(apps, app -> mAppIconRetriever.apply(app.info)), APP_ENTRY_EQUIVALENCE); } diff --git a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java index 15e0edcf1df..939c7a605c9 100644 --- a/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceController.java @@ -72,7 +72,7 @@ class ZenModeOtherLinkPreferenceController extends AbstractZenModePreferenceCont preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getOtherSoundCategoriesSummary(zenMode)); - ((CircularIconsPreference) preference).displayIcons(getSoundIcons(zenMode.getPolicy())); + ((CircularIconsPreference) preference).setIcons(getSoundIcons(zenMode.getPolicy())); } private CircularIconSet getSoundIcons(ZenPolicy policy) { diff --git a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java index 4610c35ca82..08a551e9bbb 100644 --- a/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceController.java @@ -95,7 +95,7 @@ class ZenModePeopleLinkPreferenceController extends AbstractZenModePreferenceCon preference.setEnabled(zenMode.isEnabled()); preference.setSummary(mSummaryHelper.getPeopleSummary(zenMode.getPolicy())); - ((CircularIconsPreference) preference).displayIcons(getPeopleIcons(zenMode.getPolicy()), + ((CircularIconsPreference) preference).setIcons(getPeopleIcons(zenMode.getPolicy()), PEOPLE_ITEM_EQUIVALENCE); } diff --git a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java index d145f255c5b..55448329d6f 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/CircularIconsPreferenceTest.java @@ -62,8 +62,7 @@ public class CircularIconsPreferenceTest { private Context mContext; private CircularIconsPreference mPreference; - private PreferenceViewHolder mViewHolder; - private ViewGroup mContainer; + private CircularIconsView mContainer; private int mOneIconWidth; @@ -73,179 +72,211 @@ public class CircularIconsPreferenceTest { mContext = RuntimeEnvironment.application; CircularIconSet.sExecutorService = MoreExecutors.newDirectExecutorService(); mPreference = new TestableCircularIconsPreference(mContext); - // Tests should call bindAndMeasureViewHolder() so that icons can be added. + // Tests should call bindAndLayoutViewHolder() so that icons can be added. Resources res = mContext.getResources(); mOneIconWidth = res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_diameter) + res.getDimensionPixelSize(R.dimen.zen_mode_circular_icon_margin_between); } - private void bindAndMeasureViewHolder(int viewWidth) { + private void bindAndLayoutViewHolder(int viewWidth) { bindViewHolder(); - measureViewHolder(viewWidth); + layoutViewHolder(viewWidth); } private void bindViewHolder() { View preferenceView = LayoutInflater.from(mContext).inflate(mPreference.getLayoutResource(), null); mContainer = checkNotNull(preferenceView.findViewById(R.id.circles_container)); - mViewHolder = PreferenceViewHolder.createInstanceForTests(preferenceView); - mPreference.onBindViewHolder(mViewHolder); + mContainer.setUiExecutor(MoreExecutors.directExecutor()); + PreferenceViewHolder viewHolder = PreferenceViewHolder.createInstanceForTests( + preferenceView); + mPreference.onBindViewHolder(viewHolder); } - private void measureViewHolder(int viewWidth) { + private void layoutViewHolder(int viewWidth) { checkState(mContainer != null, "Call bindViewHolder() first!"); mContainer.measure(makeMeasureSpec(viewWidth, View.MeasureSpec.EXACTLY), makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)); - mContainer.getViewTreeObserver().dispatchOnGlobalLayout(); + mContainer.layout(0, 0, viewWidth, 1000); } @Test - public void displayIcons_loadsIcons() { + public void setIcons_loadsIcons() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), ColorDrawable::new); - bindAndMeasureViewHolder(VIEW_WIDTH); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(VIEW_WIDTH); + mPreference.setIcons(iconSet); - assertThat(getIcons(mContainer)).hasSize(2); - assertThat(((ColorDrawable) getIcons(mContainer).get(0)).getColor()).isEqualTo(1); - assertThat(((ColorDrawable) getIcons(mContainer).get(1)).getColor()).isEqualTo(2); + assertThat(getDrawables(mContainer)).hasSize(2); + assertThat(((ColorDrawable) getDrawables(mContainer).get(0)).getColor()).isEqualTo(1); + assertThat(((ColorDrawable) getDrawables(mContainer).get(1)).getColor()).isEqualTo(2); assertThat(getPlusText(mContainer)).isNull(); } @Test - public void displayIcons_noIcons_hidesRow() { + public void setIcons_noIcons_hidesRow() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(), ColorDrawable::new); - bindAndMeasureViewHolder(VIEW_WIDTH); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(VIEW_WIDTH); + mPreference.setIcons(iconSet); assertThat(mContainer.getVisibility()).isEqualTo(View.GONE); } @Test - public void displayIcons_exactlyMaxIcons_loadsAllIcons() throws Exception { + public void setIcons_exactlyMaxIcons_loadsAllIcons() throws Exception { int width = 300; int fittingCircles = width / mOneIconWidth; CircularIconSet iconSet = new CircularIconSet<>( IntStream.range(0, fittingCircles).boxed().toList(), ColorDrawable::new); - bindAndMeasureViewHolder(width); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(width); + mPreference.setIcons(iconSet); - assertThat(getIcons(mContainer)).hasSize(fittingCircles); - assertThat(getIcons(mContainer)).containsExactlyElementsIn( + assertThat(getDrawables(mContainer)).hasSize(fittingCircles); + assertThat(getDrawables(mContainer)).containsExactlyElementsIn( Futures.allAsList(iconSet.getIcons()).get()).inOrder(); assertThat(getPlusText(mContainer)).isNull(); - } @Test - public void displayIcons_tooManyIcons_loadsFirstNAndPlusIcon() throws Exception { + public void setIcons_tooManyIcons_loadsFirstNAndPlusIcon() throws Exception { int width = 300; int fittingCircles = width / mOneIconWidth; CircularIconSet iconSet = new CircularIconSet<>( IntStream.range(0, fittingCircles + 5).boxed().toList(), ColorDrawable::new); - bindAndMeasureViewHolder(width); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(width); + mPreference.setIcons(iconSet); // N-1 icons, plus (+6) text. - assertThat(getIcons(mContainer)).hasSize(fittingCircles - 1); - assertThat(getIcons(mContainer)).containsExactlyElementsIn( + assertThat(getDrawables(mContainer)).hasSize(fittingCircles - 1); + assertThat(getDrawables(mContainer)).containsExactlyElementsIn( Futures.allAsList(iconSet.getIcons(fittingCircles - 1)).get()) .inOrder(); assertThat(getPlusText(mContainer)).isEqualTo("+6"); } @Test - public void displayIcons_teenyTinySpace_showsPlusIcon_noCrash() { + public void setIcons_teenyTinySpace_showsPlusIcon_noCrash() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), ColorDrawable::new); - bindAndMeasureViewHolder(1); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(1); + mPreference.setIcons(iconSet); - assertThat(getIcons(mContainer)).isEmpty(); + assertThat(getDrawables(mContainer)).isEmpty(); assertThat(getPlusText(mContainer)).isEqualTo("+2"); } @Test - public void displayIcons_beforeBind_loadsIconsOnBindAndMeasure() { + public void setIcons_beforeBind_loadsIconsOnBindAndMeasure() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2, 3), ColorDrawable::new); - mPreference.displayIcons(iconSet); - assertThat(mPreference.getLoadedIcons()).isNull(); // Hold... + mPreference.setIcons(iconSet); + assertThat(mContainer).isNull(); // Hold... bindViewHolder(); - assertThat(mPreference.getLoadedIcons()).isNull(); // Hooooold... + assertThat(getDrawables(mContainer)).hasSize(0); // Hooooold... - measureViewHolder(VIEW_WIDTH); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(3); - assertThat(getIcons(mContainer)).hasSize(3); + layoutViewHolder(VIEW_WIDTH); + assertThat(getDrawables(mContainer)).hasSize(3); } @Test - public void displayIcons_beforeMeasure_loadsIconsOnMeasure() { + public void setIcons_beforeMeasure_loadsIconsOnMeasure() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2, 3), ColorDrawable::new); bindViewHolder(); - mPreference.displayIcons(iconSet); - assertThat(mPreference.getLoadedIcons()).isNull(); + mPreference.setIcons(iconSet); + assertThat(getDrawables(mContainer)).hasSize(0); - measureViewHolder(VIEW_WIDTH); - assertThat(getIcons(mContainer)).hasSize(3); + layoutViewHolder(VIEW_WIDTH); + assertThat(getDrawables(mContainer)).hasSize(3); } @Test - public void displayIcons_calledAgain_reloadsIcons() { + public void setIcons_calledAgain_reloadsIcons() { CircularIconSet threeIcons = new CircularIconSet<>(ImmutableList.of(1, 2, 3), ColorDrawable::new); CircularIconSet twoIcons = new CircularIconSet<>(ImmutableList.of(1, 2), ColorDrawable::new); CircularIconSet fourIcons = new CircularIconSet<>(ImmutableList.of(1, 2, 3, 4), ColorDrawable::new); - bindAndMeasureViewHolder(VIEW_WIDTH); + bindAndLayoutViewHolder(VIEW_WIDTH); - mPreference.displayIcons(threeIcons); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(getIcons(mContainer)).hasSize(3); + mPreference.setIcons(threeIcons); + assertThat(getDrawables(mContainer)).hasSize(3); - mPreference.displayIcons(twoIcons); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(getIcons(mContainer)).hasSize(2); + mPreference.setIcons(twoIcons); + assertThat(getDrawables(mContainer)).hasSize(2); - mPreference.displayIcons(fourIcons); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(getIcons(mContainer)).hasSize(4); + mPreference.setIcons(fourIcons); + assertThat(getDrawables(mContainer)).hasSize(4); } @Test - public void displayIcons_sameSet_doesNotReloadIcons() { + public void setIcons_sameSet_doesNotReloadIcons() { CircularIconSet one = new CircularIconSet<>(ImmutableList.of(1, 2, 3), ColorDrawable::new); CircularIconSet same = Mockito.spy(new CircularIconSet<>(ImmutableList.of(1, 2, 3), ColorDrawable::new)); when(same.getIcons()).thenThrow(new RuntimeException("Shouldn't be called!")); - bindAndMeasureViewHolder(VIEW_WIDTH); + bindAndLayoutViewHolder(VIEW_WIDTH); - mPreference.displayIcons(one); + mPreference.setIcons(one); - mPreference.displayIcons(same); // if no exception, wasn't called. + mPreference.setIcons(same); // if no exception, wasn't called. } + @Test + public void sizeChanged_reloadsIconsIfDifferentFit() { + CircularIconSet largeIconSet = new CircularIconSet<>( + IntStream.range(0, 100).boxed().toList(), + ColorDrawable::new); + mPreference.setIcons(largeIconSet); + + // Base space -> some icons + int firstWidth = 600; + int firstFittingCircles = firstWidth / mOneIconWidth; + bindAndLayoutViewHolder(firstWidth); + + assertThat(getDrawables(mContainer)).hasSize(firstFittingCircles - 1); + assertThat(getPlusText(mContainer)).isEqualTo("+" + (100 - (firstFittingCircles - 1))); + + // More space -> more icons + int secondWidth = 1000; + int secondFittingCircles = secondWidth / mOneIconWidth; + assertThat(secondFittingCircles).isGreaterThan(firstFittingCircles); + bindAndLayoutViewHolder(secondWidth); + + assertThat(getDrawables(mContainer)).hasSize(secondFittingCircles - 1); + assertThat(getPlusText(mContainer)).isEqualTo("+" + (100 - (secondFittingCircles - 1))); + + // Less space -> fewer icons + int thirdWidth = 600; + int thirdFittingCircles = thirdWidth / mOneIconWidth; + bindAndLayoutViewHolder(thirdWidth); + + assertThat(getDrawables(mContainer)).hasSize(thirdFittingCircles - 1); + assertThat(getPlusText(mContainer)).isEqualTo("+" + (100 - (thirdFittingCircles - 1))); + } + + @Test public void onBindViewHolder_withDifferentView_reloadsIconsCorrectly() { View preferenceViewOne = LayoutInflater.from(mContext).inflate( mPreference.getLayoutResource(), null); - ViewGroup containerOne = preferenceViewOne.findViewById(R.id.circles_container); + CircularIconsView containerOne = preferenceViewOne.findViewById(R.id.circles_container); + containerOne.setUiExecutor(MoreExecutors.directExecutor()); PreferenceViewHolder viewHolderOne = PreferenceViewHolder.createInstanceForTests( preferenceViewOne); containerOne.measure(makeMeasureSpec(1000, View.MeasureSpec.EXACTLY), @@ -253,7 +284,8 @@ public class CircularIconsPreferenceTest { View preferenceViewTwo = LayoutInflater.from(mContext).inflate( mPreference.getLayoutResource(), null); - ViewGroup containerTwo = preferenceViewTwo.findViewById(R.id.circles_container); + CircularIconsView containerTwo = preferenceViewTwo.findViewById(R.id.circles_container); + containerTwo.setUiExecutor(MoreExecutors.directExecutor()); PreferenceViewHolder viewHolderTwo = PreferenceViewHolder.createInstanceForTests( preferenceViewTwo); containerTwo.measure(makeMeasureSpec(1000, View.MeasureSpec.EXACTLY), @@ -265,25 +297,25 @@ public class CircularIconsPreferenceTest { ColorDrawable::new); mPreference.onBindViewHolder(viewHolderOne); - mPreference.displayIcons(iconSetOne); - assertThat(getIcons(containerOne)).hasSize(3); + mPreference.setIcons(iconSetOne); + assertThat(getDrawables(containerOne)).hasSize(3); mPreference.onBindViewHolder(viewHolderTwo); - assertThat(getIcons(containerTwo)).hasSize(3); + assertThat(getDrawables(containerTwo)).hasSize(3); - mPreference.displayIcons(iconSetTwo); + mPreference.setIcons(iconSetTwo); // The second view is updated and the first view is unaffected. - assertThat(getIcons(containerTwo)).hasSize(2); - assertThat(getIcons(containerOne)).hasSize(3); + assertThat(getDrawables(containerTwo)).hasSize(2); + assertThat(getDrawables(containerOne)).hasSize(3); } @Test - public void setEnabled_afterDisplayIcons_showsEnabledOrDisabledImages() { + public void setEnabled_afterSetIcons_showsEnabledOrDisabledImages() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), ColorDrawable::new); - bindAndMeasureViewHolder(VIEW_WIDTH); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(VIEW_WIDTH); + mPreference.setIcons(iconSet); assertThat(getViews(mContainer)).hasSize(2); mPreference.setEnabled(false); @@ -294,13 +326,13 @@ public class CircularIconsPreferenceTest { } @Test - public void setEnabled_beforeDisplayIcons_showsEnabledOrDisabledImages() { + public void setEnabled_beforeSetIcons_showsEnabledOrDisabledImages() { CircularIconSet iconSet = new CircularIconSet<>(ImmutableList.of(1, 2), ColorDrawable::new); mPreference.setEnabled(false); - bindAndMeasureViewHolder(VIEW_WIDTH); - mPreference.displayIcons(iconSet); + bindAndLayoutViewHolder(VIEW_WIDTH); + mPreference.setIcons(iconSet); assertThat(getViews(mContainer)).hasSize(2); assertThat(getViews(mContainer).get(0).getAlpha()).isLessThan(1f); @@ -314,7 +346,7 @@ public class CircularIconsPreferenceTest { return views; } - private static List getIcons(ViewGroup container) { + private static List getDrawables(ViewGroup container) { ArrayList drawables = new ArrayList<>(); for (int i = 0; i < container.getChildCount(); i++) { if (container.getChildAt(i) instanceof ImageView imageView) { diff --git a/tests/robotests/src/com/android/settings/notification/modes/TestableCircularIconsPreference.java b/tests/robotests/src/com/android/settings/notification/modes/TestableCircularIconsPreference.java index 6fefcacad21..6c1b0597779 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/TestableCircularIconsPreference.java +++ b/tests/robotests/src/com/android/settings/notification/modes/TestableCircularIconsPreference.java @@ -20,14 +20,12 @@ import android.content.Context; import androidx.preference.PreferenceViewHolder; -import com.google.common.util.concurrent.MoreExecutors; - class TestableCircularIconsPreference extends CircularIconsPreference { private PreferenceViewHolder mLastViewHolder; TestableCircularIconsPreference(Context context) { - super(context, MoreExecutors.directExecutor()); + super(context); } @Override diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java index f656bad0f01..f77dc3ebfa0 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeAppsLinkPreferenceControllerTest.java @@ -19,6 +19,7 @@ package com.android.settings.notification.modes; import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -51,6 +52,7 @@ import android.view.View; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceViewHolder; +import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState.AppEntry; @@ -81,6 +83,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest { private ZenModeAppsLinkPreferenceController mController; private CircularIconsPreference mPreference; + private CircularIconsView mIconsView; private Context mContext; @Mock @@ -113,6 +116,8 @@ public final class ZenModeAppsLinkPreferenceControllerTest { // Ensure the preference view is bound & measured (needed to add child ImageViews). View preferenceView = LayoutInflater.from(mContext).inflate(mPreference.getLayoutResource(), null); + mIconsView = checkNotNull(preferenceView.findViewById(R.id.circles_container)); + mIconsView.setUiExecutor(MoreExecutors.directExecutor()); preferenceView.measure(View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)); PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(preferenceView); @@ -272,7 +277,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest { appEntries.add(createAppEntry("test2", mContext.getUserId())); mController.mAppSessionCallbacks.onRebuildComplete(appEntries); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(2); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(2); } @Test @@ -312,7 +317,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest { mController.updateState(mPreference, zenModeWithNone); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(0); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(0); verifyNoMoreInteractions(mApplicationsState); verifyNoMoreInteractions(mSession); @@ -321,7 +326,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest { verify(mApplicationsState).newSession(any(), any()); verify(mSession).rebuild(any(), any(), anyBoolean()); mController.mAppSessionCallbacks.onRebuildComplete(appEntries); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(1); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(1); } @Test @@ -342,11 +347,11 @@ public final class ZenModeAppsLinkPreferenceControllerTest { verify(mApplicationsState).newSession(any(), any()); verify(mSession).rebuild(any(), any(), anyBoolean()); mController.mAppSessionCallbacks.onRebuildComplete(appEntries); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(1); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(1); mController.updateState(mPreference, zenModeWithNone); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(0); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(0); verify(mSession).deactivateSession(); verifyNoMoreInteractions(mSession); verifyNoMoreInteractions(mApplicationsState); @@ -355,7 +360,7 @@ public final class ZenModeAppsLinkPreferenceControllerTest { // updateState()) is ignored. mController.mAppSessionCallbacks.onRebuildComplete(appEntries); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(0); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(0); } @Test diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java index 8aa87e6c903..3db70fa67bc 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeOtherLinkPreferenceControllerTest.java @@ -95,7 +95,7 @@ public final class ZenModeOtherLinkPreferenceControllerTest { mController.updateState(pref, mode); - verify(pref).displayIcons(argThat(iconSet -> iconSet.size() == 3)); + verify(pref).setIcons(argThat(iconSet -> iconSet.size() == 3)); } @Test @@ -107,7 +107,7 @@ public final class ZenModeOtherLinkPreferenceControllerTest { mController.updateState(pref, mode); - verify(pref).displayIcons(argThat(iconSet -> + verify(pref).setIcons(argThat(iconSet -> iconSet.size() == ZenModeSummaryHelper.OTHER_SOUND_CATEGORIES.size())); } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java index a4d141e9ca3..8555d710fa0 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModePeopleLinkPreferenceControllerTest.java @@ -22,6 +22,7 @@ import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_NONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_STARRED; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -50,6 +51,7 @@ import android.view.View; import androidx.preference.PreferenceViewHolder; +import com.android.settings.R; import com.android.settings.notification.modes.ZenHelperBackend.Contact; import com.android.settingslib.notification.ConversationIconFactory; import com.android.settingslib.notification.modes.TestModeBuilder; @@ -76,6 +78,7 @@ public final class ZenModePeopleLinkPreferenceControllerTest { private ZenModePeopleLinkPreferenceController mController; private CircularIconsPreference mPreference; + private CircularIconsView mIconsView; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @@ -94,6 +97,8 @@ public final class ZenModePeopleLinkPreferenceControllerTest { // Ensure the preference view is bound & measured (needed to add icons). View preferenceView = LayoutInflater.from(mContext).inflate(mPreference.getLayoutResource(), null); + mIconsView = checkNotNull(preferenceView.findViewById(R.id.circles_container)); + mIconsView.setUiExecutor(MoreExecutors.directExecutor()); preferenceView.measure(View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.EXACTLY)); PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(preferenceView); @@ -142,9 +147,9 @@ public final class ZenModePeopleLinkPreferenceControllerTest { mController.updateState(mPreference, mode); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(2); - assertThat(mPreference.getLoadedIcons().icons().stream() + assertThat(mIconsView.getDisplayedIcons()).isNotNull(); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(2); + assertThat(mIconsView.getDisplayedIcons().icons().stream() .map(ColorDrawable.class::cast) .map(d -> d.getColor()).toList()) .containsExactly(2, 3).inOrder(); @@ -162,9 +167,9 @@ public final class ZenModePeopleLinkPreferenceControllerTest { mController.updateState(mPreference, mode); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(4); - assertThat(mPreference.getLoadedIcons().icons().stream() + assertThat(mIconsView.getDisplayedIcons()).isNotNull(); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(4); + assertThat(mIconsView.getDisplayedIcons().icons().stream() .map(ColorDrawable.class::cast) .map(d -> d.getColor()).toList()) .containsExactly(1, 2, 3, 4).inOrder(); @@ -182,8 +187,8 @@ public final class ZenModePeopleLinkPreferenceControllerTest { mController.updateState(mPreference, mode); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(1); + assertThat(mIconsView.getDisplayedIcons()).isNotNull(); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(1); verify(mHelperBackend, never()).getContactPhoto(any()); } @@ -201,8 +206,8 @@ public final class ZenModePeopleLinkPreferenceControllerTest { mController.updateState(mPreference, mode); - assertThat(mPreference.getLoadedIcons()).isNotNull(); - assertThat(mPreference.getLoadedIcons().icons()).hasSize(3); + assertThat(mIconsView.getDisplayedIcons()).isNotNull(); + assertThat(mIconsView.getDisplayedIcons().icons()).hasSize(3); verify(mConversationIconFactory, times(3)).getConversationDrawable((ShortcutInfo) any(), any(), anyInt(), anyBoolean()); }