OSDN Git Service

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