Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 63a11c56 authored by Daniel Nishi's avatar Daniel Nishi
Browse files

Always use GB as the unit in Storage Settings.

Bug: 36901322
Test: Settings unit tests

Change-Id: I08c711db6a271522942a01d1adf3e8e5223010f7
parent 0cdade8a
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -17,14 +17,15 @@
package com.android.settings.deviceinfo;

import android.content.Context;
import android.content.res.Resources;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.format.Formatter;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;

import com.android.settings.R;
import com.android.settings.utils.FileSizeFormatter;

public class StorageItemPreference extends Preference {
    public int userHandle;
@@ -44,9 +45,12 @@ public class StorageItemPreference extends Preference {
    }

    public void setStorageSize(long size, long total) {
        setSummary(size == 0
                ? String.valueOf(0)
                : Formatter.formatFileSize(getContext(), size));
        setSummary(
                FileSizeFormatter.formatFileSize(
                        getContext(),
                        size,
                        getGigabyteSuffix(getContext().getResources()),
                        FileSizeFormatter.GIGABYTE_IN_BYTES));
        if (total == 0) {
            mProgressPercent = 0;
        } else {
@@ -75,4 +79,8 @@ public class StorageItemPreference extends Preference {
        updateProgressBar();
        super.onBindViewHolder(view);
    }

    private static int getGigabyteSuffix(Resources res) {
        return res.getIdentifier("gigabyteShort", "string", "android");
    }
}
+116 −0
Original line number Diff line number Diff line
/*
 * 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.utils;

import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.text.BidiFormatter;
import android.text.format.Formatter;

/**
 * Utility class to aid in formatting file sizes always with the same unit. This is modified from
 * android.text.format.Formatter to fit this purpose.
 */
public final class FileSizeFormatter {
    public static final long KILOBYTE_IN_BYTES = 1000;
    public static final long MEGABYTE_IN_BYTES = KILOBYTE_IN_BYTES * 1000;
    public static final long GIGABYTE_IN_BYTES = MEGABYTE_IN_BYTES * 1000;

    /**
     * Formats a content size to be in the form of bytes, kilobytes, megabytes, etc.
     *
     * <p>As of O, the prefixes are used in their standard meanings in the SI system, so kB = 1000
     * bytes, MB = 1,000,000 bytes, etc.
     *
     * <p class="note">In {@link android.os.Build.VERSION_CODES#N} and earlier, powers of 1024 are
     * used instead, with KB = 1024 bytes, MB = 1,048,576 bytes, etc.
     *
     * <p>If the context has a right-to-left locale, the returned string is wrapped in bidi
     * formatting characters to make sure it's displayed correctly if inserted inside a
     * right-to-left string. (This is useful in cases where the unit strings, like "MB", are
     * left-to-right, but the locale is right-to-left.)
     *
     * @param context Context to use to load the localized units
     * @param sizeBytes size value to be formatted, in bytes
     * @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, int suffix, long mult) {
        if (context == null) {
            return "";
        }
        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");
    }

    /**
     * A simplified version of the SettingsLib file size formatter. The primary difference is that
     * this version always assumes it is doing a "short file size" and allows for a suffix to be
     * provided.
     *
     * @param res Resources to fetch strings with.
     * @param sizeBytes File size in bytes to format.
     * @param suffix String id for the unit suffix.
     * @param mult Amount of bytes in the unit.
     */
    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;
        // Note we calculate the rounded long by ourselves, but still let String.format()
        // compute the rounded value. String.format("%f", 0.1) might not return "0.1" due to
        // floating point errors.
        final int roundFactor;
        final String roundFormat;
        if (mult == 1) {
            roundFactor = 1;
            roundFormat = "%.0f";
        } else if (result < 1) {
            roundFactor = 100;
            roundFormat = "%.2f";
        } else if (result < 10) {
            roundFactor = 10;
            roundFormat = "%.1f";
        } else { // 10 <= result < 100
            roundFactor = 1;
            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);

        final String units = res.getString(suffix);

        return new Formatter.BytesResult(roundedString, units, roundedBytes);
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
 */
package com.android.settings.deviceinfo;

import static com.android.settings.TestUtils.KILOBYTE;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;

import static com.google.common.truth.Truth.assertThat;

@@ -54,8 +54,8 @@ public class StorageItemPreferenceTest {

    @Test
    public void testAfterLoad() {
        mPreference.setStorageSize(KILOBYTE, KILOBYTE * 10);
        assertThat(((String) mPreference.getSummary())).isEqualTo("1.00KB");
        mPreference.setStorageSize(MEGABYTE_IN_BYTES * 10, MEGABYTE_IN_BYTES * 100);
        assertThat(((String) mPreference.getSummary())).isEqualTo("0.01GB");
    }

    @Test
@@ -66,7 +66,7 @@ public class StorageItemPreferenceTest {
                (ProgressBar) holder.itemView.findViewById(android.R.id.progress);

        mPreference.onBindViewHolder(holder);
        mPreference.setStorageSize(KILOBYTE, KILOBYTE * 10);
        mPreference.setStorageSize(MEGABYTE_IN_BYTES, MEGABYTE_IN_BYTES * 10);

        assertThat(progressBar.getProgress()).isEqualTo(10);
    }
+10 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.deviceinfo.storage;

import static com.google.common.truth.Truth.assertThat;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.verify;
@@ -96,13 +97,13 @@ public class SecondaryUserControllerTest {
    public void controllerUpdatesSummaryOfNewPreference() throws Exception {
        mPrimaryUser.name = TEST_NAME;
        mController.displayPreference(mScreen);
        mController.setSize(10L);
        mController.setSize(MEGABYTE_IN_BYTES * 10);
        final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);

        verify(mGroup).addPreference(argumentCaptor.capture());

        Preference preference = argumentCaptor.getValue();
        assertThat(preference.getSummary()).isEqualTo("10.00B");
        assertThat(preference.getSummary()).isEqualTo("0.01GB");
    }

    @Test
@@ -162,7 +163,12 @@ public class SecondaryUserControllerTest {
        StorageAsyncLoader.AppsStorageResult userResult =
                new StorageAsyncLoader.AppsStorageResult();
        SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
        userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
        userResult.externalStats =
                new StorageStatsSource.ExternalStorageStats(
                        MEGABYTE_IN_BYTES * 30,
                        MEGABYTE_IN_BYTES * 10,
                        MEGABYTE_IN_BYTES * 10,
                        MEGABYTE_IN_BYTES * 10);
        result.put(10, userResult);

        mController.handleResult(result);
@@ -170,7 +176,7 @@ public class SecondaryUserControllerTest {
        verify(mGroup).addPreference(argumentCaptor.capture());
        Preference preference = argumentCaptor.getValue();

        assertThat(preference.getSummary()).isEqualTo("99.00B");
        assertThat(preference.getSummary()).isEqualTo("0.03GB");
    }

    @Test
+30 −19
Original line number Diff line number Diff line
@@ -15,9 +15,9 @@
 */
package com.android.settings.deviceinfo.storage;

import static com.android.settings.TestUtils.KILOBYTE;

import static com.google.common.truth.Truth.assertThat;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
@@ -50,9 +51,11 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -80,6 +83,8 @@ public class StorageItemPreferenceControllerTest {
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        SettingsShadowResources.overrideResource("android:string/fileSizeSuffix", "%1$s %2$s");
        SettingsShadowResources.overrideResource("android:string/gigabyteShort", "GB");
        mContext = spy(RuntimeEnvironment.application.getApplicationContext());
        FakeFeatureFactory.setupForTest(mContext);
        mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
@@ -96,6 +101,11 @@ public class StorageItemPreferenceControllerTest {
                mPreference.getLayoutResource(), new LinearLayout(mContext), false);
    }

    @After
    public void tearDown() {
        SettingsShadowResources.reset();
    }

    @Test
    public void testUpdateStateWithInitialState() {
        assertThat(mPreference.getSummary().toString()).isEqualTo(
@@ -243,28 +253,29 @@ public class StorageItemPreferenceControllerTest {
                eq(StorageItemPreferenceController.FILES_KEY))).thenReturn(files);
        mController.displayPreference(screen);

        mController.setUsedSize(KILOBYTE * 200); // There should 87kB attributed.
        mController.setUsedSize(MEGABYTE_IN_BYTES * 970); // There should 870MB attributed.
        StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
        result.gamesSize = KILOBYTE * 8;
        result.videoAppsSize = KILOBYTE * 16;
        result.musicAppsSize = KILOBYTE * 4;
        result.otherAppsSize = KILOBYTE * 9;
        result.systemSize = KILOBYTE * 10; // This value is ignored and overriden now.
        result.externalStats = new StorageStatsSource.ExternalStorageStats(
                KILOBYTE * 50, // total
                KILOBYTE * 10, // audio
                KILOBYTE * 15, // video
                KILOBYTE * 20); // image
        result.gamesSize = MEGABYTE_IN_BYTES * 80;
        result.videoAppsSize = MEGABYTE_IN_BYTES * 160;
        result.musicAppsSize = MEGABYTE_IN_BYTES * 40;
        result.otherAppsSize = MEGABYTE_IN_BYTES * 90;
        result.systemSize = MEGABYTE_IN_BYTES * 100; // This value is ignored and overridden now.
        result.externalStats =
                new StorageStatsSource.ExternalStorageStats(
                        MEGABYTE_IN_BYTES * 500, // total
                        MEGABYTE_IN_BYTES * 100, // audio
                        MEGABYTE_IN_BYTES * 150, // video
                        MEGABYTE_IN_BYTES * 200); // image

        mController.onLoadFinished(result);

        assertThat(audio.getSummary().toString()).isEqualTo("14.00KB"); // 4KB apps + 10KB files
        assertThat(image.getSummary().toString()).isEqualTo("35.00KB"); // 15KB video + 20KB images
        assertThat(games.getSummary().toString()).isEqualTo("8.00KB");
        assertThat(movies.getSummary().toString()).isEqualTo("16.00KB");
        assertThat(apps.getSummary().toString()).isEqualTo("9.00KB");
        assertThat(system.getSummary().toString()).isEqualTo("113KB");
        assertThat(files.getSummary().toString()).isEqualTo("5.00KB");
        assertThat(audio.getSummary().toString()).isEqualTo("0.14GB");
        assertThat(image.getSummary().toString()).isEqualTo("0.35GB");
        assertThat(games.getSummary().toString()).isEqualTo("0.08GB");
        assertThat(movies.getSummary().toString()).isEqualTo("0.16GB");
        assertThat(apps.getSummary().toString()).isEqualTo("0.09GB");
        assertThat(system.getSummary().toString()).isEqualTo("0.10GB");
        assertThat(files.getSummary().toString()).isEqualTo("0.05GB");
    }

    @Test
Loading