// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package org.chromium.chrome.browser.download.ui; import android.content.Context; import android.os.AsyncTask; import android.os.Environment; import android.os.StatFs; import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Log; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import java.io.File; /** A View that manages the display of space used by the downloads. */ class SpaceDisplay extends RecyclerView.AdapterDataObserver { private static final String TAG = "download_ui"; private static final long BYTES_PER_KILOBYTE = 1024; private static final long BYTES_PER_MEGABYTE = 1024 * 1024; private static final long BYTES_PER_GIGABYTE = 1024 * 1024 * 1024; private final AsyncTask<Void, Void, Long> mFileSystemBytesTask; private DownloadHistoryAdapter mHistoryAdapter; private TextView mSpaceUsedTextView; private TextView mSpaceTotalTextView; private ProgressBar mSpaceBar; private long mFileSystemBytes = Long.MAX_VALUE; SpaceDisplay(final ViewGroup parent, DownloadHistoryAdapter historyAdapter) { mHistoryAdapter = historyAdapter; mSpaceUsedTextView = (TextView) parent.findViewById(R.id.space_used_display); mSpaceTotalTextView = (TextView) parent.findViewById(R.id.space_total_display); mSpaceBar = (ProgressBar) parent.findViewById(R.id.space_bar); mFileSystemBytesTask = createStorageSizeTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private AsyncTask<Void, Void, Long> createStorageSizeTask() { return new AsyncTask<Void, Void, Long>() { @Override protected Long doInBackground(Void... params) { File downloadDirectory = Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS); // Create the downloads directory, if necessary. if (!downloadDirectory.exists()) { try { // mkdirs() can fail, so we still need to check if the directory exists // later. downloadDirectory.mkdirs(); } catch (SecurityException e) { Log.e(TAG, "SecurityException when creating download directory.", e); } } // Determine how much space is available on the storage device where downloads // reside. If the downloads directory doesn't exist, it is likely that the user // doesn't have an SD card installed. long fileSystemBytes = 0; if (downloadDirectory.exists()) { StatFs statFs = new StatFs(downloadDirectory.getPath()); long totalBlocks = ApiCompatibilityUtils.getBlockCount(statFs); long blockSize = ApiCompatibilityUtils.getBlockSize(statFs); fileSystemBytes = totalBlocks * blockSize; } else { Log.e(TAG, "Download directory doesn't exist."); } return fileSystemBytes; } }; } @Override public void onChanged() { if (mFileSystemBytes == Long.MAX_VALUE) { try { mFileSystemBytes = mFileSystemBytesTask.get(); } catch (Exception e) { Log.e(TAG, "Failed to get file system size."); } // Display how big the storage is. mSpaceTotalTextView.setText(getStringForBytes(false, mFileSystemBytes)); } // Indicate how much space has been used by downloads. long usedBytes = mHistoryAdapter.getTotalDownloadSize(); int percentage = mFileSystemBytes == 0 ? 0 : (int) (100.0 * usedBytes / mFileSystemBytes); mSpaceBar.setProgress(percentage); mSpaceUsedTextView.setText(getStringForBytes(true, usedBytes)); RecordHistogram.recordPercentageHistogram("Android.DownloadManager.SpaceUsed", percentage); } private String getStringForBytes(boolean isUsedString, long bytes) { int resourceId; float bytesInCorrectUnits; if (bytes < BYTES_PER_MEGABYTE) { resourceId = isUsedString ? R.string.download_manager_ui_space_used_kb : R.string.download_manager_ui_space_available_kb; bytesInCorrectUnits = bytes / (float) BYTES_PER_KILOBYTE; } else if (bytes < BYTES_PER_GIGABYTE) { resourceId = isUsedString ? R.string.download_manager_ui_space_used_mb : R.string.download_manager_ui_space_available_mb; bytesInCorrectUnits = bytes / (float) BYTES_PER_MEGABYTE; } else { resourceId = isUsedString ? R.string.download_manager_ui_space_used_gb : R.string.download_manager_ui_space_available_gb; bytesInCorrectUnits = bytes / (float) BYTES_PER_GIGABYTE; } Context context = mSpaceUsedTextView.getContext(); return context.getResources().getString(resourceId, bytesInCorrectUnits); } }