package com.android.settings.utils;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
-import android.icu.text.DecimalFormat;
-import android.icu.text.MeasureFormat;
-import android.icu.text.NumberFormat;
-import android.icu.util.Measure;
-import android.icu.util.MeasureUnit;
import android.text.BidiFormatter;
-import android.text.TextUtils;
import android.text.format.Formatter;
-import android.view.View;
-
-import java.math.BigDecimal;
-import java.util.Locale;
/**
* Utility class to aid in formatting file sizes always with the same unit. This is modified from
public static final long MEGABYTE_IN_BYTES = KILOBYTE_IN_BYTES * 1000;
public static final long GIGABYTE_IN_BYTES = MEGABYTE_IN_BYTES * 1000;
- private static class RoundedBytesResult {
- public final float value;
- public final MeasureUnit units;
- public final int fractionDigits;
- public final long roundedBytes;
-
- public RoundedBytesResult(
- float value, MeasureUnit units, int fractionDigits, long roundedBytes) {
- this.value = value;
- this.units = units;
- this.fractionDigits = fractionDigits;
- this.roundedBytes = roundedBytes;
- }
- }
-
- private static Locale localeFromContext(@NonNull Context context) {
- return context.getResources().getConfiguration().locale;
- }
-
- private static String bidiWrap(@NonNull Context context, String source) {
- final Locale locale = localeFromContext(context);
- if (TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL) {
- return BidiFormatter.getInstance(true /* RTL*/).unicodeWrap(source);
- } else {
- return source;
- }
- }
-
- private static NumberFormat getNumberFormatter(Locale locale, int fractionDigits) {
- final NumberFormat numberFormatter = NumberFormat.getInstance(locale);
- numberFormatter.setMinimumFractionDigits(fractionDigits);
- numberFormatter.setMaximumFractionDigits(fractionDigits);
- numberFormatter.setGroupingUsed(false);
- if (numberFormatter instanceof DecimalFormat) {
- // We do this only for DecimalFormat, since in the general NumberFormat case, calling
- // setRoundingMode may throw an exception.
- numberFormatter.setRoundingMode(BigDecimal.ROUND_HALF_UP);
- }
- return numberFormatter;
- }
-
- private static String formatMeasureShort(Locale locale, NumberFormat numberFormatter,
- float value, MeasureUnit units) {
- final MeasureFormat measureFormatter = MeasureFormat.getInstance(
- locale, MeasureFormat.FormatWidth.SHORT, numberFormatter);
- return measureFormatter.format(new Measure(value, units));
- }
-
- private static String formatRoundedBytesResult(
- @NonNull Context context, @NonNull RoundedBytesResult input) {
- final Locale locale = localeFromContext(context);
- final NumberFormat numberFormatter = getNumberFormatter(locale, input.fractionDigits);
- return formatMeasureShort(locale, numberFormatter, input.value, input.units);
- }
-
/**
* Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
*
*
* @param context Context to use to load the localized units
* @param sizeBytes size value to be formatted, in bytes
- * @param unit The unit used for formatting.
- * @param mult Amount of bytes in the unit.
- * @return formatted string with the number
+ * @param suffix String id for the unit suffix.
+ * @param mult Amount of bytes in the unit. * @return formatted string with the number
*/
public static String formatFileSize(
- @Nullable Context context, long sizeBytes, MeasureUnit unit, long mult) {
+ @Nullable Context context, long sizeBytes, int suffix, long mult) {
if (context == null) {
return "";
}
- final RoundedBytesResult res = formatBytes(sizeBytes, unit, mult);
- return bidiWrap(context, formatRoundedBytesResult(context, res));
+ final Formatter.BytesResult res =
+ formatBytes(context.getResources(), sizeBytes, suffix, mult);
+ return BidiFormatter.getInstance()
+ .unicodeWrap(context.getString(getFileSizeSuffix(context), res.value, res.units));
+ }
+
+ private static int getFileSizeSuffix(Context context) {
+ final Resources res = context.getResources();
+ return res.getIdentifier("fileSizeSuffix", "string", "android");
}
/**
* @param suffix String id for the unit suffix.
* @param mult Amount of bytes in the unit.
*/
- private static RoundedBytesResult formatBytes(
- long sizeBytes, MeasureUnit unit, long mult) {
+ private static Formatter.BytesResult formatBytes(
+ Resources res, long sizeBytes, int suffix, long mult) {
final boolean isNegative = (sizeBytes < 0);
float result = isNegative ? -sizeBytes : sizeBytes;
result = result / mult;
// compute the rounded value. String.format("%f", 0.1) might not return "0.1" due to
// floating point errors.
final int roundFactor;
- final int roundDigits;
+ final String roundFormat;
if (mult == 1) {
roundFactor = 1;
- roundDigits = 0;
+ roundFormat = "%.0f";
} else if (result < 1) {
roundFactor = 100;
- roundDigits = 2;
+ roundFormat = "%.2f";
} else if (result < 10) {
roundFactor = 10;
- roundDigits = 1;
+ roundFormat = "%.1f";
} else { // 10 <= result < 100
roundFactor = 1;
- roundDigits = 0;
+ roundFormat = "%.0f";
}
if (isNegative) {
result = -result;
}
+ final String roundedString = String.format(roundFormat, result);
// Note this might overflow if abs(result) >= Long.MAX_VALUE / 100, but that's like 80PB so
// it's okay (for now)...
final long roundedBytes = (((long) Math.round(result * roundFactor)) * mult / roundFactor);
- return new RoundedBytesResult(result, unit, roundDigits, roundedBytes);
+ final String units = res.getString(suffix);
+
+ return new Formatter.BytesResult(roundedString, units, roundedBytes);
}
}
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
-import android.icu.util.MeasureUnit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
FileSizeFormatter.formatFileSize(
mContext,
0 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("0.00 GB");
}
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 11 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("0.01 GB");
}
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 155 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("0.16 GB");
}
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * 1551 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("1.6 GB");
}
FileSizeFormatter.formatFileSize(
mContext,
GIGABYTE_IN_BYTES * 15 + MEGABYTE_IN_BYTES * 50 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("15 GB");
}
FileSizeFormatter.formatFileSize(
mContext,
MEGABYTE_IN_BYTES * -155 /* size */,
- MeasureUnit.GIGABYTE,
+ com.android.internal.R.string.gigabyteShort,
GIGABYTE_IN_BYTES))
.isEqualTo("-0.16 GB");
}