diff --git a/res/layout/storage_summary_donut.xml b/res/layout/storage_summary_donut.xml
index 9cffe69c6e9..d9ead9c81a7 100644
--- a/res/layout/storage_summary_donut.xml
+++ b/res/layout/storage_summary_donut.xml
@@ -14,47 +14,61 @@
limitations under the License.
-->
-
-
+
-
+
-
+
+
+
+
+
+
diff --git a/res/values/colors.xml b/res/values/colors.xml
index a8d35dcd73d..38eb74b5eae 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -111,6 +111,9 @@
#f5f5f5
-
#3c3c3c
+
+
+ #ffd7d7d7
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 4b3dba9a4be..bc159d60ade 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -307,4 +307,7 @@
40dp
40dp
+
+
+ 16dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b9e9c1c67a8..73c7e3b04c5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8019,4 +8019,14 @@
Files
+
+ Phone Storage
+
+
+ ^1 ^2 used
+
+ %1$s free
+
+ %1$s%%
+
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a3baa21f3a9..a4a679b2ddd 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -437,4 +437,10 @@
+
+
+
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index efcf47907cc..c9572b3bfff 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -46,7 +46,6 @@ public class StorageDashboardFragment extends DashboardFragment {
private static final String TAG = "StorageDashboardFrag";
private VolumeInfo mVolume;
- private long mTotalSize;
private StorageSummaryDonutPreferenceController mSummaryController;
private StorageItemPreferenceController mPreferenceController;
@@ -70,16 +69,16 @@ public class StorageDashboardFragment extends DashboardFragment {
}
final long sharedDataSize = mVolume.getPath().getTotalSpace();
- mTotalSize = sm.getPrimaryStorageSize();
- long systemSize = mTotalSize - sharedDataSize;
+ long totalSize = sm.getPrimaryStorageSize();
+ long systemSize = totalSize - sharedDataSize;
- if (mTotalSize <= 0) {
- mTotalSize = sharedDataSize;
+ if (totalSize <= 0) {
+ totalSize = sharedDataSize;
systemSize = 0;
}
- final long usedBytes = mTotalSize - mVolume.getPath().getFreeSpace();
- mSummaryController.updateBytes(usedBytes, mTotalSize);
+ final long usedBytes = totalSize - mVolume.getPath().getFreeSpace();
+ mSummaryController.updateBytes(usedBytes, totalSize);
mPreferenceController.setVolume(mVolume);
mPreferenceController.setSystemSize(systemSize);
mPreferenceController.startMeasurement();
@@ -90,8 +89,6 @@ public class StorageDashboardFragment extends DashboardFragment {
pref.setFragment("com.android.settings.deletionhelper.AutomaticStorageManagerSettings");
pref.setIcon(R.drawable.ic_settings_storage);
pref.setEnabled(true);
-
-
}
@Override
@@ -128,13 +125,6 @@ public class StorageDashboardFragment extends DashboardFragment {
return controllers;
}
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- View root = super.onCreateView(inflater, container, savedInstanceState);
- // TODO: Add loader to load the storage sizes for the StorageItemPreferenceControllers.
- return root;
- }
/**
* For Search.
*/
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java
index d6fd3545410..9e39034f9d5 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreference.java
@@ -17,20 +17,23 @@
package com.android.settings.deviceinfo.storage;
import android.content.Context;
+import android.content.Intent;
+import android.os.storage.StorageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.View;
-import android.widget.ProgressBar;
+import android.widget.Button;
import com.android.settings.R;
+import com.android.settings.widget.DonutView;
/**
* 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 {
+public class StorageSummaryDonutPreference extends Preference implements View.OnClickListener {
private int mPercent = -1;
public StorageSummaryDonutPreference(Context context) {
@@ -55,17 +58,23 @@ public class StorageSummaryDonutPreference extends Preference {
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
- // TODO: Replace the progress bar with a donut.
- final ProgressBar progress = (ProgressBar) view.findViewById(android.R.id.progress);
- if (mPercent != -1) {
- progress.setVisibility(View.VISIBLE);
- progress.setProgress(mPercent);
- progress.setScaleY(7f);
- } else {
- progress.setVisibility(View.GONE);
+ super.onBindViewHolder(view);
+ final DonutView donut = (DonutView) view.findViewById(R.id.donut);
+ if (donut != null) {
+ donut.setPercentage(mPercent);
}
- super.onBindViewHolder(view);
+ 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()) {
+ Intent intent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+ getContext().startActivity(intent);
+ }
+ }
}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
index 1d2478aaeaa..a9626692677 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceController.java
@@ -1,16 +1,33 @@
+/*
+ * 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.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.text.format.Formatter;
-import android.util.Log;
-import android.widget.TextView;
-import com.android.settings.core.PreferenceController;
import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
+import com.android.settingslib.deviceinfo.StorageVolumeProvider;
/**
* StorgaeSummaryPreferenceController updates the donut storage summary preference to have the
@@ -37,12 +54,13 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle
StorageSummaryDonutPreference summary = (StorageSummaryDonutPreference) preference;
final Formatter.BytesResult result = Formatter.formatBytes(mContext.getResources(),
mUsedBytes, 0);
- summary.setTitle(TextUtils.expandTemplate(mContext.getText(R.string.storage_size_large),
- result.value, result.units));
- summary.setSummary(mContext.getString(R.string.storage_volume_used,
- Formatter.formatFileSize(mContext, mTotalBytes)));
- summary.setEnabled(true);
+ summary.setTitle(TextUtils.expandTemplate(
+ mContext.getText(R.string.storage_size_large_alternate), result.value,
+ result.units));
+ summary.setSummary(mContext.getString(R.string.storage_volume_free,
+ Formatter.formatFileSize(mContext, mTotalBytes - mUsedBytes)));
summary.setPercent(mUsedBytes, mTotalBytes);
+ summary.setEnabled(true);
}
@Override
@@ -50,11 +68,6 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle
return true;
}
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- return false;
- }
-
@Override
public String getPreferenceKey() {
return "pref_summary";
@@ -69,4 +82,20 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle
mUsedBytes = used;
mTotalBytes = total;
}
+
+ /**
+ * 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/widget/DonutView.java b/src/com/android/settings/widget/DonutView.java
new file mode 100644
index 00000000000..845f52c6db8
--- /dev/null
+++ b/src/com/android/settings/widget/DonutView.java
@@ -0,0 +1,102 @@
+/*
+ * 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.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+
+/**
+ * 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;
+ private float mStrokeWidth;
+ private int mPercent;
+ private Paint mBackgroundCircle;
+ private Paint mFilledArc;
+ private TextPaint mTextPaint;
+
+ public DonutView(Context context) {
+ super(context);
+ }
+
+ public DonutView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ float density = getResources().getDisplayMetrics().density;
+ mStrokeWidth = 10f * density;
+
+ mBackgroundCircle = new Paint();
+ mBackgroundCircle.setAntiAlias(true);
+ mBackgroundCircle.setStrokeCap(Paint.Cap.BUTT);
+ mBackgroundCircle.setStyle(Paint.Style.STROKE);
+ mBackgroundCircle.setStrokeWidth(mStrokeWidth);
+ mBackgroundCircle.setColor(getResources().getColor(R.color.donut_background_grey));
+
+ mFilledArc = new Paint();
+ mFilledArc.setAntiAlias(true);
+ mFilledArc.setStrokeCap(Paint.Cap.BUTT);
+ mFilledArc.setStyle(Paint.Style.STROKE);
+ mFilledArc.setStrokeWidth(mStrokeWidth);
+ mFilledArc.setColor(Utils.getColorAccent(getContext()));
+
+ mTextPaint = new TextPaint();
+ mTextPaint.setColor(Utils.getColorAccent(getContext()));
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setTextSize(18f * density);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(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 * mPercent / 100), false, mFilledArc);
+
+ int centerX = getWidth() / 2;
+ int centerY = getHeight() / 2;
+
+ String percentString =
+ String.format(getContext().getString(R.string.storage_percent_used), mPercent);
+ // drawText uses the Y dimension as the floor of the text, so we do this to center.
+ canvas.drawText(percentString, centerX,
+ centerY + getTextHeight(mTextPaint) / 2 - mTextPaint.descent(),
+ mTextPaint);
+ }
+
+ /**
+ * Set a percentage full to have the donut graph.
+ */
+ public void setPercentage(int percent) {
+ mPercent = percent;
+ invalidate();
+ }
+
+ 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/storage/StorageSummaryDonutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
new file mode 100644
index 00000000000..848616afa36
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageSummaryDonutPreferenceControllerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.storage.VolumeInfo;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.io.File;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class StorageSummaryDonutPreferenceControllerTest {
+ private static String KEY = "pref";
+
+ private Context mContext;
+ private StorageSummaryDonutPreferenceController mController;
+ private StorageSummaryDonutPreference mPreference;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = RuntimeEnvironment.application;
+ mController = new StorageSummaryDonutPreferenceController(mContext);
+ mPreference = new StorageSummaryDonutPreference(mContext);
+
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(mContext), false);
+ }
+
+ @Test
+ public void testEmpty() throws Exception {
+ mController.updateBytes(0, 0);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getTitle().toString()).isEqualTo("0.00B used");
+ assertThat(mPreference.getSummary().toString()).isEqualTo("0.00B free");
+ }
+
+ @Test
+ public void testUsedStorage() throws Exception {
+ mController.updateBytes(1024, 1024 * 10);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getTitle().toString()).isEqualTo("1.00KB used");
+ assertThat(mPreference.getSummary().toString()).isEqualTo("9.00KB free");
+ }
+
+ @Test
+ public void testPopulateWithVolume() throws Exception {
+ VolumeInfo volume = Mockito.mock(VolumeInfo.class);
+ File file = Mockito.mock(File.class);
+ StorageVolumeProvider svp = Mockito.mock(StorageVolumeProvider.class);
+ when(volume.getPath()).thenReturn(file);
+ when(file.getTotalSpace()).thenReturn(1024L * 10);
+ when(file.getFreeSpace()).thenReturn(1024L);
+ when(svp.getPrimaryStorageSize()).thenReturn(1024L * 10);
+
+ mController.updateSizes(svp, volume);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getTitle().toString()).isEqualTo("9.00KB used");
+ assertThat(mPreference.getSummary().toString()).isEqualTo("1.00KB free");
+ }
+}