Loading core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java +39 −20 Original line number Diff line number Diff line Loading @@ -300,30 +300,26 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { } private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) { UserHandle listUserHandle = activeListAdapter.getUserHandle(); if (UserHandle.myUserId() != listUserHandle.getIdentifier()) { if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(), UserHandle.myUserId(), listUserHandle.getIdentifier())) { if (listUserHandle.equals(mPersonalProfileUserHandle)) { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL) .setStrings(getMetricsCategory()) .write(); showNoWorkToPersonalIntentsEmptyState(activeListAdapter); } else { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK) .setStrings(getMetricsCategory()) .write(); showNoPersonalToWorkIntentsEmptyState(activeListAdapter); } if (shouldShowNoCrossProfileIntentsEmptyState(activeListAdapter)) { activeListAdapter.postListReadyRunnable(doPostProcessing); return false; } } return activeListAdapter.rebuildList(doPostProcessing); } private boolean shouldShowNoCrossProfileIntentsEmptyState( ResolverListAdapter activeListAdapter) { UserHandle listUserHandle = activeListAdapter.getUserHandle(); return UserHandle.myUserId() != listUserHandle.getIdentifier() && allowShowNoCrossProfileIntentsEmptyState() && !mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(), UserHandle.myUserId(), listUserHandle.getIdentifier()); } boolean allowShowNoCrossProfileIntentsEmptyState() { return true; } protected abstract void showWorkProfileOffEmptyState( ResolverListAdapter activeListAdapter, View.OnClickListener listener); Loading Loading @@ -353,12 +349,35 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { * anyway. */ void showEmptyResolverListEmptyState(ResolverListAdapter listAdapter) { if (maybeShowNoCrossProfileIntentsEmptyState(listAdapter)) { return; } if (maybeShowWorkProfileOffEmptyState(listAdapter)) { return; } maybeShowNoAppsAvailableEmptyState(listAdapter); } private boolean maybeShowNoCrossProfileIntentsEmptyState(ResolverListAdapter listAdapter) { if (!shouldShowNoCrossProfileIntentsEmptyState(listAdapter)) { return false; } if (listAdapter.getUserHandle().equals(mPersonalProfileUserHandle)) { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL) .setStrings(getMetricsCategory()) .write(); showNoWorkToPersonalIntentsEmptyState(listAdapter); } else { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK) .setStrings(getMetricsCategory()) .write(); showNoPersonalToWorkIntentsEmptyState(listAdapter); } return true; } /** * Returns {@code true} if the work profile off empty state screen is shown. */ Loading core/java/com/android/internal/app/ResolverActivity.java +45 −11 Original line number Diff line number Diff line Loading @@ -179,6 +179,7 @@ public class ResolverActivity extends Activity implements public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device"; private BroadcastReceiver mWorkProfileStateReceiver; private boolean mIsHeaderCreated; /** * Get the string resource to be used as a label for the link to the resolver activity for an Loading Loading @@ -479,13 +480,42 @@ public class ResolverActivity extends Activity implements == workProfileUserHandle.getIdentifier()), mUseLayoutForBrowsables, /* userHandle */ workProfileUserHandle); // In the edge case when we have 0 apps in the current profile and >1 apps in the other, // the intent resolver is started in the other profile. Since this is the only case when // this happens, we check for it here and set the current profile's tab. int selectedProfile = getCurrentProfile(); UserHandle intentUser = UserHandle.of(getLaunchingUserId()); if (!getUser().equals(intentUser)) { if (getPersonalProfileUserHandle().equals(intentUser)) { selectedProfile = PROFILE_PERSONAL; } else if (getWorkProfileUserHandle().equals(intentUser)) { selectedProfile = PROFILE_WORK; } } return new ResolverMultiProfilePagerAdapter( /* context */ this, personalAdapter, workAdapter, /* defaultProfile */ getCurrentProfile(), selectedProfile, getPersonalProfileUserHandle(), getWorkProfileUserHandle()); getWorkProfileUserHandle(), /* shouldShowNoCrossProfileIntentsEmptyState= */ getUser().equals(intentUser)); } /** * Returns the user id of the user that the starting intent originated from. * <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()}, * as there are edge cases when the intent resolver is launched in the other profile. * For example, when we have 0 resolved apps in current profile and multiple resolved apps * in the other profile, opening a link from the current profile launches the intent resolver * in the other one. b/148536209 for more info. */ private int getLaunchingUserId() { int contentUserHint = getIntent().getContentUserHint(); if (contentUserHint == UserHandle.USER_CURRENT) { return UserHandle.myUserId(); } return contentUserHint; } protected @Profile int getCurrentProfile() { Loading Loading @@ -856,7 +886,7 @@ public class ResolverActivity extends Activity implements private void setAlwaysButtonEnabled(boolean hasValidSelection, int checkedPos, boolean filtered) { if (mMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { if (!mMultiProfilePagerAdapter.getCurrentUserHandle().equals(getUser())) { // Never allow the inactive profile to always open an app. mAlwaysButton.setEnabled(false); return; Loading Loading @@ -995,10 +1025,7 @@ public class ResolverActivity extends Activity implements mMultiProfilePagerAdapter.showListView(listAdapter); } if (doPostProcessing) { if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() == UserHandle.myUserId()) { setHeader(); } maybeCreateHeader(listAdapter); resetButtonBar(); onListRebuilt(listAdapter); } Loading Loading @@ -1679,10 +1706,15 @@ public class ResolverActivity extends Activity implements /** * Configure the area above the app selection list (title, content preview, etc). * <p>The header is created once when first launching the activity and whenever a package is * installed or uninstalled. */ public void setHeader() { if (mMultiProfilePagerAdapter.getActiveListAdapter().getCount() == 0 && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0) { private void maybeCreateHeader(ResolverListAdapter listAdapter) { if (mIsHeaderCreated) { return; } if (!shouldShowTabs() && listAdapter.getCount() == 0 && listAdapter.getPlaceholderCount() == 0) { final TextView titleView = findViewById(R.id.title); if (titleView != null) { titleView.setVisibility(View.GONE); Loading @@ -1703,8 +1735,9 @@ public class ResolverActivity extends Activity implements final ImageView iconView = findViewById(R.id.icon); if (iconView != null) { mMultiProfilePagerAdapter.getActiveListAdapter().loadFilteredItemIconTaskAsync(iconView); listAdapter.loadFilteredItemIconTaskAsync(iconView); } mIsHeaderCreated = true; } protected void resetButtonBar() { Loading Loading @@ -1804,6 +1837,7 @@ public class ResolverActivity extends Activity implements // turning on. return; } mIsHeaderCreated = false; boolean listRebuilt = mMultiProfilePagerAdapter.rebuildActiveTab(true); if (listRebuilt) { ResolverListAdapter activeListAdapter = Loading core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java +10 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import com.android.internal.widget.PagerAdapter; public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerAdapter { private final ResolverProfileDescriptor[] mItems; private final boolean mShouldShowNoCrossProfileIntentsEmptyState; ResolverMultiProfilePagerAdapter(Context context, ResolverListAdapter adapter, Loading @@ -44,6 +45,7 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(adapter) }; mShouldShowNoCrossProfileIntentsEmptyState = true; } ResolverMultiProfilePagerAdapter(Context context, Loading @@ -51,13 +53,15 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA ResolverListAdapter workAdapter, @Profile int defaultProfile, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle) { UserHandle workProfileUserHandle, boolean shouldShowNoCrossProfileIntentsEmptyState) { super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, workProfileUserHandle); mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(personalAdapter), createProfileDescriptor(workAdapter) }; mShouldShowNoCrossProfileIntentsEmptyState = shouldShowNoCrossProfileIntentsEmptyState; } private ResolverProfileDescriptor createProfileDescriptor( Loading Loading @@ -162,6 +166,11 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA return ResolverActivity.METRICS_CATEGORY_RESOLVER; } @Override boolean allowShowNoCrossProfileIntentsEmptyState() { return mShouldShowNoCrossProfileIntentsEmptyState; } @Override protected void showWorkProfileOffEmptyState(ResolverListAdapter activeListAdapter, View.OnClickListener listener) { Loading core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +55 −0 Original line number Diff line number Diff line Loading @@ -38,13 +38,16 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.testng.Assert.assertFalse; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.UserHandle; import android.text.TextUtils; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.test.InstrumentationRegistry; import androidx.test.espresso.Espresso; Loading Loading @@ -543,6 +546,51 @@ public class ResolverActivityTest { assertThat(activity.getWorkListAdapter().getCount(), is(4)); } @Test public void testWorkTab_headerIsVisibleInPersonalTab() { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(1); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createOpenWebsiteIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); waitForIdle(); TextView headerText = activity.findViewById(R.id.title); String initialText = headerText.getText().toString(); assertFalse(initialText.isEmpty(), "Header text is empty."); assertThat(headerText.getVisibility(), is(View.VISIBLE)); } @Test public void testWorkTab_switchTabs_headerStaysSame() { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(1); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createOpenWebsiteIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); waitForIdle(); TextView headerText = activity.findViewById(R.id.title); String initialText = headerText.getText().toString(); onView(withText(R.string.resolver_work_tab)) .perform(click()); waitForIdle(); String currentText = headerText.getText().toString(); assertThat(headerText.getVisibility(), is(View.VISIBLE)); assertThat(String.format("Header text is not the same when switching tabs, personal profile" + " header was %s but work profile header is %s", initialText, currentText), TextUtils.equals(initialText, currentText)); } @Ignore // b/148156663 @Test public void testWorkTab_noPersonalApps_canStartWorkApps() Loading Loading @@ -761,6 +809,13 @@ public class ResolverActivityTest { return sendIntent; } private Intent createOpenWebsiteIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_VIEW); sendIntent.setData(Uri.parse("https://google.com")); return sendIntent; } private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) { List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults); for (int i = 0; i < numberOfResults; i++) { Loading Loading
core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java +39 −20 Original line number Diff line number Diff line Loading @@ -300,30 +300,26 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { } private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) { UserHandle listUserHandle = activeListAdapter.getUserHandle(); if (UserHandle.myUserId() != listUserHandle.getIdentifier()) { if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(), UserHandle.myUserId(), listUserHandle.getIdentifier())) { if (listUserHandle.equals(mPersonalProfileUserHandle)) { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL) .setStrings(getMetricsCategory()) .write(); showNoWorkToPersonalIntentsEmptyState(activeListAdapter); } else { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK) .setStrings(getMetricsCategory()) .write(); showNoPersonalToWorkIntentsEmptyState(activeListAdapter); } if (shouldShowNoCrossProfileIntentsEmptyState(activeListAdapter)) { activeListAdapter.postListReadyRunnable(doPostProcessing); return false; } } return activeListAdapter.rebuildList(doPostProcessing); } private boolean shouldShowNoCrossProfileIntentsEmptyState( ResolverListAdapter activeListAdapter) { UserHandle listUserHandle = activeListAdapter.getUserHandle(); return UserHandle.myUserId() != listUserHandle.getIdentifier() && allowShowNoCrossProfileIntentsEmptyState() && !mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(), UserHandle.myUserId(), listUserHandle.getIdentifier()); } boolean allowShowNoCrossProfileIntentsEmptyState() { return true; } protected abstract void showWorkProfileOffEmptyState( ResolverListAdapter activeListAdapter, View.OnClickListener listener); Loading Loading @@ -353,12 +349,35 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { * anyway. */ void showEmptyResolverListEmptyState(ResolverListAdapter listAdapter) { if (maybeShowNoCrossProfileIntentsEmptyState(listAdapter)) { return; } if (maybeShowWorkProfileOffEmptyState(listAdapter)) { return; } maybeShowNoAppsAvailableEmptyState(listAdapter); } private boolean maybeShowNoCrossProfileIntentsEmptyState(ResolverListAdapter listAdapter) { if (!shouldShowNoCrossProfileIntentsEmptyState(listAdapter)) { return false; } if (listAdapter.getUserHandle().equals(mPersonalProfileUserHandle)) { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL) .setStrings(getMetricsCategory()) .write(); showNoWorkToPersonalIntentsEmptyState(listAdapter); } else { DevicePolicyEventLogger.createEvent( DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK) .setStrings(getMetricsCategory()) .write(); showNoPersonalToWorkIntentsEmptyState(listAdapter); } return true; } /** * Returns {@code true} if the work profile off empty state screen is shown. */ Loading
core/java/com/android/internal/app/ResolverActivity.java +45 −11 Original line number Diff line number Diff line Loading @@ -179,6 +179,7 @@ public class ResolverActivity extends Activity implements public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device"; private BroadcastReceiver mWorkProfileStateReceiver; private boolean mIsHeaderCreated; /** * Get the string resource to be used as a label for the link to the resolver activity for an Loading Loading @@ -479,13 +480,42 @@ public class ResolverActivity extends Activity implements == workProfileUserHandle.getIdentifier()), mUseLayoutForBrowsables, /* userHandle */ workProfileUserHandle); // In the edge case when we have 0 apps in the current profile and >1 apps in the other, // the intent resolver is started in the other profile. Since this is the only case when // this happens, we check for it here and set the current profile's tab. int selectedProfile = getCurrentProfile(); UserHandle intentUser = UserHandle.of(getLaunchingUserId()); if (!getUser().equals(intentUser)) { if (getPersonalProfileUserHandle().equals(intentUser)) { selectedProfile = PROFILE_PERSONAL; } else if (getWorkProfileUserHandle().equals(intentUser)) { selectedProfile = PROFILE_WORK; } } return new ResolverMultiProfilePagerAdapter( /* context */ this, personalAdapter, workAdapter, /* defaultProfile */ getCurrentProfile(), selectedProfile, getPersonalProfileUserHandle(), getWorkProfileUserHandle()); getWorkProfileUserHandle(), /* shouldShowNoCrossProfileIntentsEmptyState= */ getUser().equals(intentUser)); } /** * Returns the user id of the user that the starting intent originated from. * <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()}, * as there are edge cases when the intent resolver is launched in the other profile. * For example, when we have 0 resolved apps in current profile and multiple resolved apps * in the other profile, opening a link from the current profile launches the intent resolver * in the other one. b/148536209 for more info. */ private int getLaunchingUserId() { int contentUserHint = getIntent().getContentUserHint(); if (contentUserHint == UserHandle.USER_CURRENT) { return UserHandle.myUserId(); } return contentUserHint; } protected @Profile int getCurrentProfile() { Loading Loading @@ -856,7 +886,7 @@ public class ResolverActivity extends Activity implements private void setAlwaysButtonEnabled(boolean hasValidSelection, int checkedPos, boolean filtered) { if (mMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { if (!mMultiProfilePagerAdapter.getCurrentUserHandle().equals(getUser())) { // Never allow the inactive profile to always open an app. mAlwaysButton.setEnabled(false); return; Loading Loading @@ -995,10 +1025,7 @@ public class ResolverActivity extends Activity implements mMultiProfilePagerAdapter.showListView(listAdapter); } if (doPostProcessing) { if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() == UserHandle.myUserId()) { setHeader(); } maybeCreateHeader(listAdapter); resetButtonBar(); onListRebuilt(listAdapter); } Loading Loading @@ -1679,10 +1706,15 @@ public class ResolverActivity extends Activity implements /** * Configure the area above the app selection list (title, content preview, etc). * <p>The header is created once when first launching the activity and whenever a package is * installed or uninstalled. */ public void setHeader() { if (mMultiProfilePagerAdapter.getActiveListAdapter().getCount() == 0 && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0) { private void maybeCreateHeader(ResolverListAdapter listAdapter) { if (mIsHeaderCreated) { return; } if (!shouldShowTabs() && listAdapter.getCount() == 0 && listAdapter.getPlaceholderCount() == 0) { final TextView titleView = findViewById(R.id.title); if (titleView != null) { titleView.setVisibility(View.GONE); Loading @@ -1703,8 +1735,9 @@ public class ResolverActivity extends Activity implements final ImageView iconView = findViewById(R.id.icon); if (iconView != null) { mMultiProfilePagerAdapter.getActiveListAdapter().loadFilteredItemIconTaskAsync(iconView); listAdapter.loadFilteredItemIconTaskAsync(iconView); } mIsHeaderCreated = true; } protected void resetButtonBar() { Loading Loading @@ -1804,6 +1837,7 @@ public class ResolverActivity extends Activity implements // turning on. return; } mIsHeaderCreated = false; boolean listRebuilt = mMultiProfilePagerAdapter.rebuildActiveTab(true); if (listRebuilt) { ResolverListAdapter activeListAdapter = Loading
core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java +10 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import com.android.internal.widget.PagerAdapter; public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerAdapter { private final ResolverProfileDescriptor[] mItems; private final boolean mShouldShowNoCrossProfileIntentsEmptyState; ResolverMultiProfilePagerAdapter(Context context, ResolverListAdapter adapter, Loading @@ -44,6 +45,7 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(adapter) }; mShouldShowNoCrossProfileIntentsEmptyState = true; } ResolverMultiProfilePagerAdapter(Context context, Loading @@ -51,13 +53,15 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA ResolverListAdapter workAdapter, @Profile int defaultProfile, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle) { UserHandle workProfileUserHandle, boolean shouldShowNoCrossProfileIntentsEmptyState) { super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, workProfileUserHandle); mItems = new ResolverProfileDescriptor[] { createProfileDescriptor(personalAdapter), createProfileDescriptor(workAdapter) }; mShouldShowNoCrossProfileIntentsEmptyState = shouldShowNoCrossProfileIntentsEmptyState; } private ResolverProfileDescriptor createProfileDescriptor( Loading Loading @@ -162,6 +166,11 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA return ResolverActivity.METRICS_CATEGORY_RESOLVER; } @Override boolean allowShowNoCrossProfileIntentsEmptyState() { return mShouldShowNoCrossProfileIntentsEmptyState; } @Override protected void showWorkProfileOffEmptyState(ResolverListAdapter activeListAdapter, View.OnClickListener listener) { Loading
core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +55 −0 Original line number Diff line number Diff line Loading @@ -38,13 +38,16 @@ import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.testng.Assert.assertFalse; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.UserHandle; import android.text.TextUtils; import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; import androidx.test.InstrumentationRegistry; import androidx.test.espresso.Espresso; Loading Loading @@ -543,6 +546,51 @@ public class ResolverActivityTest { assertThat(activity.getWorkListAdapter().getCount(), is(4)); } @Test public void testWorkTab_headerIsVisibleInPersonalTab() { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(1); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createOpenWebsiteIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); waitForIdle(); TextView headerText = activity.findViewById(R.id.title); String initialText = headerText.getText().toString(); assertFalse(initialText.isEmpty(), "Header text is empty."); assertThat(headerText.getVisibility(), is(View.VISIBLE)); } @Test public void testWorkTab_switchTabs_headerStaysSame() { // enable the work tab feature flag ResolverActivity.ENABLE_TABBED_VIEW = true; markWorkProfileUserAvailable(); List<ResolvedComponentInfo> personalResolvedComponentInfos = createResolvedComponentsForTestWithOtherProfile(1); List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4); setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createOpenWebsiteIntent(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); waitForIdle(); TextView headerText = activity.findViewById(R.id.title); String initialText = headerText.getText().toString(); onView(withText(R.string.resolver_work_tab)) .perform(click()); waitForIdle(); String currentText = headerText.getText().toString(); assertThat(headerText.getVisibility(), is(View.VISIBLE)); assertThat(String.format("Header text is not the same when switching tabs, personal profile" + " header was %s but work profile header is %s", initialText, currentText), TextUtils.equals(initialText, currentText)); } @Ignore // b/148156663 @Test public void testWorkTab_noPersonalApps_canStartWorkApps() Loading Loading @@ -761,6 +809,13 @@ public class ResolverActivityTest { return sendIntent; } private Intent createOpenWebsiteIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_VIEW); sendIntent.setData(Uri.parse("https://google.com")); return sendIntent; } private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) { List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults); for (int i = 0; i < numberOfResults; i++) { Loading