Loading res/xml/storage_category_fragment.xml +1 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ android:order="108"/> <!-- Preference order 100~200 are 'ONLY' for storage category preferences above. --> <PreferenceCategory android:key="pref_secondary_users" android:key="pref_non_current_users" android:title="@string/storage_other_users" android:order="201" /> </PreferenceScreen> res/xml/storage_dashboard_fragment.xml +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ android:order="108"/> <!-- Preference order 100~200 are 'ONLY' for storage category preferences above. --> <PreferenceCategory android:key="pref_secondary_users" android:key="pref_non_current_users" android:title="@string/storage_other_users" android:order="201" /> </PreferenceScreen> src/com/android/settings/deviceinfo/StorageCategoryFragment.java +34 −31 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.settings.deviceinfo; import static java.util.Collections.EMPTY_LIST; import android.app.settings.SettingsEnums; import android.app.usage.StorageStatsManager; import android.content.Context; Loading @@ -29,13 +31,15 @@ import android.view.View; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.profileselector.ProfileSelectFragment; import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController; import com.android.settings.deviceinfo.storage.SecondaryUserController; import com.android.settings.deviceinfo.storage.NonCurrentUserController; import com.android.settings.deviceinfo.storage.StorageAsyncLoader; import com.android.settings.deviceinfo.storage.StorageCacheHelper; import com.android.settings.deviceinfo.storage.StorageEntry; Loading @@ -49,7 +53,6 @@ import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * Storage Settings main UI is composed by 3 fragments: Loading @@ -70,6 +73,7 @@ public class StorageCategoryFragment extends DashboardFragment private static final String TAG = "StorageCategoryFrag"; private static final String SELECTED_STORAGE_ENTRY_KEY = "selected_storage_entry_key"; private static final String SUMMARY_PREF_KEY = "storage_summary"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final int STORAGE_JOB_ID = 0; private static final int ICON_JOB_ID = 1; private static final int VOLUME_SIZE_JOB_ID = 2; Loading @@ -81,7 +85,7 @@ public class StorageCategoryFragment extends DashboardFragment private SparseArray<StorageAsyncLoader.StorageResult> mAppsResult; private StorageItemPreferenceController mPreferenceController; private List<AbstractPreferenceController> mSecondaryUsers; private List<NonCurrentUserController> mNonCurrentUsers; private boolean mIsWorkProfile; private int mUserId; private boolean mIsLoadedFromCache; Loading @@ -98,9 +102,9 @@ public class StorageCategoryFragment extends DashboardFragment return; } // To prevent flicker, hides secondary users preference. // To prevent flicker, hides non-current users preference. // onReceivedSizes will set it visible for private storage. setSecondaryUsersVisible(false); setNonCurrentUsersVisible(false); if (!mSelectedStorageEntry.isMounted()) { // Set null volume to hide category stats. Loading Loading @@ -150,8 +154,8 @@ public class StorageCategoryFragment extends DashboardFragment if (mSelectedStorageEntry != null) { refreshUi(mSelectedStorageEntry); } updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } } Loading Loading @@ -217,17 +221,13 @@ public class StorageCategoryFragment extends DashboardFragment // Cache total size infor and used size info mStorageCacheHelper .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { SecondaryUserController userController = (SecondaryUserController) controller; for (NonCurrentUserController userController : mNonCurrentUsers) { userController.setTotalSize(mStorageInfo.totalBytes); } } mPreferenceController.onLoadFinished(mAppsResult, mUserId); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } @Override Loading @@ -253,20 +253,18 @@ public class StorageCategoryFragment extends DashboardFragment null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile); controllers.add(mPreferenceController); mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, mUserManager, mIsWorkProfile /* isWorkProfileOnly */); controllers.addAll(mSecondaryUsers); mNonCurrentUsers = mIsWorkProfile ? EMPTY_LIST : NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager); controllers.addAll(mNonCurrentUsers); return controllers; } /** * Updates the secondary user controller sizes. * Updates the non-current user controller sizes. */ private void updateSecondaryUserControllers(List<AbstractPreferenceController> controllers, private void updateNonCurrentUserControllers(List<NonCurrentUserController> controllers, SparseArray<StorageAsyncLoader.StorageResult> stats) { for (int i = 0, size = controllers.size(); i < size; i++) { final AbstractPreferenceController controller = controllers.get(i); for (AbstractPreferenceController controller : controllers) { if (controller instanceof StorageAsyncLoader.ResultHandler) { StorageAsyncLoader.ResultHandler userController = (StorageAsyncLoader.ResultHandler) controller; Loading Loading @@ -296,6 +294,15 @@ public class StorageCategoryFragment extends DashboardFragment public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.StorageResult>> loader) { } @Override public void displayResourceTilesToScreen(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (mNonCurrentUsers.isEmpty()) { screen.removePreference(group); } super.displayResourceTilesToScreen(screen); } @VisibleForTesting public PrivateStorageInfo getPrivateStorageInfo() { return mStorageInfo; Loading Loading @@ -335,13 +342,9 @@ public class StorageCategoryFragment extends DashboardFragment .isQuotaSupported(mSelectedStorageEntry.getFsUuid()); } private void setSecondaryUsersVisible(boolean visible) { final Optional<SecondaryUserController> secondaryUserController = mSecondaryUsers.stream() .filter(controller -> controller instanceof SecondaryUserController) .map(controller -> (SecondaryUserController) controller) .findAny(); if (secondaryUserController.isPresent()) { secondaryUserController.get().setPreferenceGroupVisible(visible); private void setNonCurrentUsersVisible(boolean visible) { if (!mNonCurrentUsers.isEmpty()) { mNonCurrentUsers.get(0).setPreferenceGroupVisible(visible); } } Loading @@ -361,7 +364,7 @@ public class StorageCategoryFragment extends DashboardFragment @Override public void onLoadFinished( Loader<SparseArray<Drawable>> loader, SparseArray<Drawable> data) { mSecondaryUsers mNonCurrentUsers .stream() .filter(controller -> controller instanceof UserIconLoader.UserIconHandler) .forEach( Loading src/com/android/settings/deviceinfo/StorageDashboardFragment.java +36 −34 Original line number Diff line number Diff line Loading @@ -32,11 +32,12 @@ import android.os.storage.VolumeRecord; import android.provider.SearchIndexableResource; import android.text.TextUtils; import android.util.SparseArray; import android.view.View; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.Utils; Loading @@ -44,7 +45,7 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController; import com.android.settings.deviceinfo.storage.DiskInitFragment; import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController; import com.android.settings.deviceinfo.storage.SecondaryUserController; import com.android.settings.deviceinfo.storage.NonCurrentUserController; import com.android.settings.deviceinfo.storage.StorageAsyncLoader; import com.android.settings.deviceinfo.storage.StorageCacheHelper; import com.android.settings.deviceinfo.storage.StorageEntry; Loading @@ -64,7 +65,6 @@ import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; /** * Storage Settings main UI is composed by 3 fragments: Loading @@ -86,6 +86,7 @@ public class StorageDashboardFragment extends DashboardFragment private static final String TAG = "StorageDashboardFrag"; private static final String SUMMARY_PREF_KEY = "storage_summary"; private static final String SELECTED_STORAGE_ENTRY_KEY = "selected_storage_entry_key"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final int STORAGE_JOB_ID = 0; private static final int ICON_JOB_ID = 1; private static final int VOLUME_SIZE_JOB_ID = 2; Loading @@ -101,7 +102,7 @@ public class StorageDashboardFragment extends DashboardFragment private VolumeOptionMenuController mOptionMenuController; private StorageSelectionPreferenceController mStorageSelectionController; private StorageUsageProgressBarPreferenceController mStorageUsageProgressBarController; private List<AbstractPreferenceController> mSecondaryUsers; private List<NonCurrentUserController> mNonCurrentUsers; private boolean mIsWorkProfile; private int mUserId; private boolean mIsLoadedFromCache; Loading Loading @@ -232,9 +233,9 @@ public class StorageDashboardFragment extends DashboardFragment mOptionMenuController.setSelectedStorageEntry(mSelectedStorageEntry); getActivity().invalidateOptionsMenu(); // To prevent flicker, hides secondary users preference. // To prevent flicker, hides non-current users preference. // onReceivedSizes will set it visible for private storage. setSecondaryUsersVisible(false); setNonCurrentUsersVisible(false); if (!mSelectedStorageEntry.isMounted()) { // Set null volume to hide category stats. Loading @@ -254,7 +255,7 @@ public class StorageDashboardFragment extends DashboardFragment mAppsResult = null; // Hide the loading spinner if there is cached data. if (mStorageCacheHelper.hasCachedSizeInfo()) { //TODO(b/220259287): apply cache mechanism to secondary user //TODO(b/220259287): apply cache mechanism to non-current user mPreferenceController.onLoadFinished(mAppsResult, mUserId); } else { maybeSetLoading(isQuotaSupported()); Loading Loading @@ -297,8 +298,8 @@ public class StorageDashboardFragment extends DashboardFragment mStorageEntries.addAll( StorageUtils.getAllStorageEntries(getContext(), mStorageManager)); refreshUi(); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } } Loading Loading @@ -393,17 +394,13 @@ public class StorageDashboardFragment extends DashboardFragment // Cache total size and used size mStorageCacheHelper .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { SecondaryUserController userController = (SecondaryUserController) controller; for (NonCurrentUserController userController : mNonCurrentUsers) { userController.setTotalSize(mStorageInfo.totalBytes); } } mPreferenceController.onLoadFinished(mAppsResult, mUserId); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } @Override Loading @@ -429,20 +426,19 @@ public class StorageDashboardFragment extends DashboardFragment null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile); controllers.add(mPreferenceController); mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, mUserManager, mIsWorkProfile /* isWorkProfileOnly */); controllers.addAll(mSecondaryUsers); mNonCurrentUsers = NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager); controllers.addAll(mNonCurrentUsers); return controllers; } /** * Updates the secondary user controller sizes. * Updates the non-current user controller sizes. */ private void updateSecondaryUserControllers(List<AbstractPreferenceController> controllers, private void updateNonCurrentUserControllers(List<NonCurrentUserController> controllers, SparseArray<StorageAsyncLoader.StorageResult> stats) { for (int i = 0, size = controllers.size(); i < size; i++) { final AbstractPreferenceController controller = controllers.get(i); for (AbstractPreferenceController controller : controllers) { if (controller instanceof StorageAsyncLoader.ResultHandler) { StorageAsyncLoader.ResultHandler userController = (StorageAsyncLoader.ResultHandler) controller; Loading Loading @@ -473,8 +469,8 @@ public class StorageDashboardFragment extends DashboardFragment controllers.add(new StorageItemPreferenceController(context, null /* host */, null /* volume */, new StorageManagerVolumeProvider(sm), false /* isWorkProfile */)); controllers.addAll(SecondaryUserController.getSecondaryUserControllers( context, userManager, false /* isWorkProfileOnly */)); controllers.addAll(NonCurrentUserController.getNonCurrentUserControllers( context, userManager)); return controllers; } Loading @@ -501,6 +497,16 @@ public class StorageDashboardFragment extends DashboardFragment public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.StorageResult>> loader) { } @Override public void displayResourceTilesToScreen(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (mNonCurrentUsers.isEmpty()) { screen.removePreference(group); } super.displayResourceTilesToScreen(screen); } @VisibleForTesting public PrivateStorageInfo getPrivateStorageInfo() { return mStorageInfo; Loading Loading @@ -540,13 +546,9 @@ public class StorageDashboardFragment extends DashboardFragment .isQuotaSupported(mSelectedStorageEntry.getFsUuid()); } private void setSecondaryUsersVisible(boolean visible) { final Optional<SecondaryUserController> secondaryUserController = mSecondaryUsers.stream() .filter(controller -> controller instanceof SecondaryUserController) .map(controller -> (SecondaryUserController) controller) .findAny(); if (secondaryUserController.isPresent()) { secondaryUserController.get().setPreferenceGroupVisible(visible); private void setNonCurrentUsersVisible(boolean visible) { if (!mNonCurrentUsers.isEmpty()) { mNonCurrentUsers.get(0).setPreferenceGroupVisible(visible); } } Loading @@ -566,7 +568,7 @@ public class StorageDashboardFragment extends DashboardFragment @Override public void onLoadFinished( Loader<SparseArray<Drawable>> loader, SparseArray<Drawable> data) { mSecondaryUsers mNonCurrentUsers .stream() .filter(controller -> controller instanceof UserIconLoader.UserIconHandler) .forEach( Loading src/com/android/settings/deviceinfo/storage/SecondaryUserController.java→src/com/android/settings/deviceinfo/storage/NonCurrentUserController.java +47 −69 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settings.deviceinfo.storage; import android.app.ActivityManager; import android.content.Context; import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; Loading @@ -28,7 +29,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.Utils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.deviceinfo.StorageItemPreference; import com.android.settingslib.core.AbstractPreferenceController; Loading @@ -37,14 +37,14 @@ import java.util.ArrayList; import java.util.List; /** * SecondaryUserController controls the preferences on the Storage screen which had to do with * secondary users. * NonCurrentUserController controls the preferences on the Storage screen which had to do with * other users. */ public class SecondaryUserController extends AbstractPreferenceController implements public class NonCurrentUserController extends AbstractPreferenceController implements PreferenceControllerMixin, StorageAsyncLoader.ResultHandler, UserIconLoader.UserIconHandler { // PreferenceGroupKey to try to add our preference onto. private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final String PREFERENCE_KEY_BASE = "pref_user_"; private static final int SIZE_NOT_SET = -1; Loading @@ -57,60 +57,60 @@ public class SecondaryUserController extends AbstractPreferenceController implem private long mSize; private long mTotalSizeBytes; private boolean mIsVisible; private int[] mProfiles; private StorageCacheHelper mStorageCacheHelper; /** * Adds the appropriate controllers to a controller list for handling all secondary users on * a device. * Adds the appropriate controllers to a controller list for handling all full non current * users on a device. * * @param context Context for initializing the preference controllers. * @param userManager UserManagerWrapper for figuring out which controllers to add. * @param isWorkProfileOnly only shows secondary users of work profile. * (e.g., it should be true in work profile tab) */ public static List<AbstractPreferenceController> getSecondaryUserControllers( Context context, UserManager userManager, boolean isWorkProfileOnly) { List<AbstractPreferenceController> controllers = new ArrayList<>(); UserInfo primaryUser = userManager.getPrimaryUser(); boolean addedUser = false; public static List<NonCurrentUserController> getNonCurrentUserControllers( Context context, UserManager userManager) { int currentUserId = ActivityManager.getCurrentUser(); List<NonCurrentUserController> controllers = new ArrayList<>(); List<UserInfo> infos = userManager.getUsers(); for (int i = 0, size = infos.size(); i < size; i++) { UserInfo info = infos.get(i); if (info.isPrimary()) { continue; } if (Utils.isProfileOf(primaryUser, info)) { for (UserInfo info : infos) { if (info.id == currentUserId || info.isProfile()) { continue; } if (isWorkProfileOnly && !info.isManagedProfile()) { continue; int[] profiles = userManager.getProfileIds(info.id, false /* enabledOnly */); controllers.add(new NonCurrentUserController(context, info, profiles)); } controllers.add(new SecondaryUserController(context, info)); addedUser = true; return controllers; } if (!addedUser) { controllers.add(new NoSecondaryUserController(context)); } return controllers; /** * Constructor for a given non-current user. * * @param context Context to initialize the underlying {@link AbstractPreferenceController}. * @param info {@link UserInfo} for the non-current user which these controllers cover. * @param profiles list of IDs or user and its profiles */ @VisibleForTesting NonCurrentUserController(Context context, @NonNull UserInfo info, @NonNull int[] profiles) { super(context); mUser = info; mSize = SIZE_NOT_SET; mStorageCacheHelper = new StorageCacheHelper(context, info.id); mProfiles = profiles; } /** * Constructor for a given secondary user. * Constructor for a given non-current user. * * @param context Context to initialize the underlying {@link AbstractPreferenceController}. * @param info {@link UserInfo} for the secondary user which this controllers covers. * @param info {@link UserInfo} for the non-current user which these controllers cover. */ @VisibleForTesting SecondaryUserController(Context context, @NonNull UserInfo info) { NonCurrentUserController(Context context, @NonNull UserInfo info) { super(context); mUser = info; mSize = SIZE_NOT_SET; mStorageCacheHelper = new StorageCacheHelper(context, info.id); mProfiles = new int[]{info.id}; } @Override Loading Loading @@ -140,7 +140,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem } /** * Returns the user for which this is the secondary user controller. * Returns the user for which this is the non-current user controller. */ @NonNull public UserInfo getUser() { Loading Loading @@ -169,7 +169,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem } /** * Sets visibility of the PreferenceGroup of secondary user. * Sets visibility of the PreferenceGroup of non-current user. * * @param visible Visibility of the PreferenceGroup. */ Loading @@ -187,10 +187,15 @@ public class SecondaryUserController extends AbstractPreferenceController implem return; } final StorageAsyncLoader.StorageResult result = stats.get(getUser().id); if (result != null) { setSize(result.externalStats.totalBytes, true /* animate */); long totalSize = 0; for (int id : mProfiles) { totalSize += stats.get(id).externalStats.totalBytes; } setSize(totalSize, true /* animate */); // TODO(b/171758224): Update the source of size info mStorageCacheHelper.cacheUsedSize(result.externalStats.totalBytes); mStorageCacheHelper.cacheUsedSize(totalSize); } } Loading @@ -205,31 +210,4 @@ public class SecondaryUserController extends AbstractPreferenceController implem mStoragePreference.setIcon(mUserIcon); } } @VisibleForTesting static class NoSecondaryUserController extends AbstractPreferenceController implements PreferenceControllerMixin { public NoSecondaryUserController(Context context) { super(context); } @Override public void displayPreference(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (group == null) { return; } screen.removePreference(group); } @Override public boolean isAvailable() { return true; } @Override public String getPreferenceKey() { return null; } } } Loading
res/xml/storage_category_fragment.xml +1 −1 Original line number Diff line number Diff line Loading @@ -73,7 +73,7 @@ android:order="108"/> <!-- Preference order 100~200 are 'ONLY' for storage category preferences above. --> <PreferenceCategory android:key="pref_secondary_users" android:key="pref_non_current_users" android:title="@string/storage_other_users" android:order="201" /> </PreferenceScreen>
res/xml/storage_dashboard_fragment.xml +1 −1 Original line number Diff line number Diff line Loading @@ -92,7 +92,7 @@ android:order="108"/> <!-- Preference order 100~200 are 'ONLY' for storage category preferences above. --> <PreferenceCategory android:key="pref_secondary_users" android:key="pref_non_current_users" android:title="@string/storage_other_users" android:order="201" /> </PreferenceScreen>
src/com/android/settings/deviceinfo/StorageCategoryFragment.java +34 −31 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.settings.deviceinfo; import static java.util.Collections.EMPTY_LIST; import android.app.settings.SettingsEnums; import android.app.usage.StorageStatsManager; import android.content.Context; Loading @@ -29,13 +31,15 @@ import android.view.View; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.profileselector.ProfileSelectFragment; import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController; import com.android.settings.deviceinfo.storage.SecondaryUserController; import com.android.settings.deviceinfo.storage.NonCurrentUserController; import com.android.settings.deviceinfo.storage.StorageAsyncLoader; import com.android.settings.deviceinfo.storage.StorageCacheHelper; import com.android.settings.deviceinfo.storage.StorageEntry; Loading @@ -49,7 +53,6 @@ import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider; import java.util.ArrayList; import java.util.List; import java.util.Optional; /** * Storage Settings main UI is composed by 3 fragments: Loading @@ -70,6 +73,7 @@ public class StorageCategoryFragment extends DashboardFragment private static final String TAG = "StorageCategoryFrag"; private static final String SELECTED_STORAGE_ENTRY_KEY = "selected_storage_entry_key"; private static final String SUMMARY_PREF_KEY = "storage_summary"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final int STORAGE_JOB_ID = 0; private static final int ICON_JOB_ID = 1; private static final int VOLUME_SIZE_JOB_ID = 2; Loading @@ -81,7 +85,7 @@ public class StorageCategoryFragment extends DashboardFragment private SparseArray<StorageAsyncLoader.StorageResult> mAppsResult; private StorageItemPreferenceController mPreferenceController; private List<AbstractPreferenceController> mSecondaryUsers; private List<NonCurrentUserController> mNonCurrentUsers; private boolean mIsWorkProfile; private int mUserId; private boolean mIsLoadedFromCache; Loading @@ -98,9 +102,9 @@ public class StorageCategoryFragment extends DashboardFragment return; } // To prevent flicker, hides secondary users preference. // To prevent flicker, hides non-current users preference. // onReceivedSizes will set it visible for private storage. setSecondaryUsersVisible(false); setNonCurrentUsersVisible(false); if (!mSelectedStorageEntry.isMounted()) { // Set null volume to hide category stats. Loading Loading @@ -150,8 +154,8 @@ public class StorageCategoryFragment extends DashboardFragment if (mSelectedStorageEntry != null) { refreshUi(mSelectedStorageEntry); } updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } } Loading Loading @@ -217,17 +221,13 @@ public class StorageCategoryFragment extends DashboardFragment // Cache total size infor and used size info mStorageCacheHelper .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { SecondaryUserController userController = (SecondaryUserController) controller; for (NonCurrentUserController userController : mNonCurrentUsers) { userController.setTotalSize(mStorageInfo.totalBytes); } } mPreferenceController.onLoadFinished(mAppsResult, mUserId); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } @Override Loading @@ -253,20 +253,18 @@ public class StorageCategoryFragment extends DashboardFragment null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile); controllers.add(mPreferenceController); mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, mUserManager, mIsWorkProfile /* isWorkProfileOnly */); controllers.addAll(mSecondaryUsers); mNonCurrentUsers = mIsWorkProfile ? EMPTY_LIST : NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager); controllers.addAll(mNonCurrentUsers); return controllers; } /** * Updates the secondary user controller sizes. * Updates the non-current user controller sizes. */ private void updateSecondaryUserControllers(List<AbstractPreferenceController> controllers, private void updateNonCurrentUserControllers(List<NonCurrentUserController> controllers, SparseArray<StorageAsyncLoader.StorageResult> stats) { for (int i = 0, size = controllers.size(); i < size; i++) { final AbstractPreferenceController controller = controllers.get(i); for (AbstractPreferenceController controller : controllers) { if (controller instanceof StorageAsyncLoader.ResultHandler) { StorageAsyncLoader.ResultHandler userController = (StorageAsyncLoader.ResultHandler) controller; Loading Loading @@ -296,6 +294,15 @@ public class StorageCategoryFragment extends DashboardFragment public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.StorageResult>> loader) { } @Override public void displayResourceTilesToScreen(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (mNonCurrentUsers.isEmpty()) { screen.removePreference(group); } super.displayResourceTilesToScreen(screen); } @VisibleForTesting public PrivateStorageInfo getPrivateStorageInfo() { return mStorageInfo; Loading Loading @@ -335,13 +342,9 @@ public class StorageCategoryFragment extends DashboardFragment .isQuotaSupported(mSelectedStorageEntry.getFsUuid()); } private void setSecondaryUsersVisible(boolean visible) { final Optional<SecondaryUserController> secondaryUserController = mSecondaryUsers.stream() .filter(controller -> controller instanceof SecondaryUserController) .map(controller -> (SecondaryUserController) controller) .findAny(); if (secondaryUserController.isPresent()) { secondaryUserController.get().setPreferenceGroupVisible(visible); private void setNonCurrentUsersVisible(boolean visible) { if (!mNonCurrentUsers.isEmpty()) { mNonCurrentUsers.get(0).setPreferenceGroupVisible(visible); } } Loading @@ -361,7 +364,7 @@ public class StorageCategoryFragment extends DashboardFragment @Override public void onLoadFinished( Loader<SparseArray<Drawable>> loader, SparseArray<Drawable> data) { mSecondaryUsers mNonCurrentUsers .stream() .filter(controller -> controller instanceof UserIconLoader.UserIconHandler) .forEach( Loading
src/com/android/settings/deviceinfo/StorageDashboardFragment.java +36 −34 Original line number Diff line number Diff line Loading @@ -32,11 +32,12 @@ import android.os.storage.VolumeRecord; import android.provider.SearchIndexableResource; import android.text.TextUtils; import android.util.SparseArray; import android.view.View; import androidx.annotation.VisibleForTesting; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.Utils; Loading @@ -44,7 +45,7 @@ import com.android.settings.dashboard.DashboardFragment; import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController; import com.android.settings.deviceinfo.storage.DiskInitFragment; import com.android.settings.deviceinfo.storage.ManageStoragePreferenceController; import com.android.settings.deviceinfo.storage.SecondaryUserController; import com.android.settings.deviceinfo.storage.NonCurrentUserController; import com.android.settings.deviceinfo.storage.StorageAsyncLoader; import com.android.settings.deviceinfo.storage.StorageCacheHelper; import com.android.settings.deviceinfo.storage.StorageEntry; Loading @@ -64,7 +65,6 @@ import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; /** * Storage Settings main UI is composed by 3 fragments: Loading @@ -86,6 +86,7 @@ public class StorageDashboardFragment extends DashboardFragment private static final String TAG = "StorageDashboardFrag"; private static final String SUMMARY_PREF_KEY = "storage_summary"; private static final String SELECTED_STORAGE_ENTRY_KEY = "selected_storage_entry_key"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final int STORAGE_JOB_ID = 0; private static final int ICON_JOB_ID = 1; private static final int VOLUME_SIZE_JOB_ID = 2; Loading @@ -101,7 +102,7 @@ public class StorageDashboardFragment extends DashboardFragment private VolumeOptionMenuController mOptionMenuController; private StorageSelectionPreferenceController mStorageSelectionController; private StorageUsageProgressBarPreferenceController mStorageUsageProgressBarController; private List<AbstractPreferenceController> mSecondaryUsers; private List<NonCurrentUserController> mNonCurrentUsers; private boolean mIsWorkProfile; private int mUserId; private boolean mIsLoadedFromCache; Loading Loading @@ -232,9 +233,9 @@ public class StorageDashboardFragment extends DashboardFragment mOptionMenuController.setSelectedStorageEntry(mSelectedStorageEntry); getActivity().invalidateOptionsMenu(); // To prevent flicker, hides secondary users preference. // To prevent flicker, hides non-current users preference. // onReceivedSizes will set it visible for private storage. setSecondaryUsersVisible(false); setNonCurrentUsersVisible(false); if (!mSelectedStorageEntry.isMounted()) { // Set null volume to hide category stats. Loading @@ -254,7 +255,7 @@ public class StorageDashboardFragment extends DashboardFragment mAppsResult = null; // Hide the loading spinner if there is cached data. if (mStorageCacheHelper.hasCachedSizeInfo()) { //TODO(b/220259287): apply cache mechanism to secondary user //TODO(b/220259287): apply cache mechanism to non-current user mPreferenceController.onLoadFinished(mAppsResult, mUserId); } else { maybeSetLoading(isQuotaSupported()); Loading Loading @@ -297,8 +298,8 @@ public class StorageDashboardFragment extends DashboardFragment mStorageEntries.addAll( StorageUtils.getAllStorageEntries(getContext(), mStorageManager)); refreshUi(); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } } Loading Loading @@ -393,17 +394,13 @@ public class StorageDashboardFragment extends DashboardFragment // Cache total size and used size mStorageCacheHelper .cacheTotalSizeAndTotalUsedSize(mStorageInfo.totalBytes, privateUsedBytes); for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) { final AbstractPreferenceController controller = mSecondaryUsers.get(i); if (controller instanceof SecondaryUserController) { SecondaryUserController userController = (SecondaryUserController) controller; for (NonCurrentUserController userController : mNonCurrentUsers) { userController.setTotalSize(mStorageInfo.totalBytes); } } mPreferenceController.onLoadFinished(mAppsResult, mUserId); updateSecondaryUserControllers(mSecondaryUsers, mAppsResult); setSecondaryUsersVisible(true); updateNonCurrentUserControllers(mNonCurrentUsers, mAppsResult); setNonCurrentUsersVisible(true); } @Override Loading @@ -429,20 +426,19 @@ public class StorageDashboardFragment extends DashboardFragment null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile); controllers.add(mPreferenceController); mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, mUserManager, mIsWorkProfile /* isWorkProfileOnly */); controllers.addAll(mSecondaryUsers); mNonCurrentUsers = NonCurrentUserController.getNonCurrentUserControllers(context, mUserManager); controllers.addAll(mNonCurrentUsers); return controllers; } /** * Updates the secondary user controller sizes. * Updates the non-current user controller sizes. */ private void updateSecondaryUserControllers(List<AbstractPreferenceController> controllers, private void updateNonCurrentUserControllers(List<NonCurrentUserController> controllers, SparseArray<StorageAsyncLoader.StorageResult> stats) { for (int i = 0, size = controllers.size(); i < size; i++) { final AbstractPreferenceController controller = controllers.get(i); for (AbstractPreferenceController controller : controllers) { if (controller instanceof StorageAsyncLoader.ResultHandler) { StorageAsyncLoader.ResultHandler userController = (StorageAsyncLoader.ResultHandler) controller; Loading Loading @@ -473,8 +469,8 @@ public class StorageDashboardFragment extends DashboardFragment controllers.add(new StorageItemPreferenceController(context, null /* host */, null /* volume */, new StorageManagerVolumeProvider(sm), false /* isWorkProfile */)); controllers.addAll(SecondaryUserController.getSecondaryUserControllers( context, userManager, false /* isWorkProfileOnly */)); controllers.addAll(NonCurrentUserController.getNonCurrentUserControllers( context, userManager)); return controllers; } Loading @@ -501,6 +497,16 @@ public class StorageDashboardFragment extends DashboardFragment public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.StorageResult>> loader) { } @Override public void displayResourceTilesToScreen(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (mNonCurrentUsers.isEmpty()) { screen.removePreference(group); } super.displayResourceTilesToScreen(screen); } @VisibleForTesting public PrivateStorageInfo getPrivateStorageInfo() { return mStorageInfo; Loading Loading @@ -540,13 +546,9 @@ public class StorageDashboardFragment extends DashboardFragment .isQuotaSupported(mSelectedStorageEntry.getFsUuid()); } private void setSecondaryUsersVisible(boolean visible) { final Optional<SecondaryUserController> secondaryUserController = mSecondaryUsers.stream() .filter(controller -> controller instanceof SecondaryUserController) .map(controller -> (SecondaryUserController) controller) .findAny(); if (secondaryUserController.isPresent()) { secondaryUserController.get().setPreferenceGroupVisible(visible); private void setNonCurrentUsersVisible(boolean visible) { if (!mNonCurrentUsers.isEmpty()) { mNonCurrentUsers.get(0).setPreferenceGroupVisible(visible); } } Loading @@ -566,7 +568,7 @@ public class StorageDashboardFragment extends DashboardFragment @Override public void onLoadFinished( Loader<SparseArray<Drawable>> loader, SparseArray<Drawable> data) { mSecondaryUsers mNonCurrentUsers .stream() .filter(controller -> controller instanceof UserIconLoader.UserIconHandler) .forEach( Loading
src/com/android/settings/deviceinfo/storage/SecondaryUserController.java→src/com/android/settings/deviceinfo/storage/NonCurrentUserController.java +47 −69 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settings.deviceinfo.storage; import android.app.ActivityManager; import android.content.Context; import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; Loading @@ -28,7 +29,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceScreen; import com.android.settings.Utils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settings.deviceinfo.StorageItemPreference; import com.android.settingslib.core.AbstractPreferenceController; Loading @@ -37,14 +37,14 @@ import java.util.ArrayList; import java.util.List; /** * SecondaryUserController controls the preferences on the Storage screen which had to do with * secondary users. * NonCurrentUserController controls the preferences on the Storage screen which had to do with * other users. */ public class SecondaryUserController extends AbstractPreferenceController implements public class NonCurrentUserController extends AbstractPreferenceController implements PreferenceControllerMixin, StorageAsyncLoader.ResultHandler, UserIconLoader.UserIconHandler { // PreferenceGroupKey to try to add our preference onto. private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users"; private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_non_current_users"; private static final String PREFERENCE_KEY_BASE = "pref_user_"; private static final int SIZE_NOT_SET = -1; Loading @@ -57,60 +57,60 @@ public class SecondaryUserController extends AbstractPreferenceController implem private long mSize; private long mTotalSizeBytes; private boolean mIsVisible; private int[] mProfiles; private StorageCacheHelper mStorageCacheHelper; /** * Adds the appropriate controllers to a controller list for handling all secondary users on * a device. * Adds the appropriate controllers to a controller list for handling all full non current * users on a device. * * @param context Context for initializing the preference controllers. * @param userManager UserManagerWrapper for figuring out which controllers to add. * @param isWorkProfileOnly only shows secondary users of work profile. * (e.g., it should be true in work profile tab) */ public static List<AbstractPreferenceController> getSecondaryUserControllers( Context context, UserManager userManager, boolean isWorkProfileOnly) { List<AbstractPreferenceController> controllers = new ArrayList<>(); UserInfo primaryUser = userManager.getPrimaryUser(); boolean addedUser = false; public static List<NonCurrentUserController> getNonCurrentUserControllers( Context context, UserManager userManager) { int currentUserId = ActivityManager.getCurrentUser(); List<NonCurrentUserController> controllers = new ArrayList<>(); List<UserInfo> infos = userManager.getUsers(); for (int i = 0, size = infos.size(); i < size; i++) { UserInfo info = infos.get(i); if (info.isPrimary()) { continue; } if (Utils.isProfileOf(primaryUser, info)) { for (UserInfo info : infos) { if (info.id == currentUserId || info.isProfile()) { continue; } if (isWorkProfileOnly && !info.isManagedProfile()) { continue; int[] profiles = userManager.getProfileIds(info.id, false /* enabledOnly */); controllers.add(new NonCurrentUserController(context, info, profiles)); } controllers.add(new SecondaryUserController(context, info)); addedUser = true; return controllers; } if (!addedUser) { controllers.add(new NoSecondaryUserController(context)); } return controllers; /** * Constructor for a given non-current user. * * @param context Context to initialize the underlying {@link AbstractPreferenceController}. * @param info {@link UserInfo} for the non-current user which these controllers cover. * @param profiles list of IDs or user and its profiles */ @VisibleForTesting NonCurrentUserController(Context context, @NonNull UserInfo info, @NonNull int[] profiles) { super(context); mUser = info; mSize = SIZE_NOT_SET; mStorageCacheHelper = new StorageCacheHelper(context, info.id); mProfiles = profiles; } /** * Constructor for a given secondary user. * Constructor for a given non-current user. * * @param context Context to initialize the underlying {@link AbstractPreferenceController}. * @param info {@link UserInfo} for the secondary user which this controllers covers. * @param info {@link UserInfo} for the non-current user which these controllers cover. */ @VisibleForTesting SecondaryUserController(Context context, @NonNull UserInfo info) { NonCurrentUserController(Context context, @NonNull UserInfo info) { super(context); mUser = info; mSize = SIZE_NOT_SET; mStorageCacheHelper = new StorageCacheHelper(context, info.id); mProfiles = new int[]{info.id}; } @Override Loading Loading @@ -140,7 +140,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem } /** * Returns the user for which this is the secondary user controller. * Returns the user for which this is the non-current user controller. */ @NonNull public UserInfo getUser() { Loading Loading @@ -169,7 +169,7 @@ public class SecondaryUserController extends AbstractPreferenceController implem } /** * Sets visibility of the PreferenceGroup of secondary user. * Sets visibility of the PreferenceGroup of non-current user. * * @param visible Visibility of the PreferenceGroup. */ Loading @@ -187,10 +187,15 @@ public class SecondaryUserController extends AbstractPreferenceController implem return; } final StorageAsyncLoader.StorageResult result = stats.get(getUser().id); if (result != null) { setSize(result.externalStats.totalBytes, true /* animate */); long totalSize = 0; for (int id : mProfiles) { totalSize += stats.get(id).externalStats.totalBytes; } setSize(totalSize, true /* animate */); // TODO(b/171758224): Update the source of size info mStorageCacheHelper.cacheUsedSize(result.externalStats.totalBytes); mStorageCacheHelper.cacheUsedSize(totalSize); } } Loading @@ -205,31 +210,4 @@ public class SecondaryUserController extends AbstractPreferenceController implem mStoragePreference.setIcon(mUserIcon); } } @VisibleForTesting static class NoSecondaryUserController extends AbstractPreferenceController implements PreferenceControllerMixin { public NoSecondaryUserController(Context context) { super(context); } @Override public void displayPreference(PreferenceScreen screen) { final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); if (group == null) { return; } screen.removePreference(group); } @Override public boolean isAvailable() { return true; } @Override public String getPreferenceKey() { return null; } } }