Loading src/com/android/documentsui/dirlist/Message.java +1 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ abstract class Message { update(null, mEnv.getModel().info, null, mEnv.getContext().getDrawable(R.drawable.ic_dialog_info)); } else if (mEnv.getDisplayState().action == State.ACTION_OPEN_TREE && mEnv.getDisplayState().stack.peek() != null && mEnv.getDisplayState().stack.peek().isBlockedFromTree() && mEnv.getDisplayState().restrictScopeStorage) { updateBlockFromTreeMessage(); Loading src/com/android/documentsui/files/FilesActivity.java +2 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,8 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler mDrawer, mInjector.searchManager::onSearchBarClicked); RootsFragment.show(getSupportFragmentManager(), null); RootsFragment.show(getSupportFragmentManager(), /* includeApps= */ false, /* intent= */ null); final Intent intent = getIntent(); Loading src/com/android/documentsui/picker/PickActivity.java +20 −21 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; 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.net.Uri; Loading Loading @@ -212,23 +210,23 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { saveContainer.setBackgroundColor(Color.TRANSPARENT); } if (mState.action == ACTION_GET_CONTENT) { final Intent moreApps = new Intent(intent); moreApps.setComponent(null); moreApps.setPackage(null); for (ResolveInfo info : getPackageManager().queryIntentActivities(moreApps, PackageManager.MATCH_DEFAULT_ONLY)) { if (CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { if (mState.supportsCrossProfile() && CrossProfileUtils.getCrossProfileResolveInfo( getPackageManager(), moreApps) != null) { mState.canShareAcrossProfile = true; break; } } RootsFragment.show(getSupportFragmentManager(), moreApps); } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { RootsFragment.show(getSupportFragmentManager(), (Intent) null); if (mState.action == ACTION_GET_CONTENT || mState.action == ACTION_OPEN || mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { RootsFragment.show(getSupportFragmentManager(), /* includeApps= */ mState.action == ACTION_GET_CONTENT, /* intent= */ moreApps); } } Loading Loading @@ -266,8 +264,9 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { state.copyOperationSubType = intent.getIntExtra( FileOperationService.EXTRA_OPERATION_TYPE, FileOperationService.OPERATION_COPY); } else if (Features.CROSS_PROFILE_TABS && VersionUtils.isAtLeastR() && state.action == ACTION_GET_CONTENT) { } else if (Features.CROSS_PROFILE_TABS && VersionUtils.isAtLeastR()) { // We show tabs on PickActivity except copying/moving, which does not support // cross-profile action. state.supportsCrossProfile = true; } } Loading src/com/android/documentsui/sidebar/RootsFragment.java +103 −83 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ public class RootsFragment extends Fragment { private static final String TAG = "RootsFragment"; private static final String EXTRA_INCLUDE_APPS = "includeApps"; private static final String EXTRA_INCLUDE_APPS_INTENT = "includeAppsIntent"; private static final int CONTEXT_MENU_ITEM_TIMEOUT = 500; private final OnItemClickListener mItemListener = new OnItemClickListener() { Loading Loading @@ -126,9 +127,18 @@ public class RootsFragment extends Fragment { private List<Item> mApplicationItemList; public static RootsFragment show(FragmentManager fm, Intent includeApps) { /** * Shows the {@link RootsFragment}. * @param fm the FragmentManager for interacting with fragments associated with this * fragment's activity * @param includeApps if {@code true}, query the intent from the system and include apps in * the {@RootsFragment}. * @param intent the intent to query for package manager */ public static RootsFragment show(FragmentManager fm, boolean includeApps, Intent intent) { final Bundle args = new Bundle(); args.putParcelable(EXTRA_INCLUDE_APPS, includeApps); args.putBoolean(EXTRA_INCLUDE_APPS, includeApps); args.putParcelable(EXTRA_INCLUDE_APPS_INTENT, intent); final RootsFragment fragment = new RootsFragment(); fragment.setArguments(args); Loading Loading @@ -240,7 +250,9 @@ public class RootsFragment extends Fragment { return; } Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS); boolean shouldIncludeHandlerApp = getArguments().getBoolean(EXTRA_INCLUDE_APPS, /* defaultValue= */ false); Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS_INTENT); final Intent intent = activity.getIntent(); final boolean excludeSelf = Loading @@ -248,12 +260,37 @@ public class RootsFragment extends Fragment { final String excludePackage = excludeSelf ? activity.getCallingPackage() : null; final boolean maybeShowBadge = getBaseActivity().getDisplayState().supportsCrossProfile(); List<Item> sortedItems = sortLoadResult(roots, excludePackage, handlerAppIntent, // For action which supports cross profile, update the policy value in state if // necessary. ResolveInfo crossProfileResolveInfo = null; if (state.supportsCrossProfile() && handlerAppIntent != null) { crossProfileResolveInfo = CrossProfileUtils.getCrossProfileResolveInfo( getContext().getPackageManager(), handlerAppIntent); updateCrossProfileStateAndMaybeRefresh( /* canShareAcrossProfile= */ crossProfileResolveInfo != null); } List<Item> sortedItems = sortLoadResult( state, roots, excludePackage, shouldIncludeHandlerApp ? handlerAppIntent : null, DocumentsApplication.getProvidersCache(getContext()), getBaseActivity().getSelectedUser(), DocumentsApplication.getUserIdManager(getContext()).getUserIds(), maybeShowBadge); // This will be removed when feature flag is removed. if (crossProfileResolveInfo != null && !Features.CROSS_PROFILE_TABS) { // Add profile item if we don't support cross-profile tab. sortedItems.add(new SpacerItem()); sortedItems.add(new ProfileItem(crossProfileResolveInfo, crossProfileResolveInfo.loadLabel( getContext().getPackageManager()).toString(), mActionHandler)); } // Disable drawer if only one root activity.setRootsDrawerLocked(sortedItems.size() <= 1); Loading Loading @@ -285,6 +322,20 @@ public class RootsFragment extends Fragment { }; } /** * Updates the state values of whether we can share across profiles, if necessary. Also reload * documents stack if the selected user is not the current user. */ private void updateCrossProfileStateAndMaybeRefresh(boolean canShareAcrossProfile) { final State state = getBaseActivity().getDisplayState(); if (state.canShareAcrossProfile != canShareAcrossProfile) { state.canShareAcrossProfile = canShareAcrossProfile; if (!UserId.CURRENT_USER.equals(getBaseActivity().getSelectedUser())) { mActionHandler.loadDocumentsForCurrentStack(); } } } /** * If the package name of other providers or apps capable of handling the original intent * include the preferred root source, it will have higher order than others. Loading @@ -294,6 +345,7 @@ public class RootsFragment extends Fragment { */ @VisibleForTesting List<Item> sortLoadResult( State state, Collection<RootInfo> roots, @Nullable String excludePackage, @Nullable Intent handlerAppIntent, Loading Loading @@ -344,24 +396,50 @@ public class RootsFragment extends Fragment { if (VERBOSE) Log.v(TAG, "Adding storage roots: " + storageProviders); result.addAll(storageProviders); // Include apps that can handle this intent too. final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); mApplicationItemList = new ArrayList<>(); if (handlerAppIntent != null) { includeHandlerApps(handlerAppIntent, excludePackage, result, otherProviders, userIds, maybeShowBadge); includeHandlerApps(state, handlerAppIntent, excludePackage, rootList, rootListOtherUser, otherProviders, userIds, maybeShowBadge); } else { // Only add providers Collections.sort(otherProviders, comp); if (!result.isEmpty() && !otherProviders.isEmpty()) { result.add(new SpacerItem()); for (RootItem item : otherProviders) { if (UserId.CURRENT_USER.equals(item.userId)) { rootList.add(item); } else { rootListOtherUser.add(item); } if (VERBOSE) Log.v(TAG, "Adding plain roots: " + otherProviders); result.addAll(otherProviders); mApplicationItemList = new ArrayList<>(); for (Item item : otherProviders) { mApplicationItemList.add(item); } } 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; } // 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); } return result; } Loading @@ -369,18 +447,15 @@ public class RootsFragment extends Fragment { * Adds apps capable of handling the original intent will be included in list of roots. If * the providers and apps are the same package name, combine them as RootAndAppItems. */ private void includeHandlerApps( Intent handlerAppIntent, @Nullable String excludePackage, List<Item> result, List<RootItem> otherProviders, List<UserId> userIds, boolean maybeShowBadge) { private void includeHandlerApps(State state, Intent handlerAppIntent, @Nullable String excludePackage, List<Item> rootList, List<Item> rootListOtherUser, List<RootItem> otherProviders, List<UserId> userIds, boolean maybeShowBadge) { if (VERBOSE) Log.v(TAG, "Adding handler apps for intent: " + handlerAppIntent); Context context = getContext(); final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); final List<Item> resultRootList = new ArrayList<>(); final Map<UserPackage, ResolveInfo> appsMapping = new HashMap<>(); final Map<UserPackage, Item> appItems = new HashMap<>(); ProfileItem profileItem = null; final String myPackageName = context.getPackageName(); for (UserId userId : userIds) { Loading @@ -403,13 +478,7 @@ public class RootsFragment extends Fragment { UserPackage userPackage = new UserPackage(userId, packageName); appsMapping.put(userPackage, info); // for change personal profile root. if (CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { if (UserId.CURRENT_USER.equals(userId)) { profileItem = new ProfileItem(info, info.loadLabel(pm).toString(), mActionHandler); } } else { if (!CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { final Item item = new AppItem(info, info.loadLabel(pm).toString(), userId, mActionHandler); appItems.put(userPackage, item); Loading @@ -419,14 +488,6 @@ public class RootsFragment extends Fragment { } } boolean canShareAcrossProfile = profileItem != null; if (getBaseActivity().getDisplayState().canShareAcrossProfile != canShareAcrossProfile) { getBaseActivity().getDisplayState().canShareAcrossProfile = canShareAcrossProfile; if (!UserId.CURRENT_USER.equals(getBaseActivity().getSelectedUser())) { mActionHandler.loadDocumentsForCurrentStack(); } } // If there are some providers and apps has the same package name, combine them as one item. for (RootItem rootItem : otherProviders) { final UserPackage userPackage = new UserPackage(rootItem.userId, Loading Loading @@ -462,55 +523,14 @@ public class RootsFragment extends Fragment { final String preferredRootPackage = getResources().getString( R.string.preferred_root_package, ""); final ItemComparator comp = new ItemComparator(preferredRootPackage); Collections.sort(rootList, comp); Collections.sort(rootListOtherUser, comp); if (canShareAcrossProfile && Features.CROSS_PROFILE_TABS) { // Combine lists only if we enabled profile tab feature. if (!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; if (state.supportsCrossProfile() && state.canShareAcrossProfile) { mApplicationItemList.addAll(rootList); mApplicationItemList.addAll(rootListOtherUser); } else { personalRootList = rootListOtherUser; workRootList = rootList; } Collections.sort(personalRootList, comp); Collections.sort(workRootList, comp); // Make sure mApplicationItemList has items from both profiles. final List<Item> mergeRootList = new ArrayList<>(rootList.size() + rootListOtherUser.size()); mergeRootList.addAll(rootList); mergeRootList.addAll(rootListOtherUser); mApplicationItemList = mergeRootList; // Add header and list to the result resultRootList.add(new HeaderItem(getString(R.string.personal_tab))); resultRootList.addAll(personalRootList); resultRootList.add(new HeaderItem(getString(R.string.work_tab))); resultRootList.addAll(workRootList); } else { // There is no more than 1 user, we can add all lists to result without inserting // personal or work header. resultRootList.addAll(rootList); resultRootList.addAll(rootListOtherUser); Collections.sort(resultRootList, comp); mApplicationItemList = resultRootList; } } else { resultRootList.addAll(rootList); Collections.sort(resultRootList, comp); mApplicationItemList = resultRootList; } addListToResult(result, resultRootList); // This will be removed when feature flag is removed. if (canShareAcrossProfile && !Features.CROSS_PROFILE_TABS) { // Add profile item if we don't support cross-profile tab. result.add(new SpacerItem()); result.add(profileItem); mApplicationItemList.addAll(rootList); } } Loading src/com/android/documentsui/util/CrossProfileUtils.java +20 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.documentsui.util; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import androidx.annotation.Nullable; /** * A utility class for cross-profile usage. */ Loading @@ -40,4 +44,20 @@ public class CrossProfileUtils { } return false; } /** * Returns the {@ResolveInfo} if this intent is a cross-profile intent or {@code null} * otherwise. */ @Nullable public static ResolveInfo getCrossProfileResolveInfo(PackageManager packageManager, Intent intent) { for (ResolveInfo info : packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)) { if (isCrossProfileIntentForwarderActivity(info)) { return info; } } return null; } } Loading
src/com/android/documentsui/dirlist/Message.java +1 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,7 @@ abstract class Message { update(null, mEnv.getModel().info, null, mEnv.getContext().getDrawable(R.drawable.ic_dialog_info)); } else if (mEnv.getDisplayState().action == State.ACTION_OPEN_TREE && mEnv.getDisplayState().stack.peek() != null && mEnv.getDisplayState().stack.peek().isBlockedFromTree() && mEnv.getDisplayState().restrictScopeStorage) { updateBlockFromTreeMessage(); Loading
src/com/android/documentsui/files/FilesActivity.java +2 −1 Original line number Diff line number Diff line Loading @@ -171,7 +171,8 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler mDrawer, mInjector.searchManager::onSearchBarClicked); RootsFragment.show(getSupportFragmentManager(), null); RootsFragment.show(getSupportFragmentManager(), /* includeApps= */ false, /* intent= */ null); final Intent intent = getIntent(); Loading
src/com/android/documentsui/picker/PickActivity.java +20 −21 Original line number Diff line number Diff line Loading @@ -23,8 +23,6 @@ import static com.android.documentsui.base.State.ACTION_OPEN_TREE; import static com.android.documentsui.base.State.ACTION_PICK_COPY_DESTINATION; 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.net.Uri; Loading Loading @@ -212,23 +210,23 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { saveContainer.setBackgroundColor(Color.TRANSPARENT); } if (mState.action == ACTION_GET_CONTENT) { final Intent moreApps = new Intent(intent); moreApps.setComponent(null); moreApps.setPackage(null); for (ResolveInfo info : getPackageManager().queryIntentActivities(moreApps, PackageManager.MATCH_DEFAULT_ONLY)) { if (CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { if (mState.supportsCrossProfile() && CrossProfileUtils.getCrossProfileResolveInfo( getPackageManager(), moreApps) != null) { mState.canShareAcrossProfile = true; break; } } RootsFragment.show(getSupportFragmentManager(), moreApps); } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { RootsFragment.show(getSupportFragmentManager(), (Intent) null); if (mState.action == ACTION_GET_CONTENT || mState.action == ACTION_OPEN || mState.action == ACTION_CREATE || mState.action == ACTION_OPEN_TREE || mState.action == ACTION_PICK_COPY_DESTINATION) { RootsFragment.show(getSupportFragmentManager(), /* includeApps= */ mState.action == ACTION_GET_CONTENT, /* intent= */ moreApps); } } Loading Loading @@ -266,8 +264,9 @@ public class PickActivity extends BaseActivity implements ActionHandler.Addons { state.copyOperationSubType = intent.getIntExtra( FileOperationService.EXTRA_OPERATION_TYPE, FileOperationService.OPERATION_COPY); } else if (Features.CROSS_PROFILE_TABS && VersionUtils.isAtLeastR() && state.action == ACTION_GET_CONTENT) { } else if (Features.CROSS_PROFILE_TABS && VersionUtils.isAtLeastR()) { // We show tabs on PickActivity except copying/moving, which does not support // cross-profile action. state.supportsCrossProfile = true; } } Loading
src/com/android/documentsui/sidebar/RootsFragment.java +103 −83 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ public class RootsFragment extends Fragment { private static final String TAG = "RootsFragment"; private static final String EXTRA_INCLUDE_APPS = "includeApps"; private static final String EXTRA_INCLUDE_APPS_INTENT = "includeAppsIntent"; private static final int CONTEXT_MENU_ITEM_TIMEOUT = 500; private final OnItemClickListener mItemListener = new OnItemClickListener() { Loading Loading @@ -126,9 +127,18 @@ public class RootsFragment extends Fragment { private List<Item> mApplicationItemList; public static RootsFragment show(FragmentManager fm, Intent includeApps) { /** * Shows the {@link RootsFragment}. * @param fm the FragmentManager for interacting with fragments associated with this * fragment's activity * @param includeApps if {@code true}, query the intent from the system and include apps in * the {@RootsFragment}. * @param intent the intent to query for package manager */ public static RootsFragment show(FragmentManager fm, boolean includeApps, Intent intent) { final Bundle args = new Bundle(); args.putParcelable(EXTRA_INCLUDE_APPS, includeApps); args.putBoolean(EXTRA_INCLUDE_APPS, includeApps); args.putParcelable(EXTRA_INCLUDE_APPS_INTENT, intent); final RootsFragment fragment = new RootsFragment(); fragment.setArguments(args); Loading Loading @@ -240,7 +250,9 @@ public class RootsFragment extends Fragment { return; } Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS); boolean shouldIncludeHandlerApp = getArguments().getBoolean(EXTRA_INCLUDE_APPS, /* defaultValue= */ false); Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS_INTENT); final Intent intent = activity.getIntent(); final boolean excludeSelf = Loading @@ -248,12 +260,37 @@ public class RootsFragment extends Fragment { final String excludePackage = excludeSelf ? activity.getCallingPackage() : null; final boolean maybeShowBadge = getBaseActivity().getDisplayState().supportsCrossProfile(); List<Item> sortedItems = sortLoadResult(roots, excludePackage, handlerAppIntent, // For action which supports cross profile, update the policy value in state if // necessary. ResolveInfo crossProfileResolveInfo = null; if (state.supportsCrossProfile() && handlerAppIntent != null) { crossProfileResolveInfo = CrossProfileUtils.getCrossProfileResolveInfo( getContext().getPackageManager(), handlerAppIntent); updateCrossProfileStateAndMaybeRefresh( /* canShareAcrossProfile= */ crossProfileResolveInfo != null); } List<Item> sortedItems = sortLoadResult( state, roots, excludePackage, shouldIncludeHandlerApp ? handlerAppIntent : null, DocumentsApplication.getProvidersCache(getContext()), getBaseActivity().getSelectedUser(), DocumentsApplication.getUserIdManager(getContext()).getUserIds(), maybeShowBadge); // This will be removed when feature flag is removed. if (crossProfileResolveInfo != null && !Features.CROSS_PROFILE_TABS) { // Add profile item if we don't support cross-profile tab. sortedItems.add(new SpacerItem()); sortedItems.add(new ProfileItem(crossProfileResolveInfo, crossProfileResolveInfo.loadLabel( getContext().getPackageManager()).toString(), mActionHandler)); } // Disable drawer if only one root activity.setRootsDrawerLocked(sortedItems.size() <= 1); Loading Loading @@ -285,6 +322,20 @@ public class RootsFragment extends Fragment { }; } /** * Updates the state values of whether we can share across profiles, if necessary. Also reload * documents stack if the selected user is not the current user. */ private void updateCrossProfileStateAndMaybeRefresh(boolean canShareAcrossProfile) { final State state = getBaseActivity().getDisplayState(); if (state.canShareAcrossProfile != canShareAcrossProfile) { state.canShareAcrossProfile = canShareAcrossProfile; if (!UserId.CURRENT_USER.equals(getBaseActivity().getSelectedUser())) { mActionHandler.loadDocumentsForCurrentStack(); } } } /** * If the package name of other providers or apps capable of handling the original intent * include the preferred root source, it will have higher order than others. Loading @@ -294,6 +345,7 @@ public class RootsFragment extends Fragment { */ @VisibleForTesting List<Item> sortLoadResult( State state, Collection<RootInfo> roots, @Nullable String excludePackage, @Nullable Intent handlerAppIntent, Loading Loading @@ -344,24 +396,50 @@ public class RootsFragment extends Fragment { if (VERBOSE) Log.v(TAG, "Adding storage roots: " + storageProviders); result.addAll(storageProviders); // Include apps that can handle this intent too. final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); mApplicationItemList = new ArrayList<>(); if (handlerAppIntent != null) { includeHandlerApps(handlerAppIntent, excludePackage, result, otherProviders, userIds, maybeShowBadge); includeHandlerApps(state, handlerAppIntent, excludePackage, rootList, rootListOtherUser, otherProviders, userIds, maybeShowBadge); } else { // Only add providers Collections.sort(otherProviders, comp); if (!result.isEmpty() && !otherProviders.isEmpty()) { result.add(new SpacerItem()); for (RootItem item : otherProviders) { if (UserId.CURRENT_USER.equals(item.userId)) { rootList.add(item); } else { rootListOtherUser.add(item); } if (VERBOSE) Log.v(TAG, "Adding plain roots: " + otherProviders); result.addAll(otherProviders); mApplicationItemList = new ArrayList<>(); for (Item item : otherProviders) { mApplicationItemList.add(item); } } 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; } // 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); } return result; } Loading @@ -369,18 +447,15 @@ public class RootsFragment extends Fragment { * Adds apps capable of handling the original intent will be included in list of roots. If * the providers and apps are the same package name, combine them as RootAndAppItems. */ private void includeHandlerApps( Intent handlerAppIntent, @Nullable String excludePackage, List<Item> result, List<RootItem> otherProviders, List<UserId> userIds, boolean maybeShowBadge) { private void includeHandlerApps(State state, Intent handlerAppIntent, @Nullable String excludePackage, List<Item> rootList, List<Item> rootListOtherUser, List<RootItem> otherProviders, List<UserId> userIds, boolean maybeShowBadge) { if (VERBOSE) Log.v(TAG, "Adding handler apps for intent: " + handlerAppIntent); Context context = getContext(); final List<Item> rootList = new ArrayList<>(); final List<Item> rootListOtherUser = new ArrayList<>(); final List<Item> resultRootList = new ArrayList<>(); final Map<UserPackage, ResolveInfo> appsMapping = new HashMap<>(); final Map<UserPackage, Item> appItems = new HashMap<>(); ProfileItem profileItem = null; final String myPackageName = context.getPackageName(); for (UserId userId : userIds) { Loading @@ -403,13 +478,7 @@ public class RootsFragment extends Fragment { UserPackage userPackage = new UserPackage(userId, packageName); appsMapping.put(userPackage, info); // for change personal profile root. if (CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { if (UserId.CURRENT_USER.equals(userId)) { profileItem = new ProfileItem(info, info.loadLabel(pm).toString(), mActionHandler); } } else { if (!CrossProfileUtils.isCrossProfileIntentForwarderActivity(info)) { final Item item = new AppItem(info, info.loadLabel(pm).toString(), userId, mActionHandler); appItems.put(userPackage, item); Loading @@ -419,14 +488,6 @@ public class RootsFragment extends Fragment { } } boolean canShareAcrossProfile = profileItem != null; if (getBaseActivity().getDisplayState().canShareAcrossProfile != canShareAcrossProfile) { getBaseActivity().getDisplayState().canShareAcrossProfile = canShareAcrossProfile; if (!UserId.CURRENT_USER.equals(getBaseActivity().getSelectedUser())) { mActionHandler.loadDocumentsForCurrentStack(); } } // If there are some providers and apps has the same package name, combine them as one item. for (RootItem rootItem : otherProviders) { final UserPackage userPackage = new UserPackage(rootItem.userId, Loading Loading @@ -462,55 +523,14 @@ public class RootsFragment extends Fragment { final String preferredRootPackage = getResources().getString( R.string.preferred_root_package, ""); final ItemComparator comp = new ItemComparator(preferredRootPackage); Collections.sort(rootList, comp); Collections.sort(rootListOtherUser, comp); if (canShareAcrossProfile && Features.CROSS_PROFILE_TABS) { // Combine lists only if we enabled profile tab feature. if (!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; if (state.supportsCrossProfile() && state.canShareAcrossProfile) { mApplicationItemList.addAll(rootList); mApplicationItemList.addAll(rootListOtherUser); } else { personalRootList = rootListOtherUser; workRootList = rootList; } Collections.sort(personalRootList, comp); Collections.sort(workRootList, comp); // Make sure mApplicationItemList has items from both profiles. final List<Item> mergeRootList = new ArrayList<>(rootList.size() + rootListOtherUser.size()); mergeRootList.addAll(rootList); mergeRootList.addAll(rootListOtherUser); mApplicationItemList = mergeRootList; // Add header and list to the result resultRootList.add(new HeaderItem(getString(R.string.personal_tab))); resultRootList.addAll(personalRootList); resultRootList.add(new HeaderItem(getString(R.string.work_tab))); resultRootList.addAll(workRootList); } else { // There is no more than 1 user, we can add all lists to result without inserting // personal or work header. resultRootList.addAll(rootList); resultRootList.addAll(rootListOtherUser); Collections.sort(resultRootList, comp); mApplicationItemList = resultRootList; } } else { resultRootList.addAll(rootList); Collections.sort(resultRootList, comp); mApplicationItemList = resultRootList; } addListToResult(result, resultRootList); // This will be removed when feature flag is removed. if (canShareAcrossProfile && !Features.CROSS_PROFILE_TABS) { // Add profile item if we don't support cross-profile tab. result.add(new SpacerItem()); result.add(profileItem); mApplicationItemList.addAll(rootList); } } Loading
src/com/android/documentsui/util/CrossProfileUtils.java +20 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,12 @@ package com.android.documentsui.util; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import androidx.annotation.Nullable; /** * A utility class for cross-profile usage. */ Loading @@ -40,4 +44,20 @@ public class CrossProfileUtils { } return false; } /** * Returns the {@ResolveInfo} if this intent is a cross-profile intent or {@code null} * otherwise. */ @Nullable public static ResolveInfo getCrossProfileResolveInfo(PackageManager packageManager, Intent intent) { for (ResolveInfo info : packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)) { if (isCrossProfileIntentForwarderActivity(info)) { return info; } } return null; } }