summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kelvin Kwan <kelvinkwan@google.com> 2020-02-13 15:22:38 +0000
committer Kelvin Kwan <kelvinkwan@google.com> 2020-02-13 15:22:38 +0000
commit1b9f85bf2d070007fbc8f7a04f1928219e860bf1 (patch)
treed5f724f0f0baabd2d8c24364c3b22d133a5e9aba
parent5ab79aaae4cb86a538190302339c50cb5075579d (diff)
Add TabLayout UI to on BaseActivity and show it conditionally
There will be a new tablayout UI added to PickActivity on device with managed user. Tapping on the UI does nothing at the moment. Test: atest DocumentsUIGoogleTests:com.android.documentsui.ProfileTabsTest Bug: 148264331 Change-Id: I727b28dbae7fac59a3da9da7f16ae7c3608a1a0f
-rw-r--r--res/layout/directory_header.xml6
-rw-r--r--res/values/strings.xml6
-rw-r--r--src/com/android/documentsui/BaseActivity.java13
-rw-r--r--src/com/android/documentsui/NavigationViewManager.java10
-rw-r--r--src/com/android/documentsui/ProfileTabs.java106
-rw-r--r--src/com/android/documentsui/UserIdManager.java76
-rw-r--r--src/com/android/documentsui/base/RootInfo.java11
-rw-r--r--tests/unit/com/android/documentsui/ProfileTabsTest.java258
-rw-r--r--tests/unit/com/android/documentsui/UserIdManagerTest.java36
9 files changed, 514 insertions, 8 deletions
diff --git a/res/layout/directory_header.xml b/res/layout/directory_header.xml
index 41088c137..45abeb8ba 100644
--- a/res/layout/directory_header.xml
+++ b/res/layout/directory_header.xml
@@ -28,6 +28,12 @@
<!-- used for search chip. -->
<include layout="@layout/search_chip_row"/>
+ <com.google.android.material.tabs.TabLayout
+ android:id="@+id/tabs"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"/>
+
<!-- used for apps row. -->
<include layout="@layout/apps_row"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 07410a432..7c719e644 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -483,4 +483,10 @@
<!-- Content description for deleting search history. [CHAR_LIMIT=60] -->
<string name="delete_search_history">Delete search history <xliff:g id="text" example="image">%1$s</xliff:g></string>
+
+ <!-- Label of tab to indicate personal directory [CHAR LIMIT=40] -->
+ <string name="personal_tab">Personal</string>
+
+ <!-- Label of tab to indicate work directory [CHAR LIMIT=40] -->
+ <string name="work_tab">Work</string>
</resources>
diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java
index a44cec513..afa141317 100644
--- a/src/com/android/documentsui/BaseActivity.java
+++ b/src/com/android/documentsui/BaseActivity.java
@@ -75,6 +75,7 @@ import com.android.documentsui.sorting.SortController;
import com.android.documentsui.sorting.SortModel;
import com.google.android.material.appbar.AppBarLayout;
+import com.google.android.material.tabs.TabLayout;
import java.util.ArrayList;
import java.util.Date;
@@ -95,7 +96,6 @@ public abstract class BaseActivity
protected Injector<?> mInjector;
protected ProvidersCache mProviders;
- protected UserIdManager mUserIdManager;
protected DocumentsAccess mDocs;
protected DrawerController mDrawer;
@@ -153,7 +153,6 @@ public abstract class BaseActivity
mDrawer = DrawerController.create(this, mInjector.config);
Metrics.logActivityLaunch(mState, intent);
- mUserIdManager = DocumentsApplication.getUserIdManager(this);
mProviders = DocumentsApplication.getProvidersCache(this);
mDocs = DocumentsAccess.create(this);
@@ -162,8 +161,11 @@ public abstract class BaseActivity
Breadcrumb breadcrumb = findViewById(R.id.horizontal_breadcrumb);
assert(breadcrumb != null);
+ TabLayout profileTabs = findViewById(R.id.tabs);
+ assert (profileTabs != null);
- mNavigator = new NavigationViewManager(this, mDrawer, mState, this, breadcrumb);
+ mNavigator = new NavigationViewManager(this, mDrawer, mState, this, breadcrumb,
+ profileTabs, DocumentsApplication.getUserIdManager(this));
SearchManagerListener searchListener = new SearchManagerListener() {
/**
* Called when search results changed. Refreshes the content of the directory. It
@@ -739,6 +741,11 @@ public abstract class BaseActivity
}
@Override
+ public boolean isSearching() {
+ return mSearchManager.isSearching();
+ }
+
+ @Override
public RootInfo getCurrentRoot() {
RootInfo root = mState.stack.getRoot();
if (root != null) {
diff --git a/src/com/android/documentsui/NavigationViewManager.java b/src/com/android/documentsui/NavigationViewManager.java
index d07851238..aca8c31b5 100644
--- a/src/com/android/documentsui/NavigationViewManager.java
+++ b/src/com/android/documentsui/NavigationViewManager.java
@@ -29,13 +29,13 @@ import android.view.ViewOutlineProvider;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
-import com.android.documentsui.R;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.dirlist.AnimationView;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.CollapsingToolbarLayout;
+import com.google.android.material.tabs.TabLayout;
import java.util.function.IntConsumer;
@@ -51,6 +51,7 @@ public class NavigationViewManager {
private final State mState;
private final NavigationViewManager.Environment mEnv;
private final Breadcrumb mBreadcrumb;
+ private final ProfileTabs mProfileTabs;
private final View mSearchBarView;
private final CollapsingToolbarLayout mCollapsingBarLayout;
private final Drawable mDefaultActionBarBackground;
@@ -62,7 +63,9 @@ public class NavigationViewManager {
DrawerController drawer,
State state,
NavigationViewManager.Environment env,
- Breadcrumb breadcrumb) {
+ Breadcrumb breadcrumb,
+ TabLayout tabLayout,
+ UserIdManager userIdManager) {
mToolbar = activity.findViewById(R.id.toolbar);
mDrawer = drawer;
@@ -70,6 +73,7 @@ public class NavigationViewManager {
mEnv = env;
mBreadcrumb = breadcrumb;
mBreadcrumb.setup(env, state, this::onNavigationItemSelected);
+ mProfileTabs = new ProfileTabs(tabLayout, mState, userIdManager, mEnv);
mToolbar.setNavigationOnClickListener(
new View.OnClickListener() {
@@ -122,6 +126,7 @@ public class NavigationViewManager {
public void update() {
updateScrollFlag();
updateToolbar();
+ mProfileTabs.updateView();
// TODO: Looks to me like this block is never getting hit.
if (mEnv.isSearchExpanded()) {
@@ -214,5 +219,6 @@ public class NavigationViewManager {
@Deprecated // Use CommonAddones#refreshCurrentRootAndDirectory
void refreshCurrentRootAndDirectory(int animation);
boolean isSearchExpanded();
+ boolean isSearching();
}
}
diff --git a/src/com/android/documentsui/ProfileTabs.java b/src/com/android/documentsui/ProfileTabs.java
new file mode 100644
index 000000000..24a36b2b7
--- /dev/null
+++ b/src/com/android/documentsui/ProfileTabs.java
@@ -0,0 +1,106 @@
+/*
+ * 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;
+
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.documentsui.base.State;
+import com.android.documentsui.base.UserId;
+
+import com.google.android.material.tabs.TabLayout;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A manager class to control UI on a {@link TabLayout} for cross-profile purpose.
+ */
+public class ProfileTabs {
+
+ private final TabLayout mTabs;
+ private final State mState;
+ private final NavigationViewManager.Environment mEnv;
+ private final UserIdManager mUserIdManager;
+ private List<UserId> mUserIds;
+
+ public ProfileTabs(TabLayout tabLayout, State state, UserIdManager userIdManager,
+ NavigationViewManager.Environment env) {
+ mTabs = checkNotNull(tabLayout);
+ mState = checkNotNull(state);
+ mEnv = checkNotNull(env);
+ mUserIdManager = checkNotNull(userIdManager);
+ mTabs.removeAllTabs();
+ mUserIds = Collections.singletonList(UserId.CURRENT_USER);
+ }
+
+ /**
+ * Update the tab layout based on conditions.
+ */
+ public void updateView() {
+ updateTabsIfNeeded();
+ mTabs.setVisibility(shouldShow() ? View.VISIBLE : View.GONE);
+ }
+
+ private void updateTabsIfNeeded() {
+ List<UserId> userIds = mUserIdManager.getUserIds();
+ // Add tabs if the userIds is not equals to cached mUserIds.
+ // Given that mUserIds was initialized with only the current user, if getUserIds()
+ // returns just the current user, we don't need to do anything on the tab layout.
+ if (!userIds.equals(mUserIds)) {
+ mUserIds = userIds;
+ mTabs.removeAllTabs();
+ if (mUserIds.size() > 1) {
+ mTabs.addTab(createTab(R.string.personal_tab, mUserIdManager.getSystemUser()));
+ mTabs.addTab(createTab(R.string.work_tab, mUserIdManager.getManagedUser()));
+ }
+ }
+ }
+
+ /**
+ * Returns the user represented by the selected tab. If there is no tab, return the
+ * current user.
+ */
+ @VisibleForTesting
+ public UserId getSelectedUser() {
+ if (mTabs.getTabCount() > 1 && mTabs.getSelectedTabPosition() >= 0) {
+ return (UserId) mTabs.getTabAt(mTabs.getSelectedTabPosition()).getTag();
+ }
+ return UserId.CURRENT_USER;
+ }
+
+ private boolean shouldShow() {
+ // Only show tabs when:
+ // 1. state supports cross profile, and
+ // 2. more than one tab, and
+ // 3. not in search mode, and
+ // 4. not in sub-folder, and
+ // 5. the root supports cross profile.
+ return mState.supportsCrossProfile()
+ && mTabs.getTabCount() > 1
+ && !mEnv.isSearching()
+ && mState.stack.size() <= 1
+ && mState.stack.getRoot() != null && mState.stack.getRoot().supportsCrossProfile();
+ }
+
+ private TabLayout.Tab createTab(int resId, UserId userId) {
+ return mTabs.newTab().setText(resId).setTag(userId);
+ }
+}
diff --git a/src/com/android/documentsui/UserIdManager.java b/src/com/android/documentsui/UserIdManager.java
index d489712af..03fb73309 100644
--- a/src/com/android/documentsui/UserIdManager.java
+++ b/src/com/android/documentsui/UserIdManager.java
@@ -21,13 +21,17 @@ import static androidx.core.util.Preconditions.checkNotNull;
import static com.android.documentsui.base.SharedMinimal.DEBUG;
import android.Manifest;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import androidx.annotation.GuardedBy;
import androidx.annotation.VisibleForTesting;
import androidx.core.os.BuildCompat;
@@ -36,19 +40,30 @@ import com.android.documentsui.base.UserId;
import java.util.ArrayList;
import java.util.List;
-
/**
* Interface to query user ids.
*/
public interface UserIdManager {
/**
- * Returns the {@UserId} of each profile which should be queried for documents. This
- * will always include {@link UserId#CURRENT_USER}.
+ * Returns the {@UserId} of each profile which should be queried for documents. This will always
+ * include {@link UserId#CURRENT_USER}.
*/
List<UserId> getUserIds();
/**
+ * Returns the system user from {@link #getUserIds()} if the list at least 2 users. Otherwise,
+ * returns null.
+ */
+ UserId getSystemUser();
+
+ /**
+ * Returns the managed user from {@link #getUserIds()} if the list at least 2 users. Otherwise,
+ * returns null.
+ */
+ UserId getManagedUser();
+
+ /**
* Creates an implementation of {@link UserIdManager}.
*/
static UserIdManager create(Context context) {
@@ -68,6 +83,23 @@ public interface UserIdManager {
private final UserId mCurrentUser;
private final boolean mIsDeviceSupported;
+ @GuardedBy("mUserIds")
+ private final List<UserId> mUserIds = new ArrayList<>();
+ @GuardedBy("mUserIds")
+ private UserId mSystemUser = null;
+ @GuardedBy("mUserIds")
+ private UserId mManagedUser = null;
+
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mUserIds) {
+ mUserIds.clear();
+ }
+ }
+ };
+
private RuntimeUserIdManager(Context context) {
this(context, UserId.CURRENT_USER,
ENABLE_MULTI_PROFILES && isDeviceSupported(context));
@@ -78,10 +110,45 @@ public interface UserIdManager {
mContext = context.getApplicationContext();
mCurrentUser = checkNotNull(currentUser);
mIsDeviceSupported = isDeviceSupported;
+
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_ADDED);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(mIntentReceiver, filter);
}
@Override
public List<UserId> getUserIds() {
+ synchronized (mUserIds) {
+ if (mUserIds.isEmpty()) {
+ mUserIds.addAll(getUserIdsInternal());
+ }
+ }
+ return mUserIds;
+ }
+
+ @Override
+ public UserId getSystemUser() {
+ synchronized (mUserIds) {
+ if (mUserIds.isEmpty()) {
+ getUserIds();
+ }
+ }
+ return mSystemUser;
+ }
+
+ @Override
+ public UserId getManagedUser() {
+ synchronized (mUserIds) {
+ if (mUserIds.isEmpty()) {
+ getUserIds();
+ }
+ }
+ return mManagedUser;
+ }
+
+ public List<UserId> getUserIdsInternal() {
final List<UserId> result = new ArrayList<>();
result.add(mCurrentUser);
@@ -103,6 +170,7 @@ public interface UserIdManager {
UserId systemUser = null;
UserId managedUser = null;
+
for (UserHandle userHandle : userProfiles) {
if (userHandle.isSystem()) {
systemUser = UserId.of(userHandle);
@@ -136,6 +204,8 @@ public interface UserIdManager {
+ (systemUser != null));
}
}
+ mSystemUser = systemUser;
+ mManagedUser = managedUser;
return result;
}
diff --git a/src/com/android/documentsui/base/RootInfo.java b/src/com/android/documentsui/base/RootInfo.java
index 0f9dabcf6..4f0123578 100644
--- a/src/com/android/documentsui/base/RootInfo.java
+++ b/src/com/android/documentsui/base/RootInfo.java
@@ -327,6 +327,10 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
|| derivedType == TYPE_SD;
}
+ public boolean isPhoneStorage() {
+ return derivedType == TYPE_LOCAL;
+ }
+
public boolean hasSettings() {
return (flags & Root.FLAG_HAS_SETTINGS) != 0;
}
@@ -375,6 +379,13 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
return (flags & Root.FLAG_REMOVABLE_USB) != 0;
}
+ /**
+ * Returns true if this root supports cross profile.
+ */
+ public boolean supportsCrossProfile() {
+ return isLibrary() || isDownloads() || isPhoneStorage();
+ }
+
private Drawable loadMimeTypeIcon(Context context) {
switch (derivedType) {
case TYPE_IMAGES:
diff --git a/tests/unit/com/android/documentsui/ProfileTabsTest.java b/tests/unit/com/android/documentsui/ProfileTabsTest.java
new file mode 100644
index 000000000..dc8f0f9cb
--- /dev/null
+++ b/tests/unit/com/android/documentsui/ProfileTabsTest.java
@@ -0,0 +1,258 @@
+/*
+ * 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.documentsui.base.RootInfo;
+import com.android.documentsui.base.State;
+import com.android.documentsui.base.UserId;
+import com.android.documentsui.testing.TestEnv;
+import com.android.documentsui.testing.TestProvidersAccess;
+
+import com.google.android.collect.Lists;
+import com.google.android.material.tabs.TabLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ProfileTabsTest {
+
+ private final UserId systemUser = UserId.of(UserHandle.SYSTEM);
+ private final UserId managedUser = UserId.of(100);
+
+ private ProfileTabs mProfileTabs;
+
+ private Context mContext;
+ private TabLayout mTabLayout;
+ private TestEnvironment mTestEnv;
+ private State mState;
+ private TestUserIdManager mTestUserIdManager;
+
+ @Before
+ public void setUp() {
+ TestEnv.create();
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mContext.setTheme(R.style.DocumentsTheme);
+ mContext.getTheme().applyStyle(R.style.DocumentsDefaultTheme, false);
+ LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ mState = new State();
+ mState.action = State.ACTION_GET_CONTENT;
+ mState.stack.changeRoot(TestProvidersAccess.DOWNLOADS);
+ mState.stack.push(TestEnv.FOLDER_0);
+ View view = layoutInflater.inflate(R.layout.directory_header, null);
+
+ mTabLayout = view.findViewById(R.id.tabs);
+ mTestEnv = new TestEnvironment();
+ mTestEnv.isSearching = false;
+
+ mTestUserIdManager = new TestUserIdManager();
+ }
+
+ @Test
+ public void testUpdateView_singleUser_shouldHide() {
+ initializeWithUsers(systemUser);
+
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_shouldShow() {
+ initializeWithUsers(systemUser, managedUser);
+
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(2);
+
+ TabLayout.Tab tab1 = mTabLayout.getTabAt(0);
+ assertThat(tab1.getTag()).isEqualTo(systemUser);
+ assertThat(tab1.getText()).isEqualTo(mContext.getString(R.string.personal_tab));
+
+ TabLayout.Tab tab2 = mTabLayout.getTabAt(1);
+ assertThat(tab2.getTag()).isEqualTo(managedUser);
+ assertThat(tab2.getText()).isEqualTo(mContext.getString(R.string.work_tab));
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_browse_shouldHide() {
+ initializeWithUsers(systemUser, managedUser);
+
+ mState.action = State.ACTION_BROWSE;
+ mProfileTabs.updateView();
+
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_subFolder_shouldHide() {
+ initializeWithUsers(systemUser, managedUser);
+
+ // Push 1 more folder. Now the stack has size of 2.
+ mState.stack.push(TestEnv.FOLDER_1);
+
+ mProfileTabs.updateView();
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_recents_subFolder_shouldHide() {
+ initializeWithUsers(systemUser, managedUser);
+
+ mState.stack.changeRoot(TestProvidersAccess.RECENTS);
+ // This(stack of size 2 in Recents) may not happen in real world.
+ mState.stack.push((TestEnv.FOLDER_0));
+
+ mProfileTabs.updateView();
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_thirdParty_shouldHide() {
+ initializeWithUsers(systemUser, managedUser);
+
+ mState.stack.changeRoot(TestProvidersAccess.PICKLES);
+ mState.stack.push((TestEnv.FOLDER_0));
+
+ mProfileTabs.updateView();
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testUpdateView_twoUsers_isSearching_shouldHide() {
+ mTestEnv.isSearching = true;
+ initializeWithUsers(systemUser, managedUser);
+
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mTabLayout.getTabCount()).isEqualTo(2);
+ }
+
+ @Test
+ public void testUpdateView_getSelectedUser_afterUsersChanged() {
+ initializeWithUsers(systemUser, managedUser);
+ mProfileTabs.updateView();
+ mTabLayout.selectTab(mTabLayout.getTabAt(1));
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mProfileTabs.getSelectedUser()).isEqualTo(managedUser);
+
+ mTestUserIdManager.userIds = Collections.singletonList(systemUser);
+ mProfileTabs.updateView();
+ assertThat(mTabLayout.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser);
+ }
+
+ @Test
+ public void testgetSelectedUser_twoUsers() {
+ initializeWithUsers(systemUser, managedUser);
+
+ mTabLayout.selectTab(mTabLayout.getTabAt(0));
+ assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser);
+
+ mTabLayout.selectTab(mTabLayout.getTabAt(1));
+ assertThat(mProfileTabs.getSelectedUser()).isEqualTo(managedUser);
+ }
+
+ @Test
+ public void testgetSelectedUser_singleUsers() {
+ initializeWithUsers(systemUser);
+
+ assertThat(mProfileTabs.getSelectedUser()).isEqualTo(systemUser);
+ }
+
+ private void initializeWithUsers(UserId... userIds) {
+ mTestUserIdManager.userIds = Lists.newArrayList(userIds);
+ for (UserId userId : userIds) {
+ if (userId.isSystem()) {
+ mTestUserIdManager.systemUser = userId;
+ } else {
+ mTestUserIdManager.managedUser = userId;
+ }
+ }
+
+ mProfileTabs = new ProfileTabs(mTabLayout, mState, mTestUserIdManager, mTestEnv);
+ mProfileTabs.updateView();
+ }
+
+ /**
+ * A test implementation of {@link NavigationViewManager.Environment}.
+ */
+ private static class TestEnvironment implements NavigationViewManager.Environment {
+
+ public boolean isSearching = false;
+
+ @Override
+ public RootInfo getCurrentRoot() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public String getDrawerTitle() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public void refreshCurrentRootAndDirectory(int animation) {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public boolean isSearchExpanded() {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ @Override
+ public boolean isSearching() {
+ return isSearching;
+ }
+
+ }
+
+ private static class TestUserIdManager implements UserIdManager {
+ List<UserId> userIds = new ArrayList<>();
+ UserId systemUser = null;
+ UserId managedUser = null;
+
+ @Override
+ public List<UserId> getUserIds() {
+ return userIds;
+ }
+
+ @Override
+ public UserId getSystemUser() {
+ return systemUser;
+ }
+
+ @Override
+ public UserId getManagedUser() {
+ return managedUser;
+ }
+ }
+}
+
diff --git a/tests/unit/com/android/documentsui/UserIdManagerTest.java b/tests/unit/com/android/documentsui/UserIdManagerTest.java
index 78337a7e2..1ca3c5b50 100644
--- a/tests/unit/com/android/documentsui/UserIdManagerTest.java
+++ b/tests/unit/com/android/documentsui/UserIdManagerTest.java
@@ -154,6 +154,42 @@ public class UserIdManagerTest {
}
}
+ @Test
+ public void testGetUserIds_systemUserAndManagedUser_returnCachedList() {
+ // Returns the both if there are system and managed users.
+ UserId currentUser = UserId.of(systemUser);
+ initializeUserIdManager(currentUser, Arrays.asList(systemUser, managedUser1));
+ assertThat(mUserIdManager.getUserIds()).isSameAs(mUserIdManager.getUserIds());
+ }
+
+ @Test
+ public void testGetManagedUser_contains() {
+ UserId currentUser = UserId.of(systemUser);
+ initializeUserIdManager(currentUser, Arrays.asList(systemUser, managedUser1));
+ assertThat(mUserIdManager.getManagedUser()).isEqualTo(UserId.of(managedUser1));
+ }
+
+ @Test
+ public void testGetSystemUser_contains() {
+ UserId currentUser = UserId.of(systemUser);
+ initializeUserIdManager(currentUser, Arrays.asList(systemUser, managedUser1));
+ assertThat(mUserIdManager.getSystemUser()).isEqualTo(UserId.of(systemUser));
+ }
+
+ @Test
+ public void testGetSystemUser_singletonList_returnNull() {
+ UserId currentUser = UserId.of(systemUser);
+ initializeUserIdManager(currentUser, Arrays.asList(systemUser));
+ assertThat(mUserIdManager.getSystemUser()).isNull();
+ }
+
+ @Test
+ public void testGetManagedUser_missing() {
+ UserId currentUser = UserId.of(systemUser);
+ initializeUserIdManager(currentUser, Arrays.asList(systemUser, nonManagedUser1));
+ assertThat(mUserIdManager.getManagedUser()).isNull();
+ }
+
private void initializeUserIdManager(UserId current, List<UserHandle> usersOnDevice) {
when(mockUserManager.getUserProfiles()).thenReturn(usersOnDevice);
mUserIdManager = new UserIdManager.RuntimeUserIdManager(mockContext, current, true);