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

Commit 2b6f7f58 authored by Kelvin Kwan's avatar Kelvin Kwan Committed by Android (Google) Code Review
Browse files

Merge "Fix not showing Personal providers if there is no work providers." into rvc-dev

parents 69be2f28 a1b31681
Loading
Loading
Loading
Loading
+14 −32
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
@@ -272,6 +273,7 @@ public class RootsFragment extends Fragment {
                }

                List<Item> sortedItems = sortLoadResult(
                        getResources(),
                        state,
                        roots,
                        excludePackage,
@@ -345,6 +347,7 @@ public class RootsFragment extends Fragment {
     */
    @VisibleForTesting
    List<Item> sortLoadResult(
            Resources resources,
            State state,
            Collection<RootInfo> roots,
            @Nullable String excludePackage,
@@ -396,7 +399,6 @@ public class RootsFragment extends Fragment {
        if (VERBOSE) Log.v(TAG, "Adding storage roots: " + storageProviders);
        result.addAll(storageProviders);


        final List<Item> rootList = new ArrayList<>();
        final List<Item> rootListOtherUser = new ArrayList<>();
        mApplicationItemList = new ArrayList<>();
@@ -416,31 +418,19 @@ public class RootsFragment extends Fragment {
            }
        }


        if (state.supportsCrossProfile() && state.canShareAcrossProfile
                && !rootList.isEmpty() && !rootListOtherUser.isEmpty()) {
            // Identify personal and work root list.
            final List<Item> personalRootList;
            final List<Item> workRootList;
            if (UserId.CURRENT_USER.isSystem()) {
                personalRootList = rootList;
                workRootList = rootListOtherUser;
            } else {
                personalRootList = rootListOtherUser;
                workRootList = rootList;
        List<Item> presentableList = new UserItemsCombiner(resources, state)
                .setRootListForCurrentUser(rootList)
                .setRootListForOtherUser(rootListOtherUser)
                .createPresentableList();
        addListToResult(result, presentableList);
        return result;
    }

            // Add header and list to the result
            final List<Item> resultRootList = new ArrayList<>();
            resultRootList.add(new HeaderItem(getString(R.string.personal_tab)));
            resultRootList.addAll(personalRootList);
            resultRootList.add(new HeaderItem(getString(R.string.work_tab)));
            resultRootList.addAll(workRootList);
            addListToResult(result, resultRootList);
        } else {
            addListToResult(result, rootList);
    private void addListToResult(List<Item> result, List<Item> rootList) {
        if (!result.isEmpty() && !rootList.isEmpty()) {
            result.add(new SpacerItem());
        }
        return result;
        result.addAll(rootList);
    }

    /**
@@ -534,14 +524,6 @@ public class RootsFragment extends Fragment {
        }
    }

    private void addListToResult(List<Item> result, List<Item> rootList) {
        if (!result.isEmpty() && !rootList.isEmpty()) {
            result.add(new SpacerItem());
        }

        result.addAll(rootList);
    }

    @Override
    public void onResume() {
        super.onResume();
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui.sidebar;

import android.content.res.Resources;

import static androidx.core.util.Preconditions.checkArgument;
import static androidx.core.util.Preconditions.checkNotNull;

import androidx.annotation.VisibleForTesting;

import com.android.documentsui.R;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;

import java.util.ArrayList;
import java.util.List;

/**
 * Converts user-specific lists of items into a single merged list appropriate for displaying in the
 * UI, including the relevant headers.
 */
class UserItemsCombiner {

    private UserId mCurrentUser;
    private final Resources mResources;
    private final State mState;
    private List<Item> mRootList;
    private List<Item> mRootListOtherUser;

    UserItemsCombiner(Resources resources, State state) {
        mCurrentUser = UserId.CURRENT_USER;
        mResources = checkNotNull(resources);
        mState = checkNotNull(state);
    }

    @VisibleForTesting
    UserItemsCombiner overrideCurrentUserForTest(UserId userId) {
        mCurrentUser = checkNotNull(userId);
        return this;
    }

    UserItemsCombiner setRootListForCurrentUser(List<Item> rootList) {
        mRootList = checkNotNull(rootList);
        return this;
    }

    UserItemsCombiner setRootListForOtherUser(List<Item> rootList) {
        mRootListOtherUser = checkNotNull(rootList);
        return this;
    }

    /**
     * Returns a combined lists from the provided lists. {@link HeaderItem}s indicating profile
     * will be added if the list of current user and the other user are not empty.
     */
    public List<Item> createPresentableList() {
        checkArgument(mRootList != null, "RootListForCurrentUser is not set");
        checkArgument(mRootListOtherUser != null, "setRootListForOtherUser is not set");

        final List<Item> result = new ArrayList<>();
        if (mState.supportsCrossProfile() && mState.canShareAcrossProfile) {
            if (!mRootList.isEmpty() && !mRootListOtherUser.isEmpty()) {
                // Identify personal and work root list.
                final List<Item> personalRootList;
                final List<Item> workRootList;
                if (mCurrentUser.isSystem()) {
                    personalRootList = mRootList;
                    workRootList = mRootListOtherUser;
                } else {
                    personalRootList = mRootListOtherUser;
                    workRootList = mRootList;
                }
                result.add(new HeaderItem(mResources.getString(R.string.personal_tab)));
                result.addAll(personalRootList);
                result.add(new HeaderItem(mResources.getString(R.string.work_tab)));
                result.addAll(workRootList);
            } else {
                result.addAll(mRootList);
                result.addAll(mRootListOtherUser);
            }
        } else {
            result.addAll(mRootList);
        }
        return result;
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertEquals;
import android.content.pm.ResolveInfo;

import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.documentsui.base.RootInfo;
@@ -70,6 +71,7 @@ public class RootsFragmentTest {
    @Test
    public void testSortLoadResult_WithCorrectOrder() {
        List<Item> items = mRootsFragment.sortLoadResult(
                InstrumentationRegistry.getInstrumentation().getTargetContext().getResources(),
                new State(),
                createFakeRootInfoList(),
                null /* excludePackage */, null /* handlerAppIntent */, new TestProvidersAccess(),
+235 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.documentsui.sidebar;

import static com.google.common.truth.Truth.assertThat;

import android.content.res.Resources;
import android.view.View;

import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.documentsui.R;
import com.android.documentsui.base.State;
import com.android.documentsui.base.UserId;
import com.android.documentsui.testing.TestProvidersAccess;

import com.google.common.collect.Lists;
import com.google.common.truth.Correspondence;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * A unit test for {@link UserItemsCombiner}.
 */
@RunWith(AndroidJUnit4.class)
@MediumTest
public class UserItemsCombinerTest {
    private static final UserId PERSONAL_USER = TestProvidersAccess.USER_ID;
    private static final UserId WORK_USER = TestProvidersAccess.OtherUser.USER_ID;

    private static final List<Item> PERSONAL_ITEMS = Lists.newArrayList(
            personalItem("personal 1"),
            personalItem("personal 2"),
            personalItem("personal 3")
    );

    private static final List<Item> WORK_ITEMS = Lists.newArrayList(
            workItem("work 1")
    );

    private static final Correspondence<Item, Item> ITEM_CORRESPONDENCE =
            new Correspondence<Item, Item>() {
                @Override
                public boolean compare(Item actual, Item expected) {
                    return Objects.equals(actual.title, expected.title)
                            && Objects.equals(actual.userId, expected.userId);
                }

                @Override
                public String toString() {
                    return "has same title and userId as in";
                }
            };

    private final State mState = new State();
    private final Resources mResources =
            InstrumentationRegistry.getInstrumentation().getTargetContext().getResources();
    private UserItemsCombiner mCombiner;

    @Before
    public void setUp() {
        mState.canShareAcrossProfile = true;
        mState.supportsCrossProfile = true;
    }

    @Test
    public void testCreatePresentableList_empty() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .setRootListForCurrentUser(Collections.emptyList())
                .setRootListForOtherUser(Collections.emptyList());
        assertThat(mCombiner.createPresentableList()).isEmpty();
    }

    @Test
    public void testCreatePresentableList_currentIsPersonal_personalItemsOnly() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .setRootListForCurrentUser(PERSONAL_ITEMS)
                .setRootListForOtherUser(Collections.emptyList());
        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(PERSONAL_ITEMS)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsWork_personalItemsOnly() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .overrideCurrentUserForTest(WORK_USER)
                .setRootListForCurrentUser(Collections.emptyList())
                .setRootListForOtherUser(PERSONAL_ITEMS);
        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(PERSONAL_ITEMS)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsPersonal_workItemsOnly() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .setRootListForCurrentUser(Collections.emptyList())
                .setRootListForOtherUser(WORK_ITEMS);
        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(WORK_ITEMS)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsWork_workItemsOnly() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .overrideCurrentUserForTest(WORK_USER)
                .setRootListForCurrentUser(WORK_ITEMS)
                .setRootListForOtherUser(Collections.emptyList());
        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(WORK_ITEMS)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsPersonal_personalAndWorkItems() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .setRootListForCurrentUser(PERSONAL_ITEMS)
                .setRootListForOtherUser(WORK_ITEMS);

        List<Item> expected = Lists.newArrayList();
        expected.add(new HeaderItem(mResources.getString(R.string.personal_tab)));
        expected.addAll(PERSONAL_ITEMS);
        expected.add(new HeaderItem(mResources.getString(R.string.work_tab)));
        expected.addAll(WORK_ITEMS);

        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(expected)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsWork_personalAndWorkItems() {
        mCombiner = new UserItemsCombiner(mResources, mState)
                .overrideCurrentUserForTest(WORK_USER)
                .setRootListForCurrentUser(WORK_ITEMS)
                .setRootListForOtherUser(PERSONAL_ITEMS);

        List<Item> expected = Lists.newArrayList();
        expected.add(new HeaderItem(mResources.getString(R.string.personal_tab)));
        expected.addAll(PERSONAL_ITEMS);
        expected.add(new HeaderItem(mResources.getString(R.string.work_tab)));
        expected.addAll(WORK_ITEMS);

        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(expected)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsPersonal_personalAndWorkItems_cannotShare() {
        mState.canShareAcrossProfile = false;
        mCombiner = new UserItemsCombiner(mResources, mState)
                .setRootListForCurrentUser(PERSONAL_ITEMS)
                .setRootListForOtherUser(WORK_ITEMS);

        assertThat(mCombiner.createPresentableList())
                .comparingElementsUsing(ITEM_CORRESPONDENCE)
                .containsExactlyElementsIn(PERSONAL_ITEMS)
                .inOrder();
    }

    @Test
    public void testCreatePresentableList_currentIsWork_personalItemsOnly_cannotShare() {
        mState.canShareAcrossProfile = false;
        mCombiner = new UserItemsCombiner(mResources, mState)
                .overrideCurrentUserForTest(WORK_USER)
                .setRootListForCurrentUser(Collections.emptyList())
                .setRootListForOtherUser(PERSONAL_ITEMS);

        assertThat(mCombiner.createPresentableList()).isEmpty();
    }

    private static TestItem personalItem(String title) {
        return new TestItem(title, PERSONAL_USER);
    }

    private static TestItem workItem(String title) {
        return new TestItem(title, WORK_USER);
    }

    private static class TestItem extends Item {

        TestItem(String title, UserId userId) {
            super(/* layoutId= */ 0, title, /* stringId= */ "", userId);
        }

        @Override
        void bindView(View convertView) {
        }

        @Override
        boolean isRoot() {
            return false;
        }

        @Override
        void open() {
        }

        @Override
        public String toString() {
            return title + "(" + userId + ")";
        }
    }
}