Merge "Show empty state screens in order of priority." into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
9238e32a16
@@ -300,21 +300,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
|
||||
private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
|
||||
UserHandle listUserHandle = activeListAdapter.getUserHandle();
|
||||
if (listUserHandle.equals(mWorkProfileUserHandle)
|
||||
&& mInjector.isQuietModeEnabled(mWorkProfileUserHandle)) {
|
||||
DevicePolicyEventLogger
|
||||
.createEvent(DevicePolicyEnums.RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED)
|
||||
.setStrings(getMetricsCategory())
|
||||
.write();
|
||||
showWorkProfileOffEmptyState(activeListAdapter,
|
||||
v -> {
|
||||
ProfileDescriptor descriptor = getItem(
|
||||
userHandleToPageIndex(activeListAdapter.getUserHandle()));
|
||||
showSpinner(descriptor.getEmptyStateView());
|
||||
mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UserHandle.myUserId() != listUserHandle.getIdentifier()) {
|
||||
if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(),
|
||||
UserHandle.myUserId(), listUserHandle.getIdentifier())) {
|
||||
@@ -352,7 +338,65 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
protected abstract void showNoWorkToPersonalIntentsEmptyState(
|
||||
ResolverListAdapter activeListAdapter);
|
||||
|
||||
void showNoAppsAvailableEmptyState(ResolverListAdapter listAdapter) {
|
||||
/**
|
||||
* The empty state screens are shown according to their priority:
|
||||
* <ol>
|
||||
* <li>(highest priority) cross-profile disabled by policy (handled in
|
||||
* {@link #rebuildTab(ResolverListAdapter, boolean)})</li>
|
||||
* <li>no apps available</li>
|
||||
* <li>(least priority) work is off</li>
|
||||
* </ol>
|
||||
*
|
||||
* The intention is to prevent the user from having to turn
|
||||
* the work profile on if there will not be any apps resolved
|
||||
* anyway.
|
||||
*/
|
||||
void showEmptyResolverListEmptyState(ResolverListAdapter listAdapter) {
|
||||
if (maybeShowWorkProfileOffEmptyState(listAdapter)) {
|
||||
return;
|
||||
}
|
||||
maybeShowNoAppsAvailableEmptyState(listAdapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the work profile off empty state screen is shown.
|
||||
*/
|
||||
private boolean maybeShowWorkProfileOffEmptyState(ResolverListAdapter listAdapter) {
|
||||
UserHandle listUserHandle = listAdapter.getUserHandle();
|
||||
if (!listUserHandle.equals(mWorkProfileUserHandle)
|
||||
|| !mInjector.isQuietModeEnabled(mWorkProfileUserHandle)
|
||||
|| !hasResolvedAppsInWorkProfile(listAdapter)) {
|
||||
return false;
|
||||
}
|
||||
DevicePolicyEventLogger
|
||||
.createEvent(DevicePolicyEnums.RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED)
|
||||
.setStrings(getMetricsCategory())
|
||||
.write();
|
||||
showWorkProfileOffEmptyState(listAdapter,
|
||||
v -> {
|
||||
ProfileDescriptor descriptor = getItem(
|
||||
userHandleToPageIndex(listAdapter.getUserHandle()));
|
||||
showSpinner(descriptor.getEmptyStateView());
|
||||
mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there is at least one app resolved in the work profile,
|
||||
* regardless of whether the work profile is enabled or not.
|
||||
*/
|
||||
private boolean hasResolvedAppsInWorkProfile(ResolverListAdapter listAdapter) {
|
||||
List<ResolverActivity.ResolvedComponentInfo> userStateIndependentWorkResolvers =
|
||||
listAdapter.mResolverListController.getUserStateIndependentResolversAsUser(
|
||||
listAdapter.getIntents(), mWorkProfileUserHandle);
|
||||
return userStateIndependentWorkResolvers.stream()
|
||||
.anyMatch(resolvedComponentInfo ->
|
||||
resolvedComponentInfo.getResolveInfoAt(0).targetUserId
|
||||
== UserHandle.USER_CURRENT);
|
||||
}
|
||||
|
||||
private void maybeShowNoAppsAvailableEmptyState(ResolverListAdapter listAdapter) {
|
||||
UserHandle listUserHandle = listAdapter.getUserHandle();
|
||||
if (mWorkProfileUserHandle != null
|
||||
&& (UserHandle.myUserId() == listUserHandle.getIdentifier()
|
||||
|
||||
@@ -994,8 +994,8 @@ public class ResolverActivity extends Activity implements
|
||||
if (isAutolaunching() || maybeAutolaunchActivity()) {
|
||||
return;
|
||||
}
|
||||
if (shouldShowEmptyState(listAdapter)) {
|
||||
mMultiProfilePagerAdapter.showNoAppsAvailableEmptyState(listAdapter);
|
||||
if (isResolverListEmpty(listAdapter)) {
|
||||
mMultiProfilePagerAdapter.showEmptyResolverListEmptyState(listAdapter);
|
||||
} else {
|
||||
mMultiProfilePagerAdapter.showListView(listAdapter);
|
||||
}
|
||||
@@ -1640,12 +1640,12 @@ public class ResolverActivity extends Activity implements
|
||||
|
||||
private void setupViewVisibilities() {
|
||||
ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
|
||||
if (!shouldShowEmptyState(activeListAdapter)) {
|
||||
if (!isResolverListEmpty(activeListAdapter)) {
|
||||
addUseDifferentAppLabelIfNecessary(activeListAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldShowEmptyState(ResolverListAdapter listAdapter) {
|
||||
private boolean isResolverListEmpty(ResolverListAdapter listAdapter) {
|
||||
int count = listAdapter.getUnfilteredCount();
|
||||
return count == 0 && listAdapter.getPlaceholderCount() == 0;
|
||||
}
|
||||
|
||||
@@ -120,12 +120,32 @@ public class ResolverListController {
|
||||
boolean shouldGetActivityMetadata,
|
||||
List<Intent> intents,
|
||||
UserHandle userHandle) {
|
||||
int baseFlags = PackageManager.MATCH_DEFAULT_ONLY
|
||||
| (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
|
||||
| (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
|
||||
return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of resolved intents which is user state-independent. This means it will
|
||||
* return the same results regardless of whether the {@code userHandle} user is disabled or not.
|
||||
*/
|
||||
public List<ResolverActivity.ResolvedComponentInfo> getUserStateIndependentResolversAsUser(
|
||||
List<Intent> intents,
|
||||
UserHandle userHandle) {
|
||||
int baseFlags = PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
|
||||
return getResolversForIntentAsUserInternal(intents, userHandle, baseFlags);
|
||||
}
|
||||
|
||||
private List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUserInternal(
|
||||
List<Intent> intents,
|
||||
UserHandle userHandle,
|
||||
int baseFlags) {
|
||||
List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
|
||||
for (int i = 0, N = intents.size(); i < N; i++) {
|
||||
final Intent intent = intents.get(i);
|
||||
int flags = PackageManager.MATCH_DEFAULT_ONLY
|
||||
| (shouldGetResolvedFilter ? PackageManager.GET_RESOLVED_FILTER : 0)
|
||||
| (shouldGetActivityMetadata ? PackageManager.GET_META_DATA : 0);
|
||||
int flags = baseFlags;
|
||||
if (intent.isWebIntent()
|
||||
|| (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
|
||||
flags |= PackageManager.MATCH_INSTANT;
|
||||
|
||||
@@ -1330,8 +1330,15 @@ public class ChooserActivityTest {
|
||||
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(workProfileTargets);
|
||||
when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
|
||||
Mockito.isA(List.class),
|
||||
Mockito.isA(UserHandle.class)))
|
||||
.thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
// When work profile is disabled, we get 0 results when we query the work profile
|
||||
// intents.
|
||||
setupResolverControllers(personalResolvedComponentInfos,
|
||||
/* workResolvedComponentInfos */ new ArrayList<>());
|
||||
Intent sendIntent = createSendTextIntent();
|
||||
sendIntent.setType("TestType");
|
||||
|
||||
@@ -1348,7 +1355,7 @@ public class ChooserActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_noWorkTargets_emptyStateShown() {
|
||||
public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
@@ -1372,6 +1379,57 @@ public class ChooserActivityTest {
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(3);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(0);
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
sOverrides.hasCrossProfileIntents = false;
|
||||
Intent sendIntent = createSendTextIntent();
|
||||
sendIntent.setType("TestType");
|
||||
|
||||
mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
|
||||
waitForIdle();
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
onView(withText(R.string.resolver_work_tab)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
onView(withText(R.string.resolver_cant_share_with_work_apps))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(3);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(0);
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
Intent sendIntent = createSendTextIntent();
|
||||
sendIntent.setType("TestType");
|
||||
|
||||
mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
|
||||
waitForIdle();
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
onView(withText(R.string.resolver_work_tab)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
onView(withText(R.string.resolver_no_work_apps_available_share))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
private Intent createSendTextIntent() {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
|
||||
@@ -598,7 +598,7 @@ public class ResolverActivityTest {
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
|
||||
onView(withText(R.string.resolver_cant_share_with_work_apps))
|
||||
onView(withText(R.string.resolver_cant_access_work_apps))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@@ -612,8 +612,15 @@ public class ResolverActivityTest {
|
||||
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(workProfileTargets);
|
||||
when(sOverrides.workResolverListController.getUserStateIndependentResolversAsUser(
|
||||
Mockito.isA(List.class),
|
||||
Mockito.isA(UserHandle.class)))
|
||||
.thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
// When work profile is disabled, we get 0 results when we query the work profile
|
||||
// intents.
|
||||
setupResolverControllers(personalResolvedComponentInfos,
|
||||
/* workResolvedComponentInfos */ new ArrayList<>());
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
sendIntent.setType("TestType");
|
||||
|
||||
@@ -629,7 +636,7 @@ public class ResolverActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_noWorkTargets_emptyStateShown() {
|
||||
public void testWorkTab_noWorkAppsAvailable_emptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
@@ -652,6 +659,57 @@ public class ResolverActivityTest {
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_xProfileOff_noAppsAvailable_workOff_xProfileOffEmptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(3);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(0);
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
sendIntent.setType("TestType");
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
sOverrides.hasCrossProfileIntents = false;
|
||||
|
||||
mActivityRule.launchActivity(sendIntent);
|
||||
waitForIdle();
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
onView(withText(R.string.resolver_work_tab)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
onView(withText(R.string.resolver_cant_access_work_apps))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(3);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(0);
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
sendIntent.setType("TestType");
|
||||
sOverrides.isQuietModeEnabled = true;
|
||||
|
||||
mActivityRule.launchActivity(sendIntent);
|
||||
waitForIdle();
|
||||
onView(withId(R.id.contentPanel))
|
||||
.perform(swipeUp());
|
||||
onView(withText(R.string.resolver_work_tab)).perform(click());
|
||||
waitForIdle();
|
||||
|
||||
onView(withText(R.string.resolver_no_work_apps_available_resolve))
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
private Intent createSendImageIntent() {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
|
||||
Reference in New Issue
Block a user