summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Joshua Trask <joshtrask@google.com> 2023-12-19 22:36:59 +0000
committer Joshua Trask <joshtrask@google.com> 2024-01-05 18:06:59 +0000
commit6cf3e38519ef4704b14e8ac3f94ea651fa309f68 (patch)
treeb34c2b20724181bf57f0b360796b4ce81fde2ba1 /java/src
parentaf6a22081dca5b68e99af1cd6127bae660651565 (diff)
Generalize pager-adapter to support "many" tabs
(as in "0-1-many": if we have to support "multiple" then we shouldn't hard-code limitations on the number that we *do* support.) These changes are as prototyped in ag/25335069 and described in go/chooser-ntab-refactoring, in particular replicating the changes of "snapshot 34" through "snapshot 36." See below for a "by-snapshot" breakdown of the incremental changes composed in this CL. Snapshot 1: build pager-adapters from requests that include enough details about the pages for us to be able to implement `setupProfileTabs()` from our own records, without requiring the caller to provide per-tab data. This change stops short of actually changing the implementation of `setupProfileTabs()` and mostly just establishes the bookkeeping / new convention for configuration. Snapshot 2: implement `MultiProfilePagerAdapter.setupProfileTabs()` to build tabs from its own records. Snapshot 3: look up the page number for the "default profile" page, instead of assuming it's equal to the profile ID (since that may not be true in the "n-tab" case). Bug: 310211468 Test: `IntentResolver-tests-{activity,unit}`, `ResolverActivityTest` Change-Id: I3f8b9f9e53ff7a0740d1accd3a50b08e7c01bb55
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserActivity.java15
-rw-r--r--java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java37
-rw-r--r--java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java139
-rw-r--r--java/src/com/android/intentresolver/v2/ResolverActivity.java23
-rw-r--r--java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java38
5 files changed, 169 insertions, 83 deletions
diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java
index 2e020743..25024799 100644
--- a/java/src/com/android/intentresolver/v2/ChooserActivity.java
+++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java
@@ -1164,12 +1164,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
viewPager,
R.layout.resolver_profile_tab_button,
com.android.internal.R.id.profile_pager,
- mDevicePolicyResources.getPersonalTabLabel(),
- mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
- TAB_TAG_PERSONAL,
- mDevicePolicyResources.getWorkTabLabel(),
- mDevicePolicyResources.getWorkTabAccessibilityLabel(),
- TAB_TAG_WORK,
() -> onProfileTabSelected(viewPager.getCurrentItem()),
new MultiProfilePagerAdapter.OnProfileSelectedListener() {
@Override
@@ -1338,6 +1332,9 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
targetDataLoader);
return new ChooserMultiProfilePagerAdapter(
/* context */ this,
+ mDevicePolicyResources.getPersonalTabLabel(),
+ mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
+ TAB_TAG_PERSONAL,
adapter,
createEmptyStateProvider(/* workProfileUserHandle= */ null),
/* workProfileQuietModeChecker= */ () -> false,
@@ -1371,7 +1368,13 @@ public class ChooserActivity extends Hilt_ChooserActivity implements
targetDataLoader);
return new ChooserMultiProfilePagerAdapter(
/* context */ this,
+ mDevicePolicyResources.getPersonalTabLabel(),
+ mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
+ TAB_TAG_PERSONAL,
personalAdapter,
+ mDevicePolicyResources.getWorkTabLabel(),
+ mDevicePolicyResources.getWorkTabAccessibilityLabel(),
+ TAB_TAG_WORK,
workAdapter,
createEmptyStateProvider(requireAnnotatedUserHandles().workProfileUserHandle),
() -> mLogic.getWorkProfileAvailabilityManager().isQuietModeEnabled(),
diff --git a/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
index c3db4a51..14532b67 100644
--- a/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/ChooserMultiProfilePagerAdapter.java
@@ -50,7 +50,10 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
public ChooserMultiProfilePagerAdapter(
Context context,
- ChooserGridAdapter adapter,
+ String personalTabLabel,
+ String personalTabAccessibilityLabel,
+ String personalTabTag,
+ ChooserGridAdapter personalAdapter,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
UserHandle workProfileUserHandle,
@@ -60,7 +63,13 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
this(
context,
new ChooserProfileAdapterBinder(maxTargetsPerRow),
- ImmutableList.of(adapter),
+ ImmutableList.of(
+ new TabConfig<>(
+ PROFILE_PERSONAL,
+ personalTabLabel,
+ personalTabAccessibilityLabel,
+ personalTabTag,
+ personalAdapter)),
emptyStateProvider,
workProfileQuietModeChecker,
/* defaultProfile= */ 0,
@@ -72,7 +81,13 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
public ChooserMultiProfilePagerAdapter(
Context context,
+ String personalTabLabel,
+ String personalTabAccessibilityLabel,
+ String personalTabTag,
ChooserGridAdapter personalAdapter,
+ String workTabLabel,
+ String workTabAccessibilityLabel,
+ String workTabTag,
ChooserGridAdapter workAdapter,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
@@ -84,7 +99,19 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
this(
context,
new ChooserProfileAdapterBinder(maxTargetsPerRow),
- ImmutableList.of(personalAdapter, workAdapter),
+ ImmutableList.of(
+ new TabConfig<>(
+ PROFILE_PERSONAL,
+ personalTabLabel,
+ personalTabAccessibilityLabel,
+ personalTabTag,
+ personalAdapter),
+ new TabConfig<>(
+ PROFILE_WORK,
+ workTabLabel,
+ workTabAccessibilityLabel,
+ workTabTag,
+ workAdapter)),
emptyStateProvider,
workProfileQuietModeChecker,
defaultProfile,
@@ -97,7 +124,7 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
private ChooserMultiProfilePagerAdapter(
Context context,
ChooserProfileAdapterBinder adapterBinder,
- ImmutableList<ChooserGridAdapter> gridAdapters,
+ ImmutableList<TabConfig<ChooserGridAdapter>> tabs,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
@Profile int defaultProfile,
@@ -108,7 +135,7 @@ public class ChooserMultiProfilePagerAdapter extends MultiProfilePagerAdapter<
super(
gridAdapter -> gridAdapter.getListAdapter(),
adapterBinder,
- gridAdapters,
+ tabs,
emptyStateProvider,
workProfileQuietModeChecker,
defaultProfile,
diff --git a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
index 3f772775..2883542e 100644
--- a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
@@ -38,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import java.util.HashSet;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -109,10 +110,31 @@ class MultiProfilePagerAdapter<
private int mCurrentPage;
private OnProfileSelectedListener mOnProfileSelectedListener;
+ public static class TabConfig<PageAdapterT> {
+ private final @Profile int mProfile;
+ private final String mTabLabel;
+ private final String mTabAccessibilityLabel;
+ private final String mTabTag;
+ private final PageAdapterT mPageAdapter;
+
+ public TabConfig(
+ @Profile int profile,
+ String tabLabel,
+ String tabAccessibilityLabel,
+ String tabTag,
+ PageAdapterT pageAdapter) {
+ mProfile = profile;
+ mTabLabel = tabLabel;
+ mTabAccessibilityLabel = tabAccessibilityLabel;
+ mTabTag = tabTag;
+ mPageAdapter = pageAdapter;
+ }
+ }
+
protected MultiProfilePagerAdapter(
Function<SinglePageAdapterT, ListAdapterT> listAdapterExtractor,
AdapterBinder<PageViewT, SinglePageAdapterT> adapterBinder,
- ImmutableList<SinglePageAdapterT> adapters,
+ ImmutableList<TabConfig<SinglePageAdapterT>> tabs,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
@Profile int defaultProfile,
@@ -120,7 +142,6 @@ class MultiProfilePagerAdapter<
UserHandle cloneProfileUserHandle,
Supplier<ViewGroup> pageViewInflater,
Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) {
- mCurrentPage = defaultProfile;
mLoadedPages = new HashSet<>();
mWorkProfileUserHandle = workProfileUserHandle;
mCloneProfileUserHandle = cloneProfileUserHandle;
@@ -133,38 +154,40 @@ class MultiProfilePagerAdapter<
ImmutableList.Builder<ProfileDescriptor<PageViewT, SinglePageAdapterT>> items =
new ImmutableList.Builder<>();
- // TODO: for now this only builds in personal and work tabs; any other provided `adapters`
- // are ignored. Historically this class wouldn't have behaved correctly for any more than
- // those two tabs, so this is more explicit about our current support. Upcoming changes will
- // generalize to support more tabs.
- for (SinglePageAdapterT pageAdapter : adapters) {
- ListAdapterT listAdapter = mListAdapterExtractor.apply(pageAdapter);
- if (listAdapter.getUserHandle().equals(workProfileUserHandle)) {
- items.add(
- createProfileDescriptor(
- PROFILE_WORK, pageAdapter, containerBottomPaddingOverrideSupplier));
- } else {
- // TODO: it shouldn't be possible to add multiple "personal" descriptors. For now
- // we're just trusting our clients to provide valid data. We should avoid making
- // inferences from the adapter's user handle, and instead have the pager-adapter
- // receive all the necessary configuration data (in some format that ensures
- // uniqueness of the adapters assigned to a given profile).
- items.add(
- createProfileDescriptor(
- PROFILE_PERSONAL,
- pageAdapter,
- containerBottomPaddingOverrideSupplier));
- }
+ for (TabConfig<SinglePageAdapterT> tab : tabs) {
+ // TODO: consider representing tabConfig in a different data structure that can ensure
+ // uniqueness of their profile assignments (while still respecting the client's
+ // requested tab order).
+ items.add(
+ createProfileDescriptor(
+ tab.mProfile,
+ tab.mTabLabel,
+ tab.mTabAccessibilityLabel,
+ tab.mTabTag,
+ tab.mPageAdapter,
+ containerBottomPaddingOverrideSupplier));
}
mItems = items.build();
+
+ mCurrentPage =
+ hasPageForProfile(defaultProfile) ? getPageNumberForProfile(defaultProfile) : 0;
}
private ProfileDescriptor<PageViewT, SinglePageAdapterT> createProfileDescriptor(
@Profile int profile,
+ String tabLabel,
+ String tabAccessibilityLabel,
+ String tabTag,
SinglePageAdapterT adapter,
Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) {
return new ProfileDescriptor<>(
- profile, mPageViewInflater.get(), adapter, containerBottomPaddingOverrideSupplier);
+ profile,
+ tabLabel,
+ tabAccessibilityLabel,
+ tabTag,
+ mPageViewInflater.get(),
+ adapter,
+ containerBottomPaddingOverrideSupplier);
}
private boolean hasPageForIndex(int pageIndex) {
@@ -241,6 +264,15 @@ class MultiProfilePagerAdapter<
return getItem(getPageNumberForUserHandle(userHandle));
}
+ private int getPageNumberForTabTag(String tag) {
+ for (int i = 0; i < mItems.size(); ++i) {
+ if (Objects.equals(mItems.get(i).mTabTag, tag)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
private void updateActiveTabStyle(TabHost tabHost) {
int currentTab = tabHost.getCurrentTab();
@@ -258,48 +290,34 @@ class MultiProfilePagerAdapter<
ViewPager viewPager,
int tabButtonLayoutResId,
int tabPageContentViewId,
- String personalTabLabel,
- String personalTabAccessibilityLabel,
- String personalTabTag,
- String workTabLabel,
- String workTabAccessibilityLabel,
- String workTabTag,
Runnable onTabChangeListener,
MultiProfilePagerAdapter.OnProfileSelectedListener clientOnProfileSelectedListener) {
tabHost.setup();
viewPager.setSaveEnabled(false);
- Button personalButton = (Button) layoutInflater.inflate(
- tabButtonLayoutResId, tabHost.getTabWidget(), false);
- personalButton.setText(personalTabLabel);
- personalButton.setContentDescription(personalTabAccessibilityLabel);
-
- TabHost.TabSpec personalTabSpec = tabHost.newTabSpec(personalTabTag)
- .setContent(tabPageContentViewId)
- .setIndicator(personalButton);
- tabHost.addTab(personalTabSpec);
-
- Button workButton = (Button) layoutInflater.inflate(
- tabButtonLayoutResId, tabHost.getTabWidget(), false);
- workButton.setText(workTabLabel);
- workButton.setContentDescription(workTabAccessibilityLabel);
-
- TabHost.TabSpec workTabSpec = tabHost.newTabSpec(workTabTag)
- .setContent(tabPageContentViewId)
- .setIndicator(workButton);
- tabHost.addTab(workTabSpec);
+ for (int pageNumber = 0; pageNumber < getItemCount(); ++pageNumber) {
+ ProfileDescriptor<PageViewT, SinglePageAdapterT> descriptor = mItems.get(pageNumber);
+ Button profileButton = (Button) layoutInflater.inflate(
+ tabButtonLayoutResId, tabHost.getTabWidget(), false);
+ profileButton.setText(descriptor.mTabLabel);
+ profileButton.setContentDescription(descriptor.mTabAccessibilityLabel);
+
+ TabHost.TabSpec profileTabSpec = tabHost.newTabSpec(descriptor.mTabTag)
+ .setContent(tabPageContentViewId)
+ .setIndicator(profileButton);
+ tabHost.addTab(profileTabSpec);
+ }
tabHost.getTabWidget().setVisibility(View.VISIBLE);
updateActiveTabStyle(tabHost);
- tabHost.setOnTabChangedListener(tabId -> {
+ tabHost.setOnTabChangedListener(tabTag -> {
updateActiveTabStyle(tabHost);
- // TODO: update for 3+ tabs.
- if (personalTabTag.equals(tabId)) {
- viewPager.setCurrentItem(0);
- } else {
- viewPager.setCurrentItem(1);
+
+ int pageNumber = getPageNumberForTabTag(tabTag);
+ if (pageNumber >= 0) {
+ viewPager.setCurrentItem(pageNumber);
}
onTabChangeListener.run();
});
@@ -736,6 +754,9 @@ class MultiProfilePagerAdapter<
// should be the owner of all per-profile data (especially now that the API is generic)?
private static class ProfileDescriptor<PageViewT, SinglePageAdapterT> {
final @Profile int mProfile;
+ final String mTabLabel;
+ final String mTabAccessibilityLabel;
+ final String mTabTag;
final ViewGroup mRootView;
final EmptyStateUiHelper mEmptyStateUi;
@@ -749,10 +770,16 @@ class MultiProfilePagerAdapter<
ProfileDescriptor(
@Profile int forProfile,
+ String tabLabel,
+ String tabAccessibilityLabel,
+ String tabTag,
ViewGroup rootView,
SinglePageAdapterT adapter,
Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) {
mProfile = forProfile;
+ mTabLabel = tabLabel;
+ mTabAccessibilityLabel = tabAccessibilityLabel;
+ mTabTag = tabTag;
mRootView = rootView;
mAdapter = adapter;
mEmptyStateView = rootView.findViewById(com.android.internal.R.id.resolver_empty_state);
diff --git a/java/src/com/android/intentresolver/v2/ResolverActivity.java b/java/src/com/android/intentresolver/v2/ResolverActivity.java
index 2a6ed9d5..3394c543 100644
--- a/java/src/com/android/intentresolver/v2/ResolverActivity.java
+++ b/java/src/com/android/intentresolver/v2/ResolverActivity.java
@@ -167,8 +167,8 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
/** Tracks if we should ignore future broadcasts telling us the work profile is enabled */
private final boolean mWorkProfileHasBeenEnabled = false;
- private static final String TAB_TAG_PERSONAL = "personal";
- private static final String TAB_TAG_WORK = "work";
+ protected static final String TAB_TAG_PERSONAL = "personal";
+ protected static final String TAB_TAG_WORK = "work";
private PackageMonitor mPersonalPackageMonitor;
private PackageMonitor mWorkPackageMonitor;
@@ -946,7 +946,7 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
List<ResolveInfo> resolutionList,
boolean filterLastUsed,
TargetDataLoader targetDataLoader) {
- ResolverListAdapter adapter = createResolverListAdapter(
+ ResolverListAdapter personalAdapter = createResolverListAdapter(
/* context */ this,
mLogic.getPayloadIntents(),
initialIntents,
@@ -956,7 +956,10 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
targetDataLoader);
return new ResolverMultiProfilePagerAdapter(
/* context */ this,
- adapter,
+ mDevicePolicyResources.getPersonalTabLabel(),
+ mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
+ TAB_TAG_PERSONAL,
+ personalAdapter,
createEmptyStateProvider(/* workProfileUserHandle= */ null),
/* workProfileQuietModeChecker= */ () -> false,
/* workProfileUserHandle= */ null,
@@ -1015,7 +1018,13 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
targetDataLoader);
return new ResolverMultiProfilePagerAdapter(
/* context */ this,
+ mDevicePolicyResources.getPersonalTabLabel(),
+ mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
+ TAB_TAG_PERSONAL,
personalAdapter,
+ mDevicePolicyResources.getWorkTabLabel(),
+ mDevicePolicyResources.getWorkTabAccessibilityLabel(),
+ TAB_TAG_WORK,
workAdapter,
createEmptyStateProvider(workProfileUserHandle),
() -> mLogic.getWorkProfileAvailabilityManager().isQuietModeEnabled(),
@@ -1904,12 +1913,6 @@ public class ResolverActivity extends Hilt_ResolverActivity implements
viewPager,
R.layout.resolver_profile_tab_button,
com.android.internal.R.id.profile_pager,
- mDevicePolicyResources.getPersonalTabLabel(),
- mDevicePolicyResources.getPersonalTabAccessibilityLabel(),
- TAB_TAG_PERSONAL,
- mDevicePolicyResources.getWorkTabLabel(),
- mDevicePolicyResources.getWorkTabAccessibilityLabel(),
- TAB_TAG_WORK,
() -> onProfileTabSelected(viewPager.getCurrentItem()),
new MultiProfilePagerAdapter.OnProfileSelectedListener() {
@Override
diff --git a/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
index 99de3b4d..4c1358ed 100644
--- a/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/ResolverMultiProfilePagerAdapter.java
@@ -27,7 +27,6 @@ import androidx.viewpager.widget.PagerAdapter;
import com.android.intentresolver.R;
import com.android.intentresolver.ResolverListAdapter;
import com.android.intentresolver.emptystate.EmptyStateProvider;
-import com.android.internal.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
@@ -43,14 +42,23 @@ public class ResolverMultiProfilePagerAdapter extends
public ResolverMultiProfilePagerAdapter(
Context context,
- ResolverListAdapter adapter,
+ String personalTabLabel,
+ String personalTabAccessibilityLabel,
+ String personalTabTag,
+ ResolverListAdapter personalAdapter,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
UserHandle workProfileUserHandle,
UserHandle cloneProfileUserHandle) {
this(
context,
- ImmutableList.of(adapter),
+ ImmutableList.of(
+ new TabConfig<>(
+ PROFILE_PERSONAL,
+ personalTabLabel,
+ personalTabAccessibilityLabel,
+ personalTabTag,
+ personalAdapter)),
emptyStateProvider,
workProfileQuietModeChecker,
/* defaultProfile= */ 0,
@@ -60,7 +68,13 @@ public class ResolverMultiProfilePagerAdapter extends
}
public ResolverMultiProfilePagerAdapter(Context context,
+ String personalTabLabel,
+ String personalTabAccessibilityLabel,
+ String personalTabTag,
ResolverListAdapter personalAdapter,
+ String workTabLabel,
+ String workTabAccessibilityLabel,
+ String workTabTag,
ResolverListAdapter workAdapter,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
@@ -69,7 +83,19 @@ public class ResolverMultiProfilePagerAdapter extends
UserHandle cloneProfileUserHandle) {
this(
context,
- ImmutableList.of(personalAdapter, workAdapter),
+ ImmutableList.of(
+ new TabConfig<>(
+ PROFILE_PERSONAL,
+ personalTabLabel,
+ personalTabAccessibilityLabel,
+ personalTabTag,
+ personalAdapter),
+ new TabConfig<>(
+ PROFILE_WORK,
+ workTabLabel,
+ workTabAccessibilityLabel,
+ workTabTag,
+ workAdapter)),
emptyStateProvider,
workProfileQuietModeChecker,
defaultProfile,
@@ -80,7 +106,7 @@ public class ResolverMultiProfilePagerAdapter extends
private ResolverMultiProfilePagerAdapter(
Context context,
- ImmutableList<ResolverListAdapter> listAdapters,
+ ImmutableList<TabConfig<ResolverListAdapter>> tabs,
EmptyStateProvider emptyStateProvider,
Supplier<Boolean> workProfileQuietModeChecker,
@Profile int defaultProfile,
@@ -90,7 +116,7 @@ public class ResolverMultiProfilePagerAdapter extends
super(
listAdapter -> listAdapter,
(listView, bindAdapter) -> listView.setAdapter(bindAdapter),
- listAdapters,
+ tabs,
emptyStateProvider,
workProfileQuietModeChecker,
defaultProfile,