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

Commit a1683776 authored by Daniel Nishi's avatar Daniel Nishi
Browse files

Make the storage free/total sizes consistent.

We were using a different calculation in the top level view compared to
within the Storage settings. Technically, both are correct (one of them
is aware that we're considering cache as free, one does not). This patch
aligns us on the cache as free strategy.

Change-Id: I9ac26683a4d2a30b77a1da534aa2ddd3d4da6657
Fixes: 37175551
Test: Settings robotest
parent 0cdade8a
Loading
Loading
Loading
Loading
+66 −25
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.deviceinfo;

import android.app.Activity;
import android.app.LoaderManager;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.Loader;
import android.graphics.drawable.Drawable;
@@ -29,6 +30,7 @@ import android.os.storage.VolumeInfo;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.util.SparseArray;
import android.view.View;

import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -44,9 +46,11 @@ import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
import com.android.settings.deviceinfo.storage.UserIconLoader;
import com.android.settings.deviceinfo.storage.VolumeSizesLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;

import java.util.ArrayList;
@@ -58,9 +62,12 @@ public class StorageDashboardFragment extends DashboardFragment
    private static final String TAG = "StorageDashboardFrag";
    private static final int STORAGE_JOB_ID = 0;
    private static final int ICON_JOB_ID = 1;
    private static final int VOLUME_SIZE_JOB_ID = 2;
    private static final int OPTIONS_MENU_MIGRATE_DATA = 100;

    private VolumeInfo mVolume;
    private PrivateStorageInfo mStorageInfo;
    private SparseArray<StorageAsyncLoader.AppsStorageResult> mAppsResult;

    private StorageSummaryDonutPreferenceController mSummaryController;
    private StorageItemPreferenceController mPreferenceController;
@@ -81,29 +88,6 @@ public class StorageDashboardFragment extends DashboardFragment
        }

        initializeOptionsMenu(activity);

        final long sharedDataSize = mVolume.getPath().getTotalSpace();
        long totalSize = sm.getPrimaryStorageSize();
        long systemSize = totalSize - sharedDataSize;

        if (totalSize <= 0) {
            totalSize = sharedDataSize;
            systemSize = 0;
        }

        final long usedBytes = totalSize - mVolume.getPath().getFreeSpace();
        mSummaryController.updateBytes(usedBytes, totalSize);
        mPreferenceController.setVolume(mVolume);
        mPreferenceController.setUsedSize(usedBytes);
        mPreferenceController.setTotalSize(totalSize);
        for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
            PreferenceController controller = mSecondaryUsers.get(i);
            if (controller instanceof SecondaryUserController) {
                SecondaryUserController userController = (SecondaryUserController) controller;
                userController.setTotalSize(totalSize);

            }
        }
    }

    @VisibleForTesting
@@ -115,11 +99,41 @@ public class StorageDashboardFragment extends DashboardFragment
        activity.invalidateOptionsMenu();
    }

    @Override
    public void onViewCreated(View v, Bundle savedInstanceState) {
        super.onViewCreated(v, savedInstanceState);
        setLoading(true, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        getLoaderManager().restartLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
        getLoaderManager().initLoader(ICON_JOB_ID, Bundle.EMPTY, new IconLoaderCallbacks());
        getLoaderManager().initLoader(VOLUME_SIZE_JOB_ID, Bundle.EMPTY, new VolumeSizeCallbacks());
    }

    private void onReceivedSizes() {
        if (mStorageInfo == null || mAppsResult == null) {
            return;
        }

        long privateUsedBytes = mStorageInfo.totalBytes - mStorageInfo.freeBytes;
        mSummaryController.updateBytes(privateUsedBytes, mStorageInfo.totalBytes);
        mPreferenceController.setVolume(mVolume);
        mPreferenceController.setUsedSize(privateUsedBytes);
        mPreferenceController.setTotalSize(mStorageInfo.totalBytes);
        for (int i = 0, size = mSecondaryUsers.size(); i < size; i++) {
            PreferenceController controller = mSecondaryUsers.get(i);
            if (controller instanceof SecondaryUserController) {
                SecondaryUserController userController = (SecondaryUserController) controller;
                userController.setTotalSize(mStorageInfo.totalBytes);
            }
        }

        mPreferenceController.onLoadFinished(mAppsResult.get(UserHandle.myUserId()));
        updateSecondaryUserControllers(mSecondaryUsers, mAppsResult);
        setLoading(false, true);
    }

    @Override
@@ -224,8 +238,8 @@ public class StorageDashboardFragment extends DashboardFragment
    @Override
    public void onLoadFinished(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader,
            SparseArray<StorageAsyncLoader.AppsStorageResult> data) {
        mPreferenceController.onLoadFinished(data.get(UserHandle.myUserId()));
        updateSecondaryUserControllers(mSecondaryUsers, data);
        mAppsResult = data;
        onReceivedSizes();
    }

    @Override
@@ -260,4 +274,31 @@ public class StorageDashboardFragment extends DashboardFragment
        @Override
        public void onLoaderReset(Loader<SparseArray<Drawable>> loader) {}
    }

    public final class VolumeSizeCallbacks
            implements LoaderManager.LoaderCallbacks<PrivateStorageInfo> {
        @Override
        public Loader<PrivateStorageInfo> onCreateLoader(int id, Bundle args) {
            Context context = getContext();
            StorageManager sm = context.getSystemService(StorageManager.class);
            StorageManagerVolumeProvider smvp = new StorageManagerVolumeProvider(sm);
            final StorageStatsManager stats = context.getSystemService(StorageStatsManager.class);
            return new VolumeSizesLoader(context, smvp, stats, mVolume);
        }

        @Override
        public void onLoaderReset(Loader<PrivateStorageInfo> loader) {}

        @Override
        public void onLoadFinished(
                Loader<PrivateStorageInfo> loader, PrivateStorageInfo privateStorageInfo) {
            if (privateStorageInfo == null) {
                getActivity().finish();
                return;
            }

            mStorageInfo = privateStorageInfo;
            onReceivedSizes();
        }
    }
}
+11 −3
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.settingslib.deviceinfo.StorageVolumeProvider;
public class StorageSummaryDonutPreferenceController extends PreferenceController {
    private long mUsedBytes;
    private long mTotalBytes;
    private StorageSummaryDonutPreference mSummary;

    public StorageSummaryDonutPreferenceController(Context context) {
        super(context);
@@ -41,9 +42,8 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle

    @Override
    public void displayPreference(PreferenceScreen screen) {
        StorageSummaryDonutPreference summary = (StorageSummaryDonutPreference)
                screen.findPreference("pref_summary");
        summary.setEnabled(true);
        mSummary = (StorageSummaryDonutPreference) screen.findPreference("pref_summary");
        mSummary.setEnabled(true);
    }

    @Override
@@ -61,6 +61,13 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle
        summary.setEnabled(true);
    }

    /** Invalidates the data on the view and re-renders. */
    public void invalidateData() {
        if (mSummary != null) {
            updateState(mSummary);
        }
    }

    @Override
    public boolean isAvailable() {
        return true;
@@ -79,6 +86,7 @@ public class StorageSummaryDonutPreferenceController extends PreferenceControlle
    public void updateBytes(long used, long total) {
        mUsedBytes = used;
        mTotalBytes = total;
        invalidateData();
    }

    /**
+68 −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.deviceinfo.storage;

import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.os.storage.VolumeInfo;
import android.support.annotation.VisibleForTesting;

import com.android.settings.utils.AsyncLoader;
import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;

import java.io.IOException;

public class VolumeSizesLoader extends AsyncLoader<PrivateStorageInfo> {
    private StorageVolumeProvider mVolumeProvider;
    private StorageStatsManager mStats;
    private VolumeInfo mVolume;

    public VolumeSizesLoader(
            Context context,
            StorageVolumeProvider volumeProvider,
            StorageStatsManager stats,
            VolumeInfo volume) {
        super(context);
        mVolumeProvider = volumeProvider;
        mStats = stats;
        mVolume = volume;
    }

    @Override
    protected void onDiscardResult(PrivateStorageInfo result) {}

    @Override
    public PrivateStorageInfo loadInBackground() {
        PrivateStorageInfo volumeSizes;
        try {
            volumeSizes = getVolumeSize(mVolumeProvider, mStats, mVolume);
        } catch (IOException e) {
            return null;
        }
        return volumeSizes;
    }

    @VisibleForTesting
    static PrivateStorageInfo getVolumeSize(
            StorageVolumeProvider storageVolumeProvider, StorageStatsManager stats, VolumeInfo info)
            throws IOException {
        long privateTotalBytes = storageVolumeProvider.getTotalBytes(stats, info);
        long privateFreeBytes = storageVolumeProvider.getFreeBytes(stats, info);
        return new PrivateStorageInfo(privateFreeBytes, privateTotalBytes);
    }
}
+30 −0
Original line number Diff line number Diff line
package com.android.settings.deviceinfo.storage;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.os.storage.VolumeInfo;

import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;

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

import org.junit.Test;

public class VolumeSizesLoaderTest {
    @Test
    public void getVolumeSize_getsValidSizes() throws Exception {
        VolumeInfo info = mock(VolumeInfo.class);
        StorageVolumeProvider storageVolumeProvider = mock(StorageVolumeProvider.class);
        when(storageVolumeProvider.getTotalBytes(any(), any())).thenReturn(10000L);
        when(storageVolumeProvider.getFreeBytes(any(), any())).thenReturn(1000L);

        PrivateStorageInfo storageInfo =
                VolumeSizesLoader.getVolumeSize(storageVolumeProvider, null, info);

        assertThat(storageInfo.freeBytes).isEqualTo(1000L);
        assertThat(storageInfo.totalBytes).isEqualTo(10000L);
    }
}