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