1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.deviceinfo.storage; 18 19 import android.app.usage.StorageStatsManager; 20 import android.content.Context; 21 import android.text.format.Formatter; 22 import android.util.Log; 23 24 import androidx.annotation.VisibleForTesting; 25 import androidx.preference.Preference; 26 import androidx.preference.PreferenceScreen; 27 28 import com.android.settings.R; 29 import com.android.settings.core.BasePreferenceController; 30 import com.android.settingslib.utils.ThreadUtils; 31 import com.android.settingslib.widget.UsageProgressBarPreference; 32 33 import java.io.File; 34 import java.io.IOException; 35 36 /** 37 * Shows storage summary and progress. 38 */ 39 public class StorageUsageProgressBarPreferenceController extends BasePreferenceController { 40 41 private static final String TAG = "StorageProgressCtrl"; 42 43 private final StorageStatsManager mStorageStatsManager; 44 @VisibleForTesting 45 long mUsedBytes; 46 @VisibleForTesting 47 long mTotalBytes; 48 private UsageProgressBarPreference mUsageProgressBarPreference; 49 private StorageEntry mStorageEntry; 50 boolean mIsUpdateStateFromSelectedStorageEntry; 51 StorageUsageProgressBarPreferenceController(Context context, String key)52 public StorageUsageProgressBarPreferenceController(Context context, String key) { 53 super(context, key); 54 55 mStorageStatsManager = context.getSystemService(StorageStatsManager.class); 56 } 57 58 /** Set StorageEntry to display. */ setSelectedStorageEntry(StorageEntry storageEntry)59 public void setSelectedStorageEntry(StorageEntry storageEntry) { 60 mStorageEntry = storageEntry; 61 getStorageStatsAndUpdateUi(); 62 } 63 64 @Override getAvailabilityStatus()65 public int getAvailabilityStatus() { 66 return AVAILABLE_UNSEARCHABLE; 67 } 68 69 @Override displayPreference(PreferenceScreen screen)70 public void displayPreference(PreferenceScreen screen) { 71 mUsageProgressBarPreference = screen.findPreference(getPreferenceKey()); 72 } 73 getStorageStatsAndUpdateUi()74 private void getStorageStatsAndUpdateUi() { 75 ThreadUtils.postOnBackgroundThread(() -> { 76 try { 77 if (mStorageEntry == null || !mStorageEntry.isMounted()) { 78 throw new IOException(); 79 } 80 81 if (mStorageEntry.isPrivate()) { 82 // StorageStatsManager can only query private storages. 83 mTotalBytes = mStorageStatsManager.getTotalBytes(mStorageEntry.getFsUuid()); 84 mUsedBytes = mTotalBytes 85 - mStorageStatsManager.getFreeBytes(mStorageEntry.getFsUuid()); 86 } else { 87 final File rootFile = mStorageEntry.getPath(); 88 if (rootFile == null) { 89 Log.d(TAG, "Mounted public storage has null root path: " + mStorageEntry); 90 throw new IOException(); 91 } 92 mTotalBytes = rootFile.getTotalSpace(); 93 mUsedBytes = mTotalBytes - rootFile.getFreeSpace(); 94 } 95 } catch (IOException e) { 96 // The storage device isn't present. 97 mTotalBytes = 0; 98 mUsedBytes = 0; 99 } 100 101 if (mUsageProgressBarPreference == null) { 102 return; 103 } 104 mIsUpdateStateFromSelectedStorageEntry = true; 105 ThreadUtils.postOnMainThread(() -> updateState(mUsageProgressBarPreference)); 106 }); 107 } 108 109 @Override updateState(Preference preference)110 public void updateState(Preference preference) { 111 if (!mIsUpdateStateFromSelectedStorageEntry) { 112 // Returns here to avoid jank by unnecessary UI update. 113 return; 114 } 115 mIsUpdateStateFromSelectedStorageEntry = false; 116 mUsageProgressBarPreference.setUsageSummary( 117 getStorageSummary(R.string.storage_usage_summary, mUsedBytes)); 118 mUsageProgressBarPreference.setTotalSummary( 119 getStorageSummary(R.string.storage_total_summary, mTotalBytes)); 120 mUsageProgressBarPreference.setPercent(mUsedBytes, mTotalBytes); 121 } 122 getStorageSummary(int resId, long bytes)123 private String getStorageSummary(int resId, long bytes) { 124 final Formatter.BytesResult result = Formatter.formatBytes(mContext.getResources(), 125 bytes, Formatter.FLAG_SHORTER); 126 return mContext.getString(resId, result.value, result.units); 127 } 128 } 129