Implements profile selection tab in Storage Settings

- StorageDashboardFragment and StorageItemPreferenceController works only
  for one profile per instance.
- StorageAsyncLoader loads for all users(profiles) and regards each user independent.
- SecondaryUserController will not load personal profile user in work profile tab.
- Cleanup some unused profile related files.

Bug: 174964885
Test: atest com.android.settings.deviceinfo
      atest com.android.settings.deviceinfo.storage
      make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.deviceinfo
      make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.deviceinfo.storage
Change-Id: I8361c29bc240c519c7261b19522c41439479c1c2
This commit is contained in:
Arc Wang
2021-04-29 18:54:10 +08:00
parent 7307e04ef2
commit fa6e82b879
14 changed files with 214 additions and 640 deletions

View File

@@ -469,6 +469,19 @@ public final class Utils extends com.android.settingslib.Utils {
return UserHandle.USER_NULL;
}
/** Returns user ID of current user, throws IllegalStateException if it's not available. */
public static int getCurrentUserId(UserManager userManager, boolean isWorkProfile)
throws IllegalStateException {
if (isWorkProfile) {
final UserHandle managedUserHandle = getManagedProfile(userManager);
if (managedUserHandle == null) {
throw new IllegalStateException("Work profile user ID is not available.");
}
return managedUserHandle.getIdentifier();
}
return UserHandle.myUserId();
}
/**
* Returns the target user for a Settings activity.
* <p>

View File

@@ -20,6 +20,7 @@ import android.util.ArrayMap;
import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.location.LocationServices;
import com.android.settings.location.RecentLocationAccessSeeAllFragment;
@@ -46,5 +47,7 @@ public class ProfileFragmentBridge {
ProfileSelectRecentLocationAccessFragment.class.getName());
FRAGMENT_MAP.put(LocationServices.class.getName(),
ProfileSelectLocationServicesFragment.class.getName());
FRAGMENT_MAP.put(StorageDashboardFragment.class.getName(),
ProfileSelectStorageFragment.class.getName());
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 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.settings.dashboard.profileselector;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import com.android.settings.deviceinfo.StorageDashboardFragment;
/**
* Storage Settings page for personal/managed profile.
*/
public class ProfileSelectStorageFragment extends ProfileSelectFragment {
@Override
public Fragment[] getFragments() {
final Bundle workBundle = new Bundle();
workBundle.putInt(EXTRA_PROFILE, ProfileType.WORK);
final Fragment workFragment = new StorageDashboardFragment();
workFragment.setArguments(workBundle);
final Bundle personalBundle = new Bundle();
personalBundle.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
final Fragment personalFragment = new StorageDashboardFragment();
personalFragment.setArguments(personalBundle);
return new Fragment[] {
personalFragment,
workFragment
};
}
}

View File

@@ -85,6 +85,7 @@ public class StorageDashboardFragment extends DashboardFragment
private static final int VOLUME_SIZE_JOB_ID = 2;
private StorageManager mStorageManager;
private UserManager mUserManager;
private final List<StorageEntry> mStorageEntries = new ArrayList<>();
private StorageEntry mSelectedStorageEntry;
private PrivateStorageInfo mStorageInfo;
@@ -96,7 +97,8 @@ public class StorageDashboardFragment extends DashboardFragment
private StorageSelectionPreferenceController mStorageSelectionController;
private StorageUsageProgressBarPreferenceController mStorageUsageProgressBarController;
private List<AbstractPreferenceController> mSecondaryUsers;
private boolean mPersonalOnly;
private boolean mIsWorkProfile;
private int mUserId;
private Preference mFreeUpSpacePreference;
private final StorageEventListener mStorageEventListener = new StorageEventListener() {
@@ -270,8 +272,6 @@ public class StorageDashboardFragment extends DashboardFragment
final Activity activity = getActivity();
mStorageManager = activity.getSystemService(StorageManager.class);
mPersonalOnly = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
== ProfileSelectFragment.ProfileType.PERSONAL;
if (icicle == null) {
final VolumeInfo specifiedVolumeInfo =
@@ -288,18 +288,19 @@ public class StorageDashboardFragment extends DashboardFragment
}
private void initializePreference() {
if (mPersonalOnly) {
final Preference summary = getPreferenceScreen().findPreference(SUMMARY_PREF_KEY);
if (summary != null) {
summary.setVisible(false);
}
}
mFreeUpSpacePreference = getPreferenceScreen().findPreference(FREE_UP_SPACE_PREF_KEY);
mFreeUpSpacePreference.setOnPreferenceClickListener(this);
}
@Override
public void onAttach(Context context) {
// These member variables are initialized befoer super.onAttach for
// createPreferenceControllers to work correctly.
mUserManager = context.getSystemService(UserManager.class);
mIsWorkProfile = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE)
== ProfileSelectFragment.ProfileType.WORK;
mUserId = Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
super.onAttach(context);
use(AutomaticStorageManagementSwitchPreferenceController.class).setFragmentManager(
getFragmentManager());
@@ -396,7 +397,7 @@ public class StorageDashboardFragment extends DashboardFragment
}
if (mAppsResult != null) {
mPreferenceController.onLoadFinished(mAppsResult, UserHandle.myUserId());
mPreferenceController.onLoadFinished(mAppsResult, mUserId);
updateSecondaryUserControllers(mSecondaryUsers, mAppsResult);
stopLoading = true;
}
@@ -427,14 +428,13 @@ public class StorageDashboardFragment extends DashboardFragment
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
StorageManager sm = context.getSystemService(StorageManager.class);
mPreferenceController = new StorageItemPreferenceController(context, this,
null /* volume */, new StorageManagerVolumeProvider(sm));
null /* volume */, new StorageManagerVolumeProvider(sm), mIsWorkProfile);
controllers.add(mPreferenceController);
final UserManager userManager = context.getSystemService(UserManager.class);
mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context, userManager);
mSecondaryUsers = SecondaryUserController.getSecondaryUserControllers(context,
mUserManager, mIsWorkProfile /* isWorkProfileOnly */);
controllers.addAll(mSecondaryUsers);
return controllers;
@@ -480,9 +480,10 @@ public class StorageDashboardFragment extends DashboardFragment
final UserManager userManager = context.getSystemService(UserManager.class);
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new StorageItemPreferenceController(context, null /* host */,
null /* volume */, new StorageManagerVolumeProvider(sm)));
null /* volume */, new StorageManagerVolumeProvider(sm),
false /* isWorkProfile */));
controllers.addAll(SecondaryUserController.getSecondaryUserControllers(
context, userManager));
context, userManager, false /* isWorkProfileOnly */));
return controllers;
}
@@ -492,7 +493,7 @@ public class StorageDashboardFragment extends DashboardFragment
public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id,
Bundle args) {
final Context context = getContext();
return new StorageAsyncLoader(context, context.getSystemService(UserManager.class),
return new StorageAsyncLoader(context, mUserManager,
mSelectedStorageEntry.getFsUuid(),
new StorageStatsSource(context),
context.getPackageManager());
@@ -519,7 +520,7 @@ public class StorageDashboardFragment extends DashboardFragment
metricsFeatureProvider.logClickedPreference(preference, getMetricsCategory());
metricsFeatureProvider.action(context, SettingsEnums.STORAGE_FREE_UP_SPACE_NOW);
final Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
context.startActivity(intent);
context.startActivityAsUser(intent, new UserHandle(mUserId));
return true;
}
return false;
@@ -574,16 +575,14 @@ public class StorageDashboardFragment extends DashboardFragment
}
private void initializeCacheProvider() {
mCachedStorageValuesHelper =
new CachedStorageValuesHelper(getContext(), UserHandle.myUserId());
mCachedStorageValuesHelper = new CachedStorageValuesHelper(getContext(), mUserId);
initializeCachedValues();
onReceivedSizes();
}
private void maybeCacheFreshValues() {
if (mStorageInfo != null && mAppsResult != null) {
mCachedStorageValuesHelper.cacheResult(
mStorageInfo, mAppsResult.get(UserHandle.myUserId()));
mCachedStorageValuesHelper.cacheResult(mStorageInfo, mAppsResult.get(mUserId));
}
}

View File

@@ -1,138 +0,0 @@
/*
* Copyright (C) 2017 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.settings.deviceinfo;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.SparseArray;
import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader.AppsStorageResult;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
import java.util.ArrayList;
import java.util.List;
/**
* StorageProfileFragment is a fragment which shows the storage results for a profile of the
* primary user.
*/
public class StorageProfileFragment extends DashboardFragment
implements LoaderManager.LoaderCallbacks<SparseArray<AppsStorageResult>> {
private static final String TAG = "StorageProfileFragment";
public static final String USER_ID_EXTRA = "userId";
private static final int APPS_JOB_ID = 0;
private VolumeInfo mVolume;
private int mUserId;
private StorageItemPreferenceController mPreferenceController;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Bundle args = getArguments();
// Initialize the storage sizes that we can quickly calc.
final Context context = getActivity();
final StorageManager sm = context.getSystemService(StorageManager.class);
mVolume = Utils.maybeInitializeVolume(sm, args);
if (mVolume == null) {
getActivity().finish();
return;
}
mPreferenceController.setVolume(mVolume);
mUserId = args.getInt(USER_ID_EXTRA, UserHandle.myUserId());
mPreferenceController.setUserId(UserHandle.of(mUserId));
}
@Override
public void onResume() {
super.onResume();
getLoaderManager().initLoader(APPS_JOB_ID, Bundle.EMPTY, this);
}
@Override
public int getMetricsCategory() {
return SettingsEnums.SETTINGS_STORAGE_PROFILE;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.storage_profile_fragment;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final StorageManager sm = context.getSystemService(StorageManager.class);
mPreferenceController =
new StorageItemPreferenceController(
context,
this,
mVolume,
new StorageManagerVolumeProvider(sm),
/* isWorkProfile */ true);
controllers.add(mPreferenceController);
return controllers;
}
@Override
public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) {
final Context context = getContext();
return new StorageAsyncLoader(context,
context.getSystemService(UserManager.class),
mVolume.fsUuid,
new StorageStatsSource(context),
context.getPackageManager());
}
@Override
public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
SparseArray<AppsStorageResult> result) {
mPreferenceController.onLoadFinished(result, mUserId);
}
@Override
public void onLoaderReset(Loader<SparseArray<AppsStorageResult>> loader) {
}
@VisibleForTesting
void setPreferenceController(StorageItemPreferenceController controller) {
mPreferenceController = controller;
}
}

View File

@@ -63,9 +63,11 @@ public class SecondaryUserController extends AbstractPreferenceController implem
*
* @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) {
Context context, UserManager userManager, boolean isWorkProfileOnly) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
UserInfo primaryUser = userManager.getPrimaryUser();
@@ -77,7 +79,11 @@ public class SecondaryUserController extends AbstractPreferenceController implem
continue;
}
if (info == null || Utils.isProfileOf(primaryUser, info)) {
if (Utils.isProfileOf(primaryUser, info)) {
continue;
}
if (isWorkProfileOnly && !info.isManagedProfile()) {
continue;
}

View File

@@ -82,7 +82,7 @@ public class StorageAsyncLoader
}
});
for (int i = 0, userCount = infos.size(); i < userCount; i++) {
UserInfo info = infos.get(i);
final UserInfo info = infos.get(i);
result.put(info.id, getStorageResultForUser(info.id));
}
return result;
@@ -109,7 +109,7 @@ public class StorageAsyncLoader
final long dataSize = stats.getDataBytes();
final long cacheQuota = mStatsManager.getCacheQuotaBytes(mUuid, app.uid);
final long cacheBytes = stats.getCacheBytes();
long blamedSize = dataSize;
long blamedSize = dataSize + stats.getCodeBytes();
// Technically, we could overages as freeable on the storage settings screen.
// If the app is using more cache than its quota, we would accidentally subtract the
// overage from the system size (because it shows up as unused) during our attribution.
@@ -118,12 +118,11 @@ public class StorageAsyncLoader
blamedSize = blamedSize - cacheBytes + cacheQuota;
}
// This isn't quite right because it slams the first user by user id with the whole code
// size, but this ensures that we count all apps seen once.
boolean isAddCodeBytesForFirstUserId = false;
if (!mSeenPackages.contains(app.packageName)) {
isAddCodeBytesForFirstUserId = true;
blamedSize += stats.getCodeBytes();
// Code bytes may share between different profiles. To know all the duplicate code size
// and we can get a reasonable system size in StorageItemPreferenceController.
if (mSeenPackages.contains(app.packageName)) {
result.duplicateCodeSize += stats.getCodeBytes();
} else {
mSeenPackages.add(app.packageName);
}
@@ -135,9 +134,7 @@ public class StorageAsyncLoader
// TODO(b/170918505): Should revamp audio size calculation with the data
// from media provider.
result.musicAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.musicAppsSize -= stats.getCodeBytes();
}
result.musicAppsSize -= stats.getCodeBytes();
result.otherAppsSize += blamedSize;
break;
@@ -145,9 +142,7 @@ public class StorageAsyncLoader
// TODO(b/170918505): Should revamp video size calculation with the data
// from media provider.
result.videoAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.videoAppsSize -= stats.getCodeBytes();
}
result.videoAppsSize -= stats.getCodeBytes();
result.otherAppsSize += blamedSize;
break;
@@ -155,9 +150,7 @@ public class StorageAsyncLoader
// TODO(b/170918505): Should revamp image size calculation with the data
// from media provider.
result.photosAppsSize += blamedSize;
if (isAddCodeBytesForFirstUserId) {
result.photosAppsSize -= stats.getCodeBytes();
}
result.photosAppsSize -= stats.getCodeBytes();
result.otherAppsSize += blamedSize;
break;
@@ -194,6 +187,7 @@ public class StorageAsyncLoader
public long videoAppsSize;
public long otherAppsSize;
public long cacheSize;
public long duplicateCodeSize;
public StorageStatsSource.ExternalStorageStats externalStats;
}

View File

@@ -101,6 +101,7 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
private static final int LAST_STORAGE_CATEGORY_PREFERENCE_ORDER = 200;
private PackageManager mPackageManager;
private UserManager mUserManager;
private final Fragment mFragment;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final StorageVolumeProvider mSvp;
@@ -134,15 +135,17 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
public StorageItemPreferenceController(
Context context, Fragment hostFragment, VolumeInfo volume, StorageVolumeProvider svp) {
public StorageItemPreferenceController(Context context, Fragment hostFragment,
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
super(context);
mPackageManager = context.getPackageManager();
mUserManager = context.getSystemService(UserManager.class);
mFragment = hostFragment;
mVolume = volume;
mSvp = svp;
mIsWorkProfile = isWorkProfile;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mUserId = UserHandle.myUserId();
mUserId = getCurrentUserId();
mImagesUri = Uri.parse(context.getResources()
.getString(R.string.config_images_storage_category_uri));
@@ -154,14 +157,9 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
.getString(R.string.config_documents_and_other_storage_category_uri));
}
public StorageItemPreferenceController(
Context context,
Fragment hostFragment,
VolumeInfo volume,
StorageVolumeProvider svp,
boolean isWorkProfile) {
this(context, hostFragment, volume, svp);
mIsWorkProfile = isWorkProfile;
@VisibleForTesting
int getCurrentUserId() {
return Utils.getCurrentUserId(mUserManager, mIsWorkProfile);
}
@Override
@@ -311,6 +309,9 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
* Sets the user id for which this preference controller is handling.
*/
public void setUserId(UserHandle userHandle) {
if (mIsWorkProfile && !mUserManager.isManagedProfile(userHandle.getIdentifier())) {
throw new IllegalArgumentException("Only accept work profile userHandle");
}
mUserId = userHandle.getIdentifier();
tintPreference(mPublicStoragePreference);
@@ -359,21 +360,21 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
public void onLoadFinished(SparseArray<StorageAsyncLoader.AppsStorageResult> result,
int userId) {
final StorageAsyncLoader.AppsStorageResult data = result.get(userId);
final StorageAsyncLoader.AppsStorageResult profileData = result.get(
Utils.getManagedProfileId(mContext.getSystemService(UserManager.class), userId));
mImagesPreference.setStorageSize(getImagesSize(data, profileData), mTotalSize);
mVideosPreference.setStorageSize(getVideosSize(data, profileData), mTotalSize);
mAudiosPreference.setStorageSize(getAudiosSize(data, profileData), mTotalSize);
mAppsPreference.setStorageSize(getAppsSize(data, profileData), mTotalSize);
mGamesPreference.setStorageSize(getGamesSize(data, profileData), mTotalSize);
mDocumentsAndOtherPreference.setStorageSize(getDocumentsAndOtherSize(data, profileData),
mImagesPreference.setStorageSize(getImagesSize(data), mTotalSize);
mVideosPreference.setStorageSize(getVideosSize(data), mTotalSize);
mAudiosPreference.setStorageSize(getAudiosSize(data), mTotalSize);
mAppsPreference.setStorageSize(getAppsSize(data), mTotalSize);
mGamesPreference.setStorageSize(getGamesSize(data), mTotalSize);
mDocumentsAndOtherPreference.setStorageSize(getDocumentsAndOtherSize(data),
mTotalSize);
mTrashPreference.setStorageSize(getTrashSize(data, profileData), mTotalSize);
mTrashPreference.setStorageSize(getTrashSize(data), mTotalSize);
if (mSystemPreference != null) {
// Everything else that hasn't already been attributed is tracked as
// belonging to system.
// TODO(b/170918505): Should revamp system size calculation with the data
// from media provider.
long attributedSize = 0;
for (int i = 0; i < result.size(); i++) {
final StorageAsyncLoader.AppsStorageResult otherData = result.valueAt(i);
@@ -385,6 +386,7 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
+ otherData.otherAppsSize;
attributedSize += otherData.externalStats.totalBytes
- otherData.externalStats.appBytes;
attributedSize -= otherData.duplicateCodeSize;
}
final long systemSize = Math.max(TrafficStats.GB_IN_BYTES, mUsedBytes - attributedSize);
@@ -404,47 +406,28 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
private void launchPublicStorageIntent() {
final Intent intent = mVolume.buildBrowseIntent();
if (intent != null) {
mContext.startActivity(intent);
if (intent == null) {
return;
}
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
}
private void launchActivityWithUri(Uri dataUri) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(dataUri);
mContext.startActivity(intent);
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
}
private long getImagesSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.photosAppsSize + data.externalStats.imageBytes
+ data.externalStats.videoBytes
+ profileData.photosAppsSize + profileData.externalStats.imageBytes
+ profileData.externalStats.videoBytes;
} else {
return data.photosAppsSize + data.externalStats.imageBytes
+ data.externalStats.videoBytes;
}
private long getImagesSize(StorageAsyncLoader.AppsStorageResult data) {
return data.photosAppsSize + data.externalStats.imageBytes + data.externalStats.videoBytes;
}
private long getVideosSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.videoAppsSize + profileData.videoAppsSize;
} else {
return data.videoAppsSize;
}
private long getVideosSize(StorageAsyncLoader.AppsStorageResult data) {
return data.videoAppsSize;
}
private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.musicAppsSize + data.externalStats.audioBytes
+ profileData.musicAppsSize + profileData.externalStats.audioBytes;
} else {
return data.musicAppsSize + data.externalStats.audioBytes;
}
private long getAudiosSize(StorageAsyncLoader.AppsStorageResult data) {
return data.musicAppsSize + data.externalStats.audioBytes;
}
private void launchAppsIntent() {
@@ -463,13 +446,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
Utils.launchIntent(mFragment, intent);
}
private long getAppsSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.otherAppsSize + profileData.otherAppsSize;
} else {
return data.otherAppsSize;
}
private long getAppsSize(StorageAsyncLoader.AppsStorageResult data) {
return data.otherAppsSize;
}
private void launchGamesIntent() {
@@ -486,13 +464,8 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
Utils.launchIntent(mFragment, intent);
}
private long getGamesSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.gamesSize + profileData.gamesSize;
} else {
return data.gamesSize;
}
private long getGamesSize(StorageAsyncLoader.AppsStorageResult data) {
return data.gamesSize;
}
private Bundle getWorkAnnotatedBundle(int additionalCapacity) {
@@ -502,26 +475,12 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
return args;
}
private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
if (profileData != null) {
return data.externalStats.totalBytes
- data.externalStats.audioBytes
- data.externalStats.videoBytes
- data.externalStats.imageBytes
- data.externalStats.appBytes
+ profileData.externalStats.totalBytes
- profileData.externalStats.audioBytes
- profileData.externalStats.videoBytes
- profileData.externalStats.imageBytes
- profileData.externalStats.appBytes;
} else {
return data.externalStats.totalBytes
- data.externalStats.audioBytes
- data.externalStats.videoBytes
- data.externalStats.imageBytes
- data.externalStats.appBytes;
}
private long getDocumentsAndOtherSize(StorageAsyncLoader.AppsStorageResult data) {
return data.externalStats.totalBytes
- data.externalStats.audioBytes
- data.externalStats.videoBytes
- data.externalStats.imageBytes
- data.externalStats.appBytes;
}
private void launchTrashIntent() {
@@ -530,12 +489,11 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
if (intent.resolveActivity(mPackageManager) == null) {
EmptyTrashFragment.show(mFragment);
} else {
mContext.startActivity(intent);
mContext.startActivityAsUser(intent, new UserHandle(mUserId));
}
}
private long getTrashSize(StorageAsyncLoader.AppsStorageResult data,
StorageAsyncLoader.AppsStorageResult profileData) {
private long getTrashSize(StorageAsyncLoader.AppsStorageResult data) {
// TODO(170918505): Implement it.
return 0L;
}

View File

@@ -1,138 +0,0 @@
/*
* Copyright (C) 2017 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.settings.deviceinfo.storage;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.storage.VolumeInfo;
import android.util.SparseArray;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.util.Preconditions;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settingslib.core.AbstractPreferenceController;
/**
* Defines a {@link AbstractPreferenceController} which handles a single profile of the primary
* user.
*/
public class UserProfileController extends AbstractPreferenceController implements
PreferenceControllerMixin, StorageAsyncLoader.ResultHandler,
UserIconLoader.UserIconHandler {
private static final String PREFERENCE_KEY_BASE = "pref_profile_";
private StorageItemPreference mStoragePreference;
private UserInfo mUser;
private long mTotalSizeBytes;
private final int mPreferenceOrder;
public UserProfileController(Context context, UserInfo info, int preferenceOrder) {
super(context);
mUser = Preconditions.checkNotNull(info);
mPreferenceOrder = preferenceOrder;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return PREFERENCE_KEY_BASE + mUser.id;
}
@Override
public void displayPreference(PreferenceScreen screen) {
mStoragePreference = new StorageItemPreference(screen.getContext());
mStoragePreference.setOrder(mPreferenceOrder);
mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
mStoragePreference.setTitle(mUser.name);
screen.addPreference(mStoragePreference);
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (preference != null && mStoragePreference == preference) {
final Bundle args = new Bundle();
args.putInt(StorageProfileFragment.USER_ID_EXTRA, mUser.id);
args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
new SubSettingLauncher(mContext)
.setDestination(StorageProfileFragment.class.getName())
.setArguments(args)
.setTitleText(mUser.name)
.setSourceMetricsCategory(SettingsEnums.DEVICEINFO_STORAGE)
.launch();
return true;
}
return false;
}
@Override
public void handleResult(SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
Preconditions.checkNotNull(stats);
int userId = mUser.id;
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
if (result != null) {
setSize(result.externalStats.totalBytes
+ result.otherAppsSize
+ result.videoAppsSize
+ result.musicAppsSize
+ result.gamesSize,
mTotalSizeBytes);
}
}
/**
* Sets the size for the preference using a byte count.
*/
public void setSize(long size, long totalSize) {
if (mStoragePreference != null) {
mStoragePreference.setStorageSize(size, totalSize);
}
}
public void setTotalSize(long totalSize) {
mTotalSizeBytes = totalSize;
}
@Override
public void handleUserIcons(SparseArray<Drawable> fetchedIcons) {
Drawable userIcon = fetchedIcons.get(mUser.id);
if (userIcon != null) {
mStoragePreference.setIcon(applyTint(mContext, userIcon));
}
}
private static Drawable applyTint(Context context, Drawable icon) {
icon = icon.mutate();
icon.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
return icon;
}
}

View File

@@ -36,9 +36,7 @@ com.android.settings.datausage.DataUsageList
com.android.settings.datausage.DataUsageSummary
com.android.settings.datetime.timezone.TimeZoneSettings
com.android.settings.development.compat.PlatformCompatDashboard
com.android.settings.deviceinfo.PrivateVolumeSettings
com.android.settings.deviceinfo.PublicVolumeSettings
com.android.settings.deviceinfo.StorageProfileFragment
com.android.settings.deviceinfo.legal.ModuleLicensesDashboard
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation

View File

@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -112,7 +113,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
// We should have the NoSecondaryUserController.
@@ -122,15 +124,17 @@ public class SecondaryUserControllerTest {
@Test
public void getSecondaryUserControllers_notWorkProfile_addSecondaryUserController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = new UserInfo();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(false);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
@@ -139,20 +143,41 @@ public class SecondaryUserControllerTest {
@Test
public void getSecondaryUserControllers_workProfile_addNoSecondaryUserController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = new UserInfo();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(true);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
}
@Test
public void getSecondaryUserControllers_notWorkProfileWorkProfileOnly_addNoSecondController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(false);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
true /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
}
@Test
public void profilesOfPrimaryUserAreIgnored() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
@@ -164,7 +189,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
@@ -206,7 +232,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
// We should have the NoSecondaryUserController.

View File

@@ -94,7 +94,8 @@ public class StorageItemPreferenceControllerTest {
mVolume = spy(new VolumeInfo("id", 0, null, "id"));
// Note: null is passed as the Lifecycle because we are handling it outside of the normal
// Settings fragment lifecycle for test purposes.
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp);
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
false /* isWorkProfile */);
mPreference = new StorageItemPreference(mContext);
// Inflate the preference and the widget.
@@ -165,7 +166,7 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(argumentCaptor.capture());
verify(mContext).startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(fakeBrowseAction);
@@ -176,11 +177,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -192,11 +194,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.AUDIOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -240,7 +243,8 @@ public class StorageItemPreferenceControllerTest {
@Test
public void launchAppsIntent_forWork_settingsIntent() {
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp, true);
mController = new FakeStorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
true /* isWorkProfile */);
mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
mController.handlePreferenceTreeClick(mPreference);
@@ -270,11 +274,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -304,11 +309,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -468,4 +474,20 @@ public class StorageItemPreferenceControllerTest {
when(resources.getString(anyInt())).thenReturn("");
return context;
}
private static class FakeStorageItemPreferenceController
extends StorageItemPreferenceController {
private static final int CURRENT_USER_ID = 10;
FakeStorageItemPreferenceController(Context context, Fragment hostFragment,
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
super(context, hostFragment, volume, svp, isWorkProfile);
}
@Override
int getCurrentUserId() {
return CURRENT_USER_ID;
}
}
}

View File

@@ -1,138 +0,0 @@
/*
* Copyright (C) 2017 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.settings.deviceinfo.storage;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.drawable.UserIconDrawable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class UserProfileControllerTest {
private static final String TEST_NAME = "Fred";
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private UserProfileController mController;
private UserInfo mPrimaryProfile;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
mPrimaryProfile = new UserInfo();
mController = new UserProfileController(mContext, mPrimaryProfile, 0);
when(mScreen.getContext()).thenReturn(mContext);
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
mController.displayPreference(mScreen);
}
@Test
public void controllerAddsPrimaryProfilePreference() {
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
assertThat(preference.getKey()).isEqualTo("pref_profile_10");
}
@Test
public void tappingProfilePreferenceSendsToStorageProfileFragment() {
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
final Intent intent = intentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
.isEqualTo(StorageProfileFragment.class.getName());
}
@Test
public void acceptingResultUpdatesPreferenceSize() {
final SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
final StorageAsyncLoader.AppsStorageResult userResult =
new StorageAsyncLoader.AppsStorageResult();
userResult.externalStats =
new StorageStatsSource.ExternalStorageStats(
99 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES, 0);
result.put(10, userResult);
mController.handleResult(result);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getSummary()).isEqualTo("0.10 GB");
}
@Test
public void iconCallbackChangesPreferenceIcon() {
final SparseArray<Drawable> icons = new SparseArray<>();
final UserIconDrawable drawable = mock(UserIconDrawable.class);
when(drawable.mutate()).thenReturn(drawable);
icons.put(mPrimaryProfile.id, drawable);
mController.handleUserIcons(icons);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getIcon()).isEqualTo(drawable);
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2017 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.settings.deviceinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.os.Looper;
import android.util.SparseArray;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class StorageProfileFragmentTest {
@Captor
private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
@Test
@UiThreadTest
public void verifyAppSizesAreNotZeroedOut() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
StorageProfileFragment fragment = new StorageProfileFragment();
StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
result.musicAppsSize = 100;
result.otherAppsSize = 200;
result.gamesSize = 300;
result.videoAppsSize = 400;
result.externalStats = new StorageStatsSource.ExternalStorageStats(6, 1, 2, 3, 0);
SparseArray<StorageAsyncLoader.AppsStorageResult> resultsArray = new SparseArray<>();
resultsArray.put(0, result);
fragment.setPreferenceController(controller);
fragment.onLoadFinished(null, resultsArray);
MockitoAnnotations.initMocks(this);
verify(controller).onLoadFinished(mCaptor.capture(), anyInt());
StorageAsyncLoader.AppsStorageResult extractedResult = mCaptor.getValue().get(0);
assertThat(extractedResult.musicAppsSize).isEqualTo(100);
assertThat(extractedResult.videoAppsSize).isEqualTo(400);
assertThat(extractedResult.otherAppsSize).isEqualTo(200);
assertThat(extractedResult.gamesSize).isEqualTo(300);
assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
assertThat(extractedResult.externalStats.totalBytes).isEqualTo(6);
}
}