• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.Fragment;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.graphics.Color;
27 import android.graphics.drawable.Drawable;
28 import android.os.AsyncTask;
29 import android.os.Bundle;
30 import android.os.UserHandle;
31 import android.os.UserManager;
32 import android.os.storage.DiskInfo;
33 import android.os.storage.StorageEventListener;
34 import android.os.storage.StorageManager;
35 import android.os.storage.VolumeInfo;
36 import android.os.storage.VolumeRecord;
37 import android.support.annotation.NonNull;
38 import android.support.v7.preference.Preference;
39 import android.support.v7.preference.PreferenceCategory;
40 import android.text.TextUtils;
41 import android.text.format.Formatter;
42 import android.text.format.Formatter.BytesResult;
43 import android.util.Log;
44 import android.widget.Toast;
45 
46 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
47 import com.android.settings.R;
48 import com.android.settings.SettingsPreferenceFragment;
49 import com.android.settings.Utils;
50 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
51 import com.android.settings.dashboard.SummaryLoader;
52 import com.android.settings.search.BaseSearchIndexProvider;
53 import com.android.settings.search.Indexable;
54 import com.android.settings.search.SearchIndexableRaw;
55 import com.android.settingslib.RestrictedLockUtils;
56 import com.android.settingslib.deviceinfo.PrivateStorageInfo;
57 import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
58 import com.android.settingslib.drawer.SettingsDrawerActivity;
59 
60 import java.io.File;
61 import java.text.NumberFormat;
62 import java.util.ArrayList;
63 import java.util.Collections;
64 import java.util.List;
65 
66 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
67 
68 /**
69  * Panel showing both internal storage (both built-in storage and private
70  * volumes) and removable storage (public volumes).
71  */
72 public class StorageSettings extends SettingsPreferenceFragment implements Indexable {
73     static final String TAG = "StorageSettings";
74 
75     private static final String TAG_VOLUME_UNMOUNTED = "volume_unmounted";
76     private static final String TAG_DISK_INIT = "disk_init";
77 
78     static final int COLOR_PUBLIC = Color.parseColor("#ff9e9e9e");
79 
80     static final int[] COLOR_PRIVATE = new int[] {
81             Color.parseColor("#ff26a69a"),
82             Color.parseColor("#ffab47bc"),
83             Color.parseColor("#fff2a600"),
84             Color.parseColor("#ffec407a"),
85             Color.parseColor("#ffc0ca33"),
86     };
87 
88     private StorageManager mStorageManager;
89 
90     private PreferenceCategory mInternalCategory;
91     private PreferenceCategory mExternalCategory;
92 
93     private StorageSummaryPreference mInternalSummary;
94     private static long sTotalInternalStorage;
95 
96     @Override
getMetricsCategory()97     public int getMetricsCategory() {
98         return MetricsEvent.DEVICEINFO_STORAGE;
99     }
100 
101     @Override
getHelpResource()102     protected int getHelpResource() {
103         return R.string.help_uri_storage;
104     }
105 
106     @Override
onCreate(Bundle icicle)107     public void onCreate(Bundle icicle) {
108         super.onCreate(icicle);
109 
110         final Context context = getActivity();
111 
112         mStorageManager = context.getSystemService(StorageManager.class);
113         mStorageManager.registerListener(mStorageListener);
114 
115         if (sTotalInternalStorage <= 0) {
116             sTotalInternalStorage = mStorageManager.getPrimaryStorageSize();
117         }
118 
119         addPreferencesFromResource(R.xml.device_info_storage);
120 
121         mInternalCategory = (PreferenceCategory) findPreference("storage_internal");
122         mExternalCategory = (PreferenceCategory) findPreference("storage_external");
123 
124         mInternalSummary = new StorageSummaryPreference(getPrefContext());
125 
126         setHasOptionsMenu(true);
127     }
128 
129     private final StorageEventListener mStorageListener = new StorageEventListener() {
130         @Override
131         public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
132             if (isInteresting(vol)) {
133                 refresh();
134             }
135         }
136 
137         @Override
138         public void onDiskDestroyed(DiskInfo disk) {
139             refresh();
140         }
141     };
142 
isInteresting(VolumeInfo vol)143     private static boolean isInteresting(VolumeInfo vol) {
144         switch(vol.getType()) {
145             case VolumeInfo.TYPE_PRIVATE:
146             case VolumeInfo.TYPE_PUBLIC:
147                 return true;
148             default:
149                 return false;
150         }
151     }
152 
refresh()153     private synchronized void refresh() {
154         final Context context = getPrefContext();
155 
156         getPreferenceScreen().removeAll();
157         mInternalCategory.removeAll();
158         mExternalCategory.removeAll();
159 
160         mInternalCategory.addPreference(mInternalSummary);
161 
162         int privateCount = 0;
163         long privateUsedBytes = 0;
164         long privateTotalBytes = 0;
165 
166         final List<VolumeInfo> volumes = mStorageManager.getVolumes();
167         Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
168 
169         for (VolumeInfo vol : volumes) {
170             if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
171                 final long volumeTotalBytes = PrivateStorageInfo.getTotalSize(vol,
172                         sTotalInternalStorage);
173                 final int color = COLOR_PRIVATE[privateCount++ % COLOR_PRIVATE.length];
174                 mInternalCategory.addPreference(
175                         new StorageVolumePreference(context, vol, color, volumeTotalBytes));
176                 if (vol.isMountedReadable()) {
177                     final File path = vol.getPath();
178                     privateUsedBytes += (volumeTotalBytes - path.getFreeSpace());
179                     privateTotalBytes += volumeTotalBytes;
180                 }
181             } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
182                 mExternalCategory.addPreference(
183                         new StorageVolumePreference(context, vol, COLOR_PUBLIC, 0));
184             }
185         }
186 
187         // Show missing private volumes
188         final List<VolumeRecord> recs = mStorageManager.getVolumeRecords();
189         for (VolumeRecord rec : recs) {
190             if (rec.getType() == VolumeInfo.TYPE_PRIVATE
191                     && mStorageManager.findVolumeByUuid(rec.getFsUuid()) == null) {
192                 // TODO: add actual storage type to record
193                 final Drawable icon = context.getDrawable(R.drawable.ic_sim_sd);
194                 icon.mutate();
195                 icon.setTint(COLOR_PUBLIC);
196 
197                 final Preference pref = new Preference(context);
198                 pref.setKey(rec.getFsUuid());
199                 pref.setTitle(rec.getNickname());
200                 pref.setSummary(com.android.internal.R.string.ext_media_status_missing);
201                 pref.setIcon(icon);
202                 mInternalCategory.addPreference(pref);
203             }
204         }
205 
206         // Show unsupported disks to give a chance to init
207         final List<DiskInfo> disks = mStorageManager.getDisks();
208         for (DiskInfo disk : disks) {
209             if (disk.volumeCount == 0 && disk.size > 0) {
210                 final Preference pref = new Preference(context);
211                 pref.setKey(disk.getId());
212                 pref.setTitle(disk.getDescription());
213                 pref.setSummary(com.android.internal.R.string.ext_media_status_unsupported);
214                 pref.setIcon(R.drawable.ic_sim_sd);
215                 mExternalCategory.addPreference(pref);
216             }
217         }
218 
219         final BytesResult result = Formatter.formatBytes(getResources(), privateUsedBytes, 0);
220         mInternalSummary.setTitle(TextUtils.expandTemplate(getText(R.string.storage_size_large),
221                 result.value, result.units));
222         mInternalSummary.setSummary(getString(R.string.storage_volume_used_total,
223                 Formatter.formatFileSize(context, privateTotalBytes)));
224         if (mInternalCategory.getPreferenceCount() > 0) {
225             getPreferenceScreen().addPreference(mInternalCategory);
226         }
227         if (mExternalCategory.getPreferenceCount() > 0) {
228             getPreferenceScreen().addPreference(mExternalCategory);
229         }
230 
231         if (mInternalCategory.getPreferenceCount() == 2
232                 && mExternalCategory.getPreferenceCount() == 0) {
233             // Only showing primary internal storage, so just shortcut
234             final Bundle args = new Bundle();
235             args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
236             Intent intent = Utils.onBuildStartFragmentIntent(getActivity(),
237                     StorageDashboardFragment.class.getName(), args, null,
238                     R.string.storage_settings, null, false, getMetricsCategory());
239             intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
240             getActivity().startActivity(intent);
241             finish();
242         }
243     }
244 
245     @Override
onResume()246     public void onResume() {
247         super.onResume();
248         mStorageManager.registerListener(mStorageListener);
249         refresh();
250     }
251 
252     @Override
onPause()253     public void onPause() {
254         super.onPause();
255         mStorageManager.unregisterListener(mStorageListener);
256     }
257 
258     @Override
onPreferenceTreeClick(Preference pref)259     public boolean onPreferenceTreeClick(Preference pref) {
260         final String key = pref.getKey();
261         if (pref instanceof StorageVolumePreference) {
262             // Picked a normal volume
263             final VolumeInfo vol = mStorageManager.findVolumeById(key);
264 
265             if (vol == null) {
266                 return false;
267             }
268 
269             if (vol.getState() == VolumeInfo.STATE_UNMOUNTED) {
270                 VolumeUnmountedFragment.show(this, vol.getId());
271                 return true;
272             } else if (vol.getState() == VolumeInfo.STATE_UNMOUNTABLE) {
273                 DiskInitFragment.show(this, R.string.storage_dialog_unmountable, vol.getDiskId());
274                 return true;
275             }
276 
277             if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
278                 final Bundle args = new Bundle();
279                 args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
280 
281                 if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(vol.getId())) {
282                     startFragment(this, StorageDashboardFragment.class.getCanonicalName(),
283                             R.string.storage_settings, 0, args);
284                 } else {
285                     // TODO: Go to the StorageDashboardFragment once it fully handles all of the
286                     //       SD card cases and other private internal storage cases.
287                     PrivateVolumeSettings.setVolumeSize(args, PrivateStorageInfo.getTotalSize(vol,
288                             sTotalInternalStorage));
289                     startFragment(this, PrivateVolumeSettings.class.getCanonicalName(),
290                             -1, 0, args);
291                 }
292 
293                 return true;
294 
295             } else if (vol.getType() == VolumeInfo.TYPE_PUBLIC) {
296                 if (vol.isMountedReadable()) {
297                     startActivity(vol.buildBrowseIntent());
298                     return true;
299                 } else {
300                     final Bundle args = new Bundle();
301                     args.putString(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
302                     startFragment(this, PublicVolumeSettings.class.getCanonicalName(),
303                             -1, 0, args);
304                     return true;
305                 }
306             }
307 
308         } else if (key.startsWith("disk:")) {
309             // Picked an unsupported disk
310             DiskInitFragment.show(this, R.string.storage_dialog_unsupported, key);
311             return true;
312 
313         } else {
314             // Picked a missing private volume
315             final Bundle args = new Bundle();
316             args.putString(VolumeRecord.EXTRA_FS_UUID, key);
317             startFragment(this, PrivateVolumeForget.class.getCanonicalName(),
318                     R.string.storage_menu_forget, 0, args);
319             return true;
320         }
321 
322         return false;
323     }
324 
325     public static class MountTask extends AsyncTask<Void, Void, Exception> {
326         private final Context mContext;
327         private final StorageManager mStorageManager;
328         private final String mVolumeId;
329         private final String mDescription;
330 
MountTask(Context context, VolumeInfo volume)331         public MountTask(Context context, VolumeInfo volume) {
332             mContext = context.getApplicationContext();
333             mStorageManager = mContext.getSystemService(StorageManager.class);
334             mVolumeId = volume.getId();
335             mDescription = mStorageManager.getBestVolumeDescription(volume);
336         }
337 
338         @Override
doInBackground(Void... params)339         protected Exception doInBackground(Void... params) {
340             try {
341                 mStorageManager.mount(mVolumeId);
342                 return null;
343             } catch (Exception e) {
344                 return e;
345             }
346         }
347 
348         @Override
onPostExecute(Exception e)349         protected void onPostExecute(Exception e) {
350             if (e == null) {
351                 Toast.makeText(mContext, mContext.getString(R.string.storage_mount_success,
352                         mDescription), Toast.LENGTH_SHORT).show();
353             } else {
354                 Log.e(TAG, "Failed to mount " + mVolumeId, e);
355                 Toast.makeText(mContext, mContext.getString(R.string.storage_mount_failure,
356                         mDescription), Toast.LENGTH_SHORT).show();
357             }
358         }
359     }
360 
361     public static class UnmountTask extends AsyncTask<Void, Void, Exception> {
362         private final Context mContext;
363         private final StorageManager mStorageManager;
364         private final String mVolumeId;
365         private final String mDescription;
366 
UnmountTask(Context context, VolumeInfo volume)367         public UnmountTask(Context context, VolumeInfo volume) {
368             mContext = context.getApplicationContext();
369             mStorageManager = mContext.getSystemService(StorageManager.class);
370             mVolumeId = volume.getId();
371             mDescription = mStorageManager.getBestVolumeDescription(volume);
372         }
373 
374         @Override
doInBackground(Void... params)375         protected Exception doInBackground(Void... params) {
376             try {
377                 mStorageManager.unmount(mVolumeId);
378                 return null;
379             } catch (Exception e) {
380                 return e;
381             }
382         }
383 
384         @Override
onPostExecute(Exception e)385         protected void onPostExecute(Exception e) {
386             if (e == null) {
387                 Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_success,
388                         mDescription), Toast.LENGTH_SHORT).show();
389             } else {
390                 Log.e(TAG, "Failed to unmount " + mVolumeId, e);
391                 Toast.makeText(mContext, mContext.getString(R.string.storage_unmount_failure,
392                         mDescription), Toast.LENGTH_SHORT).show();
393             }
394         }
395     }
396 
397     public static class VolumeUnmountedFragment extends InstrumentedDialogFragment {
show(Fragment parent, String volumeId)398         public static void show(Fragment parent, String volumeId) {
399             final Bundle args = new Bundle();
400             args.putString(VolumeInfo.EXTRA_VOLUME_ID, volumeId);
401 
402             final VolumeUnmountedFragment dialog = new VolumeUnmountedFragment();
403             dialog.setArguments(args);
404             dialog.setTargetFragment(parent, 0);
405             dialog.show(parent.getFragmentManager(), TAG_VOLUME_UNMOUNTED);
406         }
407 
408         @Override
getMetricsCategory()409         public int getMetricsCategory() {
410             return MetricsEvent.DIALOG_VOLUME_UNMOUNT;
411         }
412 
413         @Override
onCreateDialog(Bundle savedInstanceState)414         public Dialog onCreateDialog(Bundle savedInstanceState) {
415             final Context context = getActivity();
416             final StorageManager sm = context.getSystemService(StorageManager.class);
417 
418             final String volumeId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
419             final VolumeInfo vol = sm.findVolumeById(volumeId);
420 
421             final AlertDialog.Builder builder = new AlertDialog.Builder(context);
422             builder.setMessage(TextUtils.expandTemplate(
423                     getText(R.string.storage_dialog_unmounted), vol.getDisk().getDescription()));
424 
425             builder.setPositiveButton(R.string.storage_menu_mount,
426                     new DialogInterface.OnClickListener() {
427                 /**
428                  * Check if an {@link RestrictedLockUtils#sendShowAdminSupportDetailsIntent admin
429                  * details intent} should be shown for the restriction and show it.
430                  *
431                  * @param restriction The restriction to check
432                  * @return {@code true} iff a intent was shown.
433                  */
434                 private boolean wasAdminSupportIntentShown(@NonNull String restriction) {
435                     EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
436                             getActivity(), restriction, UserHandle.myUserId());
437                     boolean hasBaseUserRestriction = RestrictedLockUtils.hasBaseUserRestriction(
438                             getActivity(), restriction, UserHandle.myUserId());
439                     if (admin != null && !hasBaseUserRestriction) {
440                         RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), admin);
441                         return true;
442                     }
443 
444                     return false;
445                 }
446 
447                 @Override
448                 public void onClick(DialogInterface dialog, int which) {
449                     if (wasAdminSupportIntentShown(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA)) {
450                         return;
451                     }
452 
453                     if (vol.disk != null && vol.disk.isUsb() &&
454                             wasAdminSupportIntentShown(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
455                         return;
456                     }
457 
458                     new MountTask(context, vol).execute();
459                 }
460             });
461             builder.setNegativeButton(R.string.cancel, null);
462 
463             return builder.create();
464         }
465     }
466 
467     public static class DiskInitFragment extends InstrumentedDialogFragment {
468         @Override
getMetricsCategory()469         public int getMetricsCategory() {
470             return MetricsEvent.DIALOG_VOLUME_INIT;
471         }
472 
show(Fragment parent, int resId, String diskId)473         public static void show(Fragment parent, int resId, String diskId) {
474             final Bundle args = new Bundle();
475             args.putInt(Intent.EXTRA_TEXT, resId);
476             args.putString(DiskInfo.EXTRA_DISK_ID, diskId);
477 
478             final DiskInitFragment dialog = new DiskInitFragment();
479             dialog.setArguments(args);
480             dialog.setTargetFragment(parent, 0);
481             dialog.show(parent.getFragmentManager(), TAG_DISK_INIT);
482         }
483 
484         @Override
onCreateDialog(Bundle savedInstanceState)485         public Dialog onCreateDialog(Bundle savedInstanceState) {
486             final Context context = getActivity();
487             final StorageManager sm = context.getSystemService(StorageManager.class);
488 
489             final int resId = getArguments().getInt(Intent.EXTRA_TEXT);
490             final String diskId = getArguments().getString(DiskInfo.EXTRA_DISK_ID);
491             final DiskInfo disk = sm.findDiskById(diskId);
492 
493             final AlertDialog.Builder builder = new AlertDialog.Builder(context);
494             builder.setMessage(TextUtils.expandTemplate(getText(resId), disk.getDescription()));
495 
496             builder.setPositiveButton(R.string.storage_menu_set_up,
497                     new DialogInterface.OnClickListener() {
498                 @Override
499                 public void onClick(DialogInterface dialog, int which) {
500                     final Intent intent = new Intent(context, StorageWizardInit.class);
501                     intent.putExtra(DiskInfo.EXTRA_DISK_ID, diskId);
502                     startActivity(intent);
503                 }
504             });
505             builder.setNegativeButton(R.string.cancel, null);
506 
507             return builder.create();
508         }
509     }
510 
511     private static class SummaryProvider implements SummaryLoader.SummaryProvider {
512         private final Context mContext;
513         private final SummaryLoader mLoader;
514         private final StorageManagerVolumeProvider mStorageManagerVolumeProvider;
515 
SummaryProvider(Context context, SummaryLoader loader)516         private SummaryProvider(Context context, SummaryLoader loader) {
517             mContext = context;
518             mLoader = loader;
519             final StorageManager storageManager = mContext.getSystemService(StorageManager.class);
520             mStorageManagerVolumeProvider = new StorageManagerVolumeProvider(storageManager);
521         }
522 
523         @Override
setListening(boolean listening)524         public void setListening(boolean listening) {
525             if (listening) {
526                 updateSummary();
527             }
528         }
529 
updateSummary()530         private void updateSummary() {
531             // TODO: Register listener.
532             final NumberFormat percentageFormat = NumberFormat.getPercentInstance();
533             final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo(
534                     mStorageManagerVolumeProvider);
535             double privateUsedBytes = info.totalBytes - info.freeBytes;
536             mLoader.setSummary(this, mContext.getString(R.string.storage_summary,
537                     percentageFormat.format(privateUsedBytes / info.totalBytes),
538                     Formatter.formatFileSize(mContext, info.freeBytes)));
539         }
540     }
541 
542 
543     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
544             = new SummaryLoader.SummaryProviderFactory() {
545         @Override
546         public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity,
547                                                                    SummaryLoader summaryLoader) {
548             return new SummaryProvider(activity, summaryLoader);
549         }
550     };
551 
552     /**
553      * Enable indexing of searchable data
554      */
555     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
556         new BaseSearchIndexProvider() {
557             @Override
558             public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
559                 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
560 
561                 SearchIndexableRaw data = new SearchIndexableRaw(context);
562                 data.title = context.getString(R.string.storage_settings);
563                 data.screenTitle = context.getString(R.string.storage_settings);
564                 result.add(data);
565 
566                 data = new SearchIndexableRaw(context);
567                 data.title = context.getString(R.string.internal_storage);
568                 data.screenTitle = context.getString(R.string.storage_settings);
569                 result.add(data);
570 
571                 data = new SearchIndexableRaw(context);
572                 final StorageManager storage = context.getSystemService(StorageManager.class);
573                 final List<VolumeInfo> vols = storage.getVolumes();
574                 for (VolumeInfo vol : vols) {
575                     if (isInteresting(vol)) {
576                         data.title = storage.getBestVolumeDescription(vol);
577                         data.screenTitle = context.getString(R.string.storage_settings);
578                         result.add(data);
579                     }
580                 }
581 
582                 data = new SearchIndexableRaw(context);
583                 data.title = context.getString(R.string.memory_size);
584                 data.screenTitle = context.getString(R.string.storage_settings);
585                 result.add(data);
586 
587                 data = new SearchIndexableRaw(context);
588                 data.title = context.getString(R.string.memory_available);
589                 data.screenTitle = context.getString(R.string.storage_settings);
590                 result.add(data);
591 
592                 data = new SearchIndexableRaw(context);
593                 data.title = context.getString(R.string.memory_apps_usage);
594                 data.screenTitle = context.getString(R.string.storage_settings);
595                 result.add(data);
596 
597                 data = new SearchIndexableRaw(context);
598                 data.title = context.getString(R.string.memory_dcim_usage);
599                 data.screenTitle = context.getString(R.string.storage_settings);
600                 result.add(data);
601 
602                 data = new SearchIndexableRaw(context);
603                 data.title = context.getString(R.string.memory_music_usage);
604                 data.screenTitle = context.getString(R.string.storage_settings);
605                 result.add(data);
606 
607                 data = new SearchIndexableRaw(context);
608                 data.title = context.getString(R.string.memory_downloads_usage);
609                 data.screenTitle = context.getString(R.string.storage_settings);
610                 result.add(data);
611 
612                 data = new SearchIndexableRaw(context);
613                 data.title = context.getString(R.string.memory_media_cache_usage);
614                 data.screenTitle = context.getString(R.string.storage_settings);
615                 result.add(data);
616 
617                 data = new SearchIndexableRaw(context);
618                 data.title = context.getString(R.string.memory_media_misc_usage);
619                 data.screenTitle = context.getString(R.string.storage_settings);
620                 result.add(data);
621 
622                 return result;
623             }
624         };
625 }
626