1 /* 2 * Copyright (C) 2014 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.tv.settings.device.storage; 18 19 import com.android.tv.settings.R; 20 import com.android.tv.settings.device.storage.StorageMeasurement.MeasurementDetails; 21 import com.android.tv.settings.device.storage.StorageMeasurement.MeasurementReceiver; 22 import com.android.tv.settings.dialog.old.Action; 23 import com.android.tv.settings.dialog.old.ActionAdapter; 24 import com.android.tv.settings.dialog.old.ActionFragment; 25 import com.android.tv.settings.dialog.old.ContentFragment; 26 import com.android.tv.settings.dialog.old.DialogActivity; 27 28 import android.app.Activity; 29 import android.content.res.TypedArray; 30 import android.graphics.Color; 31 import android.os.Bundle; 32 import android.os.Environment; 33 import android.os.Handler; 34 import android.os.Message; 35 import android.text.format.Formatter; 36 import android.widget.ImageView; 37 import android.widget.TextView; 38 39 import java.util.ArrayList; 40 import java.util.Collections; 41 import java.util.HashMap; 42 import java.util.List; 43 44 /** 45 * Activity that shows storage information. 46 */ 47 public class StorageActivity extends DialogActivity { 48 49 private static final long INVALID_SIZE = -1; 50 51 private static final int UPDATE_MSG = 1; 52 53 private ActionFragment mActionFragment; 54 private StorageContentFragment mContentFragment; 55 private StorageMeasurement mMeasure; 56 private boolean mResumed; 57 58 private final MeasurementReceiver mReceiver = new MeasurementReceiver() { 59 60 private long[] mLastApproximateDetails = null; 61 private MeasurementDetails mLastMeasurementDetails = null; 62 63 private final Handler mUpdateHandler = new Handler() { 64 @Override 65 public void handleMessage(Message msg) { 66 if (!mResumed) { 67 return; 68 } 69 switch (msg.what) { 70 case UPDATE_MSG: 71 if (mLastMeasurementDetails != null) { 72 StorageActivity.this.updateDetails(mLastMeasurementDetails); 73 } else if (mLastApproximateDetails != null) { 74 StorageActivity.this.updateApproximate( 75 mLastApproximateDetails[0], mLastApproximateDetails[1]); 76 } 77 break; 78 default: 79 break; 80 } 81 } 82 }; 83 84 private void startUiUpdateTimer() { 85 mUpdateHandler.sendEmptyMessageDelayed(UPDATE_MSG, 1000); 86 } 87 88 @Override 89 public void updateApproximate(StorageMeasurement meas, long totalSize, long availSize) { 90 mLastApproximateDetails = new long[] { totalSize, availSize }; 91 startUiUpdateTimer(); 92 } 93 94 @Override 95 public void updateDetails(StorageMeasurement meas, MeasurementDetails details) { 96 mLastMeasurementDetails = details; 97 startUiUpdateTimer(); 98 } 99 }; 100 101 @Override 102 protected void onCreate(Bundle savedInstanceState) { 103 super.onCreate(savedInstanceState); 104 mActionFragment = ActionFragment.newInstance(getActions()); 105 mContentFragment = StorageContentFragment.newInstance(getString(R.string.storage_title), 106 getString(R.string.header_category_device), 107 String.format(getString(R.string.storage_size), formatSize(INVALID_SIZE)), 108 R.drawable.ic_settings_storage, getResources().getColor(R.color.icon_background)); 109 setContentAndActionFragments(mContentFragment, mActionFragment); 110 mMeasure = StorageMeasurement.getInstance(this, null); 111 } 112 113 @Override 114 protected void onResume() { 115 super.onResume(); 116 mResumed = true; 117 mMeasure.setReceiver(mReceiver); 118 mMeasure.invalidate(); 119 mMeasure.measure(); 120 } 121 122 @Override 123 protected void onPause() { 124 mMeasure.cleanUp(); 125 mResumed = false; 126 super.onPause(); 127 } 128 129 private ArrayList<Action> getActions() { 130 return getActions(INVALID_SIZE); 131 } 132 133 private ArrayList<Action> getActions(long availSize) { 134 return getActions(availSize, INVALID_SIZE, INVALID_SIZE, INVALID_SIZE, INVALID_SIZE, 135 INVALID_SIZE, INVALID_SIZE); 136 } 137 138 private ArrayList<Action> getActions(long availSize, long appsSize, long dcimSize, 139 long musicSize, long downloadsSize, long cacheSize, long miscSize) { 140 ArrayList<Action> actions = new ArrayList<Action>(); 141 actions.add(StorageItem.APPS.toAction(getResources(), formatSize(appsSize))); 142 actions.add(StorageItem.PICTURES_VIDEO.toAction(getResources(), formatSize(dcimSize))); 143 actions.add(StorageItem.AUDIO.toAction(getResources(), formatSize(musicSize))); 144 actions.add(StorageItem.DOWNLOADS.toAction(getResources(), formatSize(downloadsSize))); 145 actions.add(StorageItem.CACHED_DATA.toAction(getResources(), formatSize(cacheSize))); 146 actions.add(StorageItem.MISC.toAction(getResources(), formatSize(miscSize))); 147 actions.add(StorageItem.AVAILABLE.toAction(getResources(), formatSize(availSize))); 148 return actions; 149 } 150 151 private void updateActions(ArrayList<Action> actions) { 152 ((ActionAdapter) mActionFragment.getAdapter()).setActions(actions); 153 } 154 155 private void updateApproximate(long totalSize, long availSize) { 156 157 final long usedSize = totalSize - availSize; 158 159 ArrayList<PercentageBarChart.Entry> entries = new ArrayList<PercentageBarChart.Entry>(); 160 entries.add(new PercentageBarChart.Entry( 161 0, usedSize / (float) totalSize, android.graphics.Color.GRAY)); 162 163 updateActions(getActions(availSize)); 164 updateStorageContentFragment(totalSize, entries); 165 } 166 167 private void updateDetails(MeasurementDetails details) { 168 169 final long dcimSize = totalValues(details.mediaSize, Environment.DIRECTORY_DCIM, 170 Environment.DIRECTORY_MOVIES, Environment.DIRECTORY_PICTURES); 171 172 final long musicSize = totalValues(details.mediaSize, Environment.DIRECTORY_MUSIC, 173 Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS, 174 Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS); 175 176 final long downloadsSize = totalValues(details.mediaSize, Environment.DIRECTORY_DOWNLOADS); 177 178 ArrayList<PercentageBarChart.Entry> entries = new ArrayList<PercentageBarChart.Entry>(); 179 180 addEntry(entries, StorageItem.APPS, details.appsSize, details.totalSize); 181 addEntry(entries, StorageItem.PICTURES_VIDEO, dcimSize, details.totalSize); 182 addEntry(entries, StorageItem.AUDIO, musicSize, details.totalSize); 183 addEntry(entries, StorageItem.DOWNLOADS, downloadsSize, details.totalSize); 184 addEntry(entries, StorageItem.CACHED_DATA, details.cacheSize, details.totalSize); 185 addEntry(entries, StorageItem.MISC, details.miscSize, details.totalSize); 186 187 Collections.sort(entries); 188 189 updateActions(getActions( 190 details.availSize, details.appsSize, dcimSize, musicSize, downloadsSize, 191 details.cacheSize, details.miscSize)); 192 updateStorageContentFragment(details.totalSize, entries); 193 } 194 195 private static long totalValues(HashMap<String, Long> map, String... keys) { 196 long total = 0; 197 for (String key : keys) { 198 total += map.get(key); 199 } 200 return total; 201 } 202 203 private String formatSize(long size) { 204 return (size == INVALID_SIZE) ? getString(R.string.storage_calculating_size) 205 : Formatter.formatShortFileSize(this, size); 206 } 207 208 private void addEntry(List<PercentageBarChart.Entry> entries, StorageItem storageItem, 209 long size, long totalSize) { 210 if (size > 0) { 211 entries.add(new PercentageBarChart.Entry( 212 storageItem.ordinal(), size / (float) totalSize, 213 storageItem.getColor(getResources()))); 214 } 215 } 216 217 private void updateStorageContentFragment(long totalSize) { 218 updateStorageContentFragment(totalSize, new ArrayList<PercentageBarChart.Entry>()); 219 } 220 221 private void updateStorageContentFragment( 222 long totalSize, ArrayList<PercentageBarChart.Entry> entries) { 223 mContentFragment.updateEntries(entries); 224 mContentFragment.setDescriptionText( 225 String.format(getString(R.string.storage_size), formatSize(totalSize))); 226 } 227 } 228