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

Commit d5f27a5f authored by Aditya's avatar Aditya
Browse files

Introducing private tab in profile tabs and sidebar.

Updated ProfileTabs.java to user UserManagerState to get list of userIds
for which the tabs have to created, when the feature flag for private
space is enabled. RootsFragment and other associated classes have also
been updated to display private profile (or any other new profile)
section in the sidebar.

Bug: 309754864
Test: atest unit tests and manual testing
Change-Id: I130cda26346f7df81fabbb9c9f1ba92b1b859929
Merged-In: I130cda26346f7df81fabbb9c9f1ba92b1b859929
parent b1a45a54
Loading
Loading
Loading
Loading
+29 −17
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA
    public void registerDisplayStateChangedListener(Runnable l) {
        mDisplayStateChangedListener = l;
    }

    @Override
    public void unregisterDisplayStateChangedListener(Runnable l) {
        if (mDisplayStateChangedListener == l) {
@@ -372,6 +373,7 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA
    }

    // TODO: Make this private and make tests call interface method instead.

    /**
     * Behavior when a document is opened.
     */
@@ -974,24 +976,34 @@ public abstract class AbstractActionHandler<T extends FragmentActivity & CommonA
            mLoaderSemaphore.release();
        }
    }

    /**
     * A class primarily for the support of isolating our tests
     * from our concrete activity implementations.
     */
    public interface CommonAddons {
        void restoreRootAndDirectory();

        void refreshCurrentRootAndDirectory(@AnimationType int anim);

        void onRootPicked(RootInfo root);

        // TODO: Move this to PickAddons as multi-document picking is exclusive to that activity.
        void onDocumentsPicked(List<DocumentInfo> docs);

        void onDocumentPicked(DocumentInfo doc);

        RootInfo getCurrentRoot();

        DocumentInfo getCurrentDirectory();

        UserId getSelectedUser();

        /**
         * Check whether current directory is root of recent.
         */
        boolean isInRecents();

        void setRootsDrawerOpen(boolean open);

        /**
+40 −11
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.documentsui.DevicePolicyResources.Strings.WORK_TAB;

import android.app.admin.DevicePolicyManager;
import android.os.Build;
import android.os.UserManager;
import android.view.View;
import android.view.ViewGroup;

@@ -38,8 +39,10 @@ import com.android.modules.utils.build.SdkLevel;
import com.google.android.material.tabs.TabLayout;
import com.google.common.base.Objects;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * A manager class to control UI on a {@link TabLayout} for cross-profile purpose.
@@ -114,7 +117,7 @@ public class ProfileTabs implements ProfileTabsAddons {
    }

    /**
     * Update the tab layout based on conditions.
     * Update the tab layout based on status of availability of the hidden profile.
     */
    public void updateView() {
        updateTabsIfNeeded();
@@ -124,9 +127,14 @@ public class ProfileTabs implements ProfileTabsAddons {
            // Update the layout according to the current root if necessary.
            // Make sure we do not invoke callback. Otherwise, it is likely to cause infinite loop.
            mTabs.removeOnTabSelectedListener(mOnTabSelectedListener);
            if (!mUserIds.contains(currentRoot.userId)) {
                mTabs.addOnTabSelectedListener(mOnTabSelectedListener);
                mTabs.selectTab(mTabs.getTabAt(mUserIds.indexOf(UserId.CURRENT_USER)));
            } else {
                mTabs.selectTab(mTabs.getTabAt(mUserIds.indexOf(currentRoot.userId)));
                mTabs.addOnTabSelectedListener(mOnTabSelectedListener);
            }
        }
        mTabsContainer.setVisibility(shouldShow() ? View.VISIBLE : View.GONE);

        // Material next changes apply only for version S or greater
@@ -172,16 +180,15 @@ public class ProfileTabs implements ProfileTabsAddons {
        // 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;
            mUserIds = new ArrayList<>();
            mUserIds.addAll(userIds);
            mTabs.removeAllTabs();
            if (mUserIds.size() > 1) {
                // set setSelected to false otherwise it will trigger callback.
                mTabs.addTab(createTab(
                        getEnterpriseString(PERSONAL_TAB, R.string.personal_tab),
                        mUserIdManager.getSystemUser()), /* setSelected= */false);
                mTabs.addTab(createTab(
                        getEnterpriseString(WORK_TAB, R.string.work_tab),
                        mUserIdManager.getManagedUser()), /* setSelected= */false);
                if (FeatureFlagUtils.isPrivateSpaceEnabled()) {
                    addTabsPrivateSpaceEnabled();
                } else {
                    addTabsPrivateSpaceDisabled();
                }
            }
        }
    }
@@ -195,6 +202,28 @@ public class ProfileTabs implements ProfileTabsAddons {
        return mUserIdManager.getUserIds();
    }

    private void addTabsPrivateSpaceEnabled() {
        // set setSelected to false otherwise it will trigger callback.
        assert mUserManagerState != null;
        Map<UserId, String> userIdToLabelMap = mUserManagerState.getUserIdToLabelMap();
        UserManager userManager = mTabsContainer.getContext().getSystemService(UserManager.class);
        assert userManager != null;
        for (UserId userId : mUserIds) {
            mTabs.addTab(createTab(userIdToLabelMap.get(userId), userId), /* setSelected= */false);
        }
    }

    private void addTabsPrivateSpaceDisabled() {
        // set setSelected to false otherwise it will trigger callback.
        assert mUserIdManager != null;
        mTabs.addTab(createTab(
                getEnterpriseString(PERSONAL_TAB, R.string.personal_tab),
                mUserIdManager.getSystemUser()), /* setSelected= */false);
        mTabs.addTab(createTab(
                getEnterpriseString(WORK_TAB, R.string.work_tab),
                mUserIdManager.getManagedUser()), /* setSelected= */false);
    }

    private String getEnterpriseString(String updatableStringId, int defaultStringId) {
        if (SdkLevel.isAtLeastT()) {
            return getUpdatableEnterpriseString(updatableStringId, defaultStringId);
+19 −4
Original line number Diff line number Diff line
@@ -242,10 +242,12 @@ public interface UserManagerState {
                if (userHandle.getIdentifier() == ActivityManager.getCurrentUser()) {
                    result.add(UserId.of(userHandle));
                } else {
                    final UserProperties userProperties =
                            mUserManager.getUserProperties(userHandle);
                    if (userProperties.getShowInSharingSurfaces()
                            == UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) {
                    // Out of all the profiles returned by user manager the profiles that are
                    // returned should satisfy both the following conditions:
                    // 1. It has user property SHOW_IN_SHARING_SURFACES_SEPARATE
                    // 2. Quite mode is not enabled, if it is enabled then the profile's user
                    //    property is not SHOW_IN_QUIET_MODE_HIDDEN
                    if (isProfileAllowed(userHandle)) {
                        result.add(UserId.of(userHandle));
                    }
                }
@@ -255,6 +257,19 @@ public interface UserManagerState {
            }
        }

        @SuppressLint("NewApi")
        private boolean isProfileAllowed(UserHandle userHandle) {
            final UserProperties userProperties =
                    mUserManager.getUserProperties(userHandle);
            if (userProperties.getShowInSharingSurfaces()
                    == UserProperties.SHOW_IN_SHARING_SURFACES_SEPARATE) {
                return !UserId.of(userHandle).isQuietModeEnabled(mContext)
                        || userProperties.getShowInQuietMode()
                        != UserProperties.SHOW_IN_QUIET_MODE_HIDDEN;
            }
            return false;
        }

        private void getUserIdsInternalPreV(List<UserHandle> userProfiles, List<UserId> result) {
            result.add(mCurrentUser);
            UserId systemUser = null;
+2 −2
Original line number Diff line number Diff line
@@ -149,8 +149,8 @@ public final class UserId {
     * Returns true if the this user is in quiet mode.
     */
    public boolean isQuietModeEnabled(Context context) {
        final UserManager userManager =
                (UserManager) context.getSystemService(Context.USER_SERVICE);
        final UserManager userManager = context.getSystemService(UserManager.class);
        assert userManager != null;
        return userManager.isQuietModeEnabled(mUserHandle);
    }

+26 −11
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.sidebar.RootsFragment;
import com.android.documentsui.ui.DialogController;
import com.android.documentsui.ui.MessageBuilder;
import com.android.documentsui.util.FeatureFlagUtils;

import java.util.ArrayList;
import java.util.List;
@@ -83,8 +84,15 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
    }

    // make these methods visible in this package to work around compiler bug http://b/62218600
    @Override protected boolean focusSidebar() { return super.focusSidebar(); }
    @Override protected boolean popDir() { return super.popDir(); }
    @Override
    protected boolean focusSidebar() {
        return super.focusSidebar();
    }

    @Override
    protected boolean popDir() {
        return super.popDir();
    }

    @Override
    public void onCreate(Bundle icicle) {
@@ -157,8 +165,7 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
                mInjector.selectionMgr,
                mProfileTabsAddonsStub);

        mAppsRowManager = new AppsRowManager(mInjector.actions, mState.supportsCrossProfile(),
                mUserIdManager);
        mAppsRowManager = getAppsRowManager();
        mInjector.appsRowManager = mAppsRowManager;

        mActivityInputHandler =
@@ -194,6 +201,14 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
        presentFileErrors(icicle, intent);
    }

    private AppsRowManager getAppsRowManager() {
        return FeatureFlagUtils.isPrivateSpaceEnabled()
                ? new AppsRowManager(mInjector.actions, mState.supportsCrossProfile(),
                mUserManagerState)
                : new AppsRowManager(mInjector.actions, mState.supportsCrossProfile(),
                        mUserIdManager);
    }

    // This is called in the intent contains label and icon resources.
    // When that is true, the launcher activity has supplied them so we
    // can adapt our presentation to how we were launched.
@@ -244,8 +259,8 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler
        final Intent intent = getIntent();

        // This is a remnant of old logic where we used to initialize accept MIME types in
        // BaseActivity. ProvidersAccess still rely on this being correctly initialized so we still have
        // to initialize it in FilesActivity.
        // BaseActivity. ProvidersAccess still rely on this being correctly initialized, so we
        // still have to initialize it in FilesActivity.
        state.initAcceptMimes(intent, "*/*");
        state.action = State.ACTION_BROWSE;
        state.allowMultiple = true;
Loading