Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94dd284a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix broken tests and add tests for empty state screens."

parents 6fb74aee 34c6ff84
Loading
Loading
Loading
Loading
+53 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
    private Set<Integer> mLoadedPages;
    private final UserHandle mPersonalProfileUserHandle;
    private final UserHandle mWorkProfileUserHandle;
    private Injector mInjector;

    AbstractMultiProfilePagerAdapter(Context context, int currentPage,
            UserHandle personalProfileUserHandle,
@@ -70,6 +71,33 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
        mLoadedPages = new HashSet<>();
        mPersonalProfileUserHandle = personalProfileUserHandle;
        mWorkProfileUserHandle = workProfileUserHandle;
        UserManager userManager = context.getSystemService(UserManager.class);
        mInjector = new Injector() {
            @Override
            public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
                    int targetUserId) {
                return AbstractMultiProfilePagerAdapter.this
                        .hasCrossProfileIntents(intents, sourceUserId, targetUserId);
            }

            @Override
            public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
                return userManager.isQuietModeEnabled(workProfileUserHandle);
            }

            @Override
            public void requestQuietModeEnabled(boolean enabled, UserHandle workProfileUserHandle) {
                userManager.requestQuietModeEnabled(enabled, workProfileUserHandle);
            }
        };
    }

    /**
     * Overrides the default {@link Injector} for testing purposes.
     */
    @VisibleForTesting
    public void setInjector(Injector injector) {
        mInjector = injector;
    }

    void setOnProfileSelectedListener(OnProfileSelectedListener listener) {
@@ -252,19 +280,18 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {

    private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
        UserHandle listUserHandle = activeListAdapter.getUserHandle();
        UserManager userManager = mContext.getSystemService(UserManager.class);
        if (listUserHandle == mWorkProfileUserHandle
                && userManager.isQuietModeEnabled(mWorkProfileUserHandle)) {
                && mInjector.isQuietModeEnabled(mWorkProfileUserHandle)) {
            showEmptyState(activeListAdapter,
                    R.drawable.ic_work_apps_off,
                    R.string.resolver_turn_on_work_apps,
                    R.string.resolver_turn_on_work_apps_explanation,
                    (View.OnClickListener) v ->
                            userManager.requestQuietModeEnabled(false, mWorkProfileUserHandle));
                            mInjector.requestQuietModeEnabled(false, mWorkProfileUserHandle));
            return false;
        }
        if (UserHandle.myUserId() != listUserHandle.getIdentifier()) {
            if (!hasCrossProfileIntents(activeListAdapter.getIntents(),
            if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(),
                    UserHandle.myUserId(), listUserHandle.getIdentifier())) {
                if (listUserHandle == mPersonalProfileUserHandle) {
                    showEmptyState(activeListAdapter,
@@ -366,4 +393,26 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
         */
        void onProfileSelected(int profileIndex);
    }

    /**
     * Describes an injector to be used for cross profile functionality. Overridable for testing.
     */
    @VisibleForTesting
    public interface Injector {
        /**
         * Returns {@code true} if at least one of the provided {@code intents} can be forwarded
         * from {@code sourceUserId} to {@code targetUserId}.
         */
        boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId, int targetUserId);

        /**
         * Returns whether the given profile is in quiet mode or not.
         */
        boolean isQuietModeEnabled(UserHandle workProfileUserHandle);

        /**
         * Enables or disables quiet mode for a managed profile.
         */
        void requestQuietModeEnabled(boolean enabled, UserHandle workProfileUserHandle);
    }
}
 No newline at end of file
+113 −39
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.app;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.swipeUp;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
@@ -355,18 +356,14 @@ public class ChooserActivityTest {
    public void hasOtherProfileOneOption() throws Exception {
        // enable the work tab feature flag
        ResolverActivity.ENABLE_TABBED_VIEW = true;

        List<ResolvedComponentInfo> personalResolvedComponentInfos =
                createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        markWorkProfileUserAvailable();
        Intent sendIntent = createSendTextIntent();
        List<ResolvedComponentInfo> resolvedComponentInfos =
                createResolvedComponentsForTestWithOtherProfile(2);
        ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);

        when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
                Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);

        ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
        Intent sendIntent = createSendTextIntent();
        final ChooserWrapperActivity activity = mActivityRule
                .launchActivity(Intent.createChooser(sendIntent, null));
        waitForIdle();
@@ -382,9 +379,11 @@ public class ChooserActivityTest {

        // Make a stable copy of the components as the original list may be modified
        List<ResolvedComponentInfo> stableCopy =
                createResolvedComponentsForTestWithOtherProfile(2);
                createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10);
        waitForIdle();
        onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);

        onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
                .perform(click());
        waitForIdle();
        assertThat(chosen[0], is(toChoose));
@@ -1218,17 +1217,7 @@ public class ChooserActivityTest {
        int workProfileTargets = 4;
        List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
                workProfileTargets);
        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class)))
                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class),
                eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        Intent sendIntent = createSendTextIntent();
        sendIntent.setType("TestType");
        markWorkProfileUserAvailable();
@@ -1245,7 +1234,7 @@ public class ChooserActivityTest {
    }

    @Test
    public void testWorkTab_workProfileHasExpectedNumberOfTargets() {
    public void testWorkTab_workProfileHasExpectedNumberOfTargets() throws InterruptedException {
        // enable the work tab feature flag
        ResolverActivity.ENABLE_TABBED_VIEW = true;
        markWorkProfileUserAvailable();
@@ -1254,18 +1243,7 @@ public class ChooserActivityTest {
                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
        List<ResolvedComponentInfo> workResolvedComponentInfos =
                createResolvedComponentsForTest(workProfileTargets);
        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class)))
                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class),
                eq(UserHandle.SYSTEM)))
                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        Intent sendIntent = createSendTextIntent();
        sendIntent.setType("TestType");

@@ -1284,12 +1262,12 @@ public class ChooserActivityTest {
        // enable the work tab feature flag
        ResolverActivity.ENABLE_TABBED_VIEW = true;
        markWorkProfileUserAvailable();
        List<ResolvedComponentInfo> personalResolvedComponentInfos =
                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
        int workProfileTargets = 4;
        List<ResolvedComponentInfo> workResolvedComponentInfos =
                createResolvedComponentsForTest(workProfileTargets);
        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        Intent sendIntent = createSendTextIntent();
        sendIntent.setType("TestType");
        ResolveInfo[] chosen = new ResolveInfo[1];
@@ -1312,6 +1290,85 @@ public class ChooserActivityTest {
        assertThat(chosen[0], is(workResolvedComponentInfos.get(0).getResolveInfoAt(0)));
    }

    @Test
    public void testWorkTab_crossProfileIntentsDisabled_personalToWork_emptyStateShown() {
        // enable the work tab feature flag
        ResolverActivity.ENABLE_TABBED_VIEW = true;
        markWorkProfileUserAvailable();
        int workProfileTargets = 4;
        List<ResolvedComponentInfo> personalResolvedComponentInfos =
                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
        List<ResolvedComponentInfo> workResolvedComponentInfos =
                createResolvedComponentsForTest(workProfileTargets);
        sOverrides.hasCrossProfileIntents = false;
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        Intent sendIntent = createSendTextIntent();
        sendIntent.setType("TestType");

        final ChooserWrapperActivity activity =
                mActivityRule.launchActivity(Intent.createChooser(sendIntent, "work tab test"));
        waitForIdle();
        onView(withText(R.string.resolver_work_tab)).perform(click());
        waitForIdle();
        onView(withId(R.id.contentPanel))
                .perform(swipeUp());

        onView(withText(R.string.resolver_cant_share_with_work_apps))
                .check(matches(isDisplayed()));
    }

    @Test
    public void testWorkTab_workProfileDisabled_emptyStateShown() {
        // enable the work tab feature flag
        ResolverActivity.ENABLE_TABBED_VIEW = true;
        markWorkProfileUserAvailable();
        int workProfileTargets = 4;
        List<ResolvedComponentInfo> personalResolvedComponentInfos =
                createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
        List<ResolvedComponentInfo> workResolvedComponentInfos =
                createResolvedComponentsForTest(workProfileTargets);
        sOverrides.isQuietModeEnabled = true;
        setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
        Intent sendIntent = createSendTextIntent();
        sendIntent.setType("TestType");

        final ChooserWrapperActivity activity =
                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_turn_on_work_apps))
                .check(matches(isDisplayed()));
    }

    @Test
    public void testWorkTab_noWorkTargets_emptyStateShown() {
        // 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 = createSendTextIntent();
        sendIntent.setType("TestType");

        final ChooserWrapperActivity activity =
                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_apps_available))
                .check(matches(isDisplayed()));
    }

    private Intent createSendTextIntent() {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
@@ -1486,4 +1543,21 @@ public class ChooserActivityTest {
    private void markWorkProfileUserAvailable() {
        sOverrides.workProfileUserHandle = UserHandle.of(10);
    }

    private void setupResolverControllers(
            List<ResolvedComponentInfo> personalResolvedComponentInfos,
            List<ResolvedComponentInfo> workResolvedComponentInfos) {
        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class)))
                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
        when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
        when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
                Mockito.anyBoolean(),
                Mockito.isA(List.class),
                eq(UserHandle.SYSTEM)))
                .thenReturn(new ArrayList<>(personalResolvedComponentInfos));
    }
}
+33 −8
Original line number Diff line number Diff line
@@ -16,15 +16,10 @@

package com.android.internal.app;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.annotation.Nullable;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
import android.app.usage.UsageStatsManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -35,7 +30,6 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Size;

@@ -45,8 +39,7 @@ import com.android.internal.app.chooser.TargetInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import org.mockito.Mockito;

import java.util.List;
import java.util.function.Function;

public class ChooserWrapperActivity extends ChooserActivity {
@@ -56,6 +49,15 @@ public class ChooserWrapperActivity extends ChooserActivity {
    static final OverrideData sOverrides = new OverrideData();
    private UsageStatsManager mUsm;

    @Override
    protected AbstractMultiProfilePagerAdapter createMultiProfilePagerAdapter(
            Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed) {
        AbstractMultiProfilePagerAdapter multiProfilePagerAdapter =
                super.createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
        multiProfilePagerAdapter.setInjector(sOverrides.multiPagerAdapterInjector);
        return multiProfilePagerAdapter;
    }

    ChooserListAdapter getAdapter() {
        return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
    }
@@ -206,6 +208,9 @@ public class ChooserWrapperActivity extends ChooserActivity {
        public int alternateProfileSetting;
        public Resources resources;
        public UserHandle workProfileUserHandle;
        public boolean hasCrossProfileIntents;
        public boolean isQuietModeEnabled;
        public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;

        public void reset() {
            onSafelyStartCallback = null;
@@ -221,6 +226,26 @@ public class ChooserWrapperActivity extends ChooserActivity {
            alternateProfileSetting = 0;
            resources = null;
            workProfileUserHandle = null;
            hasCrossProfileIntents = true;
            isQuietModeEnabled = false;
            multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
                @Override
                public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
                        int targetUserId) {
                    return hasCrossProfileIntents;
                }

                @Override
                public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
                    return isQuietModeEnabled;
                }

                @Override
                public void requestQuietModeEnabled(boolean enabled,
                        UserHandle workProfileUserHandle) {
                    isQuietModeEnabled = enabled;
                }
            };
        }
    }
}
+118 −121

File changed.

Preview size limit exceeded, changes collapsed.

+32 −0
Original line number Diff line number Diff line
@@ -47,6 +47,15 @@ public class ResolverWrapperActivity extends ResolverActivity {
                filterLastUsed, createListController(userHandle), useLayoutForBrowsables, this);
    }

    @Override
    protected AbstractMultiProfilePagerAdapter createMultiProfilePagerAdapter(
            Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed) {
        AbstractMultiProfilePagerAdapter multiProfilePagerAdapter =
                super.createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
        multiProfilePagerAdapter.setInjector(sOverrides.multiPagerAdapterInjector);
        return multiProfilePagerAdapter;
    }

    ResolverWrapperAdapter getAdapter() {
        return (ResolverWrapperAdapter) mMultiProfilePagerAdapter.getActiveListAdapter();
    }
@@ -124,6 +133,9 @@ public class ResolverWrapperActivity extends ResolverActivity {
        public ResolverListController workResolverListController;
        public Boolean isVoiceInteraction;
        public UserHandle workProfileUserHandle;
        public boolean hasCrossProfileIntents;
        public boolean isQuietModeEnabled;
        public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;

        public void reset() {
            onSafelyStartCallback = null;
@@ -132,6 +144,26 @@ public class ResolverWrapperActivity extends ResolverActivity {
            resolverListController = mock(ResolverListController.class);
            workResolverListController = mock(ResolverListController.class);
            workProfileUserHandle = null;
            hasCrossProfileIntents = true;
            isQuietModeEnabled = false;
            multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
                @Override
                public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
                        int targetUserId) {
                    return hasCrossProfileIntents;
                }

                @Override
                public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
                    return isQuietModeEnabled;
                }

                @Override
                public void requestQuietModeEnabled(boolean enabled,
                        UserHandle workProfileUserHandle) {
                    isQuietModeEnabled = enabled;
                }
            };
        }
    }
}
 No newline at end of file