Add support for user profiles to the Storage Settings.
This adds new preferences for each profile (such as the work profile) and defines a new view for viewing the storage breakdown for the individual profile. The functionality closely mimics the presentation on the main view, but without the system-wide breakdown and without any additional users/profiles. Bug: 34715777 Test: Settings Robotests Change-Id: I19d449b648c6566331fd02e45c2e45f8c74ea7e7
This commit is contained in:
@@ -16,40 +16,50 @@
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/storage_settings">
|
||||
android:title="@string/storage_settings"
|
||||
android:orderingFromXml="false">
|
||||
<com.android.settings.deviceinfo.storage.StorageSummaryDonutPreference
|
||||
android:key="pref_summary" />
|
||||
android:key="pref_summary"
|
||||
android:order="0" />
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_photos_videos"
|
||||
android:title="@string/storage_photos_videos">
|
||||
android:title="@string/storage_photos_videos"
|
||||
android:order="1" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_music_audio"
|
||||
android:title="@string/storage_music_audio">
|
||||
android:title="@string/storage_music_audio"
|
||||
android:order="2" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_games"
|
||||
android:title="@string/storage_games">
|
||||
android:title="@string/storage_games"
|
||||
android:order="3" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_other_apps"
|
||||
android:title="@string/storage_other_apps">
|
||||
android:title="@string/storage_other_apps"
|
||||
android:order="4" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_files"
|
||||
android:title="@string/storage_files">
|
||||
android:title="@string/storage_files"
|
||||
android:order="5" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_system"
|
||||
android:title="@string/storage_detail_system">
|
||||
android:title="@string/storage_detail_system"
|
||||
android:order="100" >
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<PreferenceCategory
|
||||
android:key="pref_secondary_users"
|
||||
android:title="@string/storage_other_users" />
|
||||
android:title="@string/storage_other_users"
|
||||
android:order="200" />
|
||||
<Preference
|
||||
android:key="manage_storage"
|
||||
android:title="@string/storage_menu_manage"
|
||||
android:icon="@drawable/ic_settings_storage"
|
||||
android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
|
||||
android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings"
|
||||
android:order="300" >
|
||||
</Preference>
|
||||
</PreferenceScreen>
|
41
res/xml/storage_profile_fragment.xml
Normal file
41
res/xml/storage_profile_fragment.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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.
|
||||
-->
|
||||
|
||||
<!-- Layout for the storage breakdown for a profile of the primary user. -->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/storage_settings">
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_photos_videos"
|
||||
android:title="@string/storage_photos_videos">
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_music_audio"
|
||||
android:title="@string/storage_music_audio">
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_games"
|
||||
android:title="@string/storage_games">
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_other_apps"
|
||||
android:title="@string/storage_other_apps">
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
|
||||
android:key="pref_files"
|
||||
android:title="@string/storage_files">
|
||||
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
|
||||
</PreferenceScreen>
|
@@ -65,6 +65,7 @@ import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.preference.PreferenceFrameLayout;
|
||||
import android.provider.ContactsContract.CommonDataKinds;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
@@ -1258,4 +1259,21 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
(user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
|
||||
&& user.profileGroupId == profile.profileGroupId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to initalize a volume with the given bundle. If it is a valid, private, and readable
|
||||
* {@link VolumeInfo}, it is returned. If it is not valid, null is returned.
|
||||
*/
|
||||
@Nullable
|
||||
public static VolumeInfo maybeInitializeVolume(StorageManager sm, Bundle bundle) {
|
||||
final String volumeId = bundle.getString(VolumeInfo.EXTRA_VOLUME_ID,
|
||||
VolumeInfo.ID_PRIVATE_INTERNAL);
|
||||
VolumeInfo volume = sm.findVolumeById(volumeId);
|
||||
return isVolumeValid(volume) ? volume : null;
|
||||
}
|
||||
|
||||
private static boolean isVolumeValid(VolumeInfo volume) {
|
||||
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
|
||||
&& volume.isMountedReadable();
|
||||
}
|
||||
}
|
||||
|
@@ -25,11 +25,11 @@ import android.os.UserManager;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.PackageManagerWrapperImpl;
|
||||
import com.android.settings.applications.UserManagerWrapper;
|
||||
import com.android.settings.applications.UserManagerWrapperImpl;
|
||||
@@ -48,7 +48,6 @@ import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StorageDashboardFragment extends DashboardFragment
|
||||
implements LoaderManager.LoaderCallbacks<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
|
||||
@@ -61,11 +60,6 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
private StorageItemPreferenceController mPreferenceController;
|
||||
private List<PreferenceController> mSecondaryUsers;
|
||||
|
||||
private boolean isVolumeValid() {
|
||||
return (mVolume != null) && (mVolume.getType() == VolumeInfo.TYPE_PRIVATE)
|
||||
&& mVolume.isMountedReadable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
@@ -101,7 +95,8 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
// Initialize the storage sizes that we can quickly calc.
|
||||
final Context context = getActivity();
|
||||
StorageManager sm = context.getSystemService(StorageManager.class);
|
||||
if (!initializeVolume(sm, getArguments())) {
|
||||
mVolume = Utils.maybeInitializeVolume(sm, getArguments());
|
||||
if (mVolume == null) {
|
||||
getActivity().finish();
|
||||
return;
|
||||
}
|
||||
@@ -156,17 +151,6 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
return controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the volume with a given bundle and returns if the volume is valid.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean initializeVolume(StorageManager sm, Bundle bundle) {
|
||||
String volumeId = bundle.getString(VolumeInfo.EXTRA_VOLUME_ID,
|
||||
VolumeInfo.ID_PRIVATE_INTERNAL);
|
||||
mVolume = sm.findVolumeById(volumeId);
|
||||
return isVolumeValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the secondary user controller sizes.
|
||||
*/
|
||||
@@ -174,13 +158,10 @@ public class StorageDashboardFragment extends DashboardFragment
|
||||
SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
|
||||
for (int i = 0, size = controllers.size(); i < size; i++) {
|
||||
PreferenceController controller = controllers.get(i);
|
||||
if (controller instanceof SecondaryUserController) {
|
||||
SecondaryUserController userController = (SecondaryUserController) controller;
|
||||
int userId = userController.getUser().id;
|
||||
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
|
||||
if (result != null) {
|
||||
userController.setSize(result.externalStats.totalBytes);
|
||||
}
|
||||
if (controller instanceof StorageAsyncLoader.ResultHandler) {
|
||||
StorageAsyncLoader.ResultHandler userController =
|
||||
(StorageAsyncLoader.ResultHandler) controller;
|
||||
userController.handleResult(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
128
src/com/android/settings/deviceinfo/StorageProfileFragment.java
Normal file
128
src/com/android/settings/deviceinfo/StorageProfileFragment.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.LoaderManager;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
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 com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.PackageManagerWrapperImpl;
|
||||
import com.android.settings.applications.UserManagerWrapperImpl;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
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.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(mUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getLoaderManager().initLoader(APPS_JOB_ID, Bundle.EMPTY, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.SETTINGS_STORAGE_PROFILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.storage_profile_fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> controllers = new ArrayList<>();
|
||||
final StorageManager sm = context.getSystemService(StorageManager.class);
|
||||
mPreferenceController = new StorageItemPreferenceController(context, this,
|
||||
mVolume, new StorageManagerVolumeProvider(sm));
|
||||
controllers.add(mPreferenceController);
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) {
|
||||
Context context = getContext();
|
||||
return new StorageAsyncLoader(context,
|
||||
new UserManagerWrapperImpl(context.getSystemService(UserManager.class)),
|
||||
mVolume.fsUuid,
|
||||
new StorageStatsSource(context),
|
||||
new PackageManagerWrapperImpl(context.getPackageManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
|
||||
SparseArray<AppsStorageResult> result) {
|
||||
mPreferenceController.onLoadFinished(result.get(mUserId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<SparseArray<AppsStorageResult>> loader) {
|
||||
}
|
||||
}
|
@@ -23,6 +23,7 @@ import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.UserManagerWrapper;
|
||||
@@ -35,10 +36,12 @@ import java.util.List;
|
||||
* SecondaryUserController controls the preferences on the Storage screen which had to do with
|
||||
* secondary users.
|
||||
*/
|
||||
public class SecondaryUserController extends PreferenceController {
|
||||
public class SecondaryUserController extends PreferenceController implements
|
||||
StorageAsyncLoader.ResultHandler {
|
||||
// PreferenceGroupKey to try to add our preference onto.
|
||||
private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
|
||||
private static final String PREFERENCE_KEY_BASE = "pref_user_";
|
||||
private static final int USER_PROFILE_INSERTION_LOCATION = 6;
|
||||
private static final int SIZE_NOT_SET = -1;
|
||||
|
||||
private @NonNull UserInfo mUser;
|
||||
@@ -59,7 +62,13 @@ public class SecondaryUserController extends PreferenceController {
|
||||
List<UserInfo> infos = userManager.getUsers();
|
||||
for (int i = 0, size = infos.size(); i < size; i++) {
|
||||
UserInfo info = infos.get(i);
|
||||
if (info.equals(primaryUser)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info == null || Utils.isProfileOf(primaryUser, info)) {
|
||||
controllers.add(new UserProfileController(context, info,
|
||||
USER_PROFILE_INSERTION_LOCATION));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -131,6 +140,14 @@ public class SecondaryUserController extends PreferenceController {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleResult(SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
|
||||
int userId = getUser().id;
|
||||
StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
|
||||
if (result != null) {
|
||||
setSize(result.externalStats.totalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
private static class NoSecondaryUserController extends PreferenceController {
|
||||
public NoSecondaryUserController(Context context) {
|
||||
super(context);
|
||||
|
@@ -23,10 +23,9 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.SparseArray;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.settings.applications.PackageManagerWrapper;
|
||||
import com.android.settings.applications.UserManagerWrapper;
|
||||
@@ -34,7 +33,6 @@ import com.android.settings.utils.AsyncLoader;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* StorageAsyncLoader is a Loader which loads categorized app information and external stats for all
|
||||
@@ -118,4 +116,12 @@ public class StorageAsyncLoader
|
||||
public long otherAppsSize;
|
||||
public StorageStatsSource.ExternalStorageStats externalStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* ResultHandler defines a destination of data which can handle a result from
|
||||
* {@link StorageAsyncLoader}.
|
||||
*/
|
||||
public interface ResultHandler {
|
||||
void handleResult(SparseArray<AppsStorageResult> result);
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
@@ -36,12 +35,12 @@ import com.android.settings.Utils;
|
||||
import com.android.settings.applications.ManageApplications;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.deviceinfo.StorageMeasurement;
|
||||
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -70,7 +69,7 @@ public class StorageItemPreferenceController extends PreferenceController {
|
||||
private final MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
private final StorageVolumeProvider mSvp;
|
||||
private VolumeInfo mVolume;
|
||||
private final int mUserId;
|
||||
private int mUserId;
|
||||
private long mSystemSize;
|
||||
|
||||
private StorageItemPreferenceAlternate mPhotoPreference;
|
||||
@@ -89,8 +88,7 @@ public class StorageItemPreferenceController extends PreferenceController {
|
||||
mVolume = volume;
|
||||
mSvp = svp;
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
UserManager um = mContext.getSystemService(UserManager.class);
|
||||
mUserId = um.getUserHandle();
|
||||
mUserId = UserHandle.myUserId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,6 +155,13 @@ public class StorageItemPreferenceController extends PreferenceController {
|
||||
mVolume = volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user id for which this preference controller is handling.
|
||||
*/
|
||||
public void setUserId(int userId) {
|
||||
mUserId = userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mPhotoPreference = (StorageItemPreferenceAlternate) screen.findPreference(PHOTO_KEY);
|
||||
@@ -173,7 +178,9 @@ public class StorageItemPreferenceController extends PreferenceController {
|
||||
mAudioPreference.setStorageSize(data.musicAppsSize + data.externalStats.audioBytes);
|
||||
mGamePreference.setStorageSize(data.gamesSize);
|
||||
mAppPreference.setStorageSize(data.otherAppsSize);
|
||||
mSystemPreference.setStorageSize(mSystemSize);
|
||||
if (mSystemPreference != null) {
|
||||
mSystemPreference.setStorageSize(mSystemSize);
|
||||
}
|
||||
|
||||
long unattributedBytes = data.externalStats.totalBytes - data.externalStats.audioBytes
|
||||
- data.externalStats.videoBytes - data.externalStats.imageBytes;
|
||||
@@ -188,6 +195,20 @@ public class StorageItemPreferenceController extends PreferenceController {
|
||||
mSystemSize = systemSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of keys used by this preference controller.
|
||||
*/
|
||||
public static List<String> getUsedKeys() {
|
||||
List<String> list = new ArrayList<>();
|
||||
list.add(PHOTO_KEY);
|
||||
list.add(AUDIO_KEY);
|
||||
list.add(GAME_KEY);
|
||||
list.add(OTHER_APPS_KEY);
|
||||
list.add(SYSTEM_KEY);
|
||||
list.add(FILES_KEY);
|
||||
return list;
|
||||
}
|
||||
|
||||
private Intent getPhotosIntent() {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
||||
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.deviceinfo.StorageProfileFragment;
|
||||
import com.android.settingslib.drawer.SettingsDrawerActivity;
|
||||
|
||||
/**
|
||||
* Defines a {@link PreferenceController} which handles a single profile of the primary user.
|
||||
*/
|
||||
public class UserProfileController extends PreferenceController implements
|
||||
StorageAsyncLoader.ResultHandler {
|
||||
private static final String PREFERENCE_KEY_BASE = "pref_profile_";
|
||||
private StorageItemPreferenceAlternate mStoragePreference;
|
||||
private UserInfo mUser;
|
||||
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 StorageItemPreferenceAlternate(mContext);
|
||||
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) {
|
||||
Bundle args = new Bundle(2);
|
||||
args.putInt(StorageProfileFragment.USER_ID_EXTRA, mUser.id);
|
||||
args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
|
||||
Intent intent = Utils.onBuildStartFragmentIntent(mContext,
|
||||
StorageProfileFragment.class.getName(), args, null, 0,
|
||||
mUser.name, false, MetricsProto.MetricsEvent.DEVICEINFO_STORAGE);
|
||||
intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
|
||||
mContext.startActivity(intent);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size for the preference using a byte count.
|
||||
*/
|
||||
public void setSize(long size) {
|
||||
if (mStoragePreference != null) {
|
||||
mStoragePreference.setStorageSize(size);
|
||||
}
|
||||
}
|
||||
}
|
@@ -45,6 +45,7 @@ import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
|
||||
import com.android.settings.datausage.DataUsageMeteredSettings;
|
||||
import com.android.settings.datausage.DataUsageSummary;
|
||||
import com.android.settings.deviceinfo.StorageDashboardFragment;
|
||||
import com.android.settings.deviceinfo.StorageProfileFragment;
|
||||
import com.android.settings.deviceinfo.StorageSettings;
|
||||
import com.android.settings.display.ScreenZoomSettings;
|
||||
import com.android.settings.enterprise.EnterprisePrivacySettings;
|
||||
|
@@ -4,4 +4,5 @@ com.android.settings.notification.ZenModePrioritySettings
|
||||
com.android.settings.inputmethod.InputAndGestureSettings
|
||||
com.android.settings.accounts.AccountDetailDashboardFragment
|
||||
com.android.settings.gestures.GestureSettings
|
||||
com.android.settings.fuelgauge.PowerUsageDetail
|
||||
com.android.settings.fuelgauge.PowerUsageDetail
|
||||
com.android.settings.deviceinfo.StorageProfileFragment
|
||||
|
@@ -1,13 +1,25 @@
|
||||
package com.android.settings;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.LinkAddress;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.storage.DiskInfo;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.text.format.DateUtils;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -16,9 +28,7 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
import java.net.InetAddress;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
@@ -97,4 +107,13 @@ public class UtilsTest {
|
||||
|
||||
assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeVolumeDoesntBreakOnNullVolume() {
|
||||
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
|
||||
StorageManager storageManager = mock(StorageManager.class, RETURNS_DEEP_STUBS);
|
||||
when(storageManager.findVolumeById(anyString())).thenReturn(info);
|
||||
|
||||
Utils.maybeInitializeVolume(storageManager, new Bundle());
|
||||
}
|
||||
}
|
||||
|
@@ -79,11 +79,4 @@ public class StorageDashboardFragmentTest {
|
||||
assertThat(indexRes).isNotNull();
|
||||
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeVolumeDoesntBreakOnNullVolume() {
|
||||
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
|
||||
when(mStorageManager.findVolumeById(anyString())).thenReturn(info);
|
||||
mFragment.initializeVolume(mStorageManager, new Bundle());
|
||||
}
|
||||
}
|
@@ -28,11 +28,13 @@ import android.content.pm.UserInfo;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.applications.UserManagerWrapper;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -130,7 +132,7 @@ public class SecondaryUserControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void profilesOfPrimaryUserAreIgnored() throws Exception {
|
||||
public void profilesOfPrimaryUserAreNotIgnored() throws Exception {
|
||||
ArrayList<UserInfo> userInfos = new ArrayList<>();
|
||||
UserInfo secondaryUser = new UserInfo();
|
||||
secondaryUser.id = mPrimaryUser.id;
|
||||
@@ -142,7 +144,31 @@ public class SecondaryUserControllerTest {
|
||||
List<PreferenceController> controllers =
|
||||
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
|
||||
|
||||
assertThat(controllers).hasSize(1);
|
||||
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
|
||||
assertThat(controllers).hasSize(2);
|
||||
assertThat(controllers.get(0) instanceof UserProfileController).isTrue();
|
||||
assertThat(controllers.get(1) instanceof SecondaryUserController).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerUpdatesPreferenceOnAcceptingResult() throws Exception {
|
||||
mPrimaryUser.name = TEST_NAME;
|
||||
mPrimaryUser.id = 10;
|
||||
PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
PreferenceGroup group = mock(PreferenceGroup.class);
|
||||
when(screen.findPreference(anyString())).thenReturn(group);
|
||||
when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
|
||||
mController.displayPreference(screen);
|
||||
StorageAsyncLoader.AppsStorageResult userResult =
|
||||
new StorageAsyncLoader.AppsStorageResult();
|
||||
SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
|
||||
userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
|
||||
result.put(10, userResult);
|
||||
|
||||
mController.handleResult(result);
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(group).addPreference(argumentCaptor.capture());
|
||||
Preference preference = argumentCaptor.getValue();
|
||||
|
||||
assertThat(preference.getSummary()).isEqualTo("99.00B");
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.applications.UserManagerWrapper;
|
||||
import com.android.settings.deviceinfo.StorageProfileFragment;
|
||||
import com.android.settingslib.applications.StorageStatsSource;
|
||||
|
||||
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.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class UserProfileControllerTest {
|
||||
private static final String TEST_NAME = "Fred";
|
||||
|
||||
@Mock
|
||||
private UserManagerWrapper mUserManager;
|
||||
|
||||
private Context mContext;
|
||||
private UserProfileController mController;
|
||||
private UserInfo mPrimaryProfile;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
mPrimaryProfile = new UserInfo();
|
||||
mController = new UserProfileController(mContext, mPrimaryProfile, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controllerAddsPrimaryProfilePreference() throws Exception {
|
||||
mPrimaryProfile.name = TEST_NAME;
|
||||
mPrimaryProfile.id = 10;
|
||||
PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
mController.displayPreference(screen);
|
||||
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(screen).addPreference(argumentCaptor.capture());
|
||||
Preference preference = argumentCaptor.getValue();
|
||||
|
||||
assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
|
||||
assertThat(preference.getKey()).isEqualTo("pref_profile_10");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
|
||||
mPrimaryProfile.name = TEST_NAME;
|
||||
mPrimaryProfile.id = 10;
|
||||
PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
mController.displayPreference(screen);
|
||||
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(screen).addPreference(argumentCaptor.capture());
|
||||
Preference preference = argumentCaptor.getValue();
|
||||
assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
|
||||
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||
verify(mContext).startActivity(intentCaptor.capture());
|
||||
|
||||
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() throws Exception {
|
||||
mPrimaryProfile.name = TEST_NAME;
|
||||
mPrimaryProfile.id = 10;
|
||||
PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
mController.displayPreference(screen);
|
||||
SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
|
||||
StorageAsyncLoader.AppsStorageResult userResult =
|
||||
new StorageAsyncLoader.AppsStorageResult();
|
||||
userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
|
||||
result.put(10, userResult);
|
||||
|
||||
mController.handleResult(result);
|
||||
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||
verify(screen).addPreference(argumentCaptor.capture());
|
||||
Preference preference = argumentCaptor.getValue();
|
||||
|
||||
assertThat(preference.getSummary()).isEqualTo("99.00B");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user