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:
@@ -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>
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
|
@@ -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.
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user