diff options
Diffstat (limited to 'java/src')
3 files changed, 112 insertions, 51 deletions
diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java index 2d2c71af..f94ed247 100644 --- a/java/src/com/android/intentresolver/v2/ChooserActivity.java +++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java @@ -140,6 +140,7 @@ import com.android.intentresolver.model.AppPredictionServiceResolverComparator; import com.android.intentresolver.model.ResolverRankerServiceResolverComparator; import com.android.intentresolver.shortcuts.AppPredictorFactory; import com.android.intentresolver.shortcuts.ShortcutLoader; +import com.android.intentresolver.v2.MultiProfilePagerAdapter.Profile; import com.android.intentresolver.v2.data.repository.DevicePolicyResources; import com.android.intentresolver.v2.emptystate.NoAppsAvailableEmptyStateProvider; import com.android.intentresolver.v2.emptystate.NoCrossProfileEmptyStateProvider; @@ -1161,14 +1162,6 @@ public class ChooserActivity extends Hilt_ChooserActivity implements return false; } - private void updateActiveTabStyle(TabHost tabHost) { - int currentTab = tabHost.getCurrentTab(); - TextView selected = (TextView) tabHost.getTabWidget().getChildAt(currentTab); - TextView unselected = (TextView) tabHost.getTabWidget().getChildAt(1 - currentTab); - selected.setSelected(true); - unselected.setSelected(false); - } - private void setupProfileTabs() { TabHost tabHost = findViewById(com.android.internal.R.id.profile_tabhost); tabHost.setup(); @@ -1198,23 +1191,25 @@ public class ChooserActivity extends Hilt_ChooserActivity implements TabWidget tabWidget = tabHost.getTabWidget(); tabWidget.setVisibility(View.VISIBLE); - updateActiveTabStyle(tabHost); + + Runnable updateActiveTabStyle = () -> { + int currentTab = tabHost.getCurrentTab(); + TextView selected = (TextView) tabHost.getTabWidget().getChildAt(currentTab); + TextView unselected = (TextView) tabHost.getTabWidget().getChildAt(1 - currentTab); + selected.setSelected(true); + unselected.setSelected(false); + }; + + updateActiveTabStyle.run(); tabHost.setOnTabChangedListener(tabId -> { - updateActiveTabStyle(tabHost); + updateActiveTabStyle.run(); if (TAB_TAG_PERSONAL.equals(tabId)) { viewPager.setCurrentItem(0); } else { viewPager.setCurrentItem(1); } - setupViewVisibilities(); - maybeLogProfileChange(); - onProfileTabSelected(); - DevicePolicyEventLogger - .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS) - .setInt(viewPager.getCurrentItem()) - .setStrings(getMetricsCategory()) - .write(); + onProfileTabSelected(viewPager.getCurrentItem()); }); viewPager.setVisibility(View.VISIBLE); @@ -1222,8 +1217,8 @@ public class ChooserActivity extends Hilt_ChooserActivity implements mChooserMultiProfilePagerAdapter.setOnProfileSelectedListener( new MultiProfilePagerAdapter.OnProfileSelectedListener() { @Override - public void onProfileSelected(int index) { - tabHost.setCurrentTab(index); + public void onProfilePageSelected(@Profile int profileId, int pageNumber) { + tabHost.setCurrentTab(pageNumber); } @@ -2618,7 +2613,18 @@ public class ChooserActivity extends Hilt_ChooserActivity implements return METRICS_CATEGORY_CHOOSER; } - protected void onProfileTabSelected() { + protected void onProfileTabSelected(int currentPage) { + setupViewVisibilities(); + maybeLogProfileChange(); + if (hasWorkProfile()) { + // The device policy logger is only concerned with sessions that include a work profile. + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS) + .setInt(currentPage) + .setStrings(getMetricsCategory()) + .write(); + } + // This fixes an edge case where after performing a variety of gestures, vertical scrolling // ends up disabled. That's because at some point the old tab's vertical scrolling is // disabled and the new tab's is enabled. For context, see b/159997845 diff --git a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java index c8e9481a..dc821e88 100644 --- a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java +++ b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java @@ -129,25 +129,54 @@ class MultiProfilePagerAdapter< ImmutableList.Builder<ProfileDescriptor<PageViewT, SinglePageAdapterT>> items = new ImmutableList.Builder<>(); - for (SinglePageAdapterT adapter : adapters) { - items.add(createProfileDescriptor(adapter, containerBottomPaddingOverrideSupplier)); + // 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)); + } } mItems = items.build(); } private ProfileDescriptor<PageViewT, SinglePageAdapterT> createProfileDescriptor( + @Profile int profile, SinglePageAdapterT adapter, Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) { return new ProfileDescriptor<>( - mPageViewInflater.get(), adapter, containerBottomPaddingOverrideSupplier); + profile, mPageViewInflater.get(), adapter, containerBottomPaddingOverrideSupplier); } private @Profile int getProfileForPageNumber(int position) { - return position; + if (hasAdapterForIndex(position)) { + return mItems.get(position).mProfile; + } + return -1; } private int getPageNumberForProfile(@Profile int profile) { - return profile; + for (int i = 0; i < mItems.size(); ++i) { + if (profile == mItems.get(i).mProfile) { + return i; + } + } + return -1; } public void setOnProfileSelectedListener(OnProfileSelectedListener listener) { @@ -169,7 +198,8 @@ class MultiProfilePagerAdapter< mLoadedPages.add(position); } if (mOnProfileSelectedListener != null) { - mOnProfileSelectedListener.onProfileSelected(position); + mOnProfileSelectedListener.onProfilePageSelected( + getProfileForPageNumber(position), position); } } @@ -599,6 +629,8 @@ class MultiProfilePagerAdapter< // TODO: `ChooserActivity` also has a per-profile record type. Maybe the "multi-profile pager" // 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 ViewGroup mRootView; final EmptyStateUiHelper mEmptyStateUi; @@ -610,9 +642,11 @@ class MultiProfilePagerAdapter< private final PageViewT mView; ProfileDescriptor( + @Profile int forProfile, ViewGroup rootView, SinglePageAdapterT adapter, Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) { + mProfile = forProfile; mRootView = rootView; mAdapter = adapter; mEmptyStateView = rootView.findViewById(com.android.internal.R.id.resolver_empty_state); @@ -635,13 +669,14 @@ class MultiProfilePagerAdapter< /** Listener interface for changes between the per-profile UI tabs. */ public interface OnProfileSelectedListener { /** - * Callback for when the user changes the active tab from personal to work or vice versa. + * Callback for when the user changes the active tab. * <p>This callback is only called when the intent resolver or share sheet shows - * the work and personal profiles. - * @param profileIndex {@link #PROFILE_PERSONAL} if the personal profile was selected or - * {@link #PROFILE_WORK} if the work profile was selected. + * more than one profile. + * @param profileId the ID of the newly-selected profile, e.g. {@link #PROFILE_PERSONAL} + * if the personal profile tab was selected or {@link #PROFILE_WORK} if the work profile tab + * was selected. */ - void onProfileSelected(int profileIndex); + void onProfilePageSelected(@Profile int profileId, int pageNumber); /** diff --git a/java/src/com/android/intentresolver/v2/ResolverActivity.java b/java/src/com/android/intentresolver/v2/ResolverActivity.java index a56d15a2..bc3fb16b 100644 --- a/java/src/com/android/intentresolver/v2/ResolverActivity.java +++ b/java/src/com/android/intentresolver/v2/ResolverActivity.java @@ -774,6 +774,31 @@ public class ResolverActivity extends Hilt_ResolverActivity implements } /** + * Callback called when user changes the profile tab. + */ + /* TODO: consider merging with the customized considerations of our implemented + * {@link MultiProfilePagerAdapter.OnProfileSelectedListener}. The only apparent distinctions + * between the respective listener callbacks would occur in the triggering patterns during init + * (when the `OnProfileSelectedListener` is registered after a possible tab-change), or possibly + * if there's some way to trigger an update in one model but not the other. If there's an + * initialization dependency, we can probably reason about it with confidence. If there's a + * discrepancy between the `TabHost` and pager-adapter data models, that inconsistency is + * likely to be a bug that would benefit from consolidation. + */ + protected void onProfileTabSelected(int currentPage) { + setupViewVisibilities(); + maybeLogProfileChange(); + if (hasWorkProfile()) { + // The device policy logger is only concerned with sessions that include a work profile. + DevicePolicyEventLogger + .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS) + .setInt(currentPage) + .setStrings(getMetricsCategory()) + .write(); + } + } + + /** * Add a label to signify that the user can pick a different app. * @param adapter The adapter used to provide data to item views. */ @@ -1717,14 +1742,6 @@ public class ResolverActivity extends Hilt_ResolverActivity implements .clearCheckedItemsInInactiveProfiles(); } - private void updateActiveTabStyle(TabHost tabHost) { - int currentTab = tabHost.getCurrentTab(); - TextView selected = (TextView) tabHost.getTabWidget().getChildAt(currentTab); - TextView unselected = (TextView) tabHost.getTabWidget().getChildAt(1 - currentTab); - selected.setSelected(true); - unselected.setSelected(false); - } - private void setupViewVisibilities() { ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter(); if (!mMultiProfilePagerAdapter.shouldShowEmptyStateScreen(activeListAdapter)) { @@ -1906,22 +1923,25 @@ public class ResolverActivity extends Hilt_ResolverActivity implements TabWidget tabWidget = tabHost.getTabWidget(); tabWidget.setVisibility(View.VISIBLE); - updateActiveTabStyle(tabHost); + + Runnable updateActiveTabStyle = () -> { + int currentTab = tabHost.getCurrentTab(); + TextView selected = (TextView) tabHost.getTabWidget().getChildAt(currentTab); + TextView unselected = (TextView) tabHost.getTabWidget().getChildAt(1 - currentTab); + selected.setSelected(true); + unselected.setSelected(false); + }; + + updateActiveTabStyle.run(); tabHost.setOnTabChangedListener(tabId -> { - updateActiveTabStyle(tabHost); + updateActiveTabStyle.run(); if (TAB_TAG_PERSONAL.equals(tabId)) { viewPager.setCurrentItem(0); } else { viewPager.setCurrentItem(1); } - setupViewVisibilities(); - maybeLogProfileChange(); - DevicePolicyEventLogger - .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS) - .setInt(viewPager.getCurrentItem()) - .setStrings(getMetricsCategory()) - .write(); + onProfileTabSelected(viewPager.getCurrentItem()); }); viewPager.setVisibility(View.VISIBLE); @@ -1929,8 +1949,8 @@ public class ResolverActivity extends Hilt_ResolverActivity implements mMultiProfilePagerAdapter.setOnProfileSelectedListener( new MultiProfilePagerAdapter.OnProfileSelectedListener() { @Override - public void onProfileSelected(int index) { - tabHost.setCurrentTab(index); + public void onProfilePageSelected(@Profile int profileId, int pageNumber) { + tabHost.setCurrentTab(pageNumber); resetButtonBar(); resetCheckedItem(); } |