diff options
author | 2020-02-13 15:22:38 +0000 | |
---|---|---|
committer | 2020-02-13 15:22:38 +0000 | |
commit | 1b9f85bf2d070007fbc8f7a04f1928219e860bf1 (patch) | |
tree | d5f724f0f0baabd2d8c24364c3b22d133a5e9aba | |
parent | 5ab79aaae4cb86a538190302339c50cb5075579d (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.xml | 6 | ||||
-rw-r--r-- | res/values/strings.xml | 6 | ||||
-rw-r--r-- | src/com/android/documentsui/BaseActivity.java | 13 | ||||
-rw-r--r-- | src/com/android/documentsui/NavigationViewManager.java | 10 | ||||
-rw-r--r-- | src/com/android/documentsui/ProfileTabs.java | 106 | ||||
-rw-r--r-- | src/com/android/documentsui/UserIdManager.java | 76 | ||||
-rw-r--r-- | src/com/android/documentsui/base/RootInfo.java | 11 | ||||
-rw-r--r-- | tests/unit/com/android/documentsui/ProfileTabsTest.java | 258 | ||||
-rw-r--r-- | tests/unit/com/android/documentsui/UserIdManagerTest.java | 36 |
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); |