OSDN Git Service

CM Easy Mode File Manager Navigation fixes
[android-x86/packages-apps-CMFileManager.git] / src / com / cyanogenmod / filemanager / activities / NavigationActivity.java
1 /*
2  * Copyright (C) 2012 The CyanogenMod 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.cyanogenmod.filemanager.activities;
18
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.res.Configuration;
30 import android.content.res.XmlResourceParser;
31 import android.database.Cursor;
32 import android.graphics.Color;
33 import android.graphics.drawable.Drawable;
34 import android.net.Uri;
35 import android.nfc.NfcAdapter;
36 import android.nfc.NfcEvent;
37 import android.os.AsyncTask;
38 import android.os.Bundle;
39 import android.os.Environment;
40 import android.os.Handler;
41 import android.os.Parcelable;
42 import android.os.storage.StorageVolume;
43 import android.support.v4.app.ActionBarDrawerToggle;
44 import android.support.v4.widget.DrawerLayout;
45 import android.text.TextUtils;
46 import android.util.Log;
47 import android.view.Gravity;
48 import android.view.KeyEvent;
49 import android.view.MenuItem;
50 import android.view.View;
51 import android.view.View.OnClickListener;
52 import android.view.ViewGroup;
53 import android.view.inputmethod.InputMethodManager;
54 import android.widget.AdapterView;
55 import android.widget.AdapterView.OnItemClickListener;
56 import android.widget.ImageButton;
57 import android.widget.ImageView;
58 import android.widget.LinearLayout;
59 import android.widget.ListPopupWindow;
60 import android.widget.ListView;
61 import android.widget.PopupWindow;
62 import android.widget.SearchView;
63 import android.widget.TextView;
64 import android.widget.Toast;
65 import android.widget.Toolbar;
66 import android.widget.ArrayAdapter;
67
68 import com.android.internal.util.XmlUtils;
69 import com.cyanogenmod.filemanager.FileManagerApplication;
70 import com.cyanogenmod.filemanager.R;
71 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
72 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
73 import com.cyanogenmod.filemanager.console.Console;
74 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
75 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
76 import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
77 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
78 import com.cyanogenmod.filemanager.console.VirtualConsole;
79 import com.cyanogenmod.filemanager.console.VirtualMountPointConsole;
80 import com.cyanogenmod.filemanager.console.secure.SecureConsole;
81 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
82 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
83 import com.cyanogenmod.filemanager.model.Bookmark;
84 import com.cyanogenmod.filemanager.model.DiskUsage;
85 import com.cyanogenmod.filemanager.model.FileSystemObject;
86 import com.cyanogenmod.filemanager.model.History;
87 import com.cyanogenmod.filemanager.model.MountPoint;
88 import com.cyanogenmod.filemanager.model.Bookmark.BOOKMARK_TYPE;
89 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
90 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
91 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
92 import com.cyanogenmod.filemanager.preferences.AccessMode;
93 import com.cyanogenmod.filemanager.preferences.Bookmarks;
94 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
95 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
96 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
97 import com.cyanogenmod.filemanager.preferences.Preferences;
98 import com.cyanogenmod.filemanager.ui.IconHolder;
99 import com.cyanogenmod.filemanager.ui.ThemeManager;
100 import com.cyanogenmod.filemanager.ui.ThemeManager.Theme;
101 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
102 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
103 import com.cyanogenmod.filemanager.ui.dialogs.InitialDirectoryDialog;
104 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
105 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
106 import com.cyanogenmod.filemanager.ui.widgets.ButtonItem;
107 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
108 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
109 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
110 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
111 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
112 import com.cyanogenmod.filemanager.util.AndroidHelper;
113 import com.cyanogenmod.filemanager.util.BookmarksHelper;
114 import com.cyanogenmod.filemanager.util.CommandHelper;
115 import com.cyanogenmod.filemanager.util.DialogHelper;
116 import com.cyanogenmod.filemanager.util.ExceptionUtil;
117 import com.cyanogenmod.filemanager.util.ExceptionUtil.OnRelaunchCommandResult;
118 import com.cyanogenmod.filemanager.util.FileHelper;
119 import com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory;
120 import com.cyanogenmod.filemanager.util.StorageHelper;
121
122 import java.io.File;
123 import java.io.FileNotFoundException;
124 import java.util.ArrayList;
125 import java.util.Arrays;
126 import java.util.HashMap;
127 import java.util.List;
128 import java.util.Locale;
129 import java.util.Map;
130
131 import static com.cyanogenmod.filemanager.util.MimeTypeHelper.MimeTypeCategory.*;
132
133 /**
134  * The main navigation activity. This activity is the center of the application.
135  * From this the user can navigate, search, make actions.<br/>
136  * This activity is singleTop, so when it is displayed no other activities exists in
137  * the stack.<br/>
138  * This cause an issue with the saved instance of this class, because if another activity
139  * is displayed, and the process is killed, NavigationActivity is started and the saved
140  * instance gets corrupted.<br/>
141  * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
142  * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
143  * the app is killed, is restarted from his initial state.
144  */
145 public class NavigationActivity extends Activity
146     implements OnHistoryListener, OnRequestRefreshListener,
147     OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
148
149     private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
150
151     private static boolean DEBUG = false;
152
153     // Bookmark list XML tags
154     private static final String TAG_BOOKMARKS = "Bookmarks"; //$NON-NLS-1$
155     private static final String TAG_BOOKMARK = "bookmark"; //$NON-NLS-1$
156
157     private static final String STR_USB = "usb"; // $NON-NLS-1$
158
159     /**
160      * Intent code for request a search.
161      */
162     public static final int INTENT_REQUEST_SEARCH = 10001;
163
164     /**
165      * Intent code for request a search.
166      */
167     public static final int INTENT_REQUEST_SETTINGS = 20001;
168
169     /**
170      * Constant for extra information about selected search entry.
171      */
172     public static final String EXTRA_SEARCH_ENTRY_SELECTION =
173             "extra_search_entry_selection"; //$NON-NLS-1$
174
175     /**
176      * Constant for extra information about last search data.
177      */
178     public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
179             "extra_search_last_search_data"; //$NON-NLS-1$
180
181     /**
182      * Constant for extra information for request a navigation to the passed path.
183      */
184     public static final String EXTRA_NAVIGATE_TO =
185             "extra_navigate_to"; //$NON-NLS-1$
186
187     /**
188      * Constant for extra information for request to add navigation to the history
189      */
190     public static final String EXTRA_ADD_TO_HISTORY =
191             "extra_add_to_history"; //$NON-NLS-1$
192
193     // The timeout needed to reset the exit status for back button
194     // After this time user need to tap 2 times the back button to
195     // exit, and the toast is shown again after the first tap.
196     private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
197
198
199     private Toolbar mToolBar;
200     private SearchView mSearchView;
201     private NavigationCustomTitleView mCustomTitleView;
202     private InputMethodManager mImm;
203
204     private final BroadcastReceiver mNotificationReceiver = new BroadcastReceiver() {
205         @Override
206         public void onReceive(Context context, Intent intent) {
207             if (intent != null) {
208                 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
209                     // The settings has changed
210                     String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
211                     if (key != null) {
212                         // Disk usage warning level
213                         if (key.compareTo(FileManagerSettings.
214                                 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
215
216                             // Set the free disk space warning level of the breadcrumb widget
217                             Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
218                             String fds = Preferences.getSharedPreferences().getString(
219                                     FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
220                                     (String)FileManagerSettings.
221                                         SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
222                             breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
223                             breadcrumb.updateMountPointInfo();
224                             return;
225                         }
226
227                         // Case sensitive sort
228                         if (key.compareTo(FileManagerSettings.
229                                 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
230                             getCurrentNavigationView().refresh();
231                             return;
232                         }
233
234                         // Display thumbs
235                         if (key.compareTo(FileManagerSettings.
236                                 SETTINGS_DISPLAY_THUMBS.getId()) == 0) {
237                             // Clean the icon cache applying the current theme
238                             applyTheme();
239                             return;
240                         }
241
242                         // Use flinger
243                         if (key.compareTo(FileManagerSettings.
244                                 SETTINGS_USE_FLINGER.getId()) == 0) {
245                             boolean useFlinger =
246                                     Preferences.getSharedPreferences().getBoolean(
247                                             FileManagerSettings.SETTINGS_USE_FLINGER.getId(),
248                                                 ((Boolean)FileManagerSettings.
249                                                         SETTINGS_USE_FLINGER.
250                                                             getDefaultValue()).booleanValue());
251                             getCurrentNavigationView().setUseFlinger(useFlinger);
252                             return;
253                         }
254
255                         // Access mode
256                         if (key.compareTo(FileManagerSettings.
257                                 SETTINGS_ACCESS_MODE.getId()) == 0) {
258                             // Is it necessary to create or exit of the ChRooted?
259                             boolean chRooted =
260                                     FileManagerApplication.
261                                         getAccessMode().compareTo(AccessMode.SAFE) == 0;
262                             if (chRooted != NavigationActivity.this.mChRooted) {
263                                 if (chRooted) {
264                                     createChRooted();
265                                 } else {
266                                     exitChRooted();
267                                 }
268                             }
269                         }
270
271                         // Restricted access
272                         if (key.compareTo(FileManagerSettings.
273                                 SETTINGS_RESTRICT_SECONDARY_USERS_ACCESS.getId()) == 0) {
274                             if (AndroidHelper.isSecondaryUser(context)) {
275                                 try {
276                                     Preferences.savePreference(
277                                             FileManagerSettings.SETTINGS_ACCESS_MODE,
278                                             AccessMode.SAFE, true);
279                                 } catch (Throwable ex) {
280                                     Log.w(TAG, "can't save console preference", ex); //$NON-NLS-1$
281                                 }
282                                 ConsoleBuilder.changeToNonPrivilegedConsole(context);
283                                 createChRooted();
284                             }
285                         }
286
287                         // Filetime format mode
288                         if (key.compareTo(FileManagerSettings.
289                                 SETTINGS_FILETIME_FORMAT_MODE.getId()) == 0) {
290                             // Refresh the data
291                             synchronized (FileHelper.DATETIME_SYNC) {
292                                 FileHelper.sReloadDateTimeFormats = true;
293                                 NavigationActivity.this.getCurrentNavigationView().refresh();
294                             }
295                         }
296                     }
297
298                 } else if (intent.getAction().compareTo(
299                         FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
300                     // Retrieve the file that was changed
301                     String file =
302                             intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
303                     try {
304                         FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
305                         if (fso != null) {
306                             getCurrentNavigationView().refresh(fso);
307                         }
308                     } catch (Exception e) {
309                         ExceptionUtil.translateException(context, e, true, false);
310                     }
311
312                 } else if (intent.getAction().compareTo(
313                         FileManagerSettings.INTENT_THEME_CHANGED) == 0) {
314                     applyTheme();
315
316                 } else if (intent.getAction().compareTo(Intent.ACTION_TIME_CHANGED) == 0 ||
317                            intent.getAction().compareTo(Intent.ACTION_DATE_CHANGED) == 0 ||
318                            intent.getAction().compareTo(Intent.ACTION_TIMEZONE_CHANGED) == 0 ||
319                            intent.getAction().compareTo(Intent.ACTION_LOCALE_CHANGED) == 0) {
320                     // Refresh the data
321                     synchronized (FileHelper.DATETIME_SYNC) {
322                         FileHelper.sReloadDateTimeFormats = true;
323                         NavigationActivity.this.getCurrentNavigationView().refresh();
324                     }
325                 } else if (intent.getAction().compareTo(
326                         FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED) == 0 ||
327                             intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED) ||
328                             intent.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
329                     onRequestBookmarksRefresh();
330                     removeUnmountedHistory();
331                     removeUnmountedSelection();
332                 }
333             }
334         }
335     };
336
337     private OnClickListener mOnClickDrawerTabListener = new OnClickListener() {
338         @Override
339         public void onClick(View v) {
340             switch (v.getId()) {
341                 case R.id.drawer_bookmarks_tab:
342                     if (!mBookmarksTab.isSelected()) {
343                         mBookmarksTab.setSelected(true);
344                         mHistoryTab.setSelected(false);
345                         mBookmarksTab.setTextAppearance(
346                                 NavigationActivity.this, R.style.primary_text_appearance);
347                         mHistoryTab.setTextAppearance(
348                                 NavigationActivity.this, R.style.secondary_text_appearance);
349                         mHistoryLayout.setVisibility(View.GONE);
350                         mBookmarksLayout.setVisibility(View.VISIBLE);
351                         applyTabTheme();
352
353                         try {
354                             Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
355                                     Integer.valueOf(0), true);
356                         } catch (Exception ex) {
357                             Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
358                         }
359
360                         mClearHistory.setVisibility(View.GONE);
361                     }
362                     break;
363                 case R.id.drawer_history_tab:
364                     if (!mHistoryTab.isSelected()) {
365                         mHistoryTab.setSelected(true);
366                         mBookmarksTab.setSelected(false);
367                         mHistoryTab.setTextAppearance(
368                                 NavigationActivity.this, R.style.primary_text_appearance);
369                         mBookmarksTab.setTextAppearance(
370                                 NavigationActivity.this, R.style.secondary_text_appearance);
371                         mBookmarksLayout.setVisibility(View.GONE);
372                         mHistoryLayout.setVisibility(View.VISIBLE);
373                         applyTabTheme();
374
375                         try {
376                             Preferences.savePreference(FileManagerSettings.USER_PREF_LAST_DRAWER_TAB,
377                                     Integer.valueOf(1), true);
378                         } catch (Exception ex) {
379                             Log.e(TAG, "Can't save last drawer tab", ex); //$NON-NLS-1$
380                         }
381
382                         mClearHistory.setVisibility(mHistory.size() > 0 ? View.VISIBLE : View.GONE);
383                     }
384                     break;
385                 default:
386                     break;
387             }
388         }
389     };
390
391     private OnClickListener mOnClickDrawerActionBarListener = new OnClickListener() {
392         @Override
393         public void onClick(View v) {
394             switch (v.getId()) {
395                 case R.id.ab_settings:
396                     mDrawerLayout.closeDrawer(Gravity.START);
397                     openSettings();
398                     break;
399                 case R.id.ab_clear_history:
400                     clearHistory();
401                     mClearHistory.setVisibility(View.GONE);
402                     break;
403                 default:
404                     break;
405             }
406         }
407     };
408
409     static String MIME_TYPE_LOCALIZED_NAMES[];
410     /**
411      * @hide
412      */
413     static Map<MimeTypeCategory, Drawable> EASY_MODE_ICONS = new
414             HashMap<MimeTypeCategory, Drawable>();
415
416     /**
417      * @hide
418      */
419     NavigationView[] mNavigationViews;
420     /**
421      * @hide
422      */
423     ListView mEasyModeListView;
424     private List<History> mHistory;
425
426     private static final List<MimeTypeCategory> EASY_MODE_LIST = new ArrayList<MimeTypeCategory>() {
427         {
428             add(NONE);
429             add(IMAGE);
430             add(VIDEO);
431             add(AUDIO);
432             add(DOCUMENT);
433             add(APP);
434         }
435     };
436
437     private ArrayAdapter<MimeTypeCategory> mEasyModeAdapter;
438     private View.OnClickListener mEasyModeItemClickListener = new View.OnClickListener() {
439         @Override
440         public void onClick(View view) {
441             Integer position = (Integer) view.getTag();
442             onClicked(position);
443         }
444     };
445
446     private int mCurrentNavigationView;
447
448     private ViewGroup mActionBar;
449     private SelectionView mSelectionBar;
450
451     private DrawerLayout mDrawerLayout;
452     private ViewGroup mDrawer;
453     private ActionBarDrawerToggle mDrawerToggle;
454     private LinearLayout mDrawerHistory;
455     private TextView mDrawerHistoryEmpty;
456
457     private TextView mBookmarksTab;
458     private TextView mHistoryTab;
459     private View mBookmarksLayout;
460     private View mHistoryLayout;
461
462     private ButtonItem mSettings;
463     private ButtonItem mClearHistory;
464
465     private List<Bookmark> mBookmarks;
466     private List<Bookmark> mSdBookmarks;
467     private LinearLayout mDrawerBookmarks;
468
469     private boolean mExitFlag = false;
470     private long mExitBackTimeout = -1;
471
472     private Dialog mActiveDialog = null;
473
474     private int mOrientation;
475
476     private boolean mNeedsEasyMode = false;
477
478     /**
479      * @hide
480      */
481     boolean mChRooted;
482
483     /**
484      * @hide
485      */
486     Handler mHandler;
487
488     private AsyncTask<Void, Void, Boolean> mBookmarksTask;
489
490     /**
491      * {@inheritDoc}
492      */
493     @Override
494     protected void onCreate(Bundle state) {
495
496         if (DEBUG) {
497             Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
498         }
499
500         // Register the broadcast receiver
501         IntentFilter filter = new IntentFilter();
502         filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
503         filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
504         filter.addAction(FileManagerSettings.INTENT_THEME_CHANGED);
505         filter.addAction(Intent.ACTION_DATE_CHANGED);
506         filter.addAction(Intent.ACTION_TIME_CHANGED);
507         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
508         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
509         filter.addAction(FileManagerSettings.INTENT_MOUNT_STATUS_CHANGED);
510         registerReceiver(this.mNotificationReceiver, filter);
511
512         // This filter needs the file data scheme, so it must be defined separately.
513         IntentFilter newFilter = new IntentFilter();
514         newFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
515         newFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
516         newFilter.addDataScheme(ContentResolver.SCHEME_FILE);
517         registerReceiver(mNotificationReceiver, newFilter);
518
519         //the input manager service
520         mImm = (InputMethodManager) this.getSystemService(
521                 Context.INPUT_METHOD_SERVICE);
522
523         // Set the theme before setContentView
524         Theme theme = ThemeManager.getCurrentTheme(this);
525         theme.setBaseThemeNoActionBar(this);
526
527         //Set the main layout of the activity
528         setContentView(R.layout.navigation);
529
530         //Initialize nfc adapter
531         NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
532         if (mNfcAdapter != null) {
533             mNfcAdapter.setBeamPushUrisCallback(new NfcAdapter.CreateBeamUrisCallback() {
534                 @Override
535                 public Uri[] createBeamUris(NfcEvent event) {
536                     List<FileSystemObject> selectedFiles =
537                             getCurrentNavigationView().getSelectedFiles();
538                     if (selectedFiles.size() > 0) {
539                         List<Uri> fileUri = new ArrayList<Uri>();
540                         for (FileSystemObject f : selectedFiles) {
541                             //Beam ignores folders and system files
542                             if (!FileHelper.isDirectory(f) && !FileHelper.isSystemFile(f)) {
543                                 fileUri.add(Uri.fromFile(new File(f.getFullPath())));
544                             }
545                         }
546                         if (fileUri.size() > 0) {
547                             return fileUri.toArray(new Uri[fileUri.size()]);
548                         }
549                     }
550                     return null;
551                 }
552             }, this);
553         }
554
555         //Initialize activity
556         init();
557
558         //Navigation views
559         initNavigationViews();
560
561         // As we're using a Toolbar, we should retrieve it and set it
562         // to be our ActionBar
563         mToolBar = (Toolbar) findViewById(R.id.material_toolbar);
564         setActionBar(mToolBar);
565
566         //Initialize action bars
567         initTitleActionBar();
568         initStatusActionBar();
569         initSelectionBar();
570
571         // Initialize navigation drawer
572         initDrawer();
573         initBookmarks();
574
575         // Adjust layout (only when start on landscape mode)
576         int orientation = getResources().getConfiguration().orientation;
577         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
578             onLayoutChanged();
579         }
580         this.mOrientation = orientation;
581
582         // Apply the theme
583         applyTheme();
584
585         // Show welcome message
586         showWelcomeMsg();
587
588         this.mHandler = new Handler();
589         this.mHandler.post(new Runnable() {
590             @Override
591             public void run() {
592                 // Initialize console
593                 initConsole();
594
595                 //Initialize navigation
596                 int cc = NavigationActivity.this.mNavigationViews.length;
597                 for (int i = 0; i < cc; i++) {
598                     initNavigation(i, false, getIntent());
599                 }
600
601                 //Check the intent action
602                 checkIntent(getIntent());
603             }
604         });
605
606         MIME_TYPE_LOCALIZED_NAMES = MimeTypeCategory.getFriendlyLocalizedNames(NavigationActivity
607             .this);
608
609         EASY_MODE_ICONS.put(MimeTypeCategory.NONE, getResources().getDrawable(R.drawable
610                 .ic_em_all));
611         EASY_MODE_ICONS.put(MimeTypeCategory.IMAGE, getResources().getDrawable(R.drawable
612                 .ic_em_image));
613         EASY_MODE_ICONS.put(MimeTypeCategory.VIDEO, getResources().getDrawable(R.drawable
614                 .ic_em_video));
615         EASY_MODE_ICONS.put(MimeTypeCategory.AUDIO, getResources().getDrawable(R.drawable
616                 .ic_em_music));
617         EASY_MODE_ICONS.put(MimeTypeCategory.DOCUMENT, getResources().getDrawable(R.drawable
618                 .ic_em_document));
619         EASY_MODE_ICONS.put(MimeTypeCategory.APP, getResources().getDrawable(R.drawable
620                 .ic_em_application));
621
622         //Save state
623         super.onCreate(state);
624     }
625
626     @Override
627     protected void onResume() {
628         super.onResume();
629
630         if (mSearchView.getVisibility() == View.VISIBLE) {
631             closeSearch();
632         }
633
634         // Check restrictions
635         if (!FileManagerApplication.checkRestrictSecondaryUsersAccess(this, mChRooted)) {
636             return;
637         }
638
639         // Check that the current dir is mounted (for virtual filesystems)
640         String curDir = mNavigationViews[mCurrentNavigationView].getCurrentDir();
641         if (curDir != null) {
642             VirtualMountPointConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(
643                     mNavigationViews[mCurrentNavigationView].getCurrentDir());
644             if (vc != null && !vc.isMounted()) {
645                 onRequestBookmarksRefresh();
646                 removeUnmountedHistory();
647                 removeUnmountedSelection();
648
649                 Intent intent = new Intent();
650                 intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
651                 initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
652             }
653         }
654     }
655
656     @Override
657     protected void onPostCreate(Bundle savedInstanceState) {
658         super.onPostCreate(savedInstanceState);
659         // Sync the toggle state after onRestoreInstanceState has occurred.
660         mDrawerToggle.syncState();
661     }
662
663     /**
664      * {@inheritDoc}
665      */
666     @Override
667     protected void onNewIntent(Intent intent) {
668         //Initialize navigation
669         initNavigation(this.mCurrentNavigationView, true, intent);
670
671         //Check the intent action
672         checkIntent(intent);
673     }
674
675     /**
676      * {@inheritDoc}
677      */
678     @Override
679     public void onConfigurationChanged(Configuration newConfig) {
680         super.onConfigurationChanged(newConfig);
681         onLayoutChanged();
682         mDrawerToggle.onConfigurationChanged(newConfig);
683     }
684
685     /**
686      * {@inheritDoc}
687      */
688     @Override
689     public boolean onOptionsItemSelected(MenuItem item) {
690         if (mDrawerToggle.onOptionsItemSelected(item)) {
691           return true;
692         }
693
694         if (mNeedsEasyMode) {
695             if (item.getItemId() == android.R.id.home) {
696                 if (mHistory.size() == 0 && !isEasyModeVisible()) {
697                     performShowEasyMode();
698                 } else {
699                     back();
700                 }
701             }
702         }
703         return super.onOptionsItemSelected(item);
704     }
705
706     /**
707      * {@inheritDoc}
708      */
709     @Override
710     protected void onDestroy() {
711         if (DEBUG) {
712             Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
713         }
714
715         if (mActiveDialog != null && mActiveDialog.isShowing()) {
716             mActiveDialog.dismiss();
717         }
718
719         // Unregister the receiver
720         try {
721             unregisterReceiver(this.mNotificationReceiver);
722         } catch (Throwable ex) {
723             /**NON BLOCK**/
724         }
725
726         //All destroy. Continue
727         super.onDestroy();
728     }
729
730     /**
731      * Method that returns the current navigation view.
732      *
733      * @return NavigationView The current navigation view
734      */
735     public NavigationView getCurrentNavigationView() {
736         return getNavigationView(this.mCurrentNavigationView);
737     }
738
739     /**
740      * Method that returns the current navigation view.
741      *
742      * @param viewId The view to return
743      * @return NavigationView The current navigation view
744      */
745     public NavigationView getNavigationView(int viewId) {
746         if (this.mNavigationViews == null) return null;
747         return this.mNavigationViews[viewId];
748     }
749
750     /**
751      * Method that initializes the activity.
752      */
753     private void init() {
754         this.mHistory = new ArrayList<History>();
755         this.mChRooted = FileManagerApplication.getAccessMode().compareTo(AccessMode.SAFE) == 0;
756     }
757
758     /**
759      * Method that displays a welcome message the first time the user
760      * access the application
761      */
762     private void showWelcomeMsg() {
763         boolean firstUse = Preferences.getSharedPreferences().getBoolean(
764                 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
765                 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
766
767         //Display the welcome message?
768         if (firstUse && FileManagerApplication.hasShellCommands()) {
769             // open navigation drawer to show user that it exists
770             mDrawerLayout.openDrawer(Gravity.START);
771
772             AlertDialog dialog = DialogHelper.createAlertDialog(this,
773                     R.mipmap.ic_launcher_filemanager, R.string.welcome_title,
774                     getString(R.string.welcome_msg), false);
775             DialogHelper.delegateDialogShow(this, dialog);
776
777             // Don't display again this dialog
778             try {
779                 Preferences.savePreference(
780                         FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
781             } catch (Exception e) {/**NON BLOCK**/}
782         }
783     }
784
785     /**
786      * Method that initializes the titlebar of the activity.
787      */
788     private void initTitleActionBar() {
789         //Inflate the view and associate breadcrumb
790         View titleLayout = getLayoutInflater().inflate(
791                 R.layout.navigation_view_customtitle, null, false);
792         NavigationCustomTitleView title =
793                 (NavigationCustomTitleView)titleLayout.findViewById(R.id.navigation_title_flipper);
794         title.setOnHistoryListener(this);
795         Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
796         int cc = this.mNavigationViews.length;
797         for (int i = 0; i < cc; i++) {
798             this.mNavigationViews[i].setBreadcrumb(breadcrumb);
799             this.mNavigationViews[i].setOnHistoryListener(this);
800             this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
801             this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
802             this.mNavigationViews[i].setCustomTitle(title);
803         }
804
805         // Set the free disk space warning level of the breadcrumb widget
806         String fds = Preferences.getSharedPreferences().getString(
807                 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
808                 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
809         breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
810
811         //Configure the action bar options
812         getActionBar().setBackgroundDrawable(
813                 getResources().getDrawable(R.drawable.bg_material_titlebar));
814         mToolBar.addView(titleLayout);
815     }
816
817     /**
818      * Method that initializes the statusbar of the activity.
819      */
820     private void initStatusActionBar() {
821         //Performs a width calculation of buttons. Buttons exceeds the width
822         //of the action bar should be hidden
823         //This application not use android ActionBar because the application
824         //make uses of the title and bottom areas, and wants to force to show
825         //the overflow button (without care of physical buttons)
826         this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
827         this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
828             @Override
829             public void onLayoutChange(
830                     View v, int left, int top, int right, int bottom, int oldLeft,
831                     int oldTop, int oldRight, int oldBottom) {
832                 //Get the width of the action bar
833                 int w = v.getMeasuredWidth();
834
835                 //Wake through children calculation his dimensions
836                 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
837                 int cw = 0;
838                 final ViewGroup abView = ((ViewGroup)v);
839                 int cc = abView.getChildCount();
840                 for (int i = 0; i < cc; i++) {
841                     View child = abView.getChildAt(i);
842                     child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
843                     cw += bw;
844                 }
845             }
846         });
847
848         // Have overflow menu? Actually no. There is only a search action, so just hide
849         // the overflow
850         View overflow = findViewById(R.id.ab_overflow);
851         overflow.setVisibility(View.GONE);
852
853         // Show the status bar
854         View statusBar = findViewById(R.id.navigation_statusbar_portrait_holder);
855         statusBar.setVisibility(View.VISIBLE);
856     }
857
858     /**
859      * Method that initializes the selectionbar of the activity.
860      */
861     private void initSelectionBar() {
862         this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
863     }
864
865     /**
866      * Method that initializes the navigation drawer of the activity.
867      */
868     private void initDrawer() {
869         mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
870         //Set our status bar color
871         mDrawerLayout.setStatusBarBackgroundColor(R.color.material_palette_blue_primary_dark);
872         mDrawer = (ViewGroup) findViewById(R.id.drawer);
873         mDrawerBookmarks = (LinearLayout) findViewById(R.id.bookmarks_list);
874         mDrawerHistory = (LinearLayout) findViewById(R.id.history_list);
875         mDrawerHistoryEmpty = (TextView) findViewById(R.id.history_empty);
876
877         mBookmarksLayout = findViewById(R.id.drawer_bookmarks);
878         mHistoryLayout = findViewById(R.id.drawer_history);
879         mBookmarksTab = (TextView) findViewById(R.id.drawer_bookmarks_tab);
880         mHistoryTab = (TextView) findViewById(R.id.drawer_history_tab);
881         mBookmarksTab.setOnClickListener(mOnClickDrawerTabListener);
882         mHistoryTab.setOnClickListener(mOnClickDrawerTabListener);
883
884         mSettings = (ButtonItem) findViewById(R.id.ab_settings);
885         mSettings.setOnClickListener(mOnClickDrawerActionBarListener);
886         mClearHistory = (ButtonItem) findViewById(R.id.ab_clear_history);
887         mClearHistory.setOnClickListener(mOnClickDrawerActionBarListener);
888
889         // Restore the last tab pressed
890         Integer lastTab = Preferences.getSharedPreferences().getInt(
891                 FileManagerSettings.USER_PREF_LAST_DRAWER_TAB.getId(),
892                 (Integer) FileManagerSettings.USER_PREF_LAST_DRAWER_TAB
893                         .getDefaultValue());
894         mOnClickDrawerTabListener.onClick(lastTab == 0 ? mBookmarksTab : mHistoryTab);
895
896         // Set the navigation drawer "hamburger" icon
897         mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
898                 R.drawable.ic_material_light_navigation_drawer,
899                 R.string.drawer_open, R.string.drawer_close) {
900
901             /** Called when a drawer has settled in a completely closed state. */
902             public void onDrawerClosed(View view) {
903                 super.onDrawerClosed(view);
904             }
905
906             /** Called when a drawer has settled in a completely open state. */
907             public void onDrawerOpened(View drawerView) {
908                 onDrawerLayoutOpened(drawerView);
909                 super.onDrawerOpened(drawerView);
910             }
911         };
912         getActionBar().setDisplayHomeAsUpEnabled(true);
913
914         // Set the drawer toggle as the DrawerListener
915         mDrawerLayout.setDrawerListener(mDrawerToggle);
916     }
917
918     /***
919      * Method that do something when the DrawerLayout opened.
920      */
921     private void onDrawerLayoutOpened(View drawerView){
922         if (mSearchView != null && mSearchView.getVisibility() == View.VISIBLE) {
923             closeSearch();
924             hideSoftInput(drawerView);
925         }
926     }
927
928     /**
929      * Method that hide the software when the software showing.
930      *
931      * */
932     private void hideSoftInput(View view){
933         if (mImm != null) {
934             mImm.hideSoftInputFromWindow(view.getWindowToken(), 0);
935         }
936     }
937
938     /**
939      * Method that adds a history entry to the history list in the drawer
940      */
941     private void addHistoryToDrawer(int index, HistoryNavigable navigable) {
942         // hide empty message
943         mDrawerHistoryEmpty.setVisibility(View.GONE);
944
945         Theme theme = ThemeManager.getCurrentTheme(this);
946         IconHolder iconholder = new IconHolder(this, false);
947
948         // inflate single bookmark layout item and fill it
949         LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
950                 R.layout.history_item, null);
951
952         ImageView iconView = (ImageView) view
953                 .findViewById(R.id.history_item_icon);
954         TextView name = (TextView) view.findViewById(R.id.history_item_name);
955         TextView directory = (TextView) view
956                 .findViewById(R.id.history_item_directory);
957
958         Drawable icon = iconholder.getDrawable("ic_fso_folder_drawable"); //$NON-NLS-1$
959         if (navigable instanceof SearchInfoParcelable) {
960             icon = iconholder.getDrawable("ic_history_search_drawable"); //$NON-NLS-1$
961         }
962         iconView.setImageDrawable(icon);
963
964         String title = navigable.getTitle();
965         if (title == null || title.trim().length() == 0) {
966             title = getString(R.string.root_directory_name);
967         }
968
969         name.setText(title);
970         directory.setText(navigable.getDescription());
971
972         theme.setTextColor(this, name, "text_color");
973         theme.setTextColor(this, directory, "text_color");
974
975         // handle item click
976         view.setOnClickListener(new OnClickListener() {
977             @Override
978             public void onClick(View v) {
979                 final int index = mDrawerHistory.indexOfChild(v);
980                 final int count = mDrawerHistory.getChildCount();
981                 final History history = mHistory.get(count - index - 1);
982
983                 navigateToHistory(history);
984                 mDrawerLayout.closeDrawer(Gravity.START);
985             }
986         });
987
988         // add as first child
989         mDrawerHistory.addView(view, 0);
990
991         // Show clear button if history tab is selected
992         mClearHistory.setVisibility(mHistoryTab.isSelected() ? View.VISIBLE : View.GONE);
993     }
994
995     /**
996      * Method takes a bookmark as argument and adds it to mBookmarks and the
997      * list in the drawer
998      */
999     public void addBookmark(Bookmark bookmark) {
1000         mBookmarks.add(bookmark);
1001         addBookmarkToDrawer(bookmark);
1002     }
1003
1004     /**
1005      * Show the easy mode view
1006      */
1007     private void performShowEasyMode() {
1008         mEasyModeListView.setVisibility(View.VISIBLE);
1009         getCurrentNavigationView().setVisibility(View.GONE);
1010         performShowBackArrow(false);
1011     }
1012
1013     /**
1014      * Hide the easy mode view
1015      */
1016     private void performHideEasyMode() {
1017         mEasyModeListView.setVisibility(View.GONE);
1018         getCurrentNavigationView().setVisibility(View.VISIBLE);
1019     }
1020
1021     private void performShowBackArrow(boolean showBackArrow) {
1022         if (mNeedsEasyMode) {
1023             mDrawerToggle.setDrawerIndicatorEnabled(!showBackArrow);
1024         }
1025     }
1026
1027     private boolean isEasyModeVisible() {
1028         return mEasyModeListView.getVisibility() != View.GONE;
1029     }
1030
1031     /**
1032      * Method takes a bookmark as argument and adds it to the bookmark list in
1033      * the drawer
1034      */
1035     private void addBookmarkToDrawer(Bookmark bookmark) {
1036         Theme theme = ThemeManager.getCurrentTheme(this);
1037         IconHolder iconholder = new IconHolder(this, false);
1038
1039         // inflate single bookmark layout item and fill it
1040         LinearLayout view = (LinearLayout) getLayoutInflater().inflate(
1041                 R.layout.bookmarks_item, null);
1042
1043         ImageView icon = (ImageView) view
1044                 .findViewById(R.id.bookmarks_item_icon);
1045         TextView name = (TextView) view.findViewById(R.id.bookmarks_item_name);
1046         TextView path = (TextView) view.findViewById(R.id.bookmarks_item_path);
1047         ImageButton actionButton = (ImageButton) view
1048                 .findViewById(R.id.bookmarks_item_action);
1049
1050         name.setText(bookmark.mName);
1051         path.setText(bookmark.mPath);
1052
1053         theme.setTextColor(this, name, "text_color");
1054         theme.setTextColor(this, path, "text_color");
1055
1056         icon.setImageDrawable(iconholder.getDrawable(BookmarksHelper
1057                 .getIcon(bookmark)));
1058
1059         Drawable action = null;
1060         String actionCd = null;
1061         if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1062             action = iconholder.getDrawable("ic_edit_home_bookmark_drawable"); //$NON-NLS-1$
1063             actionCd = getApplicationContext().getString(
1064                     R.string.bookmarks_button_config_cd);
1065         }
1066         else if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1067             action = iconholder.getDrawable("ic_close_drawable"); //$NON-NLS-1$
1068             actionCd = getApplicationContext().getString(
1069                     R.string.bookmarks_button_remove_bookmark_cd);
1070         }
1071
1072         actionButton.setImageDrawable(action);
1073         actionButton.setVisibility(action != null ? View.VISIBLE : View.GONE);
1074         actionButton.setOnClickListener(new OnClickListener() {
1075             @Override
1076             public void onClick(View view) {
1077                 final View v = (View) view.getParent();
1078                 final int index = mDrawerBookmarks.indexOfChild(v);
1079                 final Bookmark bookmark = mBookmarks.get(index);
1080
1081                 // Configure home
1082                 if (bookmark.mType.compareTo(BOOKMARK_TYPE.HOME) == 0) {
1083                     // Show a dialog for configure initial directory
1084                     InitialDirectoryDialog dialog = new InitialDirectoryDialog(
1085                             NavigationActivity.this);
1086                     dialog.setOnValueChangedListener(new InitialDirectoryDialog.OnValueChangedListener() {
1087                         @Override
1088                         public void onValueChanged(String newInitialDir) {
1089                             bookmark.mPath = newInitialDir;
1090
1091                             // reset drawer bookmarks list
1092                             initBookmarks();
1093                         }
1094                     });
1095                     dialog.show();
1096                     return;
1097                 }
1098
1099                 // Remove bookmark
1100                 if (bookmark.mType.compareTo(BOOKMARK_TYPE.USER_DEFINED) == 0) {
1101                     boolean result = Bookmarks.removeBookmark(
1102                             getApplicationContext(), bookmark);
1103                     if (!result) { // Show warning
1104                         DialogHelper.showToast(getApplicationContext(),
1105                                 R.string.msgs_operation_failure,
1106                                 Toast.LENGTH_SHORT);
1107                         return;
1108                     }
1109                     mBookmarks.remove(bookmark);
1110                     mDrawerBookmarks.removeView(v);
1111                     return;
1112                 }
1113             }
1114         });
1115         actionButton.setContentDescription(actionCd);
1116
1117         // handle item click
1118         view.setOnClickListener(new OnClickListener() {
1119             @Override
1120             public void onClick(View v) {
1121                 final int index = mDrawerBookmarks.indexOfChild(v);
1122                 final Bookmark bookmark = mBookmarks.get(index);
1123
1124                 boolean showEasyMode = (mSdBookmarks.contains(bookmark)) &&
1125                         getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1126
1127                 // try to navigate to the bookmark path
1128                 try {
1129                     FileSystemObject fso = CommandHelper.getFileInfo(
1130                             getApplicationContext(), bookmark.mPath, null);
1131                     if (fso != null) {
1132                         if (showEasyMode) {
1133                             performShowEasyMode();
1134                         } else {
1135                             performHideEasyMode();
1136                         }
1137                         performShowBackArrow(!mDrawerToggle.isDrawerIndicatorEnabled());
1138                         getCurrentNavigationView().open(fso);
1139                         mDrawerLayout.closeDrawer(Gravity.START);
1140                     }
1141                     else {
1142                         // The bookmark does not exist, delete the user-defined
1143                         // bookmark
1144                         try {
1145                             Bookmarks.removeBookmark(getApplicationContext(),
1146                                     bookmark);
1147
1148                             // reset bookmarks list to default
1149                             initBookmarks();
1150                         }
1151                         catch (Exception ex) {
1152                         }
1153                     }
1154                 }
1155                 catch (Exception e) { // Capture the exception
1156                     ExceptionUtil
1157                             .translateException(NavigationActivity.this, e);
1158                     if (e instanceof NoSuchFileOrDirectory
1159                             || e instanceof FileNotFoundException) {
1160                         // The bookmark does not exist, delete the user-defined
1161                         // bookmark
1162                         try {
1163                             Bookmarks.removeBookmark(getApplicationContext(),
1164                                     bookmark);
1165
1166                             // reset bookmarks list to default
1167                             initBookmarks();
1168                         }
1169                         catch (Exception ex) {
1170                         }
1171                     }
1172                     return;
1173                 }
1174             }
1175         });
1176
1177         mDrawerBookmarks.addView(view);
1178     }
1179
1180     /**
1181      * Method that initializes the bookmarks.
1182      */
1183     private synchronized void initBookmarks() {
1184         if (mBookmarksTask != null &&
1185                 !mBookmarksTask.getStatus().equals(AsyncTask.Status.FINISHED)) {
1186             return;
1187         }
1188
1189         // Retrieve the loading view
1190         final View waiting = findViewById(R.id.bookmarks_loading);
1191
1192         // Load bookmarks in background
1193         mBookmarksTask = new AsyncTask<Void, Void, Boolean>() {
1194             Exception mCause;
1195
1196             @Override
1197             protected Boolean doInBackground(Void... params) {
1198                 try {
1199                     mBookmarks = loadBookmarks();
1200                     return Boolean.TRUE;
1201
1202                 }
1203                 catch (Exception e) {
1204                     this.mCause = e;
1205                     return Boolean.FALSE;
1206                 }
1207             }
1208
1209             @Override
1210             protected void onPreExecute() {
1211                 waiting.setVisibility(View.VISIBLE);
1212                 mDrawerBookmarks.removeAllViews();
1213             }
1214
1215             @Override
1216             protected void onPostExecute(Boolean result) {
1217                 waiting.setVisibility(View.GONE);
1218                 if (result.booleanValue()) {
1219                     for (Bookmark bookmark : mBookmarks) {
1220                         addBookmarkToDrawer(bookmark);
1221                     }
1222                 }
1223                 else {
1224                     if (this.mCause != null) {
1225                         ExceptionUtil.translateException(
1226                                 NavigationActivity.this, this.mCause);
1227                     }
1228                 }
1229                 mBookmarksTask = null;
1230             }
1231
1232             @Override
1233             protected void onCancelled() {
1234                 waiting.setVisibility(View.GONE);
1235                 mBookmarksTask = null;
1236             }
1237         };
1238         mBookmarksTask.execute();
1239     }
1240
1241     /**
1242      * Method that loads all kind of bookmarks and join in an array to be used
1243      * in the listview adapter.
1244      *
1245      * @return List<Bookmark>
1246      * @hide
1247      */
1248     List<Bookmark> loadBookmarks() {
1249         // Bookmarks = HOME + FILESYSTEM + SD STORAGES + USER DEFINED
1250         // In ChRooted mode = SD STORAGES + USER DEFINED (from SD STORAGES)
1251         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1252         if (!this.mChRooted) {
1253             bookmarks.add(loadHomeBookmarks());
1254             bookmarks.addAll(loadFilesystemBookmarks());
1255         }
1256         mSdBookmarks = loadSdStorageBookmarks();
1257         bookmarks.addAll(mSdBookmarks);
1258         bookmarks.addAll(loadVirtualBookmarks());
1259         bookmarks.addAll(loadUserBookmarks());
1260         return bookmarks;
1261     }
1262
1263     /**
1264      * Method that loads the home bookmark from the user preference.
1265      *
1266      * @return Bookmark The bookmark loaded
1267      */
1268     private Bookmark loadHomeBookmarks() {
1269         String initialDir = Preferences.getSharedPreferences().getString(
1270                 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1271                 (String) FileManagerSettings.SETTINGS_INITIAL_DIR
1272                         .getDefaultValue());
1273         return new Bookmark(BOOKMARK_TYPE.HOME,
1274                 getString(R.string.bookmarks_home), initialDir);
1275     }
1276
1277     /**
1278      * Method that loads the filesystem bookmarks from the internal xml file.
1279      * (defined by this application)
1280      *
1281      * @return List<Bookmark> The bookmarks loaded
1282      */
1283     private List<Bookmark> loadFilesystemBookmarks() {
1284         try {
1285             // Initialize the bookmarks
1286             List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1287
1288             // Read the command list xml file
1289             XmlResourceParser parser = getResources().getXml(
1290                     R.xml.filesystem_bookmarks);
1291
1292             try {
1293                 // Find the root element
1294                 XmlUtils.beginDocument(parser, TAG_BOOKMARKS);
1295                 while (true) {
1296                     XmlUtils.nextElement(parser);
1297                     String element = parser.getName();
1298                     if (element == null) {
1299                         break;
1300                     }
1301
1302                     if (TAG_BOOKMARK.equals(element)) {
1303                         CharSequence name = null;
1304                         CharSequence directory = null;
1305
1306                         try {
1307                             name = getString(parser.getAttributeResourceValue(
1308                                     R.styleable.Bookmark_name, 0));
1309                         }
1310                         catch (Exception e) {
1311                             /** NON BLOCK **/
1312                         }
1313                         try {
1314                             directory = getString(parser
1315                                     .getAttributeResourceValue(
1316                                             R.styleable.Bookmark_directory, 0));
1317                         }
1318                         catch (Exception e) {
1319                             /** NON BLOCK **/
1320                         }
1321                         if (directory == null) {
1322                             directory = parser
1323                                     .getAttributeValue(R.styleable.Bookmark_directory);
1324                         }
1325                         if (name != null && directory != null) {
1326                             bookmarks.add(new Bookmark(
1327                                     BOOKMARK_TYPE.FILESYSTEM, name.toString(),
1328                                     directory.toString()));
1329                         }
1330                     }
1331                 }
1332
1333                 // Return the bookmarks
1334                 return bookmarks;
1335
1336             }
1337             finally {
1338                 parser.close();
1339             }
1340         }
1341         catch (Throwable ex) {
1342             Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1343         }
1344
1345         // No data
1346         return new ArrayList<Bookmark>();
1347     }
1348
1349     /**
1350      * Method that loads the secure digital card storage bookmarks from the
1351      * system.
1352      *
1353      * @return List<Bookmark> The bookmarks loaded
1354      */
1355     private List<Bookmark> loadSdStorageBookmarks() {
1356         // Initialize the bookmarks
1357         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1358
1359         try {
1360             // Recovery sdcards from storage manager
1361             StorageVolume[] volumes = StorageHelper
1362                     .getStorageVolumes(getApplication(), true);
1363             for (StorageVolume volume: volumes) {
1364                 if (volume != null) {
1365                     String mountedState = volume.getState();
1366                     String path = volume.getPath();
1367                     if (!Environment.MEDIA_MOUNTED.equalsIgnoreCase(mountedState) &&
1368                             !Environment.MEDIA_MOUNTED_READ_ONLY.equalsIgnoreCase(mountedState)) {
1369                         Log.w(TAG, "Ignoring '" + path + "' with state of '"+ mountedState + "'");
1370                         continue;
1371                     }
1372                     if (!TextUtils.isEmpty(path)) {
1373                         String lowerPath = path.toLowerCase(Locale.ROOT);
1374                         Bookmark bookmark;
1375                         if (lowerPath.contains(STR_USB)) {
1376                             bookmark = new Bookmark(BOOKMARK_TYPE.USB, StorageHelper
1377                                     .getStorageVolumeDescription(getApplication(), volume), path);
1378                         } else {
1379                             bookmark = new Bookmark(BOOKMARK_TYPE.SDCARD, StorageHelper
1380                                     .getStorageVolumeDescription(getApplication(), volume), path);
1381                         }
1382                         bookmarks.add(bookmark);
1383                     }
1384                 }
1385             }
1386
1387             // Return the bookmarks
1388             return bookmarks;
1389         }
1390         catch (Throwable ex) {
1391             Log.e(TAG, "Load filesystem bookmarks failed", ex); //$NON-NLS-1$
1392         }
1393
1394         // No data
1395         return new ArrayList<Bookmark>();
1396     }
1397
1398     /**
1399      * Method that loads all virtual mount points.
1400      *
1401      * @return List<Bookmark> The bookmarks loaded
1402      */
1403     private List<Bookmark> loadVirtualBookmarks() {
1404         // Initialize the bookmarks
1405         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1406         List<MountPoint> mps = VirtualMountPointConsole.getVirtualMountPoints();
1407         for (MountPoint mp : mps) {
1408             BOOKMARK_TYPE type = null;
1409             String name = null;
1410             if (mp.isSecure()) {
1411                 type = BOOKMARK_TYPE.SECURE;
1412                 name = getString(R.string.bookmarks_secure);
1413             } else if (mp.isRemote()) {
1414                 type = BOOKMARK_TYPE.REMOTE;
1415                 name = getString(R.string.bookmarks_remote);
1416             } else {
1417                 continue;
1418             }
1419             bookmarks.add(new Bookmark(type, name, mp.getMountPoint()));
1420         }
1421         return bookmarks;
1422     }
1423
1424     /**
1425      * Method that loads the user bookmarks (added by the user).
1426      *
1427      * @return List<Bookmark> The bookmarks loaded
1428      */
1429     private List<Bookmark> loadUserBookmarks() {
1430         List<Bookmark> bookmarks = new ArrayList<Bookmark>();
1431         Cursor cursor = Bookmarks.getAllBookmarks(this.getContentResolver());
1432         try {
1433             if (cursor != null && cursor.moveToFirst()) {
1434                 do {
1435                     Bookmark bm = new Bookmark(cursor);
1436                     if (this.mChRooted
1437                             && !StorageHelper.isPathInStorageVolume(bm.mPath)) {
1438                         continue;
1439                     }
1440                     bookmarks.add(bm);
1441                 }
1442                 while (cursor.moveToNext());
1443             }
1444         }
1445         finally {
1446             try {
1447                 if (cursor != null) {
1448                     cursor.close();
1449                 }
1450             }
1451             catch (Exception e) {
1452                 /** NON BLOCK **/
1453             }
1454         }
1455
1456         // Remove bookmarks from virtual storage if the filesystem is not mount
1457         int c = bookmarks.size() - 1;
1458         for (int i = c; i >= 0; i--) {
1459             VirtualMountPointConsole vc =
1460                     VirtualMountPointConsole.getVirtualConsoleForPath(bookmarks.get(i).mPath);
1461             if (vc != null && !vc.isMounted()) {
1462                 bookmarks.remove(i);
1463             }
1464         }
1465
1466         return bookmarks;
1467     }
1468
1469     /**
1470      * Method that initializes the navigation views of the activity
1471      */
1472     private void initNavigationViews() {
1473         //Get the navigation views (wishlist: multiple view; for now only one view)
1474         this.mNavigationViews = new NavigationView[1];
1475         this.mCurrentNavigationView = 0;
1476         //- 0
1477         this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
1478         this.mNavigationViews[0].setId(0);
1479         this.mEasyModeListView = (ListView) findViewById(R.id.lv_easy_mode);
1480         mEasyModeAdapter = new ArrayAdapter<MimeTypeCategory>(this, R.layout
1481                 .navigation_view_simple_item) {
1482             @Override
1483             public View getView(int position, View convertView, ViewGroup parent) {
1484                 convertView = (convertView == null) ?getLayoutInflater().inflate(R.layout
1485                         .navigation_view_simple_item, parent, false) : convertView;
1486                 MimeTypeCategory item = getItem(position);
1487                 String typeTitle = MIME_TYPE_LOCALIZED_NAMES[item.ordinal()];
1488                 TextView typeTitleTV = (TextView) convertView
1489                         .findViewById(R.id.navigation_view_item_name);
1490                 ImageView typeIconIV = (ImageView) convertView
1491                         .findViewById(R.id.navigation_view_item_icon);
1492                 View checkBoxView = convertView.findViewById(R.id.navigation_view_item_check);
1493                 checkBoxView.setVisibility(View.GONE);
1494                 typeTitleTV.setText(typeTitle);
1495                 typeIconIV.setImageDrawable(EASY_MODE_ICONS.get(item));
1496                 convertView.setOnClickListener(mEasyModeItemClickListener);
1497                 convertView.setTag(position);
1498                 return convertView;
1499             }
1500         };
1501         mEasyModeAdapter.addAll(EASY_MODE_LIST);
1502         mEasyModeListView.setAdapter(mEasyModeAdapter);
1503     }
1504
1505     private void onClicked(int position) {
1506         Intent intent = new Intent(this, SearchActivity.class);
1507         intent.setAction(Intent.ACTION_SEARCH);
1508         intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
1509                 getCurrentNavigationView().getCurrentDir());
1510         intent.putExtra(SearchManager.QUERY, "*"); // Use wild-card '*'
1511
1512         if (position == 0) {
1513             // the user has selected all items, they want to see their folders so let's do that.
1514             performHideEasyMode();
1515             performShowBackArrow(true);
1516             return;
1517
1518         } else {
1519             ArrayList<MimeTypeCategory> searchCategories = new ArrayList<MimeTypeCategory>();
1520             MimeTypeCategory selectedCategory = EASY_MODE_LIST.get(position);
1521             searchCategories.add(selectedCategory);
1522             // a one off case where we implicitly want to also search for TEXT mimetypes when the
1523             // DOCUMENTS category is selected
1524             if (selectedCategory == MimeTypeCategory.DOCUMENT) {
1525                 searchCategories.add(MimeTypeCategory.TEXT);
1526             }
1527             intent.putExtra(SearchActivity.EXTRA_SEARCH_MIMETYPE, searchCategories);
1528         }
1529
1530         startActivity(intent);
1531     }
1532
1533     /**
1534      * Method that initialize the console
1535      * @hide
1536      */
1537     void initConsole() {
1538         //Create the default console (from the preferences)
1539         try {
1540             Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
1541             if (console == null) {
1542                 throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
1543             }
1544         } catch (Throwable ex) {
1545             if (!NavigationActivity.this.mChRooted) {
1546                 //Show exception and exit
1547                 Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
1548                 // We don't have any console
1549                 // Show exception and exit
1550                 DialogHelper.showToast(
1551                         NavigationActivity.this,
1552                         R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1553                 exit();
1554                 return;
1555             }
1556
1557             // We are in a trouble (something is not allowing creating the console)
1558             // Ask the user to return to prompt or root access mode mode with a
1559             // non-privileged console, prior to make crash the application
1560             askOrExit();
1561             return;
1562         }
1563     }
1564
1565     /**
1566      * Method that initializes the navigation.
1567      *
1568      * @param viewId The navigation view identifier where apply the navigation
1569      * @param restore Initialize from a restore info
1570      * @param intent The current intent
1571      * @hide
1572      */
1573     void initNavigation(final int viewId, final boolean restore, final Intent intent) {
1574         final NavigationView navigationView = getNavigationView(viewId);
1575         this.mHandler.post(new Runnable() {
1576             @Override
1577             public void run() {
1578                 //Is necessary navigate?
1579                 if (!restore) {
1580                     applyInitialDir(navigationView, intent);
1581                 }
1582             }
1583         });
1584     }
1585
1586     /**
1587      * Method that applies the user-defined initial directory
1588      *
1589      * @param navigationView The navigation view
1590      * @param intent The current intent
1591      * @hide
1592      */
1593     void applyInitialDir(final NavigationView navigationView, final Intent intent) {
1594         //Load the user-defined initial directory
1595         String initialDir =
1596                 Preferences.getSharedPreferences().getString(
1597                     FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
1598                     (String)FileManagerSettings.
1599                         SETTINGS_INITIAL_DIR.getDefaultValue());
1600
1601         // Check if request navigation to directory (use as default), and
1602         // ensure chrooted and absolute path
1603         String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
1604         String intentAction = intent.getAction();
1605         if (navigateTo != null && navigateTo.length() > 0) {
1606             initialDir = navigateTo;
1607         } else if (intentAction != null && intentAction.equals(Intent.ACTION_VIEW)) {
1608             Uri data = intent.getData();
1609             if (data != null && (FileHelper.FILE_URI_SCHEME.equals(data.getScheme())
1610                     || FileHelper.FOLDER_URI_SCHEME.equals(data.getScheme())
1611                     || FileHelper.DIRECTORY_URI_SCHEME.equals(data.getScheme()))) {
1612                 File path = new File(data.getPath());
1613                 if (path.isDirectory()) {
1614                     initialDir = path.getAbsolutePath();
1615                 }
1616             }
1617         }
1618
1619         // Add to history
1620         final boolean addToHistory = intent.getBooleanExtra(EXTRA_ADD_TO_HISTORY, true);
1621
1622         // We cannot navigate to a secure console if it is unmounted. So go to root in that case
1623         VirtualConsole vc = VirtualMountPointConsole.getVirtualConsoleForPath(initialDir);
1624         if (vc != null && vc instanceof SecureConsole && !((SecureConsole) vc).isMounted()) {
1625             initialDir = FileHelper.ROOT_DIRECTORY;
1626         }
1627
1628         if (this.mChRooted) {
1629             // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
1630             if (!StorageHelper.isPathInStorageVolume(initialDir)) {
1631                 StorageVolume[] volumes =
1632                         StorageHelper.getStorageVolumes(this, false);
1633                 if (volumes != null && volumes.length > 0) {
1634                     initialDir = volumes[0].getPath();
1635                     int count = volumes.length;
1636                     for (int i = 0; i < count; i++) {
1637                         StorageVolume volume = volumes[i];
1638                         if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(volume.getState())) {
1639                             initialDir = volume.getPath();
1640                             break;
1641                         }
1642                     }
1643                     //Ensure that initial directory is an absolute directory
1644                     initialDir = FileHelper.getAbsPath(initialDir);
1645                 } else {
1646                     // Show exception and exit
1647                     DialogHelper.showToast(
1648                             this,
1649                             R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1650                     exit();
1651                     return;
1652                 }
1653             }
1654         } else {
1655             //Ensure that initial directory is an absolute directory
1656             final String userInitialDir = initialDir;
1657             initialDir = FileHelper.getAbsPath(initialDir);
1658             final String absInitialDir = initialDir;
1659             File f = new File(initialDir);
1660             boolean exists = f.exists();
1661             if (!exists) {
1662                 // Fix for /data/media/0. Libcore doesn't detect it correctly.
1663                 try {
1664                     exists = CommandHelper.getFileInfo(this, initialDir, false, null) != null;
1665                 } catch (InsufficientPermissionsException ipex) {
1666                     ExceptionUtil.translateException(
1667                             this, ipex, false, true, new OnRelaunchCommandResult() {
1668                         @Override
1669                         public void onSuccess() {
1670                             navigationView.changeCurrentDir(absInitialDir, addToHistory);
1671                         }
1672                         @Override
1673                         public void onFailed(Throwable cause) {
1674                             showInitialInvalidDirectoryMsg(userInitialDir);
1675                             navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1676                                     addToHistory);
1677                         }
1678                         @Override
1679                         public void onCancelled() {
1680                             showInitialInvalidDirectoryMsg(userInitialDir);
1681                             navigationView.changeCurrentDir(FileHelper.ROOT_DIRECTORY,
1682                                     addToHistory);
1683                         }
1684                     });
1685
1686                     // Asynchronous mode
1687                     return;
1688                 } catch (Exception ex) {
1689                     // We are not interested in other exceptions
1690                     ExceptionUtil.translateException(this, ex, true, false);
1691                 }
1692
1693                 // Check again the initial directory
1694                 if (!exists) {
1695                     showInitialInvalidDirectoryMsg(userInitialDir);
1696                     initialDir = FileHelper.ROOT_DIRECTORY;
1697                 }
1698
1699                 // Weird, but we have a valid initial directory
1700             }
1701         }
1702
1703         boolean needsEasyMode = false;
1704         if (mSdBookmarks != null ) {
1705             for (Bookmark bookmark :mSdBookmarks) {
1706                 if (bookmark.mPath.equalsIgnoreCase(initialDir)) {
1707                     needsEasyMode = true;
1708                     break;
1709                 }
1710             }
1711         }
1712
1713         mNeedsEasyMode = getResources().getBoolean(R.bool.cmcc_show_easy_mode);
1714
1715         needsEasyMode = needsEasyMode && mNeedsEasyMode;
1716         if (needsEasyMode) {
1717             performShowEasyMode();
1718         } else {
1719             performHideEasyMode();
1720         }
1721         // Change the current directory to the user-defined initial directory
1722         navigationView.changeCurrentDir(initialDir, addToHistory);
1723     }
1724
1725     /**
1726      * Displays a message reporting invalid directory
1727      *
1728      * @param initialDir The initial directory
1729      * @hide
1730      */
1731     void showInitialInvalidDirectoryMsg(String initialDir) {
1732         // Change to root directory
1733         DialogHelper.showToast(
1734                 this,
1735                 getString(
1736                         R.string.msgs_settings_invalid_initial_directory,
1737                         initialDir),
1738                 Toast.LENGTH_SHORT);
1739     }
1740
1741     /**
1742      * Method that verifies the intent passed to the activity, and checks
1743      * if a request is made like Search.
1744      *
1745      * @param intent The intent to check
1746      * @hide
1747      */
1748     void checkIntent(Intent intent) {
1749         //Search action
1750         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
1751             Intent searchIntent = new Intent(this, SearchActivity.class);
1752             searchIntent.setAction(Intent.ACTION_SEARCH);
1753             //- SearchActivity.EXTRA_SEARCH_DIRECTORY
1754             searchIntent.putExtra(
1755                     SearchActivity.EXTRA_SEARCH_DIRECTORY,
1756                     getCurrentNavigationView().getCurrentDir());
1757             //- SearchManager.APP_DATA
1758             if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
1759                 Bundle bundle = new Bundle();
1760                 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
1761                 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
1762             }
1763             //-- SearchManager.QUERY
1764             String query = intent.getStringExtra(SearchManager.QUERY);
1765             if (query != null) {
1766                 searchIntent.putExtra(SearchManager.QUERY, query);
1767             }
1768             //- android.speech.RecognizerIntent.EXTRA_RESULTS
1769             ArrayList<String> extraResults =
1770                     intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
1771             if (extraResults != null) {
1772                 searchIntent.putStringArrayListExtra(
1773                         android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
1774             }
1775             startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1776             return;
1777         }
1778     }
1779
1780     /**
1781      * {@inheritDoc}
1782      */
1783     @Override
1784     public boolean onKeyUp(int keyCode, KeyEvent event) {
1785         if (keyCode == KeyEvent.KEYCODE_MENU) {
1786             if (mDrawerLayout.isDrawerOpen(mDrawer)) {
1787                 mDrawerLayout.closeDrawer(Gravity.START);
1788             } else {
1789                 mDrawerLayout.openDrawer(Gravity.START);
1790             }
1791             return true;
1792         }
1793         return super.onKeyUp(keyCode, event);
1794     }
1795
1796     @Override
1797     public void onBackPressed() {
1798         if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
1799             mDrawerLayout.closeDrawer(Gravity.START);
1800             return;
1801         }
1802         if (checkBackAction()) {
1803             performHideEasyMode();
1804             return;
1805         } else {
1806             if (mNeedsEasyMode && !isEasyModeVisible()) {
1807                 performShowEasyMode();
1808                 return;
1809             }
1810         }
1811
1812         // An exit event has occurred, force the destroy the consoles
1813         exit();
1814     }
1815
1816     /**
1817      * Method invoked when an action item is clicked.
1818      *
1819      * @param view The button pushed
1820      */
1821     public void onActionBarItemClick(View view) {
1822         switch (view.getId()) {
1823             //######################
1824             //Navigation Custom Title
1825             //######################
1826             case R.id.ab_configuration:
1827                 //Show navigation view configuration toolbar
1828                 getCurrentNavigationView().getCustomTitle().showConfigurationView();
1829                 break;
1830             case R.id.ab_close:
1831                 //Hide navigation view configuration toolbar
1832                 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
1833                 break;
1834
1835             //######################
1836             //Breadcrumb Actions
1837             //######################
1838             case R.id.ab_filesystem_info:
1839                 //Show information of the filesystem
1840                 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
1841                 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
1842                 showMountPointInfo(mp, du);
1843                 break;
1844
1845             //######################
1846             //Navigation view options
1847             //######################
1848             case R.id.ab_sort_mode:
1849                 showSettingsPopUp(view,
1850                         Arrays.asList(
1851                                 new FileManagerSettings[]{
1852                                         FileManagerSettings.SETTINGS_SORT_MODE}));
1853                 break;
1854             case R.id.ab_layout_mode:
1855                 showSettingsPopUp(view,
1856                         Arrays.asList(
1857                                 new FileManagerSettings[]{
1858                                         FileManagerSettings.SETTINGS_LAYOUT_MODE}));
1859                 break;
1860             case R.id.ab_view_options:
1861                 // If we are in ChRooted mode, then don't show non-secure items
1862                 if (this.mChRooted) {
1863                     showSettingsPopUp(view,
1864                             Arrays.asList(new FileManagerSettings[]{
1865                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
1866                 } else {
1867                     showSettingsPopUp(view,
1868                             Arrays.asList(new FileManagerSettings[]{
1869                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
1870                                     FileManagerSettings.SETTINGS_SHOW_HIDDEN,
1871                                     FileManagerSettings.SETTINGS_SHOW_SYSTEM,
1872                                     FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
1873                 }
1874
1875                 break;
1876
1877             //######################
1878             //Selection Actions
1879             //######################
1880             case R.id.ab_selection_done:
1881                 //Show information of the filesystem
1882                 getCurrentNavigationView().onDeselectAll();
1883                 break;
1884
1885             //######################
1886             //Action Bar buttons
1887             //######################
1888             case R.id.ab_actions:
1889                 openActionsDialog(getCurrentNavigationView().getCurrentDir(),
1890                         true);
1891                 break;
1892
1893             case R.id.ab_search:
1894
1895                 openSearch();
1896                 break;
1897
1898             default:
1899                 break;
1900         }
1901     }
1902
1903     /**
1904      * {@inheritDoc}
1905      */
1906     @Override
1907     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
1908         if (requestCode == INTENT_REQUEST_SETTINGS) {
1909             // reset bookmarks list to default as the user could changed the
1910             // root mode which changes the system bookmarks
1911             initBookmarks();
1912             return;
1913         }
1914
1915         if (data != null) {
1916             switch (requestCode) {
1917                 case INTENT_REQUEST_SEARCH:
1918                     if (resultCode == RESULT_OK) {
1919                         //Change directory?
1920                         Bundle bundle = data.getExtras();
1921                         if (bundle != null) {
1922                             FileSystemObject fso = (FileSystemObject) bundle.getSerializable(
1923                                     EXTRA_SEARCH_ENTRY_SELECTION);
1924                             SearchInfoParcelable searchInfo =
1925                                     bundle.getParcelable(EXTRA_SEARCH_LAST_SEARCH_DATA);
1926                             if (fso != null) {
1927                                 //Goto to new directory
1928                                 getCurrentNavigationView().open(fso, searchInfo);
1929                                 performHideEasyMode();
1930                             }
1931                         }
1932                     } else if (resultCode == RESULT_CANCELED) {
1933                         SearchInfoParcelable searchInfo =
1934                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
1935                         if (searchInfo != null && searchInfo.isSuccessNavigation()) {
1936                             //Navigate to previous history
1937                             back();
1938                         } else {
1939                             // I don't know is the search view was changed, so try to do a refresh
1940                             // of the navigation view
1941                             getCurrentNavigationView().refresh(true);
1942                         }
1943                     }
1944                     // reset bookmarks list to default as the user could have set a
1945                     // new bookmark in the search activity
1946                     initBookmarks();
1947                     break;
1948
1949                 default:
1950                     break;
1951             }
1952         }
1953     }
1954
1955     /**
1956      * {@inheritDoc}
1957      */
1958     @Override
1959     public void onNewHistory(HistoryNavigable navigable) {
1960         addHistoryToDrawer(this.mHistory.size(), navigable);
1961         //Recollect information about current status
1962         History history = new History(this.mHistory.size(), navigable);
1963         this.mHistory.add(history);
1964     }
1965
1966     /**
1967      * {@inheritDoc}
1968      */
1969     @Override
1970     public void onCheckHistory() {
1971     }
1972
1973     /**
1974      * {@inheritDoc}
1975      */
1976     @Override
1977     public void onRequestRefresh(Object o, boolean clearSelection) {
1978         if (o instanceof FileSystemObject) {
1979             // Refresh only the item
1980             this.getCurrentNavigationView().refresh((FileSystemObject)o);
1981         } else if (o == null) {
1982             // Refresh all
1983             getCurrentNavigationView().refresh();
1984         }
1985         if (clearSelection) {
1986             this.getCurrentNavigationView().onDeselectAll();
1987         }
1988     }
1989
1990     /**
1991      * {@inheritDoc}
1992      */
1993     @Override
1994     public void onRequestBookmarksRefresh() {
1995         initBookmarks();
1996     }
1997
1998     /**
1999      * {@inheritDoc}
2000      */
2001     @Override
2002     public void onRequestRemove(Object o, boolean clearSelection) {
2003         if (o instanceof FileSystemObject) {
2004             // Remove from view
2005             this.getCurrentNavigationView().removeItem((FileSystemObject)o);
2006
2007             //Remove from history
2008             removeFromHistory((FileSystemObject)o);
2009         } else {
2010             onRequestRefresh(null, clearSelection);
2011         }
2012         if (clearSelection) {
2013             this.getCurrentNavigationView().onDeselectAll();
2014         }
2015     }
2016
2017     /**
2018      * {@inheritDoc}
2019      */
2020     @Override
2021     public void onNavigateTo(Object o) {
2022         // Ignored
2023     }
2024
2025     @Override
2026     public void onCancel(){
2027         // nop
2028     }
2029
2030     /**
2031      * {@inheritDoc}
2032      */
2033     @Override
2034     public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
2035         this.mSelectionBar.setSelection(selectedItems);
2036     }
2037
2038     /**
2039      * {@inheritDoc}
2040      */
2041     @Override
2042     public void onRequestMenu(NavigationView navView, FileSystemObject item) {
2043         // Show the actions dialog
2044         openActionsDialog(item, false);
2045     }
2046
2047     /**
2048      * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
2049      *
2050      * @param anchor The action button that was pressed
2051      * @param settings The array of settings associated with the action button
2052      */
2053     private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
2054         //Create the adapter
2055         final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
2056
2057         //Create a show the popup menu
2058         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
2059         popup.setOnItemClickListener(new OnItemClickListener() {
2060             @Override
2061             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
2062                 FileManagerSettings setting =
2063                         ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
2064                 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
2065                 popup.dismiss();
2066                 try {
2067                     if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
2068                         //Need to change the layout
2069                         getCurrentNavigationView().changeViewMode(
2070                                 NavigationLayoutMode.fromId(value));
2071                     } else {
2072                         //Save and refresh
2073                         if (setting.getDefaultValue() instanceof Enum<?>) {
2074                             //Enumeration
2075                             Preferences.savePreference(setting, new ObjectIdentifier() {
2076                                 @Override
2077                                 public int getId() {
2078                                     return value;
2079                                 }
2080                             }, false);
2081                         } else {
2082                             //Boolean
2083                             boolean newval =
2084                                     Preferences.getSharedPreferences().
2085                                         getBoolean(
2086                                             setting.getId(),
2087                                             ((Boolean)setting.getDefaultValue()).booleanValue());
2088                             Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
2089                         }
2090                         getCurrentNavigationView().refresh();
2091                     }
2092                 } catch (Exception e) {
2093                     Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
2094                     NavigationActivity.this.mHandler.post(new Runnable() {
2095                         @Override
2096                         public void run() {
2097                             DialogHelper.showToast(
2098                                     NavigationActivity.this,
2099                                     R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
2100                         }
2101                     });
2102
2103                 } finally {
2104                     adapter.dispose();
2105                     getCurrentNavigationView().getCustomTitle().restoreView();
2106                 }
2107
2108             }
2109         });
2110         popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
2111             @Override
2112             public void onDismiss() {
2113                 adapter.dispose();
2114             }
2115         });
2116         popup.show();
2117     }
2118
2119     /**
2120      * Method that show the information of a filesystem mount point.
2121      *
2122      * @param mp The mount point info
2123      * @param du The disk usage of the mount point
2124      */
2125     private void showMountPointInfo(MountPoint mp, DiskUsage du) {
2126         //Has mount point info?
2127         if (mp == null) {
2128             //There is no information
2129             AlertDialog alert =
2130                     DialogHelper.createWarningDialog(
2131                             this,
2132                             R.string.filesystem_info_warning_title,
2133                             R.string.filesystem_info_warning_msg);
2134             DialogHelper.delegateDialogShow(this, alert);
2135             return;
2136         }
2137
2138         //Show a the filesystem info dialog
2139         FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
2140         dialog.setOnMountListener(new OnMountListener() {
2141             @Override
2142             public void onRemount(MountPoint mountPoint) {
2143                 //Update the statistics of breadcrumb, only if mount point is the same
2144                 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
2145                 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
2146                     breadcrumb.updateMountPointInfo();
2147                 }
2148                 if (mountPoint.isSecure()) {
2149                     // Secure mountpoints only can be unmount, so we need to move the navigation
2150                     // to a secure storage (do not add to history)
2151                     Intent intent = new Intent();
2152                     intent.putExtra(EXTRA_ADD_TO_HISTORY, false);
2153                     initNavigation(NavigationActivity.this.mCurrentNavigationView, false, intent);
2154                 }
2155             }
2156         });
2157         dialog.show();
2158     }
2159
2160     /**
2161      * Method that checks the action that must be realized when the
2162      * back button is pushed.
2163      *
2164      * @return boolean Indicates if the action must be intercepted
2165      */
2166     private boolean checkBackAction() {
2167         // We need a basic structure to check this
2168         if (getCurrentNavigationView() == null) return false;
2169
2170         if (mSearchView.getVisibility() == View.VISIBLE) {
2171             closeSearch();
2172         }
2173
2174         //Check if the configuration view is showing. In this case back
2175         //action must be "close configuration"
2176         if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
2177             getCurrentNavigationView().getCustomTitle().restoreView();
2178             return true;
2179         }
2180
2181         //Do back operation over the navigation history
2182         boolean flag = this.mExitFlag;
2183
2184         this.mExitFlag = !back();
2185
2186         // Retrieve if the exit status timeout has expired
2187         long now = System.currentTimeMillis();
2188         boolean timeout = (this.mExitBackTimeout == -1 ||
2189                             (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
2190
2191         //Check if there no history and if the user was advised in the last back action
2192         if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
2193             //Communicate the user that the next time the application will be closed
2194             this.mExitBackTimeout = System.currentTimeMillis();
2195             DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
2196             if (mNeedsEasyMode) {
2197                 return isEasyModeVisible();
2198             } else {
2199                 return true;
2200             }
2201         }
2202
2203         //Back action not applied
2204         return !this.mExitFlag;
2205     }
2206
2207     @Override
2208     public void startActivity(Intent intent) {
2209         // check if search intent
2210         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
2211             intent.putExtra(SearchActivity.EXTRA_SEARCH_DIRECTORY,
2212                     getCurrentNavigationView().getCurrentDir());
2213         }
2214
2215         super.startActivity(intent);
2216     }
2217
2218     /**
2219      * Method that returns the history size.
2220      */
2221     private void clearHistory() {
2222         this.mHistory.clear();
2223         mDrawerHistory.removeAllViews();
2224         mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2225     }
2226
2227     /**
2228      * Method that navigates to the passed history reference.
2229      *
2230      * @param history The history reference
2231      * @return boolean A problem occurs while navigate
2232      */
2233     public synchronized boolean navigateToHistory(History history) {
2234         try {
2235             //Gets the history
2236             History realHistory = this.mHistory.get(history.getPosition());
2237
2238             //Navigate to item. Check what kind of history is
2239             if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
2240                 //Navigation
2241                 NavigationViewInfoParcelable info =
2242                         (NavigationViewInfoParcelable)realHistory.getItem();
2243                 int viewId = info.getId();
2244                 NavigationView view = getNavigationView(viewId);
2245                 // Selected items must not be restored from on history navigation
2246                 info.setSelectedFiles(view.getSelectedFiles());
2247                 if (!view.onRestoreState(info)) {
2248                     return true;
2249                 }
2250
2251             } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
2252                 //Search (open search with the search results)
2253                 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
2254                 Intent searchIntent = new Intent(this, SearchActivity.class);
2255                 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
2256                 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
2257                 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
2258             } else {
2259                 //The type is unknown
2260                 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
2261             }
2262
2263             //Remove the old history
2264             int cc = realHistory.getPosition();
2265             for (int i = this.mHistory.size() - 1; i >= cc; i--) {
2266                 this.mHistory.remove(i);
2267                 mDrawerHistory.removeViewAt(0);
2268             }
2269
2270             if (mDrawerHistory.getChildCount() == 0) {
2271                 mDrawerHistoryEmpty.setVisibility(View.VISIBLE);
2272             }
2273
2274             //Navigate
2275             boolean clearHistory = mHistoryTab.isSelected() && mHistory.size() > 0;
2276             mClearHistory.setVisibility(clearHistory ? View.VISIBLE : View.GONE);
2277             return true;
2278
2279         } catch (Throwable ex) {
2280             if (history != null) {
2281                 Log.e(TAG,
2282                         String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
2283                                 Integer.valueOf(history.getPosition()),
2284                                 history.getItem().getTitle()), ex);
2285             } else {
2286                 Log.e(TAG,
2287                         String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
2288             }
2289             this.mHandler.post(new Runnable() {
2290                 @Override
2291                 public void run() {
2292                     DialogHelper.showToast(
2293                             NavigationActivity.this,
2294                             R.string.msgs_history_unknown, Toast.LENGTH_LONG);
2295                 }
2296             });
2297
2298             //Not change directory
2299             return false;
2300         }
2301     }
2302
2303     /**
2304      * Method that request a back action over the navigation history.
2305      *
2306      * @return boolean If a back action was applied
2307      */
2308     public boolean back() {
2309         // Check that has valid history
2310         while (this.mHistory.size() > 0) {
2311             History h = this.mHistory.get(this.mHistory.size() - 1);
2312             if (h.getItem() instanceof NavigationViewInfoParcelable) {
2313                 // Verify that the path exists
2314                 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
2315
2316                 try {
2317                     FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
2318                     if (info != null) {
2319                         break;
2320                     }
2321                     this.mHistory.remove(this.mHistory.size() - 1);
2322                 } catch (Exception e) {
2323                     ExceptionUtil.translateException(this, e, true, false);
2324                     this.mHistory.remove(this.mHistory.size() - 1);
2325                 }
2326             } else {
2327                 break;
2328             }
2329         }
2330
2331         //Navigate to history
2332         if (this.mHistory.size() > 0) {
2333             return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
2334         }
2335
2336         //Nothing to apply
2337         mClearHistory.setVisibility(View.GONE);
2338         return false;
2339     }
2340
2341     /**
2342      * Method that opens the actions dialog
2343      *
2344      * @param item The path or the {@link FileSystemObject}
2345      * @param global If the menu to display is the one with global actions
2346      */
2347     private void openActionsDialog(Object item, boolean global) {
2348         // Resolve the full path
2349         String path = String.valueOf(item);
2350         if (item instanceof FileSystemObject) {
2351             path = ((FileSystemObject)item).getFullPath();
2352         }
2353
2354         // Prior to show the dialog, refresh the item reference
2355         FileSystemObject fso = null;
2356         try {
2357             fso = CommandHelper.getFileInfo(this, path, false, null);
2358             if (fso == null) {
2359                 throw new NoSuchFileOrDirectory(path);
2360             }
2361
2362         } catch (Exception e) {
2363             // Notify the user
2364             ExceptionUtil.translateException(this, e);
2365
2366             // Remove the object
2367             if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
2368                 // If have a FileSystemObject reference then there is no need to search
2369                 // the path (less resources used)
2370                 if (item instanceof FileSystemObject) {
2371                     getCurrentNavigationView().removeItem((FileSystemObject)item);
2372                 } else {
2373                     getCurrentNavigationView().removeItem((String)item);
2374                 }
2375             }
2376             return;
2377         }
2378
2379         // Show the dialog
2380         ActionsDialog dialog = new ActionsDialog(this, this, fso, global, false);
2381         dialog.setOnRequestRefreshListener(this);
2382         dialog.setOnSelectionListener(getCurrentNavigationView());
2383         dialog.show();
2384     }
2385
2386     /**
2387      * Method that opens the search view.
2388      *
2389      * @hide
2390      */
2391     void openSearch() {
2392         mSearchView.setVisibility(View.VISIBLE);
2393         mSearchView.onActionViewExpanded();
2394         mCustomTitleView.setVisibility(View.GONE);
2395     }
2396
2397     void closeSearch() {
2398         mSearchView.setVisibility(View.GONE);
2399         mSearchView.onActionViewCollapsed();
2400         mCustomTitleView.setVisibility(View.VISIBLE);
2401     }
2402
2403     /**
2404      * Method that opens the settings activity.
2405      *
2406      * @hide
2407      */
2408     void openSettings() {
2409         Intent settingsIntent = new Intent(NavigationActivity.this,
2410                 SettingsPreferences.class);
2411         startActivityForResult(settingsIntent, INTENT_REQUEST_SETTINGS);
2412     }
2413
2414     /**
2415      * Method that remove the {@link FileSystemObject} from the history
2416      */
2417     private void removeFromHistory(FileSystemObject fso) {
2418         if (this.mHistory != null) {
2419             int cc = this.mHistory.size() - 1;
2420             for (int i = cc; i >= 0 ; i--) {
2421                 History history = this.mHistory.get(i);
2422                 if (history.getItem() instanceof NavigationViewInfoParcelable) {
2423                     String p0 = fso.getFullPath();
2424                     String p1 = ((NavigationViewInfoParcelable) history.getItem()).getCurrentDir();
2425                     if (p0.compareTo(p1) == 0) {
2426                         this.mHistory.remove(i);
2427                         mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2428                         mDrawerHistoryEmpty.setVisibility(
2429                                 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2430                         updateHistoryPositions();
2431                     }
2432                 }
2433             }
2434         }
2435     }
2436
2437     /**
2438      * Update the history positions after one of the history is removed from drawer
2439      */
2440     private void updateHistoryPositions() {
2441         int cc = this.mHistory.size() - 1;
2442         for (int i = 0; i <= cc ; i++) {
2443             History history = this.mHistory.get(i);
2444             history.setPosition(i + 1);
2445         }
2446     }
2447
2448     /**
2449      * Method that ask the user to change the access mode prior to crash.
2450      * @hide
2451      */
2452     void askOrExit() {
2453         //Show a dialog asking the user
2454         AlertDialog dialog =
2455             DialogHelper.createYesNoDialog(
2456                 this,
2457                 R.string.msgs_change_to_prompt_access_mode_title,
2458                 R.string.msgs_change_to_prompt_access_mode_msg,
2459                 new DialogInterface.OnClickListener() {
2460                     @Override
2461                     public void onClick(DialogInterface alertDialog, int which) {
2462                         if (which == DialogInterface.BUTTON_NEGATIVE) {
2463                             // We don't have any console
2464                             // Show exception and exit
2465                             DialogHelper.showToast(
2466                                     NavigationActivity.this,
2467                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2468                             exit();
2469                             return;
2470                         }
2471
2472                         // Ok. Now try to change to prompt mode. Any crash
2473                         // here is a fatal error. We won't have any console to operate.
2474                         try {
2475                             // Change console
2476                             ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
2477
2478                             // Save preferences
2479                             Preferences.savePreference(
2480                                     FileManagerSettings.SETTINGS_ACCESS_MODE,
2481                                     AccessMode.PROMPT, true);
2482
2483                         } catch (Exception e) {
2484                             // Displays an exception and exit
2485                             Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
2486                             DialogHelper.showToast(
2487                                     NavigationActivity.this,
2488                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
2489                             exit();
2490                         }
2491                     }
2492                });
2493         DialogHelper.delegateDialogShow(this, dialog);
2494     }
2495
2496     /**
2497      * Method that creates a ChRooted environment, protecting the user to break anything in
2498      * the device
2499      * @hide
2500      */
2501     void createChRooted() {
2502         // If we are in a ChRooted mode, then do nothing
2503         if (this.mChRooted) return;
2504         this.mChRooted = true;
2505
2506         int cc = this.mNavigationViews.length;
2507         for (int i = 0; i < cc; i++) {
2508             this.mNavigationViews[i].createChRooted();
2509         }
2510
2511         // Remove the selection
2512         cc = this.mNavigationViews.length;
2513         for (int i = 0; i < cc; i++) {
2514             getCurrentNavigationView().onDeselectAll();
2515         }
2516
2517         // Remove the history (don't allow to access to previous data)
2518         clearHistory();
2519     }
2520
2521     /**
2522      * Method that exits from a ChRooted
2523      * @hide
2524      */
2525     void exitChRooted() {
2526         // If we aren't in a ChRooted mode, then do nothing
2527         if (!this.mChRooted) return;
2528         this.mChRooted = false;
2529
2530         int cc = this.mNavigationViews.length;
2531         for (int i = 0; i < cc; i++) {
2532             this.mNavigationViews[i].exitChRooted();
2533         }
2534     }
2535
2536     /**
2537      * Method called when a controlled exit is required
2538      * @hide
2539      */
2540     void exit() {
2541         // Recycle the navigation views
2542         int cc = this.mNavigationViews.length;
2543         for (int i = 0; i < cc; i++) {
2544             this.mNavigationViews[i].recycle();
2545         }
2546         try {
2547             FileManagerApplication.destroyBackgroundConsole();
2548         } catch (Throwable ex) {
2549             /**NON BLOCK**/
2550         }
2551         try {
2552             ConsoleBuilder.destroyConsole();
2553         } catch (Throwable ex) {
2554             /**NON BLOCK**/
2555         }
2556         finish();
2557     }
2558
2559     /**
2560      * Method that reconfigures the layout for better fit in portrait and landscape modes
2561      */
2562     private void onLayoutChanged() {
2563         Theme theme = ThemeManager.getCurrentTheme(this);
2564         boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2565
2566         // Apply only when the orientation was changed
2567         int orientation = getResources().getConfiguration().orientation;
2568         if (this.mOrientation == orientation) return;
2569         this.mOrientation = orientation;
2570
2571         // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2572         if (drawerOpen) {
2573             mDrawerLayout.closeDrawer(Gravity.START);
2574         }
2575
2576         if (this.mOrientation == Configuration.ORIENTATION_LANDSCAPE) {
2577             // Landscape mode
2578             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2579             if (statusBar.getParent() != null) {
2580                 ViewGroup parent = (ViewGroup) statusBar.getParent();
2581                 parent.removeView(statusBar);
2582             }
2583
2584             // Calculate the action button size (all the buttons must fit in the title bar)
2585             int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
2586             int abw = this.mActionBar.getChildCount() * bw;
2587             int rbw = 0;
2588             int cc = statusBar.getChildCount();
2589             for (int i = 0; i < cc; i++) {
2590                 View child = statusBar.getChildAt(i);
2591                 if (child instanceof ButtonItem) {
2592                     rbw += bw;
2593                 }
2594             }
2595             // Currently there isn't overflow menu
2596             int w = abw + rbw - bw;
2597
2598             // Add to the new location
2599             ViewGroup newParent = (ViewGroup)findViewById(R.id.navigation_title_landscape_holder);
2600             LinearLayout.LayoutParams params =
2601                     new LinearLayout.LayoutParams(
2602                             w,
2603                             ViewGroup.LayoutParams.MATCH_PARENT);
2604             statusBar.setLayoutParams(params);
2605             newParent.addView(statusBar);
2606
2607             // Apply theme
2608             theme.setBackgroundDrawable(this, statusBar, "titlebar_drawable"); //$NON-NLS-1$
2609
2610             // Hide holder
2611             View holder = findViewById(R.id.navigation_statusbar_portrait_holder);
2612             holder.setVisibility(View.GONE);
2613
2614         } else {
2615             // Portrait mode
2616             ViewGroup statusBar = (ViewGroup)findViewById(R.id.navigation_statusbar);
2617             if (statusBar.getParent() != null) {
2618                 ViewGroup parent = (ViewGroup) statusBar.getParent();
2619                 parent.removeView(statusBar);
2620             }
2621
2622             // Add to the new location
2623             ViewGroup newParent = (ViewGroup)findViewById(
2624                     R.id.navigation_statusbar_portrait_holder);
2625             LinearLayout.LayoutParams params =
2626                     new LinearLayout.LayoutParams(
2627                             ViewGroup.LayoutParams.MATCH_PARENT,
2628                             ViewGroup.LayoutParams.MATCH_PARENT);
2629             statusBar.setLayoutParams(params);
2630             newParent.addView(statusBar);
2631
2632             // Apply theme
2633             theme.setBackgroundDrawable(this, statusBar, "statusbar_drawable"); //$NON-NLS-1$
2634
2635             // Show holder
2636             newParent.setVisibility(View.VISIBLE);
2637         }
2638
2639         // if drawer was open, imitate reopening
2640         if (drawerOpen) {
2641             mDrawerToggle.onDrawerOpened(mDrawer);
2642         }
2643     }
2644
2645     /**
2646      * Method that removes all the history items that refers to virtual unmounted filesystems
2647      */
2648     private void removeUnmountedHistory() {
2649         int cc = mHistory.size() - 1;
2650         for (int i = cc; i >= 0; i--) {
2651             History history = mHistory.get(i);
2652             if (history.getItem() instanceof NavigationViewInfoParcelable) {
2653                 NavigationViewInfoParcelable navigableInfo =
2654                         ((NavigationViewInfoParcelable) history.getItem());
2655                 VirtualMountPointConsole vc =
2656                         VirtualMountPointConsole.getVirtualConsoleForPath(
2657                                 navigableInfo.getCurrentDir());
2658                 if (vc != null && !vc.isMounted()) {
2659                     mHistory.remove(i);
2660                     mDrawerHistory.removeViewAt(mDrawerHistory.getChildCount() - i - 1);
2661                 }
2662             }
2663         }
2664         mDrawerHistoryEmpty.setVisibility(
2665                 mDrawerHistory.getChildCount() == 0 ? View.VISIBLE : View.GONE);
2666         updateHistoryPositions();
2667     }
2668
2669     /**
2670      * Method that removes all the selection items that refers to virtual unmounted filesystems
2671      */
2672     private void removeUnmountedSelection() {
2673         for (NavigationView view : mNavigationViews) {
2674             view.removeUnmountedSelection();
2675         }
2676         mSelectionBar.setSelection(getNavigationView(mCurrentNavigationView).getSelectedFiles());
2677     }
2678
2679     /**
2680      * Method that applies the current theme to the activity
2681      * @hide
2682      */
2683     void applyTheme() {
2684         int orientation = getResources().getConfiguration().orientation;
2685         Theme theme = ThemeManager.getCurrentTheme(this);
2686         theme.setBaseThemeNoActionBar(this);
2687         applyTabTheme();
2688
2689         // imitate a closed drawer while layout is rebuilt to avoid NullPointerException
2690         boolean drawerOpen = mDrawerLayout.isDrawerOpen(Gravity.START);
2691         if (drawerOpen) {
2692             mDrawerLayout.closeDrawer(Gravity.START);
2693         }
2694
2695         //- Layout
2696         View v = findViewById(R.id.navigation_layout);
2697         theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2698
2699         //- ActionBar
2700         theme.setTitlebarDrawable(this, getActionBar(), "titlebar_drawable"); //$NON-NLS-1$
2701
2702         // Hackery to theme search view
2703         mSearchView = (SearchView) findViewById(R.id.navigation_search_bar);
2704         int searchPlateId = mSearchView.getContext().getResources()
2705                 .getIdentifier("android:id/search_plate", null, null);
2706         View searchPlate = mSearchView.findViewById(searchPlateId);
2707         if (searchPlate != null) {
2708             int searchTextId = searchPlate.getContext().getResources()
2709                     .getIdentifier("android:id/search_src_text", null, null);
2710             TextView searchText = (TextView) searchPlate.findViewById(searchTextId);
2711             if (searchText != null) {
2712                 searchText.setTextColor(Color.WHITE);
2713                 searchText.setHintTextColor(Color.WHITE);
2714             }
2715
2716             int magId = getResources().getIdentifier("android:id/search_mag_icon", null, null);
2717             ImageView magImage = (ImageView) mSearchView.findViewById(magId);
2718             if (magImage != null) {
2719                 magImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
2720             }
2721         }
2722
2723         SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
2724         mSearchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
2725         mSearchView.setIconifiedByDefault(false);
2726
2727         mCustomTitleView = (NavigationCustomTitleView) findViewById(R.id.navigation_title_flipper);
2728         mCustomTitleView.setVisibility(View.VISIBLE);
2729
2730         //- StatusBar
2731         v = findViewById(R.id.navigation_statusbar);
2732         if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
2733             theme.setBackgroundDrawable(this, v, "titlebar_drawable"); //$NON-NLS-1$
2734         } else {
2735             theme.setBackgroundDrawable(this, v, "statusbar_drawable"); //$NON-NLS-1$
2736         }
2737         v = findViewById(R.id.ab_overflow);
2738         theme.setImageDrawable(this, (ImageView)v, "ab_overflow_drawable"); //$NON-NLS-1$
2739         v = findViewById(R.id.ab_actions);
2740         theme.setImageDrawable(this, (ImageView)v, "ab_actions_drawable"); //$NON-NLS-1$
2741         v = findViewById(R.id.ab_search);
2742         theme.setImageDrawable(this, (ImageView)v, "ab_search_drawable"); //$NON-NLS-1$
2743
2744         //- Expanders
2745         v = findViewById(R.id.ab_configuration);
2746         theme.setImageDrawable(this, (ImageView)v, "expander_open_drawable"); //$NON-NLS-1$
2747         v = findViewById(R.id.ab_close);
2748         theme.setImageDrawable(this, (ImageView)v, "expander_close_drawable"); //$NON-NLS-1$
2749         v = findViewById(R.id.ab_sort_mode);
2750         theme.setImageDrawable(this, (ImageView)v, "ab_sort_mode_drawable"); //$NON-NLS-1$
2751         v = findViewById(R.id.ab_layout_mode);
2752         theme.setImageDrawable(this, (ImageView)v, "ab_layout_mode_drawable"); //$NON-NLS-1$
2753         v = findViewById(R.id.ab_view_options);
2754         theme.setImageDrawable(this, (ImageView)v, "ab_view_options_drawable"); //$NON-NLS-1$
2755
2756         //- SelectionBar
2757         v = findViewById(R.id.navigation_selectionbar);
2758         theme.setBackgroundDrawable(this, v, "selectionbar_drawable"); //$NON-NLS-1$
2759         v = findViewById(R.id.ab_selection_done);
2760         theme.setImageDrawable(this, (ImageView)v, "ab_selection_done_drawable"); //$NON-NLS-1$
2761         v = findViewById(R.id.navigation_status_selection_label);
2762         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2763
2764         // - Navigation drawer
2765         v = findViewById(R.id.history_empty);
2766         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2767
2768         for (int i=0; i<mDrawerHistory.getChildCount(); i++) {
2769             View item = mDrawerHistory.getChildAt(i);
2770
2771             v = item.findViewById(R.id.history_item_name);
2772             theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2773             v = item.findViewById(R.id.history_item_directory);
2774             theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2775         }
2776
2777         //- NavigationView
2778         int cc = this.mNavigationViews.length;
2779         for (int i = 0; i < cc; i++) {
2780             getNavigationView(i).applyTheme();
2781         }
2782
2783         // if drawer was open, imitate reopening
2784         if (drawerOpen) {
2785             mDrawerToggle.onDrawerOpened(mDrawer);
2786         }
2787     }
2788
2789     /**
2790      * Method that applies the current theme to the tab host
2791      */
2792     private void applyTabTheme() {
2793         // Apply the theme
2794         Theme theme = ThemeManager.getCurrentTheme(this);
2795
2796         View v = findViewById(R.id.drawer);
2797         theme.setBackgroundDrawable(this, v, "background_drawable"); //$NON-NLS-1$
2798
2799         v = findViewById(R.id.drawer_bookmarks_tab);
2800         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2801         v = findViewById(R.id.drawer_history_tab);
2802         theme.setTextColor(this, (TextView)v, "text_color"); //$NON-NLS-1$
2803
2804         v = findViewById(R.id.ab_settings);
2805         theme.setImageDrawable(this, (ButtonItem) v, "ab_settings_drawable"); //$NON-NLS-1$
2806         v = findViewById(R.id.ab_clear_history);
2807         theme.setImageDrawable(this, (ButtonItem) v, "ab_delete_drawable"); //$NON-NLS-1$
2808     }
2809
2810     public void updateActiveDialog(Dialog dialog) {
2811         mActiveDialog = dialog;
2812     }
2813 }