From 9f3eb8d0461a4426373c5ac7b110f102aece2751 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Fri, 10 Jun 2022 11:10:50 +0000 Subject: [PATCH] Update the number of columns on config change in share sheet mMaxTargetsPerRow wasn't updated in the chooser multi profile pager adapter, this adapter sets the number of columns in the grid layout manager. This led to incorrect number of columns when display size changes in runtime. Bug: 235572712 Test: open share sheet, fold the device => check that the number of columns is updated Change-Id: I1f3f3bff8a4d23909ccd4c00b74091183c28821b --- .../android/internal/app/ChooserActivity.java | 1 + .../app/ChooserMultiProfilePagerAdapter.java | 4 + .../internal/app/ChooserActivityTest.java | 83 +++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 66abe30d0123d..1dedec366b75c 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1002,6 +1002,7 @@ public class ChooserActivity extends ResolverActivity implements mShouldDisplayLandscape = shouldDisplayLandscape(newConfig.orientation); mMaxTargetsPerRow = getResources().getInteger(R.integer.config_chooser_max_targets_per_row); + mChooserMultiProfilePagerAdapter.setMaxTargetsPerRow(mMaxTargetsPerRow); adjustPreviewWidth(newConfig.orientation, null); updateStickyContentPreview(); updateTabPadding(); diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java index e6cc62472f5c1..df1130be5ec6f 100644 --- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java @@ -93,6 +93,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd return profileDescriptor; } + public void setMaxTargetsPerRow(int maxTargetsPerRow) { + mMaxTargetsPerRow = maxTargetsPerRow; + } + RecyclerView getListViewForIndex(int index) { return getItem(index).recyclerView; } diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index b38e1c274b45f..82148422aabf1 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -84,17 +84,23 @@ import android.service.chooser.ChooserTarget; import android.view.View; import androidx.annotation.CallSuper; +import androidx.test.espresso.matcher.BoundedDiagnosingMatcher; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; +import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.DisplayResolveInfo; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.widget.GridLayoutManager; +import com.android.internal.widget.RecyclerView; +import org.hamcrest.Description; import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -1680,6 +1686,25 @@ public class ChooserActivityTest { wrapper.getAdapter().getItem(1).getDisplayLabel(), is("testTitle1")); } + @Test + public void testUpdateMaxTargetsPerRow_columnCountIsUpdated() throws InterruptedException { + updateMaxTargetsPerRowResource(/* targetsPerRow= */ 4); + givenAppTargets(/* appCount= */ 16); + Intent sendIntent = createSendTextIntent(); + final ChooserActivity activity = + mActivityRule.launchActivity(Intent.createChooser(sendIntent, null)); + + updateMaxTargetsPerRowResource(/* targetsPerRow= */ 6); + InstrumentationRegistry.getInstrumentation() + .runOnMainSync(() -> activity.onConfigurationChanged( + InstrumentationRegistry.getInstrumentation() + .getContext().getResources().getConfiguration())); + + waitForIdle(); + onView(withIdFromRuntimeResource("resolver_list")) + .check(matches(withGridColumnCount(6))); + } + // This test is too long and too slow and should not be taken as an example for future tests. @Test @Ignore public void testDirectTargetLoggingWithAppTargetNotRankedPortrait() @@ -3063,6 +3088,64 @@ public class ChooserActivityTest { return withText(getRuntimeResourceId(id, "string")); } + private static GridRecyclerSpanCountMatcher withGridColumnCount(int columnCount) { + return new GridRecyclerSpanCountMatcher(Matchers.is(columnCount)); + } + + private static class GridRecyclerSpanCountMatcher extends + BoundedDiagnosingMatcher { + + private final Matcher mIntegerMatcher; + + private GridRecyclerSpanCountMatcher(Matcher integerMatcher) { + super(RecyclerView.class); + this.mIntegerMatcher = integerMatcher; + } + + @Override + protected void describeMoreTo(Description description) { + description.appendText("RecyclerView grid layout span count to match: "); + this.mIntegerMatcher.describeTo(description); + } + + @Override + protected boolean matchesSafely(RecyclerView view, Description mismatchDescription) { + int spanCount = ((GridLayoutManager) view.getLayoutManager()).getSpanCount(); + if (this.mIntegerMatcher.matches(spanCount)) { + return true; + } else { + mismatchDescription.appendText("RecyclerView grid layout span count was ") + .appendValue(spanCount); + return false; + } + } + } + + private void givenAppTargets(int appCount) { + List resolvedComponentInfos = + createResolvedComponentsForTest(appCount); + when( + ChooserActivityOverrideData + .getInstance() + .resolverListController + .getResolversForIntent( + Mockito.anyBoolean(), + Mockito.anyBoolean(), + Mockito.isA(List.class))) + .thenReturn(resolvedComponentInfos); + } + + private void updateMaxTargetsPerRowResource(int targetsPerRow) { + ChooserActivityOverrideData.getInstance().resources = Mockito.spy( + InstrumentationRegistry.getInstrumentation().getContext().getResources()); + when( + ChooserActivityOverrideData + .getInstance() + .resources + .getInteger(R.integer.config_chooser_max_targets_per_row)) + .thenReturn(targetsPerRow); + } + // ChooserWrapperActivity inherits from the framework ChooserActivity, so if the framework // resources have been updated since the framework was last built/pushed, the inherited behavior // (which is the focus of our testing) will still be implemented in terms of the old resource