diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7f73d2cc899..8a5539b4466 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1296,7 +1296,7 @@
@@ -1979,13 +1979,6 @@
android:value="true" />
-
-
-
-
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout-land/storage_summary_donut.xml b/res/layout-land/storage_summary_donut.xml
deleted file mode 100644
index 2e5ee93a085..00000000000
--- a/res/layout-land/storage_summary_donut.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout-sw360dp/storage_summary_donut.xml b/res/layout-sw360dp/storage_summary_donut.xml
deleted file mode 100644
index 2e5ee93a085..00000000000
--- a/res/layout-sw360dp/storage_summary_donut.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/preference_storage_action.xml b/res/layout/preference_storage_action.xml
deleted file mode 100644
index 19d776324f9..00000000000
--- a/res/layout/preference_storage_action.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/res/layout/storage_summary_donut.xml b/res/layout/storage_summary_donut.xml
deleted file mode 100644
index cc4df2046f7..00000000000
--- a/res/layout/storage_summary_donut.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/storage_volume.xml b/res/layout/storage_volume.xml
deleted file mode 100644
index ca368b9488d..00000000000
--- a/res/layout/storage_volume.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/menu/storage_volume.xml b/res/menu/storage_volume.xml
index 87f75152ce3..422355d0fb7 100644
--- a/res/menu/storage_volume.xml
+++ b/res/menu/storage_volume.xml
@@ -29,12 +29,10 @@
android:title="@string/storage_menu_format" />
+ android:title="@string/storage_menu_format_public" />
+ android:title="@string/storage_menu_format_private" />
@@ -43,6 +41,5 @@
android:title="@string/storage_menu_free" />
+ android:title="@string/storage_menu_forget" />
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index d426411a7f1..37e71e2174e 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -30,9 +30,4 @@
160dp
-
- 30sp
-
- 14sp
-
diff --git a/res/values-sw360dp/dimens.xml b/res/values-sw360dp/dimens.xml
index b81a98a695c..23a11761ebb 100755
--- a/res/values-sw360dp/dimens.xml
+++ b/res/values-sw360dp/dimens.xml
@@ -25,8 +25,4 @@
22dp
-
- 30sp
-
- 14sp
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index bde52886e69..573d906b166 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -139,15 +139,6 @@
-
-
-
-
-
-
-
-
-
diff --git a/res/values/colors.xml b/res/values/colors.xml
index ae288ec3659..e107b65ce42 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -189,4 +189,7 @@
#ffe1bee7
#fff48fb1
#ffef9a9a
+
+
+ #5f6368
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index e56b2c81b68..304feb82021 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -295,6 +295,10 @@
24dp
+
+ 32dp
+ 18dp
+
16dp
@@ -321,19 +325,6 @@
12dp
8dp
-
- 16dp
-
- 45sp
-
- 20sp
-
- 21sp
-
- 10sp
-
- 4dp
-
66dp
100dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c1c165e7362..72f57f48f2b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3426,11 +3426,6 @@
Erases all data on the SD card, such as music and photos
-
- Clear cached data?
-
- This will clear cached data for all apps.
-
MTP or PTP function is active
@@ -3482,8 +3477,6 @@
Forget
Set up
-
- Explore
Free up space
@@ -3520,14 +3513,10 @@
Portable storage
-
- %1$s used of %2$s
^1 ^2
Used of %1$s
-
- Total used of %1$s
%1$s is mounted
@@ -3555,10 +3544,6 @@
This ^1 is corrupted.
\n\nTo use this ^1, you have to set it up first.
-
- This device doesn\u2019t support this ^1.
-\n\nTo use this ^1 with this device, you have to set it up first.
-
After formatting, you can use this ^1 in other devices.
\n\nAll data on this ^1 will be erased. Consider backing up first.
@@ -3582,34 +3567,11 @@
All the apps, photos, and data stored on this ^1 will be lost forever.
-
- Apps
Images
-
- Videos
-
- Audio
-
- Cached data
-
- Other
-
- System
-
- Explore ^1
-
-
- Other includes shared files saved by apps, files downloaded from the internet or Bluetooth, Android files, and so on.
-\n\nTo see the visible contents of this ^1, tap Explore.
-
System includes files used to run Android version %s
-
- ^1 may have saved photos, music, apps, or other data, using ^2 of storage.
-\n\nTo view details, switch to ^1.
-
Set up your ^1
@@ -12604,6 +12566,8 @@
To get started, restart your device. Then you can add another SIM.
Continue
+
+ Yes
Restart
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 444ec72e9f1..d5376ec1357 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -281,4 +281,9 @@
- @*android:color/primary_device_default_settings_light
- @*android:color/accent_device_default_light
+
+
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index ac51a82e180..ec22cf0ac27 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -43,9 +43,9 @@
android:title="@string/accessibility_text_and_display_title"
settings:searchable="true"/>
-
-
-
-
-
-
-
-
-
-
diff --git a/res/xml/device_info_storage_volume.xml b/res/xml/device_info_storage_volume.xml
index cb02d9a9eae..47abe0dcecb 100644
--- a/res/xml/device_info_storage_volume.xml
+++ b/res/xml/device_info_storage_volume.xml
@@ -17,7 +17,6 @@
+ android:title="@string/storage_settings">
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index adc29d33d71..71d07127aa3 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -18,7 +18,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/storage_settings"
- android:orderingFromXml="false">
+ android:orderingFromXml="false"
+ settings:keywords="@string/keywords_storage">
+
+
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 95e68de1ca9..48793e9c93f 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -79,7 +79,6 @@ public class Settings extends SettingsActivity {
public static class DataSaverSummaryActivity extends SettingsActivity{ /* empty */ }
public static class DateTimeSettingsActivity extends SettingsActivity { /* empty */ }
public static class PrivateVolumeForgetActivity extends SettingsActivity { /* empty */ }
- public static class PrivateVolumeSettingsActivity extends SettingsActivity { /* empty */ }
public static class PublicVolumeSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiSettingsActivity extends SettingsActivity { /* empty */ }
public static class WifiSettings2Activity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index c08c14945cd..1ea7e177082 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -78,10 +78,8 @@ import com.android.settings.datetime.DateTimeSettings;
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.development.DevelopmentSettingsDashboardFragment;
import com.android.settings.deviceinfo.PrivateVolumeForget;
-import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.PublicVolumeSettings;
import com.android.settings.deviceinfo.StorageDashboardFragment;
-import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionSettings;
import com.android.settings.deviceinfo.legal.ModuleLicensesDashboard;
@@ -215,9 +213,7 @@ public class SettingsGateway {
ToggleDaltonizerPreferenceFragment.class.getName(),
ToggleReduceBrightColorsPreferenceFragment.class.getName(),
TextToSpeechSettings.class.getName(),
- StorageSettings.class.getName(),
PrivateVolumeForget.class.getName(),
- PrivateVolumeSettings.class.getName(),
PublicVolumeSettings.class.getName(),
DevelopmentSettingsDashboardFragment.class.getName(),
AndroidBeam.class.getName(),
diff --git a/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceController.java b/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceController.java
new file mode 100644
index 00000000000..38c32082b9a
--- /dev/null
+++ b/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceController.java
@@ -0,0 +1,53 @@
+/*
+ * 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.development.transcode;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * The controller (in the Media transcoding settings) indicating the user's preference to disable
+ * the cache for transcoding.
+ */
+public class TranscodeDisableCachePreferenceController extends TogglePreferenceController {
+ @VisibleForTesting
+ static final String TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY =
+ "persist.sys.fuse.disable_transcode_cache";
+
+ public TranscodeDisableCachePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return SystemProperties.getBoolean(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, false);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ SystemProperties.set(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, String.valueOf(isChecked));
+ return true;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/MigrateEstimateTask.java b/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
index 9198ade659f..03e2b045692 100644
--- a/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
+++ b/src/com/android/settings/deviceinfo/MigrateEstimateTask.java
@@ -16,8 +16,6 @@
package com.android.settings.deviceinfo;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.app.usage.ExternalStorageStats;
import android.app.usage.StorageStatsManager;
import android.content.Context;
@@ -37,6 +35,8 @@ import java.io.IOException;
import java.util.UUID;
public abstract class MigrateEstimateTask extends AsyncTask {
+ private static final String TAG = "MigrateEstimateTask";
+
private static final String EXTRA_SIZE_BYTES = "size_bytes";
/**
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
deleted file mode 100644
index 08d6ca462b4..00000000000
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * Copyright (C) 2015 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.Dialog;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.os.storage.StorageEventListener;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.os.storage.VolumeRecord;
-import android.provider.DocumentsContract;
-import android.text.TextUtils;
-import android.text.format.Formatter;
-import android.text.format.Formatter.BytesResult;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.EditText;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.Fragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.Settings.StorageUseActivity;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import com.android.settings.applications.manageapplications.ManageApplications;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.deviceinfo.StorageSettings.MountTask;
-import com.android.settingslib.deviceinfo.StorageMeasurement;
-import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementDetails;
-import com.android.settingslib.deviceinfo.StorageMeasurement.MeasurementReceiver;
-
-import com.google.android.collect.Lists;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Panel showing summary and actions for a {@link VolumeInfo#TYPE_PRIVATE}
- * storage volume.
- */
-public class PrivateVolumeSettings extends SettingsPreferenceFragment {
- // TODO: disable unmount when providing over MTP/PTP
- // TODO: warn when mounted read-only
-
- private static final String TAG = "PrivateVolumeSettings";
- private static final boolean LOGV = false;
-
- private static final String TAG_RENAME = "rename";
- private static final String TAG_OTHER_INFO = "otherInfo";
- private static final String TAG_SYSTEM_INFO = "systemInfo";
- private static final String TAG_USER_INFO = "userInfo";
- private static final String TAG_CONFIRM_CLEAR_CACHE = "confirmClearCache";
-
- private static final String EXTRA_VOLUME_SIZE = "volume_size";
-
- private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
-
- private static final int[] ITEMS_NO_SHOW_SHARED = new int[] {
- R.string.storage_detail_apps,
- R.string.storage_detail_system,
- };
-
- private static final int[] ITEMS_SHOW_SHARED = new int[] {
- R.string.storage_detail_apps,
- R.string.storage_detail_images,
- R.string.storage_detail_videos,
- R.string.storage_detail_audio,
- R.string.storage_detail_system,
- R.string.storage_detail_other,
- };
-
- private StorageManager mStorageManager;
- private UserManager mUserManager;
-
- private String mVolumeId;
- private VolumeInfo mVolume;
- private VolumeInfo mSharedVolume;
- private long mTotalSize;
- private long mSystemSize;
-
- private StorageMeasurement mMeasure;
-
- private UserInfo mCurrentUser;
-
- private StorageSummaryPreference mSummary;
- private List mItemPreferencePool = Lists.newArrayList();
- private List mHeaderPreferencePool = Lists.newArrayList();
- private int mHeaderPoolIndex;
- private int mItemPoolIndex;
-
- private Preference mExplore;
-
- private boolean mNeedsUpdate;
-
- private boolean isVolumeValid() {
- return (mVolume != null) && (mVolume.getType() == VolumeInfo.TYPE_PRIVATE)
- && mVolume.isMountedReadable();
- }
-
- public PrivateVolumeSettings() {
- setRetainInstance(true);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DEVICEINFO_STORAGE;
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final Context context = getActivity();
-
- mUserManager = context.getSystemService(UserManager.class);
- mStorageManager = context.getSystemService(StorageManager.class);
-
- mVolumeId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
- mVolume = mStorageManager.findVolumeById(mVolumeId);
-
- final long sharedDataSize = mVolume.getPath().getTotalSpace();
- mTotalSize = getArguments().getLong(EXTRA_VOLUME_SIZE, 0);
- mSystemSize = mTotalSize - sharedDataSize;
- if (LOGV) Log.v(TAG,
- "onCreate() mTotalSize: " + mTotalSize + " sharedDataSize: " + sharedDataSize);
-
- if (mTotalSize <= 0) {
- mTotalSize = sharedDataSize;
- mSystemSize = 0;
- }
-
- // Find the emulated shared storage layered above this private volume
- mSharedVolume = mStorageManager.findEmulatedForPrivate(mVolume);
-
- mMeasure = new StorageMeasurement(context, mVolume, mSharedVolume);
- mMeasure.setReceiver(mReceiver);
-
- if (!isVolumeValid()) {
- getActivity().finish();
- return;
- }
-
- addPreferencesFromResource(R.xml.device_info_storage_volume);
- getPreferenceScreen().setOrderingAsAdded(true);
-
- mSummary = new StorageSummaryPreference(getPrefContext());
- mCurrentUser = mUserManager.getUserInfo(UserHandle.myUserId());
-
- mExplore = buildAction(R.string.storage_menu_explore);
-
- mNeedsUpdate = true;
-
- setHasOptionsMenu(true);
- }
-
- private void setTitle() {
- getActivity().setTitle(mStorageManager.getBestVolumeDescription(mVolume));
- }
-
- private void update() {
- if (!isVolumeValid()) {
- getActivity().finish();
- return;
- }
-
- setTitle();
-
- // Valid options may have changed
- getActivity().invalidateOptionsMenu();
-
- final Context context = getActivity();
- final PreferenceScreen screen = getPreferenceScreen();
-
- screen.removeAll();
-
- addPreference(screen, mSummary);
-
- List allUsers = mUserManager.getUsers();
- final int userCount = allUsers.size();
- final boolean showHeaders = userCount > 1;
- final boolean showShared = (mSharedVolume != null) && mSharedVolume.isMountedReadable();
-
- mItemPoolIndex = 0;
- mHeaderPoolIndex = 0;
-
- int addedUserCount = 0;
- // Add current user and its profiles first
- for (int userIndex = 0; userIndex < userCount; ++userIndex) {
- final UserInfo userInfo = allUsers.get(userIndex);
- if (Utils.isProfileOf(mCurrentUser, userInfo)) {
- final PreferenceGroup details = showHeaders ?
- addCategory(screen, userInfo.name) : screen;
- addDetailItems(details, showShared, userInfo.id);
- ++addedUserCount;
- }
- }
-
- // Add rest of users
- if (userCount - addedUserCount > 0) {
- PreferenceGroup otherUsers = addCategory(screen,
- getText(R.string.storage_other_users));
- for (int userIndex = 0; userIndex < userCount; ++userIndex) {
- final UserInfo userInfo = allUsers.get(userIndex);
- if (!Utils.isProfileOf(mCurrentUser, userInfo)) {
- addItem(otherUsers, /* titleRes */ 0, userInfo.name, userInfo.id);
- }
- }
- }
-
- addItem(screen, R.string.storage_detail_cached, null, UserHandle.USER_NULL);
-
- if (showShared) {
- addPreference(screen, mExplore);
- }
-
- final long freeBytes = mVolume.getPath().getFreeSpace();
- final long usedBytes = mTotalSize - freeBytes;
-
- if (LOGV) Log.v(TAG, "update() freeBytes: " + freeBytes + " usedBytes: " + usedBytes);
-
- final BytesResult result = Formatter.formatBytes(getResources(), usedBytes, 0);
- mSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
- result.value, result.units));
- mSummary.setSummary(getString(R.string.storage_volume_used,
- Formatter.formatFileSize(context, mTotalSize)));
- mSummary.setPercent(usedBytes, mTotalSize);
-
- mMeasure.forceMeasure();
- mNeedsUpdate = false;
- }
-
- private void addPreference(PreferenceGroup group, Preference pref) {
- pref.setOrder(Preference.DEFAULT_ORDER);
- group.addPreference(pref);
- }
-
- private PreferenceCategory addCategory(PreferenceGroup group, CharSequence title) {
- PreferenceCategory category;
- if (mHeaderPoolIndex < mHeaderPreferencePool.size()) {
- category = mHeaderPreferencePool.get(mHeaderPoolIndex);
- } else {
- category = new PreferenceCategory(getPrefContext());
- mHeaderPreferencePool.add(category);
- }
- category.setTitle(title);
- category.removeAll();
- addPreference(group, category);
- ++mHeaderPoolIndex;
- return category;
- }
-
- private void addDetailItems(PreferenceGroup category, boolean showShared, int userId) {
- final int[] itemsToAdd = (showShared ? ITEMS_SHOW_SHARED : ITEMS_NO_SHOW_SHARED);
- for (int i = 0; i < itemsToAdd.length; ++i) {
- addItem(category, itemsToAdd[i], null, userId);
- }
- }
-
- private void addItem(PreferenceGroup group, int titleRes, CharSequence title, int userId) {
- if (titleRes == R.string.storage_detail_system) {
- if (mSystemSize <= 0) {
- Log.w(TAG, "Skipping System storage because its size is " + mSystemSize);
- return;
- }
- if (userId != UserHandle.myUserId()) {
- // Only display system on current user.
- return;
- }
- }
- StorageItemPreference item;
- if (mItemPoolIndex < mItemPreferencePool.size()) {
- item = mItemPreferencePool.get(mItemPoolIndex);
- } else {
- item = buildItem();
- mItemPreferencePool.add(item);
- }
- if (title != null) {
- item.setTitle(title);
- item.setKey(title.toString());
- } else {
- item.setTitle(titleRes);
- item.setKey(Integer.toString(titleRes));
- }
- item.setSummary(R.string.memory_calculating_size);
- item.userHandle = userId;
- addPreference(group, item);
- ++mItemPoolIndex;
- }
-
- private StorageItemPreference buildItem() {
- final StorageItemPreference item = new StorageItemPreference(getPrefContext());
- item.setIcon(R.drawable.empty_icon);
- return item;
- }
-
- private Preference buildAction(int titleRes) {
- final Preference pref = new Preference(getPrefContext());
- pref.setTitle(titleRes);
- pref.setKey(Integer.toString(titleRes));
- return pref;
- }
-
- static void setVolumeSize(Bundle args, long size) {
- args.putLong(EXTRA_VOLUME_SIZE, size);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- // Refresh to verify that we haven't been formatted away
- mVolume = mStorageManager.findVolumeById(mVolumeId);
- if (!isVolumeValid()) {
- getActivity().finish();
- return;
- }
-
- mStorageManager.registerListener(mStorageListener);
-
- if (mNeedsUpdate) {
- update();
- } else {
- setTitle();
- }
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mStorageManager.unregisterListener(mStorageListener);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mMeasure != null) {
- mMeasure.onDestroy();
- }
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- inflater.inflate(R.menu.storage_volume, menu);
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- if (!isVolumeValid()) return;
-
- final MenuItem rename = menu.findItem(R.id.storage_rename);
- final MenuItem mount = menu.findItem(R.id.storage_mount);
- final MenuItem unmount = menu.findItem(R.id.storage_unmount);
- final MenuItem format = menu.findItem(R.id.storage_format);
- final MenuItem migrate = menu.findItem(R.id.storage_migrate);
- final MenuItem manage = menu.findItem(R.id.storage_free);
-
- // Actions live in menu for non-internal private volumes; they're shown
- // as preference items for public volumes.
- if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(mVolume.getId())) {
- rename.setVisible(false);
- mount.setVisible(false);
- unmount.setVisible(false);
- format.setVisible(false);
- manage.setVisible(getResources().getBoolean(
- R.bool.config_storage_manager_settings_enabled));
- } else {
- rename.setVisible(mVolume.getType() == VolumeInfo.TYPE_PRIVATE);
- mount.setVisible(mVolume.getState() == VolumeInfo.STATE_UNMOUNTED);
- unmount.setVisible(mVolume.isMountedReadable());
- format.setVisible(true);
- manage.setVisible(false);
- }
-
- format.setTitle(R.string.storage_menu_format_public);
-
- // Only offer to migrate when not current storage
- final VolumeInfo privateVol = getActivity().getPackageManager()
- .getPrimaryStorageCurrentVolume();
- migrate.setVisible((privateVol != null)
- && (privateVol.getType() == VolumeInfo.TYPE_PRIVATE)
- && !Objects.equals(mVolume, privateVol)
- && privateVol.isMountedWritable());
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- final Context context = getActivity();
- final Bundle args = new Bundle();
- int i = item.getItemId();
- if (i == R.id.storage_rename) {
- RenameFragment.show(this, mVolume);
- return true;
- } else if (i == R.id.storage_mount) {
- new MountTask(context, mVolume).execute();
- return true;
- } else if (i == R.id.storage_unmount) {
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
- new SubSettingLauncher(context)
- .setDestination(PrivateVolumeUnmount.class.getCanonicalName())
- .setTitleRes(R.string.storage_menu_unmount)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- return true;
- } else if (i == R.id.storage_format) {
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
- new SubSettingLauncher(context)
- .setDestination(PrivateVolumeFormat.class.getCanonicalName())
- .setTitleRes(R.string.storage_menu_format)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- return true;
- } else if (i == R.id.storage_migrate) {
- final Intent intent = new Intent(context, StorageWizardMigrateConfirm.class);
- intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
- startActivity(intent);
- return true;
- } else if (i == R.id.storage_free) {
- final Intent deletion_helper_intent =
- new Intent(StorageManager.ACTION_MANAGE_STORAGE);
- startActivity(deletion_helper_intent);
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference pref) {
- // TODO: launch better intents for specific volume
-
- final int userId = (pref instanceof StorageItemPreference ?
- ((StorageItemPreference) pref).userHandle : -1);
- int itemTitleId;
- try {
- itemTitleId = Integer.parseInt(pref.getKey());
- } catch (NumberFormatException e) {
- itemTitleId = 0;
- }
- Intent intent = null;
- if (itemTitleId == R.string.storage_detail_apps) {
- Bundle args = new Bundle();
- args.putString(ManageApplications.EXTRA_CLASSNAME,
- StorageUseActivity.class.getName());
- args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
- args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
- args.putInt(
- ManageApplications.EXTRA_STORAGE_TYPE,
- ManageApplications.STORAGE_TYPE_LEGACY);
- intent = new SubSettingLauncher(getActivity())
- .setDestination(ManageApplications.class.getName())
- .setArguments(args)
- .setTitleRes(R.string.apps_storage)
- .setSourceMetricsCategory(getMetricsCategory())
- .toIntent();
- } else if (itemTitleId == R.string.storage_detail_images) {
- intent = getIntentForStorage(AUTHORITY_MEDIA, "images_root");
- } else if (itemTitleId == R.string.storage_detail_videos) {
- intent = getIntentForStorage(AUTHORITY_MEDIA, "videos_root");
- } else if (itemTitleId == R.string.storage_detail_audio) {
- intent = getIntentForStorage(AUTHORITY_MEDIA, "audio_root");
- } else if (itemTitleId == R.string.storage_detail_system) {
- SystemInfoFragment.show(this);
- return true;
- } else if (itemTitleId == R.string.storage_detail_other) {
- OtherInfoFragment.show(this, mStorageManager.getBestVolumeDescription(mVolume),
- mSharedVolume, userId);
- return true;
- } else if (itemTitleId == R.string.storage_detail_cached) {
- ConfirmClearCacheFragment.show(this);
- return true;
- } else if (itemTitleId == R.string.storage_menu_explore) {
- intent = mSharedVolume.buildBrowseIntent();
- } else if (itemTitleId == 0) {
- UserInfoFragment.show(this, pref.getTitle(), pref.getSummary());
- return true;
- }
-
- if (intent != null) {
- intent.putExtra(Intent.EXTRA_USER_ID, userId);
-
- Utils.launchIntent(this, intent);
- return true;
- }
- return super.onPreferenceTreeClick(pref);
- }
-
- private Intent getIntentForStorage(String authority, String root) {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(
- DocumentsContract.buildRootUri(authority, root),
- DocumentsContract.Root.MIME_TYPE_ITEM);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
-
- return intent;
- }
-
- private final MeasurementReceiver mReceiver = new MeasurementReceiver() {
- @Override
- public void onDetailsChanged(MeasurementDetails details) {
- updateDetails(details);
- }
- };
-
- private void updateDetails(MeasurementDetails details) {
- StorageItemPreference otherItem = null;
- long accountedSize = 0;
- long totalMiscSize = 0;
- long totalDownloadsSize = 0;
-
- for (int i = 0; i < mItemPoolIndex; ++i) {
- StorageItemPreference item = mItemPreferencePool.get(i);
- final int userId = item.userHandle;
- int itemTitleId;
- try {
- itemTitleId = Integer.parseInt(item.getKey());
- } catch (NumberFormatException e) {
- itemTitleId = 0;
- }
- // Cannot display 'Other' until all known items are accounted for.
- if (itemTitleId == R.string.storage_detail_system) {
- updatePreference(item, mSystemSize);
- accountedSize += mSystemSize;
- if (LOGV) Log.v(TAG, "mSystemSize: " + mSystemSize
- + " accountedSize: " + accountedSize);
- } else if (itemTitleId == R.string.storage_detail_apps) {
- updatePreference(item, details.appsSize.get(userId));
- accountedSize += details.appsSize.get(userId);
- if (LOGV) Log.v(TAG, "appsSize: " + details.appsSize.get(userId)
- + " accountedSize: " + accountedSize);
- } else if (itemTitleId == R.string.storage_detail_images) {
- final long imagesSize = totalValues(details, userId,
- Environment.DIRECTORY_DCIM, Environment.DIRECTORY_PICTURES);
- updatePreference(item, imagesSize);
- accountedSize += imagesSize;
- if (LOGV) Log.v(TAG, "imagesSize: " + imagesSize
- + " accountedSize: " + accountedSize);
- } else if (itemTitleId == R.string.storage_detail_videos) {
- final long videosSize = totalValues(details, userId,
- Environment.DIRECTORY_MOVIES);
- updatePreference(item, videosSize);
- accountedSize += videosSize;
- if (LOGV) Log.v(TAG, "videosSize: " + videosSize
- + " accountedSize: " + accountedSize);
- } else if (itemTitleId == R.string.storage_detail_audio) {
- final long audioSize = totalValues(details, userId,
- Environment.DIRECTORY_MUSIC,
- Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
- Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS);
- updatePreference(item, audioSize);
- accountedSize += audioSize;
- if (LOGV) Log.v(TAG, "audioSize: " + audioSize
- + " accountedSize: " + accountedSize);
- } else if (itemTitleId == R.string.storage_detail_other) {
- final long downloadsSize = totalValues(details, userId,
- Environment.DIRECTORY_DOWNLOADS);
- final long miscSize = details.miscSize.get(userId);
- totalDownloadsSize += downloadsSize;
- totalMiscSize += miscSize;
- accountedSize += miscSize + downloadsSize;
- if (LOGV)
- Log.v(TAG, "miscSize for " + userId + ": " + miscSize + "(total: "
- + totalMiscSize + ") \ndownloadsSize: " + downloadsSize + "(total: "
- + totalDownloadsSize + ") accountedSize: " + accountedSize);
- otherItem = item;
- } else if (itemTitleId == R.string.storage_detail_cached) {
- updatePreference(item, details.cacheSize);
- accountedSize += details.cacheSize;
- if (LOGV)
- Log.v(TAG, "cacheSize: " + details.cacheSize + " accountedSize: "
- + accountedSize);
- } else if (itemTitleId == 0) {
- final long userSize = details.usersSize.get(userId);
- updatePreference(item, userSize);
- accountedSize += userSize;
- if (LOGV) Log.v(TAG, "userSize: " + userSize
- + " accountedSize: " + accountedSize);
- }
- }
- if (otherItem != null) {
- final long usedSize = mTotalSize - details.availSize;
- final long unaccountedSize = usedSize - accountedSize;
- final long otherSize = totalMiscSize + totalDownloadsSize + unaccountedSize;
- Log.v(TAG, "Other items: \n\tmTotalSize: " + mTotalSize + " availSize: "
- + details.availSize + " usedSize: " + usedSize + "\n\taccountedSize: "
- + accountedSize + " unaccountedSize size: " + unaccountedSize
- + "\n\ttotalMiscSize: " + totalMiscSize + " totalDownloadsSize: "
- + totalDownloadsSize + "\n\tdetails: " + details);
- updatePreference(otherItem, otherSize);
- }
- }
-
- private void updatePreference(StorageItemPreference pref, long size) {
- pref.setStorageSize(size, mTotalSize);
- }
-
- private static long totalValues(MeasurementDetails details, int userId, String... keys) {
- long total = 0;
- HashMap map = details.mediaSize.get(userId);
- if (map != null) {
- for (String key : keys) {
- if (map.containsKey(key)) {
- total += map.get(key);
- }
- }
- } else {
- Log.w(TAG, "MeasurementDetails mediaSize array does not have key for user " + userId);
- }
- return total;
- }
-
- private final StorageEventListener mStorageListener = new StorageEventListener() {
- @Override
- public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
- if (Objects.equals(mVolume.getId(), vol.getId())) {
- mVolume = vol;
- update();
- }
- }
-
- @Override
- public void onVolumeRecordChanged(VolumeRecord rec) {
- if (Objects.equals(mVolume.getFsUuid(), rec.getFsUuid())) {
- mVolume = mStorageManager.findVolumeById(mVolumeId);
- update();
- }
- }
- };
-
- /**
- * Dialog that allows editing of volume nickname.
- */
- public static class RenameFragment extends InstrumentedDialogFragment {
- public static void show(PrivateVolumeSettings parent, VolumeInfo vol) {
- if (!parent.isAdded()) return;
-
- final RenameFragment dialog = new RenameFragment();
- dialog.setTargetFragment(parent, 0);
- final Bundle args = new Bundle();
- args.putString(VolumeRecord.EXTRA_FS_UUID, vol.getFsUuid());
- dialog.setArguments(args);
- dialog.show(parent.getFragmentManager(), TAG_RENAME);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_VOLUME_RENAME;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
- final StorageManager storageManager = context.getSystemService(StorageManager.class);
-
- final String fsUuid = getArguments().getString(VolumeRecord.EXTRA_FS_UUID);
- final VolumeInfo vol = storageManager.findVolumeByUuid(fsUuid);
- final VolumeRecord rec = storageManager.findRecordByUuid(fsUuid);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
-
- final View view = dialogInflater.inflate(R.layout.dialog_edittext, null, false);
- final EditText nickname = (EditText) view.findViewById(R.id.edittext);
- nickname.setText(rec.getNickname());
-
- builder.setTitle(R.string.storage_rename_title);
- builder.setView(view);
-
- builder.setPositiveButton(R.string.save,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // TODO: move to background thread
- storageManager.setVolumeNickname(fsUuid,
- nickname.getText().toString());
- }
- });
- builder.setNegativeButton(R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- public static class SystemInfoFragment extends InstrumentedDialogFragment {
- public static void show(Fragment parent) {
- if (!parent.isAdded()) return;
-
- final SystemInfoFragment dialog = new SystemInfoFragment();
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_SYSTEM_INFO);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_STORAGE_SYSTEM_INFO;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- return new AlertDialog.Builder(getActivity())
- .setMessage(getContext().getString(R.string.storage_detail_dialog_system,
- Build.VERSION.RELEASE_OR_CODENAME))
- .setPositiveButton(android.R.string.ok, null)
- .create();
- }
- }
-
- public static class OtherInfoFragment extends InstrumentedDialogFragment {
- public static void show(Fragment parent, String title, VolumeInfo sharedVol, int userId) {
- if (!parent.isAdded()) return;
-
- final OtherInfoFragment dialog = new OtherInfoFragment();
- dialog.setTargetFragment(parent, 0);
- final Bundle args = new Bundle();
- args.putString(Intent.EXTRA_TITLE, title);
-
- final Intent intent = sharedVol.buildBrowseIntent();
- intent.putExtra(Intent.EXTRA_USER_ID, userId);
- args.putParcelable(Intent.EXTRA_INTENT, intent);
- dialog.setArguments(args);
- dialog.show(parent.getFragmentManager(), TAG_OTHER_INFO);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_STORAGE_OTHER_INFO;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
-
- final String title = getArguments().getString(Intent.EXTRA_TITLE);
- final Intent intent = getArguments().getParcelable(Intent.EXTRA_INTENT);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setMessage(
- TextUtils.expandTemplate(getText(R.string.storage_detail_dialog_other), title));
-
- builder.setPositiveButton(R.string.storage_menu_explore,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Utils.launchIntent(OtherInfoFragment.this, intent);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- public static class UserInfoFragment extends InstrumentedDialogFragment {
- public static void show(Fragment parent, CharSequence userLabel, CharSequence userSize) {
- if (!parent.isAdded()) return;
-
- final UserInfoFragment dialog = new UserInfoFragment();
- dialog.setTargetFragment(parent, 0);
- final Bundle args = new Bundle();
- args.putCharSequence(Intent.EXTRA_TITLE, userLabel);
- args.putCharSequence(Intent.EXTRA_SUBJECT, userSize);
- dialog.setArguments(args);
- dialog.show(parent.getFragmentManager(), TAG_USER_INFO);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_STORAGE_USER_INFO;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
-
- final CharSequence userLabel = getArguments().getCharSequence(Intent.EXTRA_TITLE);
- final CharSequence userSize = getArguments().getCharSequence(Intent.EXTRA_SUBJECT);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setMessage(TextUtils.expandTemplate(
- getText(R.string.storage_detail_dialog_user), userLabel, userSize));
-
- builder.setPositiveButton(android.R.string.ok, null);
-
- return builder.create();
- }
- }
-
- /**
- * Dialog to request user confirmation before clearing all cache data.
- */
- public static class ConfirmClearCacheFragment extends InstrumentedDialogFragment {
- public static void show(Fragment parent) {
- if (!parent.isAdded()) return;
-
- final ConfirmClearCacheFragment dialog = new ConfirmClearCacheFragment();
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_CONFIRM_CLEAR_CACHE);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_STORAGE_CLEAR_CACHE;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setTitle(R.string.memory_clear_cache_title);
- builder.setMessage(getString(R.string.memory_clear_cache_message));
-
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final PrivateVolumeSettings target = (PrivateVolumeSettings) getTargetFragment();
- final PackageManager pm = context.getPackageManager();
- final UserManager um = context.getSystemService(UserManager.class);
-
- for (int userId : um.getProfileIdsWithDisabled(context.getUserId())) {
- final List infos = pm.getInstalledPackagesAsUser(0, userId);
- final ClearCacheObserver observer = new ClearCacheObserver(
- target, infos.size());
- for (PackageInfo info : infos) {
- pm.deleteApplicationCacheFilesAsUser(info.packageName, userId,
- observer);
- }
- }
- }
- });
- builder.setNegativeButton(android.R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- private static class ClearCacheObserver extends IPackageDataObserver.Stub {
- private final PrivateVolumeSettings mTarget;
- private int mRemaining;
-
- public ClearCacheObserver(PrivateVolumeSettings target, int remaining) {
- mTarget = target;
- mRemaining = remaining;
- }
-
- @Override
- public void onRemoveCompleted(final String packageName, final boolean succeeded) {
- synchronized (this) {
- if (--mRemaining == 0) {
- mTarget.getActivity().runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mTarget.update();
- }
- });
- }
- }
- }
- }
-}
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
index 3289df9ae3b..738c3ca520a 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
@@ -31,7 +31,7 @@ import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.core.InstrumentedFragment;
-import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
+import com.android.settings.deviceinfo.storage.StorageUtils.UnmountTask;
import com.android.settings.search.actionbar.SearchMenuController;
public class PrivateVolumeUnmount extends InstrumentedFragment {
diff --git a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
index b4724ae5698..5315347afbc 100644
--- a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
@@ -40,8 +40,8 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.util.Preconditions;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.deviceinfo.StorageSettings.MountTask;
-import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
+import com.android.settings.deviceinfo.storage.StorageUtils.MountTask;
+import com.android.settings.deviceinfo.storage.StorageUtils.UnmountTask;
import java.io.File;
import java.util.Objects;
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
deleted file mode 100644
index 871844c5031..00000000000
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * Copyright (C) 2015 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.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import android.app.Dialog;
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.os.storage.DiskInfo;
-import android.os.storage.StorageEventListener;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.os.storage.VolumeRecord;
-import android.text.TextUtils;
-import android.text.format.Formatter;
-import android.text.format.Formatter.BytesResult;
-import android.util.Log;
-import android.widget.Toast;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-import androidx.fragment.app.Fragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.deviceinfo.PrivateStorageInfo;
-import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
-import com.android.settingslib.search.Indexable;
-import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.search.SearchIndexableRaw;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Panel showing both internal storage (both built-in storage and private
- * volumes) and removable storage (public volumes).
- */
-@SearchIndexable
-public class StorageSettings extends SettingsPreferenceFragment implements Indexable {
- static final String TAG = "StorageSettings";
-
- private static final String KEY_STORAGE_SETTINGS = "storage_settings";
- private static final String KEY_INTERNAL_STORAGE = "storage_settings_internal_storage";
- private static final String KEY_STORAGE_SETTINGS_VOLUME = "storage_settings_volume_";
- private static final String KEY_STORAGE_SETTINGS_MEMORY_SIZE = "storage_settings_memory_size";
- private static final String KEY_STORAGE_SETTINGS_MEMORY = "storage_settings_memory_available";
- private static final String KEY_STORAGE_SETTINGS_DCIM = "storage_settings_dcim_space";
- private static final String KEY_STORAGE_SETTINGS_MUSIC = "storage_settings_music_space";
- private static final String KEY_STORAGE_SETTINGS_MISC = "storage_settings_misc_space";
- private static final String KEY_STORAGE_SETTINGS_FREE_SPACE = "storage_settings_free_space";
-
- private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
- private static final String TAG_DISK_INIT = "disk_init";
- private static final int METRICS_CATEGORY = SettingsEnums.DEVICEINFO_STORAGE;
-
- private StorageManager mStorageManager;
-
- private PreferenceCategory mInternalCategory;
- private PreferenceCategory mExternalCategory;
-
- private StorageSummaryPreference mInternalSummary;
- private static long sTotalInternalStorage;
-
- private boolean mHasLaunchedPrivateVolumeSettings = false;
-
- @Override
- public int getMetricsCategory() {
- return METRICS_CATEGORY;
- }
-
- @Override
- public int getHelpResource() {
- return R.string.help_uri_storage;
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final Context context = getActivity();
-
- mStorageManager = context.getSystemService(StorageManager.class);
-
- if (sTotalInternalStorage <= 0) {
- sTotalInternalStorage = mStorageManager.getPrimaryStorageSize();
- }
-
- addPreferencesFromResource(R.xml.device_info_storage);
-
- mInternalCategory = (PreferenceCategory) findPreference("storage_internal");
- mExternalCategory = (PreferenceCategory) findPreference("storage_external");
-
- mInternalSummary = new StorageSummaryPreference(getPrefContext());
-
- setHasOptionsMenu(true);
- }
-
- private final StorageEventListener mStorageListener = new StorageEventListener() {
- @Override
- public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
- if (isInteresting(vol)) {
- refresh();
- }
- }
-
- @Override
- public void onDiskDestroyed(DiskInfo disk) {
- refresh();
- }
- };
-
- private static boolean isInteresting(VolumeInfo vol) {
- switch (vol.getType()) {
- case VolumeInfo.TYPE_PRIVATE:
- case VolumeInfo.TYPE_PUBLIC:
- case VolumeInfo.TYPE_STUB:
- return true;
- default:
- return false;
- }
- }
-
- private synchronized void refresh() {
- final Context context = getPrefContext();
-
- getPreferenceScreen().removeAll();
- mInternalCategory.removeAll();
- mExternalCategory.removeAll();
-
- mInternalCategory.addPreference(mInternalSummary);
-
- final StorageManagerVolumeProvider smvp = new StorageManagerVolumeProvider(mStorageManager);
- final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(smvp);
- final long privateTotalBytes = info.totalBytes;
- final long privateUsedBytes = info.totalBytes - info.freeBytes;
-
- final List volumes = mStorageManager.getVolumes();
- Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
-
- for (VolumeInfo vol : volumes) {
- if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
-
- if (vol.getState() == VolumeInfo.STATE_UNMOUNTABLE) {
- mInternalCategory.addPreference(
- new StorageVolumePreference(context, vol, 0));
- } else {
- final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,
- sTotalInternalStorage);
- mInternalCategory.addPreference(
- new StorageVolumePreference(context, vol, volumeTotalBytes));
- }
- } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC
- || vol.getType() == VolumeInfo.TYPE_STUB) {
- mExternalCategory.addPreference(
- new StorageVolumePreference(context, vol, 0));
- }
- }
-
- // Show missing private volumes
- final List recs = mStorageManager.getVolumeRecords();
- for (VolumeRecord rec : recs) {
- if (rec.getType() == VolumeInfo.TYPE_PRIVATE
- && mStorageManager.findVolumeByUuid(rec.getFsUuid()) == null) {
- // TODO: add actual storage type to record
- final Preference pref = new Preference(context);
- pref.setKey(rec.getFsUuid());
- pref.setTitle(rec.getNickname());
- pref.setSummary(com.android.internal.R.string.ext_media_status_missing);
- pref.setIcon(R.drawable.ic_sim_sd);
- mInternalCategory.addPreference(pref);
- }
- }
-
- // Show unsupported disks to give a chance to init
- final List disks = mStorageManager.getDisks();
- for (DiskInfo disk : disks) {
- if (disk.volumeCount == 0 && disk.size > 0) {
- final Preference pref = new Preference(context);
- pref.setKey(disk.getId());
- pref.setTitle(disk.getDescription());
- pref.setSummary(com.android.internal.R.string.ext_media_status_unsupported);
- pref.setIcon(R.drawable.ic_sim_sd);
- mExternalCategory.addPreference(pref);
- }
- }
-
- final BytesResult result = Formatter.formatBytes(getResources(), privateUsedBytes, 0);
- mInternalSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
- result.value, result.units));
- mInternalSummary.setSummary(getString(R.string.storage_volume_used_total,
- Formatter.formatFileSize(context, privateTotalBytes)));
- if (mInternalCategory.getPreferenceCount() > 0) {
- getPreferenceScreen().addPreference(mInternalCategory);
- }
- if (mExternalCategory.getPreferenceCount() > 0) {
- getPreferenceScreen().addPreference(mExternalCategory);
- }
-
- if (mInternalCategory.getPreferenceCount() == 2
- && mExternalCategory.getPreferenceCount() == 0) {
- // Only showing primary internal storage, so just shortcut
- if (!mHasLaunchedPrivateVolumeSettings) {
- mHasLaunchedPrivateVolumeSettings = true;
- final Bundle args = new Bundle();
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
- new SubSettingLauncher(getActivity())
- .setDestination(StorageDashboardFragment.class.getName())
- .setArguments(args)
- .setTitleRes(R.string.storage_settings)
- .setSourceMetricsCategory(getMetricsCategory())
- .launch();
- finish();
- }
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mStorageManager.registerListener(mStorageListener);
- refresh();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mStorageManager.unregisterListener(mStorageListener);
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference pref) {
- final String key = pref.getKey();
- if (pref instanceof StorageVolumePreference) {
- // Picked a normal volume
- final VolumeInfo vol = mStorageManager.findVolumeById(key);
-
- if (vol == null) {
- return false;
- }
-
- if (vol.getState() == VolumeInfo.STATE_UNMOUNTED) {
- VolumeUnmountedFragment.show(this, vol.getId());
- return true;
- } else if (vol.getState() == VolumeInfo.STATE_UNMOUNTABLE) {
- DiskInitFragment.show(this, R.string.storage_dialog_unmountable, vol.getDiskId());
- return true;
- }
-
- if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
- final Bundle args = new Bundle();
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
-
- if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
- new SubSettingLauncher(getContext())
- .setDestination(StorageDashboardFragment.class.getCanonicalName())
- .setTitleRes(R.string.storage_settings)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- } else {
- // TODO: Go to the StorageDashboardFragment once it fully handles all of the
- // SD card cases and other private internal storage cases.
- PrivateVolumeSettings.setVolumeSize(args, PrivateStorageInfo.getTotalSize(vol,
- sTotalInternalStorage));
- new SubSettingLauncher(getContext())
- .setDestination(PrivateVolumeSettings.class.getCanonicalName())
- .setTitleRes(-1)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- }
-
- return true;
-
- } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
- return handlePublicVolumeClick(getContext(), vol);
- } else if (vol.getType() == VolumeInfo.TYPE_STUB) {
- return handleStubVolumeClick(getContext(), vol);
- }
-
- } else if (key.startsWith("disk:")) {
- // Picked an unsupported disk
- DiskInitFragment.show(this, R.string.storage_dialog_unsupported, key);
- return true;
-
- } else {
- // Picked a missing private volume
- final Bundle args = new Bundle();
- args.putString(VolumeRecord.EXTRA_FS_UUID, key);
- new SubSettingLauncher(getContext())
- .setDestination(PrivateVolumeForget.class.getCanonicalName())
- .setTitleRes(R.string.storage_menu_forget)
- .setSourceMetricsCategory(getMetricsCategory())
- .setArguments(args)
- .launch();
- return true;
- }
-
- return false;
- }
-
- @VisibleForTesting
- static boolean handleStubVolumeClick(Context context, VolumeInfo vol) {
- final Intent intent = vol.buildBrowseIntent();
- if (vol.isMountedReadable() && intent != null) {
- context.startActivity(intent);
- return true;
- }
- return false;
- }
-
- @VisibleForTesting
- static boolean handlePublicVolumeClick(Context context, VolumeInfo vol) {
- final Intent intent = vol.buildBrowseIntent();
- if (vol.isMountedReadable() && intent != null) {
- context.startActivity(intent);
- return true;
- } else {
- final Bundle args = new Bundle();
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
- new SubSettingLauncher(context)
- .setDestination(PublicVolumeSettings.class.getCanonicalName())
- .setTitleRes(-1)
- .setSourceMetricsCategory(METRICS_CATEGORY)
- .setArguments(args)
- .launch();
- return true;
- }
- }
-
- public static class MountTask extends AsyncTask {
- private final Context mContext;
- private final StorageManager mStorageManager;
- private final String mVolumeId;
- private final String mDescription;
-
- public MountTask(Context context, VolumeInfo volume) {
- mContext = context.getApplicationContext();
- mStorageManager = mContext.getSystemService(StorageManager.class);
- mVolumeId = volume.getId();
- mDescription = mStorageManager.getBestVolumeDescription(volume);
- }
-
- @Override
- protected Exception doInBackground(Void... params) {
- try {
- mStorageManager.mount(mVolumeId);
- return null;
- } catch (Exception e) {
- return e;
- }
- }
-
- @Override
- protected void onPostExecute(Exception e) {
- if (e == null) {
- Toast.makeText(mContext, mContext.getString(R.string.storage_mount_success,
- mDescription), Toast.LENGTH_SHORT).show();
- } else {
- Log.e(TAG, "Failed to mount " + mVolumeId, e);
- Toast.makeText(mContext, mContext.getString(R.string.storage_mount_failure,
- mDescription), Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- public static class UnmountTask extends AsyncTask {
- private final Context mContext;
- private final StorageManager mStorageManager;
- private final String mVolumeId;
- private final String mDescription;
-
- public UnmountTask(Context context, VolumeInfo volume) {
- mContext = context.getApplicationContext();
- mStorageManager = mContext.getSystemService(StorageManager.class);
- mVolumeId = volume.getId();
- mDescription = mStorageManager.getBestVolumeDescription(volume);
- }
-
- @Override
- protected Exception doInBackground(Void... params) {
- try {
- mStorageManager.unmount(mVolumeId);
- return null;
- } catch (Exception e) {
- return e;
- }
- }
-
- @Override
- protected void onPostExecute(Exception e) {
- if (e == null) {
- Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_success,
- mDescription), Toast.LENGTH_SHORT).show();
- } else {
- Log.e(TAG, "Failed to unmount " + mVolumeId, e);
- Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_failure,
- mDescription), Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- public static class VolumeUnmountedFragment extends InstrumentedDialogFragment {
- public static void show(Fragment parent, String volumeId) {
- final Bundle args = new Bundle();
- args.putString(VolumeInfo.EXTRA_VOLUME_ID, volumeId);
-
- final VolumeUnmountedFragment dialog = new VolumeUnmountedFragment();
- dialog.setArguments(args);
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_VOLUME_UNMOUNTED);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_VOLUME_UNMOUNT;
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
- final StorageManager sm = context.getSystemService(StorageManager.class);
-
- final String volumeId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
- final VolumeInfo vol = sm.findVolumeById(volumeId);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setMessage(TextUtils.expandTemplate(
- getText(R.string.storage_dialog_unmounted), vol.getDisk().getDescription()));
-
- builder.setPositiveButton(R.string.storage_menu_mount,
- new DialogInterface.OnClickListener() {
- /**
- * Check if an {@link
- * RestrictedLockUtils#sendShowAdminSupportDetailsIntent admin
- * details intent} should be shown for the restriction and show it.
- *
- * @param restriction The restriction to check
- * @return {@code true} iff a intent was shown.
- */
- private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
- EnforcedAdmin admin = RestrictedLockUtilsInternal
- .checkIfRestrictionEnforced(getActivity(), restriction,
- UserHandle.myUserId());
- boolean hasBaseUserRestriction =
- RestrictedLockUtilsInternal.hasBaseUserRestriction(
- getActivity(), restriction, UserHandle.myUserId());
- if (admin != null && !hasBaseUserRestriction) {
- RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(),
- admin);
- return true;
- }
-
- return false;
- }
-
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (wasAdminSupportIntentShown(
- UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
- return;
- }
-
- if (vol.disk != null && vol.disk.isUsb() &&
- wasAdminSupportIntentShown(
- UserManager.DISALLOW_USB_FILE_TRANSFER)) {
- return;
- }
-
- new MountTask(context, vol).execute();
- }
- });
- builder.setNegativeButton(R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- public static class DiskInitFragment extends InstrumentedDialogFragment {
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.DIALOG_VOLUME_INIT;
- }
-
- public static void show(Fragment parent, int resId, String diskId) {
- final Bundle args = new Bundle();
- args.putInt(Intent.EXTRA_TEXT, resId);
- args.putString(DiskInfo.EXTRA_DISK_ID, diskId);
-
- final DiskInitFragment dialog = new DiskInitFragment();
- dialog.setArguments(args);
- dialog.setTargetFragment(parent, 0);
- dialog.show(parent.getFragmentManager(), TAG_DISK_INIT);
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final Context context = getActivity();
- final StorageManager sm = context.getSystemService(StorageManager.class);
-
- final int resId = getArguments().getInt(Intent.EXTRA_TEXT);
- final String diskId = getArguments().getString(DiskInfo.EXTRA_DISK_ID);
- final DiskInfo disk = sm.findDiskById(diskId);
-
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setMessage(TextUtils.expandTemplate(getText(resId), disk.getDescription()));
-
- builder.setPositiveButton(R.string.storage_menu_set_up,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final Intent intent = new Intent(context, StorageWizardInit.class);
- intent.putExtra(DiskInfo.EXTRA_DISK_ID, diskId);
- startActivity(intent);
- }
- });
- builder.setNegativeButton(R.string.cancel, null);
-
- return builder.create();
- }
- }
-
- /** Enable indexing of searchable data */
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider() {
- @Override
- public List getRawDataToIndex(
- Context context, boolean enabled) {
- final List result = new ArrayList<>();
-
- SearchIndexableRaw data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.storage_settings);
- data.key = KEY_STORAGE_SETTINGS;
- data.screenTitle = context.getString(R.string.storage_settings);
- data.keywords = context.getString(R.string.keywords_storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.internal_storage);
- data.key = KEY_INTERNAL_STORAGE;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- final StorageManager storage = context.getSystemService(StorageManager.class);
- final List vols = storage.getVolumes();
- for (VolumeInfo vol : vols) {
- if (isInteresting(vol)) {
- data.title = storage.getBestVolumeDescription(vol);
- data.key = KEY_STORAGE_SETTINGS_VOLUME + vol.id;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
- }
- }
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.memory_size);
- data.key = KEY_STORAGE_SETTINGS_MEMORY_SIZE;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.memory_available);
- data.key = KEY_STORAGE_SETTINGS_MEMORY;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.memory_dcim_usage);
- data.key = KEY_STORAGE_SETTINGS_DCIM;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.memory_music_usage);
- data.key = KEY_STORAGE_SETTINGS_MUSIC;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.memory_media_misc_usage);
- data.key = KEY_STORAGE_SETTINGS_MISC;
- data.screenTitle = context.getString(R.string.storage_settings);
- result.add(data);
-
- data = new SearchIndexableRaw(context);
- data.title = context.getString(R.string.storage_menu_free);
- data.key = KEY_STORAGE_SETTINGS_FREE_SPACE;
- data.screenTitle = context.getString(R.string.storage_menu_free);
- data.intentAction = StorageManager.ACTION_MANAGE_STORAGE;
- data.keywords = context.getString(R.string.keywords_storage_menu_free);
- result.add(data);
-
- return result;
- }
-
- @Override
- public List getNonIndexableKeys(Context context) {
- final List niks = super.getNonIndexableKeys(context);
- if (isExternalExist(context)) {
- niks.add(KEY_STORAGE_SETTINGS);
- niks.add(KEY_INTERNAL_STORAGE);
- niks.add(KEY_STORAGE_SETTINGS_MEMORY_SIZE);
- niks.add(KEY_STORAGE_SETTINGS_MEMORY);
- niks.add(KEY_STORAGE_SETTINGS_DCIM);
- niks.add(KEY_STORAGE_SETTINGS_MUSIC);
- niks.add(KEY_STORAGE_SETTINGS_MISC);
- niks.add(KEY_STORAGE_SETTINGS_FREE_SPACE);
-
- final StorageManager storage = context.getSystemService(
- StorageManager.class);
- final List vols = storage.getVolumes();
- for (VolumeInfo vol : vols) {
- if (isInteresting(vol)) {
- niks.add(KEY_STORAGE_SETTINGS_VOLUME + vol.id);
- }
- }
- }
- return niks;
- }
-
- @Override
- protected boolean isPageSearchEnabled(Context context) {
- return !isExternalExist(context);
- }
-
- private boolean isExternalExist(Context context) {
- int internalCount = 0;
- StorageManager storageManager = context.getSystemService(StorageManager.class);
- final List volumes = storageManager.getVolumes();
- for (VolumeInfo vol : volumes) {
- //External storage
- if (vol.getType() == VolumeInfo.TYPE_PUBLIC
- || vol.getType() == VolumeInfo.TYPE_STUB) {
- return true;
- } else if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
- internalCount++;
- }
- }
-
- // Unsupported disks
- final List disks = storageManager.getDisks();
- for (DiskInfo disk : disks) {
- if (disk.volumeCount == 0 && disk.size > 0) {
- return true;
- }
- }
-
- // Missing private volumes
- final List recs = storageManager.getVolumeRecords();
- for (VolumeRecord rec : recs) {
- if (rec.getType() == VolumeInfo.TYPE_PRIVATE
- && storageManager.findVolumeByUuid(rec.getFsUuid()) == null) {
- internalCount++;
- }
- }
-
- return (internalCount != 1);
- }
- };
-}
diff --git a/src/com/android/settings/deviceinfo/StorageUnmountReceiver.java b/src/com/android/settings/deviceinfo/StorageUnmountReceiver.java
index 81ac97b21d3..41f59b42e16 100644
--- a/src/com/android/settings/deviceinfo/StorageUnmountReceiver.java
+++ b/src/com/android/settings/deviceinfo/StorageUnmountReceiver.java
@@ -16,8 +16,6 @@
package com.android.settings.deviceinfo;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -25,9 +23,11 @@ import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.Log;
-import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
+import com.android.settings.deviceinfo.storage.StorageUtils.UnmountTask;
public class StorageUnmountReceiver extends BroadcastReceiver {
+ private static final String TAG = "StorageUnmountReceiver";
+
@Override
public void onReceive(Context context, Intent intent) {
final StorageManager storage = context.getSystemService(StorageManager.class);
diff --git a/src/com/android/settings/deviceinfo/StorageVolumePreference.java b/src/com/android/settings/deviceinfo/StorageVolumePreference.java
deleted file mode 100644
index bd7ca822a98..00000000000
--- a/src/com/android/settings/deviceinfo/StorageVolumePreference.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2015 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.usage.StorageStatsManager;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.drawable.Drawable;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.text.format.Formatter;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
-import com.android.settingslib.Utils;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Preference line representing a single {@link VolumeInfo}, possibly including
- * quick actions like unmounting.
- */
-public class StorageVolumePreference extends Preference {
- private static final String TAG = StorageVolumePreference.class.getSimpleName();
-
- private final StorageManager mStorageManager;
- private final VolumeInfo mVolume;
-
- private int mUsedPercent = -1;
- private ColorStateList mColorTintList;
-
- // TODO: ideally, VolumeInfo should have a total physical size.
- public StorageVolumePreference(Context context, VolumeInfo volume, long totalBytes) {
- super(context);
-
- mStorageManager = context.getSystemService(StorageManager.class);
- mVolume = volume;
- mColorTintList = Utils.getColorAttr(context, android.R.attr.colorControlNormal);
-
- setLayoutResource(R.layout.storage_volume);
-
- setKey(volume.getId());
- setTitle(mStorageManager.getBestVolumeDescription(volume));
-
- Drawable icon;
- if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(volume.getId())) {
- icon = context.getDrawable(R.drawable.ic_storage);
- } else {
- icon = context.getDrawable(R.drawable.ic_sim_sd);
- }
-
- if (volume.isMountedReadable()) {
- // TODO: move statfs() to background thread
- final File path = volume.getPath();
-
- long freeBytes = 0;
- long usedBytes = 0;
- if (volume.getType() == VolumeInfo.TYPE_PRIVATE) {
- final StorageStatsManager stats =
- context.getSystemService(StorageStatsManager.class);
- try {
- totalBytes = stats.getTotalBytes(volume.getFsUuid());
- freeBytes = stats.getFreeBytes(volume.getFsUuid());
- usedBytes = totalBytes - freeBytes;
- } catch (IOException e) {
- Log.w(TAG, e);
- }
- } else {
- // StorageStatsManager can only query private volumes.
- // Default to previous storage calculation for public volumes.
- if (totalBytes <= 0) {
- totalBytes = path.getTotalSpace();
- }
- freeBytes = path.getFreeSpace();
- usedBytes = totalBytes - freeBytes;
- }
-
- final String used = Formatter.formatFileSize(context, usedBytes);
- final String total = Formatter.formatFileSize(context, totalBytes);
- setSummary(context.getString(R.string.storage_volume_summary, used, total));
- if (totalBytes > 0) {
- mUsedPercent = (int) ((usedBytes * 100) / totalBytes);
- }
-
- if (freeBytes < mStorageManager.getStorageLowBytes(path)) {
- mColorTintList = Utils.getColorAttr(context, android.R.attr.colorError);
- icon = context.getDrawable(R.drawable.ic_warning_24dp);
- icon.mutate();
- icon.setTintList(mColorTintList);
- }
-
- } else {
- setSummary(volume.getStateDescription());
- mUsedPercent = -1;
- }
-
- setIcon(icon);
-
- if (volume.getType() == VolumeInfo.TYPE_PUBLIC
- && volume.isMountedReadable()) {
- setWidgetLayoutResource(R.layout.preference_storage_action);
- }
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- final ImageView unmount = (ImageView) view.findViewById(R.id.unmount);
- if (unmount != null) {
- unmount.setOnClickListener(mUnmountListener);
- }
-
- final ProgressBar progress = (ProgressBar) view.findViewById(android.R.id.progress);
- if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE && mUsedPercent != -1) {
- progress.setVisibility(View.VISIBLE);
- progress.setProgress(mUsedPercent);
- progress.setProgressTintList(mColorTintList);
- } else {
- progress.setVisibility(View.GONE);
- }
-
- super.onBindViewHolder(view);
- }
-
- private final View.OnClickListener mUnmountListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- new UnmountTask(getContext(), mVolume).execute();
- }
- };
-}
diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java
index 92afa56cc0a..b1b956e5fb5 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardBase.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java
@@ -19,8 +19,6 @@ package com.android.settings.deviceinfo;
import static android.os.storage.DiskInfo.EXTRA_DISK_ID;
import static android.os.storage.VolumeInfo.EXTRA_VOLUME_ID;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.annotation.LayoutRes;
import android.annotation.NonNull;
import android.content.Intent;
@@ -54,6 +52,8 @@ import java.util.List;
import java.util.Objects;
public abstract class StorageWizardBase extends FragmentActivity {
+ private static final String TAG = "StorageWizardBase";
+
protected static final String EXTRA_FORMAT_FORGET_UUID = "format_forget_uuid";
protected static final String EXTRA_FORMAT_PRIVATE = "format_private";
protected static final String EXTRA_FORMAT_SLOW = "format_slow";
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
index 88968b3bd2a..ea4a2fd29e6 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
@@ -18,8 +18,6 @@ package com.android.settings.deviceinfo;
import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.content.Intent;
import android.content.pm.IPackageMoveObserver;
import android.os.AsyncTask;
@@ -40,6 +38,8 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class StorageWizardFormatProgress extends StorageWizardBase {
+ private static final String TAG = "StorageWizardFormatProgress";
+
private static final String PROP_DEBUG_STORAGE_SLOW = "sys.debug.storage_slow";
private boolean mFormatPrivate;
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
index 7d20aa715db..0d513e5b5fe 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
@@ -16,8 +16,6 @@
package com.android.settings.deviceinfo;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -39,6 +37,8 @@ import com.android.settings.password.ChooseLockSettingsHelper;
import java.util.Objects;
public class StorageWizardMigrateConfirm extends StorageWizardBase {
+ private static final String TAG = "StorageWizardMigrateConfirm";
+
private static final int REQUEST_CREDENTIAL = 100;
private MigrateEstimateTask mEstimate;
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
index b6f2a8d2fa4..7e042c1f395 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
@@ -18,8 +18,6 @@ package com.android.settings.deviceinfo;
import static android.content.pm.PackageManager.EXTRA_MOVE_ID;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -34,6 +32,8 @@ import android.widget.Toast;
import com.android.settings.R;
public class StorageWizardMigrateProgress extends StorageWizardBase {
+ private static final String TAG = "StorageWizardMigrateProgress";
+
private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD";
private int mMoveId;
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
index 034eb079fe2..b0f8cbd5cc1 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
@@ -21,8 +21,6 @@ import static android.content.Intent.EXTRA_TITLE;
import static android.content.pm.PackageManager.EXTRA_MOVE_ID;
import static android.os.storage.VolumeInfo.EXTRA_VOLUME_ID;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -39,6 +37,8 @@ import com.android.settings.R;
import com.android.settings.password.ChooseLockSettingsHelper;
public class StorageWizardMoveConfirm extends StorageWizardBase {
+ private static final String TAG = "StorageWizardMoveConfirm";
+
private static final int REQUEST_CREDENTIAL = 100;
private String mPackageName;
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
index 1966c9534ae..8dc1e2f5670 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
@@ -19,8 +19,6 @@ package com.android.settings.deviceinfo;
import static android.content.Intent.EXTRA_TITLE;
import static android.content.pm.PackageManager.EXTRA_MOVE_ID;
-import static com.android.settings.deviceinfo.StorageSettings.TAG;
-
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.MoveCallback;
import android.os.Bundle;
@@ -32,6 +30,8 @@ import android.widget.Toast;
import com.android.settings.R;
public class StorageWizardMoveProgress extends StorageWizardBase {
+ private static final String TAG = "StorageWizardMoveProgress";
+
private int mMoveId;
@Override
diff --git a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
index 0932447bf20..d4f93fa83cd 100644
--- a/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
+++ b/src/com/android/settings/deviceinfo/VolumeOptionMenuController.java
@@ -35,11 +35,11 @@ import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.deviceinfo.StorageSettings.MountTask;
-import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
import com.android.settings.deviceinfo.storage.StorageEntry;
import com.android.settings.deviceinfo.storage.StorageRenameFragment;
import com.android.settings.deviceinfo.storage.StorageUtils;
+import com.android.settings.deviceinfo.storage.StorageUtils.MountTask;
+import com.android.settings.deviceinfo.storage.StorageUtils.UnmountTask;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
import com.android.settingslib.core.lifecycle.events.OnOptionsItemSelected;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 052fc98074c..48174852060 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -45,8 +45,8 @@ import com.android.settings.Utils;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.deviceinfo.PrivateVolumeSettings.SystemInfoFragment;
import com.android.settings.deviceinfo.StorageItemPreference;
+import com.android.settings.deviceinfo.storage.StorageUtils.SystemInfoFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java
deleted file mode 100644
index caf5b4e1f79..00000000000
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2016 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.Intent;
-import android.os.storage.StorageManager;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.Button;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.DonutView;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-
-/**
- * StorageSummaryDonutPreference is a preference which summarizes the used and remaining storage left
- * on a given storage volume. It is visualized with a donut graphing the % used.
- */
-public class StorageSummaryDonutPreference extends Preference implements View.OnClickListener {
- private double mPercent = -1;
-
- public StorageSummaryDonutPreference(Context context) {
- this(context, null);
- }
-
- public StorageSummaryDonutPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setLayoutResource(R.layout.storage_summary_donut);
- setEnabled(false);
- }
-
- public void setPercent(long usedBytes, long totalBytes) {
- if (totalBytes == 0) {
- return;
- }
-
- mPercent = usedBytes / (double) totalBytes;
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
- view.itemView.setClickable(false);
-
- final DonutView donut = (DonutView) view.findViewById(R.id.donut);
- if (donut != null) {
- donut.setPercentage(mPercent);
- }
-
- final Button deletionHelperButton = (Button) view.findViewById(R.id.deletion_helper_button);
- if (deletionHelperButton != null) {
- deletionHelperButton.setOnClickListener(this);
- }
- }
-
- @Override
- public void onClick(View v) {
- if (v != null && R.id.deletion_helper_button == v.getId()) {
- final Context context = getContext();
- final MetricsFeatureProvider metricsFeatureProvider =
- FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- metricsFeatureProvider.logClickedPreference(this,
- getExtras().getInt(DashboardFragment.CATEGORY));
- metricsFeatureProvider.action(context, SettingsEnums.STORAGE_FREE_UP_SPACE_NOW);
- final Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
- context.startActivity(intent);
- }
- }
-}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
deleted file mode 100644
index d8ee7118ff3..00000000000
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
+++ /dev/null
@@ -1,136 +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.content.Context;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.text.TextUtils;
-import android.text.format.Formatter;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.deviceinfo.PrivateStorageInfo;
-import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
-import com.android.settingslib.deviceinfo.StorageVolumeProvider;
-import com.android.settingslib.utils.ThreadUtils;
-
-import java.text.NumberFormat;
-
-/**
- * SummaryPreferenceController updates the donut storage summary preference to have the
- * correct sizes showing.
- */
-public class StorageSummaryDonutPreferenceController extends BasePreferenceController {
- private long mUsedBytes;
- private long mTotalBytes;
- private StorageSummaryDonutPreference mSummary;
- private final StorageManager mStorageManager;
- private final StorageManagerVolumeProvider mStorageManagerVolumeProvider;
-
- public StorageSummaryDonutPreferenceController(Context context, String key) {
- super(context, key);
- mStorageManager = mContext.getSystemService(StorageManager.class);
- mStorageManagerVolumeProvider = new StorageManagerVolumeProvider(mStorageManager);
- }
-
- /**
- * Converts a used storage amount to a formatted text.
- *
- * @param usedBytes used bytes of storage
- * @return a formatted text.
- */
- public static CharSequence convertUsedBytesToFormattedText(Context context, long usedBytes) {
- final Formatter.BytesResult result = Formatter.formatBytes(context.getResources(),
- usedBytes, 0);
- return TextUtils.expandTemplate(context.getText(R.string.storage_size_large_alternate),
- result.value, result.units);
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- mSummary = screen.findPreference(getPreferenceKey());
- mSummary.setEnabled(true);
-
- ThreadUtils.postOnBackgroundThread(() -> {
- final NumberFormat percentageFormat = NumberFormat.getPercentInstance();
- final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
- mStorageManagerVolumeProvider);
- final double privateUsedBytes = info.totalBytes - info.freeBytes;
- mTotalBytes = info.totalBytes;
- mUsedBytes = info.totalBytes - info.freeBytes;
-
- ThreadUtils.postOnMainThread(() -> {
- updateState(mSummary);
- });
- });
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- mSummary.setTitle(convertUsedBytesToFormattedText(mContext, mUsedBytes));
- mSummary.setSummary(mContext.getString(R.string.storage_volume_total,
- Formatter.formatShortFileSize(mContext, mTotalBytes)));
- mSummary.setPercent(mUsedBytes, mTotalBytes);
- mSummary.setEnabled(true);
- }
-
- /** Invalidates the data on the view and re-renders. */
- public void invalidateData() {
- if (mSummary != null) {
- updateState(mSummary);
- }
- }
-
- @Override
- public int getAvailabilityStatus() {
- return AVAILABLE;
- }
-
- /**
- * Updates the state of the donut preference for the next update.
- *
- * @param used Total number of used bytes on the summarized volume.
- * @param total Total number of bytes on the summarized volume.
- */
- public void updateBytes(long used, long total) {
- mUsedBytes = used;
- mTotalBytes = total;
- invalidateData();
- }
-
- /**
- * Updates the state of the donut preference for the next update using volume to summarize.
- *
- * @param volume VolumeInfo to use to populate the informayion.
- */
- public void updateSizes(StorageVolumeProvider svp, VolumeInfo volume) {
- final long sharedDataSize = volume.getPath().getTotalSpace();
- long totalSize = svp.getPrimaryStorageSize();
-
- if (totalSize <= 0) {
- totalSize = sharedDataSize;
- }
-
- final long usedBytes = totalSize - volume.getPath().getFreeSpace();
- updateBytes(usedBytes, totalSize);
- }
-}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageUtils.java b/src/com/android/settings/deviceinfo/storage/StorageUtils.java
index 26bdec0556c..919908dbda1 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageUtils.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageUtils.java
@@ -16,18 +16,31 @@
package com.android.settings.deviceinfo.storage;
+import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.deviceinfo.PrivateVolumeForget;
/** Storage utilities */
public class StorageUtils {
+ private static final String TAG = "StorageUtils";
+
/** Launches the fragment to forget a specified missing volume record. */
public static void launchForgetMissingVolumeRecordFragment(Context context,
StorageEntry storageEntry) {
@@ -44,4 +57,104 @@ public class StorageUtils {
.setArguments(args)
.launch();
}
+
+ /** An AsyncTask to unmount a specified volume. */
+ public static class UnmountTask extends AsyncTask {
+ private final Context mContext;
+ private final StorageManager mStorageManager;
+ private final String mVolumeId;
+ private final String mDescription;
+
+ public UnmountTask(Context context, VolumeInfo volume) {
+ mContext = context.getApplicationContext();
+ mStorageManager = mContext.getSystemService(StorageManager.class);
+ mVolumeId = volume.getId();
+ mDescription = mStorageManager.getBestVolumeDescription(volume);
+ }
+
+ @Override
+ protected Exception doInBackground(Void... params) {
+ try {
+ mStorageManager.unmount(mVolumeId);
+ return null;
+ } catch (Exception e) {
+ return e;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Exception e) {
+ if (e == null) {
+ Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_success,
+ mDescription), Toast.LENGTH_SHORT).show();
+ } else {
+ Log.e(TAG, "Failed to unmount " + mVolumeId, e);
+ Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_failure,
+ mDescription), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ /** An AsyncTask to mount a specified volume. */
+ public static class MountTask extends AsyncTask {
+ private final Context mContext;
+ private final StorageManager mStorageManager;
+ private final String mVolumeId;
+ private final String mDescription;
+
+ public MountTask(Context context, VolumeInfo volume) {
+ mContext = context.getApplicationContext();
+ mStorageManager = mContext.getSystemService(StorageManager.class);
+ mVolumeId = volume.getId();
+ mDescription = mStorageManager.getBestVolumeDescription(volume);
+ }
+
+ @Override
+ protected Exception doInBackground(Void... params) {
+ try {
+ mStorageManager.mount(mVolumeId);
+ return null;
+ } catch (Exception e) {
+ return e;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Exception e) {
+ if (e == null) {
+ Toast.makeText(mContext, mContext.getString(R.string.storage_mount_success,
+ mDescription), Toast.LENGTH_SHORT).show();
+ } else {
+ Log.e(TAG, "Failed to mount " + mVolumeId, e);
+ Toast.makeText(mContext, mContext.getString(R.string.storage_mount_failure,
+ mDescription), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ /* Shows information about system storage. */
+ public static class SystemInfoFragment extends InstrumentedDialogFragment {
+ /** Shows the fragment. */
+ public static void show(Fragment parent) {
+ if (!parent.isAdded()) return;
+
+ final SystemInfoFragment dialog = new SystemInfoFragment();
+ dialog.setTargetFragment(parent, 0);
+ dialog.show(parent.getFragmentManager(), "systemInfo");
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DIALOG_STORAGE_SYSTEM_INFO;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(getContext().getString(R.string.storage_detail_dialog_system,
+ Build.VERSION.RELEASE_OR_CODENAME))
+ .setPositiveButton(android.R.string.ok, null)
+ .create();
+ }
+ }
}
diff --git a/src/com/android/settings/emergency/EmergencyDashboardFragment.java b/src/com/android/settings/emergency/EmergencyDashboardFragment.java
index 19834309300..33566458a08 100644
--- a/src/com/android/settings/emergency/EmergencyDashboardFragment.java
+++ b/src/com/android/settings/emergency/EmergencyDashboardFragment.java
@@ -17,12 +17,18 @@
package com.android.settings.emergency;
import android.app.settings.SettingsEnums;
+import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.notification.EmergencyBroadcastPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* {@link DashboardFragment} that hosts emergency/safety related settings.
@@ -31,6 +37,7 @@ import com.android.settingslib.search.SearchIndexable;
public class EmergencyDashboardFragment extends DashboardFragment {
private static final String TAG = "EmergencyDashboard";
+ private static final String WEA_PREF_KEY = "app_and_notif_cell_broadcast_settings";
@Override
protected int getPreferenceScreenResId() {
@@ -47,6 +54,17 @@ public class EmergencyDashboardFragment extends DashboardFragment {
return SettingsEnums.EMERGENCY_SETTINGS;
}
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context);
+ }
+
+ private static List buildPreferenceControllers(Context context) {
+ final List controllers = new ArrayList<>();
+ controllers.add(new EmergencyBroadcastPreferenceController(context, WEA_PREF_KEY));
+ return controllers;
+ }
+
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.emergency_settings);
}
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index 5e4d9809aa9..26eb3e40c55 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -255,7 +255,8 @@ public class BatteryChartView extends AppCompatImageView implements View.OnClick
private int getTrapezoidIndex(float x) {
for (int index = 0; index < mTrapezoidSlot.length; index++) {
final TrapezoidSlot slot = mTrapezoidSlot[index];
- if (x >= slot.mLeft && x <= slot.mRight) {
+ if (x >= slot.mLeft - mTrapezoidHOffset
+ && x <= slot.mRight + mTrapezoidHOffset) {
return index;
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
index 1f61b8b2e1e..da3825f0b80 100644
--- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
@@ -22,13 +22,22 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import java.time.Duration;
import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
/** A container class to carry battery data in a specific time slot. */
public final class BatteryDiffEntry {
private static final String TAG = "BatteryDiffEntry";
+ static Locale sCurrentLocale = null;
+ // Caches app label and icon to improve loading performance.
+ static final Map sResourceCache = new HashMap<>();
+
/** A comparator for {@link BatteryDiffEntry} based on consumed percentage. */
public static final Comparator COMPARATOR =
(a, b) -> Double.compare(b.getPercentOfTotal(), a.getPercentOfTotal());
@@ -42,9 +51,11 @@ public final class BatteryDiffEntry {
private double mPercentOfTotal;
private Context mContext;
- private String mAppLabel = null;
- private Drawable mAppIcon = null;
- private boolean mIsLoaded = false;
+ private String mDefaultPackageName = null;
+
+ @VisibleForTesting String mAppLabel = null;
+ @VisibleForTesting Drawable mAppIcon = null;
+ @VisibleForTesting boolean mIsLoaded = false;
public BatteryDiffEntry(
Context context,
@@ -84,7 +95,10 @@ public final class BatteryDiffEntry {
/** Gets the app label name for this entry. */
public String getAppLabel() {
loadLabelAndIcon();
- return mAppLabel;
+ // Returns default applicationn label if we cannot find it.
+ return mAppLabel == null || mAppLabel.length() == 0
+ ? mBatteryHistEntry.mAppLabel
+ : mAppLabel;
}
/** Gets the app icon {@link Drawable} for this entry. */
@@ -93,6 +107,11 @@ public final class BatteryDiffEntry {
return mAppIcon;
}
+ /** Gets the searching package name for UID battery type. */
+ public String getPackageName() {
+ return mDefaultPackageName;
+ }
+
private void loadLabelAndIcon() {
if (mIsLoaded) {
return;
@@ -121,13 +140,80 @@ public final class BatteryDiffEntry {
}
break;
case ConvertUtils.CONSUMER_TYPE_UID_BATTERY:
+ final BatteryEntry.NameAndIcon nameAndIcon = getCache();
+ if (nameAndIcon != null) {
+ mAppLabel = nameAndIcon.name;
+ mAppIcon = nameAndIcon.icon;
+ break;
+ }
loadNameAndIconForUid();
+ // Uses application default icon if we cannot find it from package.
+ if (mAppIcon == null) {
+ mAppIcon = mContext.getPackageManager().getDefaultActivityIcon();
+ }
+ if (mAppLabel != null && mAppIcon != null) {
+ sResourceCache.put(
+ mBatteryHistEntry.getKey(),
+ new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, /*iconId=*/ 0));
+ }
break;
}
}
+ private BatteryEntry.NameAndIcon getCache() {
+ final Locale locale = Locale.getDefault();
+ if (sCurrentLocale != locale) {
+ Log.d(TAG, String.format("clearCache() locale is changed from %s to %s",
+ sCurrentLocale, locale));
+ sCurrentLocale = locale;
+ clearCache();
+ }
+ return sResourceCache.get(mBatteryHistEntry.getKey());
+ }
+
private void loadNameAndIconForUid() {
- // TODO(b/185187669) fetch label and icon for UID battery type
+ final String packageName = mBatteryHistEntry.mPackageName;
+ final PackageManager packageManager = mContext.getPackageManager();
+ // Gets the application label from PackageManager.
+ if (packageName != null && packageName.length() != 0) {
+ try {
+ final ApplicationInfo appInfo =
+ packageManager.getApplicationInfo(packageName, /*no flags*/ 0);
+ if (appInfo != null) {
+ mAppLabel = packageManager.getApplicationLabel(appInfo).toString();
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "failed to retrieve ApplicationInfo for: " + packageName);
+ mAppLabel = packageName;
+ }
+ }
+
+ final int uid = (int) mBatteryHistEntry.mUid;
+ final String[] packages = packageManager.getPackagesForUid(uid);
+ // Loads special defined application label and icon if available.
+ if (packages == null || packages.length == 0) {
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryEntry.getNameAndIconFromUid(mContext, mAppLabel, uid);
+ mAppLabel = nameAndIcon.name;
+ mAppIcon = nameAndIcon.icon;
+ }
+
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryEntry.loadNameAndIcon(
+ mContext, uid, /*uid=*/ null, /*batteryEntry=*/ null,
+ packageName, mAppLabel, mAppIcon);
+ // Clears BatteryEntry internal cache since we will have another one.
+ BatteryEntry.clearUidCache();
+ if (nameAndIcon != null) {
+ mAppLabel = getNonNull(mAppLabel, nameAndIcon.name);
+ mAppIcon = getNonNull(mAppIcon, nameAndIcon.icon);
+ mDefaultPackageName = nameAndIcon.packageName;
+ if (mDefaultPackageName != null
+ && !mDefaultPackageName.equals(nameAndIcon.packageName)) {
+ Log.w(TAG, String.format("found different package: %s | %s",
+ mDefaultPackageName, nameAndIcon.packageName));
+ }
+ }
}
@Override
@@ -144,4 +230,12 @@ public final class BatteryDiffEntry {
mBatteryHistEntry.mPackageName, mBatteryHistEntry.mUid));
return builder.toString();
}
+
+ static void clearCache() {
+ sResourceCache.clear();
+ }
+
+ private static T getNonNull(T originalObj, T newObj) {
+ return newObj != null ? newObj : originalObj;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index c0ed092bb9e..2d9f715fca9 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -110,7 +110,8 @@ public class BatteryEntry {
}
final NameAndIcon nameAndIcon =
BatteryEntry.loadNameAndIcon(
- be.mContext, be.getUid(), sHandler, be, be.mDefaultPackageName);
+ be.mContext, be.getUid(), sHandler, be,
+ be.mDefaultPackageName, be.name, be.icon);
if (nameAndIcon != null) {
be.icon = getNonNull(be.icon, nameAndIcon.icon);
be.name = getNonNull(be.name, nameAndIcon.name);
@@ -273,6 +274,7 @@ public class BatteryEntry {
icon = mContext.getPackageManager().getDefaultActivityIcon();
}
+ // Avoids post the loading icon and label in the background request.
if (sHandler != null && loadDataInBackground) {
synchronized (sRequestQueue) {
sRequestQueue.add(this);
@@ -288,9 +290,9 @@ public class BatteryEntry {
int uid,
Handler handler,
BatteryEntry batteryEntry,
- String defaultPackageName) {
- String name = null;
- Drawable icon = null;
+ String defaultPackageName,
+ String name,
+ Drawable icon) {
// Bail out if the current sipper is not an App sipper.
if (uid == 0 || uid == Process.INVALID_UID) {
return null;
diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
index e8cbce5bfd5..9611de18ec0 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
@@ -65,6 +65,7 @@ public final class BatteryHistEntry {
public final int mBatteryStatus;
public final int mBatteryHealth;
+ private String mKey = null;
private boolean mIsValidEntry = true;
public BatteryHistEntry(ContentValues values) {
@@ -114,7 +115,20 @@ public final class BatteryHistEntry {
/** Gets an identifier to represent this {@link BatteryHistEntry}. */
public String getKey() {
- return mPackageName + "-" + mUserId;
+ if (mKey == null) {
+ switch (mConsumerType) {
+ case ConvertUtils.CONSUMER_TYPE_UID_BATTERY:
+ mKey = Long.toString(mUid);
+ break;
+ case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY:
+ mKey = "S|" + mDrainType;
+ break;
+ case ConvertUtils.CONSUMER_TYPE_USER_BATTERY:
+ mKey = "U|" + mUserId;
+ break;
+ }
+ }
+ return mKey;
}
@Override
diff --git a/src/com/android/settings/security/ChangeScreenLockPreferenceController.java b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
index 1587746fbab..7ea9879047d 100644
--- a/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
+++ b/src/com/android/settings/security/ChangeScreenLockPreferenceController.java
@@ -28,6 +28,7 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
@@ -48,7 +49,7 @@ public class ChangeScreenLockPreferenceController extends AbstractPreferenceCont
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
protected final DevicePolicyManager mDPM;
- protected final SecuritySettings mHost;
+ protected final SettingsPreferenceFragment mHost;
protected final UserManager mUm;
protected final LockPatternUtils mLockPatternUtils;
@@ -58,7 +59,7 @@ public class ChangeScreenLockPreferenceController extends AbstractPreferenceCont
protected RestrictedPreference mPreference;
- public ChangeScreenLockPreferenceController(Context context, SecuritySettings host) {
+ public ChangeScreenLockPreferenceController(Context context, SettingsPreferenceFragment host) {
super(context);
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
diff --git a/src/com/android/settings/sim/DsdsDialogActivity.java b/src/com/android/settings/sim/DsdsDialogActivity.java
index 1390c817bf6..62a6995a54c 100644
--- a/src/com/android/settings/sim/DsdsDialogActivity.java
+++ b/src/com/android/settings/sim/DsdsDialogActivity.java
@@ -123,7 +123,7 @@ public class DsdsDialogActivity extends SubscriptionActionDialogActivity
DIALOG_TAG_ENABLE_DSDS_CONFIRMATION,
getString(R.string.sim_action_enable_dsds_title),
getString(R.string.sim_action_enable_dsds_text),
- getString(R.string.sim_action_continue),
+ getString(R.string.sim_action_yes),
getString(R.string.sim_action_no_thanks));
}
diff --git a/src/com/android/settings/widget/DonutView.java b/src/com/android/settings/widget/DonutView.java
deleted file mode 100644
index 13716636d91..00000000000
--- a/src/com/android/settings/widget/DonutView.java
+++ /dev/null
@@ -1,265 +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.widget;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Typeface;
-import android.icu.text.DecimalFormatSymbols;
-import android.text.Layout;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.StaticLayout;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.style.RelativeSizeSpan;
-import android.util.AttributeSet;
-import android.view.View;
-
-import androidx.annotation.ColorRes;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.settings.R;
-import com.android.settings.Utils;
-
-import java.util.Locale;
-
-/**
- * DonutView represents a donut graph. It visualizes a certain percentage of fullness with a
- * corresponding label with the fullness on the inside (i.e. "50%" inside of the donut).
- */
-public class DonutView extends View {
- private static final int TOP = -90;
- // From manual testing, this is the longest we can go without visual errors.
- private static final int LINE_CHARACTER_LIMIT = 10;
- private float mStrokeWidth;
- private double mPercent;
- private Paint mBackgroundCircle;
- private Paint mFilledArc;
- private TextPaint mTextPaint;
- private TextPaint mBigNumberPaint;
- private String mPercentString;
- private String mFullString;
- private boolean mShowPercentString = true;
- private int mMeterBackgroundColor;
- private int mMeterConsumedColor;
-
- public DonutView(Context context) {
- super(context);
- }
-
- public DonutView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mMeterBackgroundColor = context.getColor(R.color.meter_background_color);
- mMeterConsumedColor = Utils.getColorStateListDefaultColor(mContext,
- R.color.meter_consumed_color);
- boolean applyColorAccent = true;
- Resources resources = context.getResources();
- mStrokeWidth = resources.getDimension(R.dimen.storage_donut_thickness);
-
- if (attrs != null) {
- TypedArray styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.DonutView);
- mMeterBackgroundColor = styledAttrs.getColor(R.styleable.DonutView_meterBackgroundColor,
- mMeterBackgroundColor);
- mMeterConsumedColor = styledAttrs.getColor(R.styleable.DonutView_meterConsumedColor,
- mMeterConsumedColor);
- applyColorAccent = styledAttrs.getBoolean(R.styleable.DonutView_applyColorAccent,
- true);
- mShowPercentString = styledAttrs.getBoolean(R.styleable.DonutView_showPercentString,
- true);
- mStrokeWidth = styledAttrs.getDimensionPixelSize(R.styleable.DonutView_thickness,
- (int) mStrokeWidth);
- styledAttrs.recycle();
- }
-
- mBackgroundCircle = new Paint();
- mBackgroundCircle.setAntiAlias(true);
- mBackgroundCircle.setStrokeCap(Paint.Cap.BUTT);
- mBackgroundCircle.setStyle(Paint.Style.STROKE);
- mBackgroundCircle.setStrokeWidth(mStrokeWidth);
- mBackgroundCircle.setColor(mMeterBackgroundColor);
-
- mFilledArc = new Paint();
- mFilledArc.setAntiAlias(true);
- mFilledArc.setStrokeCap(Paint.Cap.BUTT);
- mFilledArc.setStyle(Paint.Style.STROKE);
- mFilledArc.setStrokeWidth(mStrokeWidth);
- mFilledArc.setColor(mMeterConsumedColor);
-
- if (applyColorAccent) {
- final ColorFilter mAccentColorFilter =
- new PorterDuffColorFilter(
- Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent),
- PorterDuff.Mode.SRC_IN);
- mBackgroundCircle.setColorFilter(mAccentColorFilter);
- mFilledArc.setColorFilter(mAccentColorFilter);
- }
-
- final Locale locale = resources.getConfiguration().locale;
- final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
- final int bidiFlags = (layoutDirection == LAYOUT_DIRECTION_LTR)
- ? Paint.BIDI_LTR
- : Paint.BIDI_RTL;
-
- mTextPaint = new TextPaint();
- mTextPaint.setColor(Utils.getColorAccentDefaultColor(getContext()));
- mTextPaint.setAntiAlias(true);
- mTextPaint.setTextSize(
- resources.getDimension(R.dimen.storage_donut_view_label_text_size));
- mTextPaint.setTextAlign(Paint.Align.CENTER);
- mTextPaint.setBidiFlags(bidiFlags);
-
- mBigNumberPaint = new TextPaint();
- mBigNumberPaint.setColor(Utils.getColorAccentDefaultColor(getContext()));
- mBigNumberPaint.setAntiAlias(true);
- mBigNumberPaint.setTextSize(
- resources.getDimension(R.dimen.storage_donut_view_percent_text_size));
- mBigNumberPaint.setTypeface(Typeface.create(
- context.getString(com.android.internal.R.string.config_headlineFontFamily),
- Typeface.NORMAL));
- mBigNumberPaint.setBidiFlags(bidiFlags);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- drawDonut(canvas);
- if (mShowPercentString) {
- drawInnerText(canvas);
- }
- }
-
- private void drawDonut(Canvas canvas) {
- canvas.drawArc(
- 0 + mStrokeWidth,
- 0 + mStrokeWidth,
- getWidth() - mStrokeWidth,
- getHeight() - mStrokeWidth,
- TOP,
- 360,
- false,
- mBackgroundCircle);
-
- canvas.drawArc(
- 0 + mStrokeWidth,
- 0 + mStrokeWidth,
- getWidth() - mStrokeWidth,
- getHeight() - mStrokeWidth,
- TOP,
- (360 * (float) mPercent),
- false,
- mFilledArc);
- }
-
- private void drawInnerText(Canvas canvas) {
- final float centerX = getWidth() / 2;
- final float centerY = getHeight() / 2;
- final float totalHeight = getTextHeight(mTextPaint) + getTextHeight(mBigNumberPaint);
- final float startY = centerY + totalHeight / 2;
- // Support from Android P
- final String localizedPercentSign = new DecimalFormatSymbols().getPercentString();
-
- // The first line y-coordinates start at (total height - all TextPaint height) / 2
- canvas.save();
- final Spannable percentStringSpan =
- getPercentageStringSpannable(getResources(), mPercentString, localizedPercentSign);
- final StaticLayout percentStringLayout = new StaticLayout(percentStringSpan,
- mBigNumberPaint, getWidth(), Layout.Alignment.ALIGN_CENTER, 1, 0, false);
- canvas.translate(0, (getHeight() - totalHeight) / 2);
- percentStringLayout.draw(canvas);
- canvas.restore();
-
- // The second line starts at the bottom + room for the descender.
- canvas.drawText(mFullString, centerX, startY - mTextPaint.descent(), mTextPaint);
- }
-
- /**
- * Set a percentage full to have the donut graph.
- */
- public void setPercentage(double percent) {
- mPercent = percent;
- mPercentString = Utils.formatPercentage(mPercent);
- mFullString = getContext().getString(R.string.storage_percent_full);
- if (mFullString.length() > LINE_CHARACTER_LIMIT) {
- mTextPaint.setTextSize(
- getContext()
- .getResources()
- .getDimension(
- R.dimen.storage_donut_view_shrunken_label_text_size));
- }
- setContentDescription(getContext().getString(
- R.string.join_two_unrelated_items, mPercentString, mFullString));
- invalidate();
- }
-
- @ColorRes
- public int getMeterBackgroundColor() {
- return mMeterBackgroundColor;
- }
-
- public void setMeterBackgroundColor(@ColorRes int meterBackgroundColor) {
- mMeterBackgroundColor = meterBackgroundColor;
- mBackgroundCircle.setColor(meterBackgroundColor);
- invalidate();
- }
-
- @ColorRes
- public int getMeterConsumedColor() {
- return mMeterConsumedColor;
- }
-
- public void setMeterConsumedColor(@ColorRes int meterConsumedColor) {
- mMeterConsumedColor = meterConsumedColor;
- mFilledArc.setColor(meterConsumedColor);
- invalidate();
- }
-
- @VisibleForTesting
- static Spannable getPercentageStringSpannable(
- Resources resources, String percentString, String percentageSignString) {
- final float fontProportion =
- resources.getDimension(R.dimen.storage_donut_view_percent_sign_size)
- / resources.getDimension(R.dimen.storage_donut_view_percent_text_size);
- final Spannable percentStringSpan = new SpannableString(percentString);
- int startIndex = percentString.indexOf(percentageSignString);
- int endIndex = startIndex + percentageSignString.length();
-
- // Fallback to no small string if we can't find the percentage sign.
- if (startIndex < 0) {
- startIndex = 0;
- endIndex = percentString.length();
- }
-
- percentStringSpan.setSpan(
- new RelativeSizeSpan(fontProportion),
- startIndex,
- endIndex,
- Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
- return percentStringSpan;
- }
-
- private float getTextHeight(TextPaint paint) {
- // Technically, this should be the cap height, but I can live with the descent - ascent.
- return paint.descent() - paint.ascent();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
deleted file mode 100644
index d96473bf922..00000000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
+++ /dev/null
@@ -1,80 +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 org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.storage.VolumeInfo;
-
-import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class StorageSettingsTest {
-
- @Mock
- private StorageManagerVolumeProvider mStorageManagerVolumeProvider;
- @Mock
- private Activity mActivity;
-
- private List mVolumes;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mVolumes = new ArrayList<>();
- mVolumes.add(mock(VolumeInfo.class, RETURNS_DEEP_STUBS));
- when(mStorageManagerVolumeProvider.getVolumes()).thenReturn(mVolumes);
- }
-
- @Test
- public void handlePublicVolumeClick_startsANonNullActivityWhenVolumeHasNoBrowse() {
- VolumeInfo volumeInfo = mock(VolumeInfo.class, RETURNS_DEEP_STUBS);
- when(volumeInfo.isMountedReadable()).thenReturn(true);
- StorageSettings.handlePublicVolumeClick(mActivity, volumeInfo);
-
- verify(mActivity, never()).startActivity(null);
- verify(mActivity).startActivity(any(Intent.class));
- }
-
- @Test
- public void handleStubVolumeClick_startsANonNullActivityWhenVolumeHasNoBrowse() {
- VolumeInfo volumeInfo = mock(VolumeInfo.class, RETURNS_DEEP_STUBS);
- when(volumeInfo.isMountedReadable()).thenReturn(true);
-
- StorageSettings.handleStubVolumeClick(mActivity, volumeInfo);
-
- verify(mActivity, never()).startActivity(null);
- verify(mActivity).startActivity(any(Intent.class));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index b7bf7f56606..4a1ea40ad8b 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -48,7 +48,6 @@ import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
-import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.applications.StorageStatsSource;
@@ -329,7 +328,7 @@ public class StorageItemPreferenceControllerTest {
assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
verify(mFragment.getFragmentManager().beginTransaction())
- .add(nullable(PrivateVolumeSettings.SystemInfoFragment.class), nullable(String.class));
+ .add(nullable(StorageUtils.SystemInfoFragment.class), nullable(String.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
deleted file mode 100644
index cd6f0822788..00000000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
+++ /dev/null
@@ -1,164 +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.TestUtils.GIGABYTE;
-import static com.android.settings.TestUtils.KILOBYTE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.storage.VolumeInfo;
-import android.text.format.Formatter;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-
-import androidx.preference.PreferenceScreen;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.shadow.ShadowPrivateStorageInfo;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.deviceinfo.PrivateStorageInfo;
-import com.android.settingslib.deviceinfo.StorageVolumeProvider;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-import java.io.File;
-
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowPrivateStorageInfo.class)
-public class StorageSummaryDonutPreferenceControllerTest {
-
- private Context mContext;
- private StorageSummaryDonutPreferenceController mController;
- private StorageSummaryDonutPreference mPreference;
- private PreferenceViewHolder mHolder;
- private FakeFeatureFactory mFakeFeatureFactory;
- private MetricsFeatureProvider mMetricsFeatureProvider;
- private PreferenceScreen mScreen;
-
- @Before
- public void setUp() throws Exception {
- ShadowPrivateStorageInfo.setPrivateStorageInfo(new PrivateStorageInfo(10L, 100L));
- mContext = spy(Robolectric.setupActivity(Activity.class));
- mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
- mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
- mController = new StorageSummaryDonutPreferenceController(mContext, "key");
- mPreference = new StorageSummaryDonutPreference(mContext);
- mScreen = spy(new PreferenceScreen(mContext, null));
- when(mScreen.findPreference("key")).thenReturn(mPreference);
-
- LayoutInflater inflater = LayoutInflater.from(mContext);
- final View view =
- inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(mContext),
- false);
- mHolder = PreferenceViewHolder.createInstanceForTests(view);
- }
-
- @After
- public void tearDown() {
- ShadowPrivateStorageInfo.reset();
- }
-
- @Test
- public void testEmpty() {
- final long totalSpace = 32 * GIGABYTE;
- final long usedSpace = 0;
- mController.displayPreference(mScreen);
- mController.updateBytes(0, 32 * GIGABYTE);
- mController.updateState(mPreference);
-
- final Formatter.BytesResult usedSpaceResults =
- Formatter.formatBytes(mContext.getResources(), usedSpace, 0 /* flags */);
- assertThat(mPreference.getTitle().toString())
- .isEqualTo(usedSpaceResults.value + " " + usedSpaceResults.units);
- assertThat(mPreference.getSummary().toString())
- .isEqualTo("Used of " + Formatter.formatShortFileSize(mContext, totalSpace));
- }
-
- @Test
- public void testTotalStorage() {
- final long totalSpace = KILOBYTE * 10;
- final long usedSpace = KILOBYTE;
- mController.displayPreference(mScreen);
- mController.updateBytes(KILOBYTE, totalSpace);
- mController.updateState(mPreference);
-
- final Formatter.BytesResult usedSpaceResults =
- Formatter.formatBytes(mContext.getResources(), usedSpace, 0 /* flags */);
- assertThat(mPreference.getTitle().toString())
- .isEqualTo(usedSpaceResults.value + " " + usedSpaceResults.units);
- assertThat(mPreference.getSummary().toString())
- .isEqualTo("Used of " + Formatter.formatShortFileSize(mContext, totalSpace));
- }
-
- @Test
- public void testPopulateWithVolume() {
- final long totalSpace = KILOBYTE * 10;
- final long freeSpace = KILOBYTE;
- final long usedSpace = totalSpace - freeSpace;
- final VolumeInfo volume = Mockito.mock(VolumeInfo.class);
- final File file = Mockito.mock(File.class);
- final StorageVolumeProvider svp = Mockito.mock(StorageVolumeProvider.class);
- when(volume.getPath()).thenReturn(file);
- when(file.getTotalSpace()).thenReturn(totalSpace);
- when(file.getFreeSpace()).thenReturn(freeSpace);
- when(svp.getPrimaryStorageSize()).thenReturn(totalSpace);
- mController.displayPreference(mScreen);
-
- mController.updateSizes(svp, volume);
- mController.updateState(mPreference);
-
- final Formatter.BytesResult usedSpaceResults =
- Formatter.formatBytes(mContext.getResources(), usedSpace, 0 /* flags */);
- assertThat(mPreference.getTitle().toString())
- .isEqualTo(usedSpaceResults.value + " " + usedSpaceResults.units);
- assertThat(mPreference.getSummary().toString())
- .isEqualTo("Used of " + Formatter.formatShortFileSize(mContext, totalSpace));
- }
-
- @Test
- public void testFreeUpSpaceMetricIsTriggered() {
- mPreference.onBindViewHolder(mHolder);
- final Button button = (Button) mHolder.findViewById(R.id.deletion_helper_button);
-
- mPreference.onClick(button);
-
- verify(mMetricsFeatureProvider, times(1))
- .action(any(Context.class), eq(MetricsEvent.STORAGE_FREE_UP_SPACE_NOW));
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
index afbfe84883a..84ff07b3c2c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
@@ -17,11 +17,15 @@ package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.content.ContentValues;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
import android.os.SystemBatteryConsumer;
import android.os.UserManager;
@@ -36,19 +40,26 @@ import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
@RunWith(RobolectricTestRunner.class)
public final class BatteryDiffEntryTest {
private Context mContext;
- @Mock
- private UserManager mockUserManager;
+
+ @Mock private ApplicationInfo mockAppInfo;
+ @Mock private PackageManager mockPackageManager;
+ @Mock private UserManager mockUserManager;
+ @Mock private Drawable mockDrawable;
+ @Mock private Drawable mockDrawable2;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
doReturn(mockUserManager).when(mContext).getSystemService(UserManager.class);
+ doReturn(mockPackageManager).when(mContext).getPackageManager();
+ BatteryDiffEntry.clearCache();
}
@Test
@@ -96,9 +107,8 @@ public final class BatteryDiffEntryTest {
@Test
public void testLoadLabelAndIcon_forSystemBattery_returnExpectedResult() {
// Generates fake testing data.
- final ContentValues values = new ContentValues();
- values.put("consumerType",
- Integer.valueOf(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY));
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
values.put("drainType",
Integer.valueOf(SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
@@ -106,15 +116,15 @@ public final class BatteryDiffEntryTest {
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
assertThat(entry.getAppLabel()).isEqualTo("Ambient display");
+ assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
}
@Test
public void testLoadLabelAndIcon_forUserBattery_returnExpectedResult() {
doReturn(null).when(mockUserManager).getUserInfo(1001);
// Generates fake testing data.
- final ContentValues values = new ContentValues();
- values.put("consumerType",
- Integer.valueOf(ConvertUtils.CONSUMER_TYPE_USER_BATTERY));
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
values.put("userId", Integer.valueOf(1001));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
@@ -122,6 +132,109 @@ public final class BatteryDiffEntryTest {
assertThat(entry.getAppLabel()).isEqualTo("Removed user");
assertThat(entry.getAppIcon()).isNull();
+ assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ }
+
+ @Test
+ public void testGetAppLabel_loadDataFromApplicationInfo() throws Exception {
+ final String expectedAppLabel = "fake app label";
+ final String fakePackageName = "com.fake.google.com";
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+ values.put("uid", /*invalid uid*/ 10001);
+ values.put("packageName", fakePackageName);
+ doReturn(mockAppInfo).when(mockPackageManager)
+ .getApplicationInfo(fakePackageName, 0);
+ doReturn(expectedAppLabel).when(mockPackageManager)
+ .getApplicationLabel(mockAppInfo);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
+
+ assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel);
+ assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
+ // Verifies the app label in the cache.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(batteryHistEntry.getKey());
+ assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
+ }
+
+ @Test
+ public void testGetAppLabel_loadDataFromPreDefinedNameAndUid() {
+ final String expectedAppLabel = "Android OS";
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
+
+ assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel);
+ assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
+ // Verifies the app label in the cache.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(batteryHistEntry.getKey());
+ assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
+ }
+
+ @Test
+ public void testGetAppLabel_nullAppLabel_returnAppLabelInBatteryHistEntry() {
+ final String expectedAppLabel = "fake app label";
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+ values.put("appLabel", expectedAppLabel);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
+
+ entry.mIsLoaded = true;
+ assertThat(entry.getAppLabel()).isEqualTo(expectedAppLabel);
+ assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ }
+
+ @Test
+ public void testGetAppIcon_nonUidConsumer_returnAppIconInBatteryDiffEntry() {
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
+
+ entry.mIsLoaded = true;
+ entry.mAppIcon = mockDrawable;
+ assertThat(entry.getAppIcon()).isEqualTo(mockDrawable);
+ assertThat(BatteryDiffEntry.sResourceCache).isEmpty();
+ }
+
+ @Test
+ public void testGetAppIcon_uidConsumerWithNullIcon_returnDefaultActivityIcon()
+ throws Exception {
+ final BatteryDiffEntry entry = createBatteryDiffEntry(mockDrawable);
+
+ entry.mAppIcon = null;
+ assertThat(entry.getAppIcon()).isEqualTo(mockDrawable);
+ assertThat(BatteryDiffEntry.sResourceCache).hasSize(1);
+ // Verifies the app label in the cache.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(entry.mBatteryHistEntry.getKey());
+ assertThat(nameAndIcon.icon).isEqualTo(mockDrawable);
+ }
+
+ @Test
+ public void testClearCache_switchLocale_clearCacheIconAndLabel() throws Exception {
+ Locale.setDefault(new Locale("en_US"));
+ final BatteryDiffEntry entry1 = createBatteryDiffEntry(mockDrawable);
+ assertThat(entry1.getAppIcon()).isEqualTo(mockDrawable);
+ // Switch the locale into another one.
+ Locale.setDefault(new Locale("zh_TW"));
+
+ final BatteryDiffEntry entry2 = createBatteryDiffEntry(mockDrawable2);
+
+ // We should get new drawable without caching.
+ assertThat(entry2.getAppIcon()).isEqualTo(mockDrawable2);
+ // Verifies the cache is updated into the new drawable.
+ final BatteryEntry.NameAndIcon nameAndIcon =
+ BatteryDiffEntry.sResourceCache.get(entry2.mBatteryHistEntry.getKey());
+ assertThat(nameAndIcon.icon).isEqualTo(mockDrawable2);
}
private BatteryDiffEntry createBatteryDiffEntry(
@@ -135,4 +248,23 @@ public final class BatteryDiffEntryTest {
entry.setTotalConsumePower(100.0);
return entry;
}
+
+ private static ContentValues getContentValuesWithType(int consumerType) {
+ final ContentValues values = new ContentValues();
+ values.put("consumerType", Integer.valueOf(consumerType));
+ return values;
+ }
+
+ private BatteryDiffEntry createBatteryDiffEntry(Drawable drawable) throws Exception {
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+ values.put("uid", 1001);
+ values.put("packageName", "com.a.b.c");
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+ doReturn(drawable).when(mockPackageManager).getDefaultActivityIcon();
+ doReturn(null).when(mockPackageManager).getApplicationInfo("com.a.b.c", 0);
+ doReturn(new String[] {"com.a.b.c"}).when(mockPackageManager)
+ .getPackagesForUid(1001);
+ return createBatteryDiffEntry(10, batteryHistEntry);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
index d97b0d22baf..72ccebe1b43 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
@@ -137,6 +137,42 @@ public final class BatteryHistEntryTest {
/*percentOfTotal=*/ 0.3);
}
+ @Test
+ public void testGetKey_consumerUidType_returnExpectedString() {
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
+ values.put("uid", 3);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ assertThat(batteryHistEntry.getKey()).isEqualTo("3");
+ }
+
+ @Test
+ public void testGetKey_consumerUserType_returnExpectedString() {
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
+ values.put("userId", 2);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ assertThat(batteryHistEntry.getKey()).isEqualTo("U|2");
+ }
+
+ @Test
+ public void testGetKey_consumerSystemType_returnExpectedString() {
+ final ContentValues values = getContentValuesWithType(
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
+ values.put("drainType", 1);
+ final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
+
+ assertThat(batteryHistEntry.getKey()).isEqualTo("S|1");
+ }
+
+ private static ContentValues getContentValuesWithType(int consumerType) {
+ final ContentValues values = new ContentValues();
+ values.put("consumerType", Integer.valueOf(consumerType));
+ return values;
+ }
+
private void assertBatteryHistEntry(
BatteryHistEntry entry, int drainType, double percentOfTotal) {
assertThat(entry.isValidEntry()).isTrue();
@@ -161,7 +197,5 @@ public final class BatteryHistEntryTest {
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(entry.mBatteryHealth)
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
- assertThat(entry.getKey())
- .isEqualTo("com.google.android.settings.battery-" + entry.mUserId);
}
}
diff --git a/tests/unit/src/com/android/settings/development/transcode/TranscodeDefaultOptionPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/transcode/TranscodeDefaultOptionPreferenceControllerTest.java
index 550613bd62d..e3fa0766acc 100644
--- a/tests/unit/src/com/android/settings/development/transcode/TranscodeDefaultOptionPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/development/transcode/TranscodeDefaultOptionPreferenceControllerTest.java
@@ -70,7 +70,7 @@ public class TranscodeDefaultOptionPreferenceControllerTest {
}
@Test
- public void getAvailabilityStatus_shouldReturn_isAvailable() {
+ public void getAvailabilityStatus_shouldReturnAVAILABLE() {
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
diff --git a/tests/unit/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceControllerTest.java
new file mode 100644
index 00000000000..89c8773fe16
--- /dev/null
+++ b/tests/unit/src/com/android/settings/development/transcode/TranscodeDisableCachePreferenceControllerTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.development.transcode;
+
+import static com.android.settings.development.transcode.TranscodeDisableCachePreferenceController.TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class TranscodeDisableCachePreferenceControllerTest {
+
+ private TranscodeUserControlPreferenceController mUnderTest;
+
+ @Before
+ public void setUp() {
+ Context context = ApplicationProvider.getApplicationContext();
+ mUnderTest = new TranscodeUserControlPreferenceController(context, "some_key");
+ }
+
+ @Test
+ public void isChecked_whenSysPropSet_shouldReturnTrue() {
+ SystemProperties.set(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, "true");
+ assertThat(mUnderTest.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_whenSysPropUnset_shouldReturnFalse() {
+ SystemProperties.set(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, "false");
+ assertThat(mUnderTest.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setChecked_withTrue_shouldSetSysProp() {
+ mUnderTest.setChecked(true);
+ assertThat(
+ SystemProperties.getBoolean(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, false)).isTrue();
+ }
+
+ @Test
+ public void setChecked_withFalse_shouldUnsetSysProp() {
+ mUnderTest.setChecked(false);
+ assertThat(
+ SystemProperties.getBoolean(TRANSCODE_DISABLE_CACHE_SYS_PROP_KEY, true)).isFalse();
+ }
+
+ @Test
+ public void getAvailabilityStatus_shouldReturnAVAILABLE() {
+ assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/development/transcode/TranscodeNotificationPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/transcode/TranscodeNotificationPreferenceControllerTest.java
index 0903c72a099..65bfbf571e2 100644
--- a/tests/unit/src/com/android/settings/development/transcode/TranscodeNotificationPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/development/transcode/TranscodeNotificationPreferenceControllerTest.java
@@ -69,7 +69,7 @@ public class TranscodeNotificationPreferenceControllerTest {
}
@Test
- public void getAvailabilityStatus_shouldReturn_isAvailable() {
+ public void getAvailabilityStatus_shouldReturnAVAILABLE() {
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
diff --git a/tests/unit/src/com/android/settings/development/transcode/TranscodeUserControlPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/transcode/TranscodeUserControlPreferenceControllerTest.java
index 3caf8ae3c65..63a6ac6cb22 100644
--- a/tests/unit/src/com/android/settings/development/transcode/TranscodeUserControlPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/development/transcode/TranscodeUserControlPreferenceControllerTest.java
@@ -70,7 +70,7 @@ public class TranscodeUserControlPreferenceControllerTest {
}
@Test
- public void getAvailabilityStatus_shouldReturn_isAvailable() {
+ public void getAvailabilityStatus_shouldReturnAVAILABLE() {
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
diff --git a/tests/unit/src/com/android/settings/widget/DonutViewTest.java b/tests/unit/src/com/android/settings/widget/DonutViewTest.java
deleted file mode 100644
index ad02d0ebe5e..00000000000
--- a/tests/unit/src/com/android/settings/widget/DonutViewTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2020 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.widget;
-
-import android.content.Context;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class DonutViewTest {
- @Test
- public void getPercentageStringSpannable_doesntCrashForMissingPercentage() {
- Context context = ApplicationProvider.getApplicationContext();
-
- DonutView.getPercentageStringSpannable(context.getResources(), "50%", "h");
- }
-}