OSDN Git Service

The overflow menu should not show as an icon on devices with a physical
[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.ActionBar;
20 import android.app.Activity;
21 import android.app.AlertDialog;
22 import android.app.SearchManager;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.content.pm.ActivityInfo;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.os.Parcelable;
32 import android.os.storage.StorageVolume;
33 import android.util.Log;
34 import android.view.KeyEvent;
35 import android.view.Menu;
36 import android.view.MenuItem;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.widget.AdapterView;
40 import android.widget.AdapterView.OnItemClickListener;
41 import android.widget.ListPopupWindow;
42 import android.widget.PopupWindow;
43 import android.widget.Toast;
44
45 import com.cyanogenmod.filemanager.FileManagerApplication;
46 import com.cyanogenmod.filemanager.R;
47 import com.cyanogenmod.filemanager.activities.preferences.SettingsPreferences;
48 import com.cyanogenmod.filemanager.adapters.HighlightedSimpleMenuListAdapter;
49 import com.cyanogenmod.filemanager.adapters.MenuSettingsAdapter;
50 import com.cyanogenmod.filemanager.adapters.SimpleMenuListAdapter;
51 import com.cyanogenmod.filemanager.console.Console;
52 import com.cyanogenmod.filemanager.console.ConsoleAllocException;
53 import com.cyanogenmod.filemanager.console.ConsoleBuilder;
54 import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
55 import com.cyanogenmod.filemanager.listeners.OnHistoryListener;
56 import com.cyanogenmod.filemanager.listeners.OnRequestRefreshListener;
57 import com.cyanogenmod.filemanager.model.DiskUsage;
58 import com.cyanogenmod.filemanager.model.FileSystemObject;
59 import com.cyanogenmod.filemanager.model.History;
60 import com.cyanogenmod.filemanager.model.MountPoint;
61 import com.cyanogenmod.filemanager.parcelables.HistoryNavigable;
62 import com.cyanogenmod.filemanager.parcelables.NavigationViewInfoParcelable;
63 import com.cyanogenmod.filemanager.parcelables.SearchInfoParcelable;
64 import com.cyanogenmod.filemanager.preferences.FileManagerSettings;
65 import com.cyanogenmod.filemanager.preferences.NavigationLayoutMode;
66 import com.cyanogenmod.filemanager.preferences.ObjectIdentifier;
67 import com.cyanogenmod.filemanager.preferences.Preferences;
68 import com.cyanogenmod.filemanager.ui.dialogs.ActionsDialog;
69 import com.cyanogenmod.filemanager.ui.dialogs.ChooseConsoleDialog;
70 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog;
71 import com.cyanogenmod.filemanager.ui.dialogs.FilesystemInfoDialog.OnMountListener;
72 import com.cyanogenmod.filemanager.ui.widgets.Breadcrumb;
73 import com.cyanogenmod.filemanager.ui.widgets.NavigationCustomTitleView;
74 import com.cyanogenmod.filemanager.ui.widgets.NavigationView;
75 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationRequestMenuListener;
76 import com.cyanogenmod.filemanager.ui.widgets.NavigationView.OnNavigationSelectionChangedListener;
77 import com.cyanogenmod.filemanager.ui.widgets.SelectionView;
78 import com.cyanogenmod.filemanager.util.AndroidHelper;
79 import com.cyanogenmod.filemanager.util.CommandHelper;
80 import com.cyanogenmod.filemanager.util.DialogHelper;
81 import com.cyanogenmod.filemanager.util.ExceptionUtil;
82 import com.cyanogenmod.filemanager.util.FileHelper;
83 import com.cyanogenmod.filemanager.util.StorageHelper;
84
85 import java.io.FileNotFoundException;
86 import java.io.Serializable;
87 import java.util.ArrayList;
88 import java.util.Arrays;
89 import java.util.List;
90
91 /**
92  * The main navigation activity. This activity is the center of the application.
93  * From this the user can navigate, search, make actions.<br/>
94  * This activity is singleTop, so when it is displayed no other activities exists in
95  * the stack.<br/>
96  * This cause an issue with the saved instance of this class, because if another activity
97  * is displayed, and the process is killed, NavigationActivity is started and the saved
98  * instance gets corrupted.<br/>
99  * For this reason the methods {link {@link Activity#onSaveInstanceState(Bundle)} and
100  * {@link Activity#onRestoreInstanceState(Bundle)} are not implemented, and every time
101  * the app is killed, is restarted from his initial state.
102  */
103 public class NavigationActivity extends Activity
104     implements OnHistoryListener, OnRequestRefreshListener,
105     OnNavigationRequestMenuListener, OnNavigationSelectionChangedListener {
106
107     private static final String TAG = "NavigationActivity"; //$NON-NLS-1$
108
109     private static boolean DEBUG = false;
110
111     /**
112      * Intent code for request a bookmark selection.
113      */
114     public static final int INTENT_REQUEST_BOOKMARK = 10001;
115
116     /**
117      * Intent code for request a history selection.
118      */
119     public static final int INTENT_REQUEST_HISTORY = 20001;
120
121     /**
122      * Intent code for request a search.
123      */
124     public static final int INTENT_REQUEST_SEARCH = 30001;
125
126
127     /**
128      * Constant for extra information about selected bookmark.
129      */
130     public static final String EXTRA_BOOKMARK_SELECTION =
131             "extra_bookmark_selection"; //$NON-NLS-1$
132
133     /**
134      * Constant for extra information about selected history entry.
135      */
136     public static final String EXTRA_HISTORY_ENTRY_SELECTION =
137             "extra_history_entry_selection"; //$NON-NLS-1$
138
139     /**
140      * Constant for extra information about clear selection action.
141      */
142     public static final String EXTRA_HISTORY_CLEAR =
143             "extra_history_clear_history"; //$NON-NLS-1$
144
145     /**
146      * Constant for extra information about selected search entry.
147      */
148     public static final String EXTRA_SEARCH_ENTRY_SELECTION =
149             "extra_search_entry_selection"; //$NON-NLS-1$
150
151     /**
152      * Constant for extra information about last search data.
153      */
154     public static final String EXTRA_SEARCH_LAST_SEARCH_DATA =
155             "extra_search_last_search_data"; //$NON-NLS-1$
156
157     /**
158      * Constant for extra information for request a navigation to the passed path.
159      */
160     public static final String EXTRA_NAVIGATE_TO =
161             "extra_navigate_to"; //$NON-NLS-1$
162
163     // The timeout needed to reset the exit status for back button
164     // After this time user need to tap 2 times the back button to
165     // exit, and the toast is shown again after the first tap.
166     private static final int RELEASE_EXIT_CHECK_TIMEOUT = 3500;
167
168     private final BroadcastReceiver mOnSettingChangeReceiver = new BroadcastReceiver() {
169         @Override
170         public void onReceive(Context context, Intent intent) {
171             if (intent != null) {
172                 if (intent.getAction().compareTo(FileManagerSettings.INTENT_SETTING_CHANGED) == 0) {
173                     // The settings has changed
174                     String key = intent.getStringExtra(FileManagerSettings.EXTRA_SETTING_CHANGED_KEY);
175                     if (key != null) {
176                         // Disk usage warning level
177                         if (key.compareTo(FileManagerSettings.
178                                 SETTINGS_DISK_USAGE_WARNING_LEVEL.getId()) == 0) {
179     
180                             // Set the free disk space warning level of the breadcrumb widget
181                             Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
182                             String fds = Preferences.getSharedPreferences().getString(
183                                     FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
184                                     (String)FileManagerSettings.
185                                         SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
186                             breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
187                             breadcrumb.updateMountPointInfo();
188                             return;
189                         }
190     
191                         // Case sensitive sort
192                         if (key.compareTo(FileManagerSettings.
193                                 SETTINGS_CASE_SENSITIVE_SORT.getId()) == 0) {
194                             getCurrentNavigationView().refresh();
195                             return;
196                         }
197     
198                         // Advanced mode
199                         if (key.compareTo(FileManagerSettings.
200                                 SETTINGS_ADVANCE_MODE.getId()) == 0) {
201                             // Is it necessary to create or exit of the ChRooted?
202                             boolean chRooted = !FileManagerApplication.isAdvancedMode();
203                             if (chRooted != NavigationActivity.this.mChRooted) {
204                                 if (chRooted) {
205                                     createChRooted();
206                                 } else {
207                                     exitChRooted();
208                                 }
209                             }
210                         }
211                     }
212
213                 } else if (intent.getAction().compareTo(
214                         FileManagerSettings.INTENT_FILE_CHANGED) == 0) {
215                     // Retrieve the file that was changed
216                     String file =
217                             intent.getStringExtra(FileManagerSettings.EXTRA_FILE_CHANGED_KEY);
218                     try {
219                         FileSystemObject fso = CommandHelper.getFileInfo(context, file, null);
220                         if (fso != null) {
221                             getCurrentNavigationView().refresh(fso);
222                         }
223                     } catch (Exception e) {
224                         ExceptionUtil.translateException(context, e, true, false);
225                     }
226                 }
227             }
228         }
229     };
230
231     /**
232      * @hide
233      */
234     NavigationView[] mNavigationViews;
235     private List<History> mHistory;
236
237     private int mCurrentNavigationView;
238
239     private ViewGroup mActionBar;
240     private SelectionView mSelectionBar;
241
242     private boolean mExitFlag = false;
243     private long mExitBackTimeout = -1;
244
245     private View mOptionsAnchorView;
246
247     /**
248      * @hide
249      */
250     boolean mChRooted;
251
252     /**
253      * @hide
254      */
255     Handler mHandler;
256
257     /**
258      * {@inheritDoc}
259      */
260     @Override
261     protected void onCreate(Bundle state) {
262
263         if (DEBUG) {
264             Log.d(TAG, "NavigationActivity.onCreate"); //$NON-NLS-1$
265         }
266
267         // Register the broadcast receiver
268         IntentFilter filter = new IntentFilter();
269         filter.addAction(FileManagerSettings.INTENT_SETTING_CHANGED);
270         filter.addAction(FileManagerSettings.INTENT_FILE_CHANGED);
271         registerReceiver(this.mOnSettingChangeReceiver, filter);
272
273         //Request features
274         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
275
276         //Set the main layout of the activity
277         setContentView(R.layout.navigation);
278
279         // Show welcome message
280         showWelcomeMsg();
281
282         //Initialize activity
283         init();
284
285         //Navigation views
286         initNavigationViews();
287
288         //Initialize action bars
289         initTitleActionBar();
290         initStatusActionBar();
291         initSelectionBar();
292
293         this.mHandler = new Handler();
294         this.mHandler.post(new Runnable() {
295             @Override
296             public void run() {
297                 //Initialize navigation
298                 int cc = NavigationActivity.this.mNavigationViews.length;
299                 for (int i = 0; i < cc; i++) {
300                     initNavigation(i, false);
301                 }
302
303                 //Check the intent action
304                 checkIntent(getIntent());
305             }
306         });
307
308         //Save state
309         super.onCreate(state);
310     }
311
312     /**
313      * {@inheritDoc}
314      */
315     @Override
316     protected void onNewIntent(Intent intent) {
317         //Initialize navigation
318         initNavigation(this.mCurrentNavigationView, true);
319
320         //Check the intent action
321         checkIntent(intent);
322     }
323
324     /**
325      * {@inheritDoc}
326      */
327     @Override
328     protected void onDestroy() {
329         if (DEBUG) {
330             Log.d(TAG, "NavigationActivity.onDestroy"); //$NON-NLS-1$
331         }
332
333         // Unregister the receiver
334         try {
335             unregisterReceiver(this.mOnSettingChangeReceiver);
336         } catch (Throwable ex) {
337             /**NON BLOCK**/
338         }
339
340         //All destroy. Continue
341         super.onDestroy();
342     }
343
344     /**
345      * Method that returns the current navigation view.
346      *
347      * @return NavigationView The current navigation view
348      */
349     public NavigationView getCurrentNavigationView() {
350         return getNavigationView(this.mCurrentNavigationView);
351     }
352
353     /**
354      * Method that returns the current navigation view.
355      *
356      * @param viewId The view to return
357      * @return NavigationView The current navigation view
358      */
359     public NavigationView getNavigationView(int viewId) {
360         return this.mNavigationViews[viewId];
361     }
362
363     /**
364      * Method that initializes the activity.
365      */
366     private void init() {
367         this.mHistory = new ArrayList<History>();
368         this.mChRooted = !FileManagerApplication.isAdvancedMode();
369     }
370
371     /**
372      * Method that displays a welcome message the first time the user
373      * access the application
374      */
375     private void showWelcomeMsg() {
376         boolean firstUse = Preferences.getSharedPreferences().getBoolean(
377                 FileManagerSettings.SETTINGS_FIRST_USE.getId(),
378                 ((Boolean)FileManagerSettings.SETTINGS_FIRST_USE.getDefaultValue()).booleanValue());
379
380         //Display the welcome message?
381         if (firstUse) {
382             AlertDialog dialog = DialogHelper.createAlertDialog(
383                 this, R.drawable.ic_launcher, R.string.welcome_title, R.string.welcome_msg);
384             dialog.show();
385
386             // Don't display again this dialog
387             try {
388                 Preferences.savePreference(
389                         FileManagerSettings.SETTINGS_FIRST_USE, Boolean.FALSE, true);
390             } catch (Exception e) {/**NON BLOCK**/}
391         }
392     }
393
394     /**
395      * Method that initializes the titlebar of the activity.
396      */
397     private void initTitleActionBar() {
398         //Inflate the view and associate breadcrumb
399         NavigationCustomTitleView title =
400                 (NavigationCustomTitleView)getLayoutInflater().inflate(
401                         R.layout.navigation_view_customtitle, null, false);
402         title.setOnHistoryListener(this);
403         Breadcrumb breadcrumb = (Breadcrumb)title.findViewById(R.id.breadcrumb_view);
404         int cc = this.mNavigationViews.length;
405         for (int i = 0; i < cc; i++) {
406             this.mNavigationViews[i].setBreadcrumb(breadcrumb);
407             this.mNavigationViews[i].setOnHistoryListener(this);
408             this.mNavigationViews[i].setOnNavigationSelectionChangedListener(this);
409             this.mNavigationViews[i].setOnNavigationOnRequestMenuListener(this);
410             this.mNavigationViews[i].setCustomTitle(title);
411         }
412
413         // Set the free disk space warning level of the breadcrumb widget
414         String fds = Preferences.getSharedPreferences().getString(
415                 FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getId(),
416                 (String)FileManagerSettings.SETTINGS_DISK_USAGE_WARNING_LEVEL.getDefaultValue());
417         breadcrumb.setFreeDiskSpaceWarningLevel(Integer.parseInt(fds));
418
419         //Configure the action bar options
420         getActionBar().setBackgroundDrawable(
421                 getResources().getDrawable(R.drawable.bg_holo_titlebar));
422         getActionBar().setDisplayOptions(
423                 ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
424         getActionBar().setCustomView(title);
425     }
426
427     /**
428      * Method that initializes the statusbar of the activity.
429      */
430     private void initStatusActionBar() {
431         //Performs a width calculation of buttons. Buttons exceeds the width
432         //of the action bar should be hidden
433         //This application not use android ActionBar because the application
434         //make uses of the title and bottom areas, and wants to force to show
435         //the overflow button (without care of physical buttons)
436         this.mActionBar = (ViewGroup)findViewById(R.id.navigation_actionbar);
437         this.mActionBar.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
438             @Override
439             public void onLayoutChange(
440                     View v, int left, int top, int right, int bottom, int oldLeft,
441                     int oldTop, int oldRight, int oldBottom) {
442                 //Get the width of the action bar
443                 int w = v.getMeasuredWidth();
444
445                 //Wake through children calculation his dimensions
446                 int bw = (int)getResources().getDimension(R.dimen.default_buttom_width);
447                 int cw = 0;
448                 final ViewGroup abView = ((ViewGroup)v);
449                 int cc = abView.getChildCount();
450                 for (int i = 0; i < cc; i++) {
451                     View child = abView.getChildAt(i);
452                     child.setVisibility(cw + bw > w ? View.INVISIBLE : View.VISIBLE);
453                     cw += bw;
454                 }
455             }
456         });
457
458         // Have overflow menu?
459         View overflow = findViewById(R.id.ab_overflow);
460         boolean showOptionsMenu = AndroidHelper.showOptionsMenu(getApplicationContext());
461         overflow.setVisibility(showOptionsMenu ? View.VISIBLE : View.GONE);
462         this.mOptionsAnchorView = showOptionsMenu ? overflow : this.mActionBar;
463     }
464
465     /**
466      * Method that initializes the selectionbar of the activity.
467      */
468     private void initSelectionBar() {
469         this.mSelectionBar = (SelectionView)findViewById(R.id.navigation_selectionbar);
470     }
471
472     /**
473      * Method that initializes the navigation views of the activity
474      */
475     private void initNavigationViews() {
476         //Get the navigation views (wishlist: multiple view; for now only one view)
477         this.mNavigationViews = new NavigationView[1];
478         this.mCurrentNavigationView = 0;
479         //- 0
480         this.mNavigationViews[0] = (NavigationView)findViewById(R.id.navigation_view);
481         this.mNavigationViews[0].setId(0);
482     }
483
484     /**
485      * Method that initializes the navigation.
486      *
487      * @param viewId The navigation view identifier where apply the navigation
488      * @param restore Initialize from a restore info
489      * @hide
490      */
491     void initNavigation(final int viewId, final boolean restore) {
492         final NavigationView navigationView = getNavigationView(viewId);
493         this.mHandler.post(new Runnable() {
494             @Override
495             public void run() {
496                 //Create the default console (from the preferences)
497                 try {
498                     Console console = ConsoleBuilder.getConsole(NavigationActivity.this);
499                     if (console == null) {
500                         throw new ConsoleAllocException("console == null"); //$NON-NLS-1$
501                     }
502                 } catch (Throwable ex) {
503                     if (!NavigationActivity.this.mChRooted) {
504                         //Show exception and exists
505                         Log.e(TAG, getString(R.string.msgs_cant_create_console), ex);
506                         // We don't have any console
507                         // Show exception and exists
508                         DialogHelper.showToast(
509                                 NavigationActivity.this,
510                                 R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
511                         exit();
512                         return;
513                     }
514
515                     // We are in a trouble (something is not allowing creating the console)
516                     // Ask the user to return to advanced console mode with a
517                     // non-privileged console, prior to make crash the application
518                     askOrExit();
519                     return;
520                 }
521
522                 //Is necessary navigate?
523                 if (!restore) {
524                     //Load the preference initial directory
525                     String initialDir =
526                             Preferences.getSharedPreferences().getString(
527                                 FileManagerSettings.SETTINGS_INITIAL_DIR.getId(),
528                                 (String)FileManagerSettings.SETTINGS_INITIAL_DIR.getDefaultValue());
529                     if (NavigationActivity.this.mChRooted) {
530                         // Initial directory is the first external sdcard (sdcard, emmc, usb, ...)
531                         StorageVolume[] volumes =
532                                 StorageHelper.getStorageVolumes(NavigationActivity.this);
533                         if (volumes != null && volumes.length > 0) {
534                             initialDir = volumes[0].getPath();
535                         }
536                     }
537
538                     //Ensure initial is an absolute directory
539                     try {
540                         initialDir =
541                                 CommandHelper.getAbsolutePath(
542                                         NavigationActivity.this, initialDir, null);
543                     } catch (Throwable e) {
544                         Log.e(TAG, "Resolve of initital directory fails", e); //$NON-NLS-1$
545                         String msg =
546                                 getString(
547                                         R.string.msgs_settings_invalid_initial_directory,
548                                         initialDir);
549                         DialogHelper.showToast(NavigationActivity.this, msg, Toast.LENGTH_SHORT);
550                         initialDir = FileHelper.ROOT_DIRECTORY;
551                     }
552
553                     // Change the current directory to the preference initial directory or the
554                     // request if exists
555                     String navigateTo = getIntent().getStringExtra(EXTRA_NAVIGATE_TO);
556                     if (navigateTo != null && navigateTo.length() > 0) {
557                         navigationView.changeCurrentDir(navigateTo);
558                     } else {
559                         navigationView.changeCurrentDir(initialDir);
560                     }
561                 }
562             }
563         });
564     }
565
566     /**
567      * Method that verifies the intent passed to the activity, and checks
568      * if a request is made like Search.
569      *
570      * @param intent The intent to check
571      * @hide
572      */
573     void checkIntent(Intent intent) {
574         //Search action
575         if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
576             Intent searchIntent = new Intent(this, SearchActivity.class);
577             searchIntent.setAction(Intent.ACTION_SEARCH);
578             //- SearchActivity.EXTRA_SEARCH_DIRECTORY
579             searchIntent.putExtra(
580                     SearchActivity.EXTRA_SEARCH_DIRECTORY,
581                     getCurrentNavigationView().getCurrentDir());
582             //- SearchManager.APP_DATA
583             if (intent.getBundleExtra(SearchManager.APP_DATA) != null) {
584                 Bundle bundle = new Bundle();
585                 bundle.putAll(intent.getBundleExtra(SearchManager.APP_DATA));
586                 searchIntent.putExtra(SearchManager.APP_DATA, bundle);
587             }
588             //-- SearchManager.QUERY
589             String query = intent.getStringExtra(SearchManager.QUERY);
590             if (query != null) {
591                 searchIntent.putExtra(SearchManager.QUERY, query);
592             }
593             //- android.speech.RecognizerIntent.EXTRA_RESULTS
594             ArrayList<String> extraResults =
595                     intent.getStringArrayListExtra(android.speech.RecognizerIntent.EXTRA_RESULTS);
596             if (extraResults != null) {
597                 searchIntent.putStringArrayListExtra(
598                         android.speech.RecognizerIntent.EXTRA_RESULTS, extraResults);
599             }
600             startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
601             return;
602         }
603
604         // Navigate to the requested path
605         String navigateTo = intent.getStringExtra(EXTRA_NAVIGATE_TO);
606         if (navigateTo != null && navigateTo.length() >= 0) {
607             getCurrentNavigationView().changeCurrentDir(navigateTo);
608         }
609     }
610
611
612     /**
613      * {@inheritDoc}
614      */
615     @Override
616     public boolean onKeyUp(int keyCode, KeyEvent event) {
617         if (keyCode == KeyEvent.KEYCODE_MENU) {
618             showOverflowPopUp(this.mOptionsAnchorView);
619             return true;
620         }
621         if (keyCode == KeyEvent.KEYCODE_BACK) {
622             if (checkBackAction()) {
623                 return true;
624             }
625         }
626         return super.onKeyUp(keyCode, event);
627     }
628
629     /**
630      * {@inheritDoc}
631      */
632     @Override
633     public boolean onOptionsItemSelected(MenuItem item) {
634        switch (item.getItemId()) {
635           case android.R.id.home:
636               if ((getActionBar().getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP)
637                       == ActionBar.DISPLAY_HOME_AS_UP) {
638                   checkBackAction();
639               }
640               return true;
641           default:
642              return super.onOptionsItemSelected(item);
643        }
644     }
645
646     /**
647      * Method invoked when an action item is clicked.
648      *
649      * @param view The button pushed
650      */
651     public void onActionBarItemClick(View view) {
652         switch (view.getId()) {
653             //######################
654             //Navigation Custom Title
655             //######################
656             case R.id.ab_configuration:
657                 //Show navigation view configuration toolbar
658                 getCurrentNavigationView().getCustomTitle().showConfigurationView();
659                 getActionBar().setDisplayHomeAsUpEnabled(true);
660                 getActionBar().setHomeButtonEnabled(true);
661                 break;
662             case R.id.ab_close:
663                 //Hide navigation view configuration toolbar
664                 getCurrentNavigationView().getCustomTitle().hideConfigurationView();
665                 break;
666
667             //######################
668             //Breadcrumb Actions
669             //######################
670             case R.id.ab_filesystem_info:
671                 //Show information of the filesystem
672                 MountPoint mp = getCurrentNavigationView().getBreadcrumb().getMountPointInfo();
673                 DiskUsage du = getCurrentNavigationView().getBreadcrumb().getDiskUsageInfo();
674                 showMountPointInfo(mp, du);
675                 break;
676
677             //######################
678             //Navigation view options
679             //######################
680             case R.id.ab_sort_mode:
681                 showSettingsPopUp(view,
682                         Arrays.asList(new FileManagerSettings[]{FileManagerSettings.SETTINGS_SORT_MODE}));
683                 break;
684             case R.id.ab_layout_mode:
685                 showSettingsPopUp(view,
686                         Arrays.asList(
687                                 new FileManagerSettings[]{FileManagerSettings.SETTINGS_LAYOUT_MODE}));
688                 break;
689             case R.id.ab_view_options:
690                 // If we are in ChRooted mode, then don't show non-secure items
691                 if (this.mChRooted) {
692                     showSettingsPopUp(view,
693                             Arrays.asList(new FileManagerSettings[]{
694                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST}));
695                 } else {
696                     showSettingsPopUp(view,
697                             Arrays.asList(new FileManagerSettings[]{
698                                     FileManagerSettings.SETTINGS_SHOW_DIRS_FIRST,
699                                     FileManagerSettings.SETTINGS_SHOW_HIDDEN,
700                                     FileManagerSettings.SETTINGS_SHOW_SYSTEM,
701                                     FileManagerSettings.SETTINGS_SHOW_SYMLINKS}));
702                 }
703
704                 break;
705
706             //######################
707             //Selection Actions
708             //######################
709             case R.id.ab_selection_done:
710                 //Show information of the filesystem
711                 getCurrentNavigationView().onDeselectAll();
712                 break;
713
714             //######################
715             //Action Bar buttons
716             //######################
717             case R.id.ab_actions:
718                 openActionsDialog(getCurrentNavigationView().getCurrentDir(), true);
719                 break;
720
721             case R.id.ab_bookmarks:
722                 openBookmarks();
723                 break;
724
725             case R.id.ab_history:
726                 openHistory();
727                 break;
728
729             case R.id.ab_search:
730                 openSearch();
731                 break;
732
733             case R.id.ab_overflow:
734                 showOverflowPopUp(view);
735                 break;
736
737             default:
738                 break;
739         }
740     }
741
742     /**
743      * {@inheritDoc}
744      */
745     @Override
746     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
747         if (data != null) {
748             switch (requestCode) {
749                 case INTENT_REQUEST_BOOKMARK:
750                     if (resultCode == RESULT_OK) {
751                         FileSystemObject fso =
752                                 (FileSystemObject)data.
753                                     getSerializableExtra(EXTRA_BOOKMARK_SELECTION);
754                         if (fso != null) {
755                             //Open the fso
756                             getCurrentNavigationView().open(fso);
757                         }
758                     }
759                     break;
760
761                 case INTENT_REQUEST_HISTORY:
762                     if (resultCode == RESULT_OK) {
763                         //Change current directory
764                         History history =
765                                 (History)data.getSerializableExtra(EXTRA_HISTORY_ENTRY_SELECTION);
766                         navigateToHistory(history);
767                     } else if (resultCode == RESULT_CANCELED) {
768                         boolean clear = data.getBooleanExtra(EXTRA_HISTORY_CLEAR, false);
769                         if (clear) {
770                             clearHistory();
771                         }
772                     }
773                     break;
774
775                 case INTENT_REQUEST_SEARCH:
776                     if (resultCode == RESULT_OK) {
777                         //Change directory?
778                         FileSystemObject fso =
779                                 (FileSystemObject)data.
780                                     getSerializableExtra(EXTRA_SEARCH_ENTRY_SELECTION);
781                         SearchInfoParcelable searchInfo =
782                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
783                         if (fso != null) {
784                             //Goto to new directory
785                             getCurrentNavigationView().open(fso, searchInfo);
786                         }
787                     } else if (resultCode == RESULT_CANCELED) {
788                         SearchInfoParcelable searchInfo =
789                                 data.getParcelableExtra(EXTRA_SEARCH_LAST_SEARCH_DATA);
790                         if (searchInfo != null && searchInfo.isSuccessNavigation()) {
791                             //Navigate to previous history
792                             back();
793                         } else {
794                             // I don't know is the search view was changed, so do a refresh
795                             // of the navigation view
796                             getCurrentNavigationView().refresh();
797                         }
798                     }
799                     break;
800
801                 default:
802                     break;
803             }
804         }
805     }
806
807     /**
808      * {@inheritDoc}
809      */
810     @Override
811     public void onNewHistory(HistoryNavigable navigable) {
812         //Recollect information about current status
813         History history = new History(this.mHistory.size(), navigable);
814         this.mHistory.add(history);
815         getActionBar().setDisplayHomeAsUpEnabled(true);
816         getActionBar().setHomeButtonEnabled(true);
817     }
818
819     /**
820      * {@inheritDoc}
821      */
822     @Override
823     public void onCheckHistory() {
824         //Need to show HomeUp Button
825         boolean enabled = this.mHistory != null && this.mHistory.size() > 0;
826         getActionBar().setDisplayHomeAsUpEnabled(enabled);
827         getActionBar().setHomeButtonEnabled(enabled);
828     }
829
830     /**
831      * {@inheritDoc}
832      */
833     @Override
834     public void onRequestRefresh(Object o) {
835         if (o instanceof FileSystemObject) {
836             // Refresh only the item
837             this.getCurrentNavigationView().refresh((FileSystemObject)o);
838         } else if (o == null) {
839             // Refresh all
840             getCurrentNavigationView().refresh();
841         }
842         this.getCurrentNavigationView().onDeselectAll();
843     }
844
845     /**
846      * {@inheritDoc}
847      */
848     @Override
849     public void onRequestRemove(Object o) {
850         if (o instanceof FileSystemObject) {
851             // Remove from view
852             this.getCurrentNavigationView().removeItem((FileSystemObject)o);
853
854             //Remove from history
855             removeFromHistory((FileSystemObject)o);
856         }
857         this.getCurrentNavigationView().onDeselectAll();
858     }
859
860     /**
861      * {@inheritDoc}
862      */
863     @Override
864     public void onNavigateTo(Object o) {
865         // Ignored
866     }
867
868     /**
869      * {@inheritDoc}
870      */
871     @Override
872     public void onSelectionChanged(NavigationView navView, List<FileSystemObject> selectedItems) {
873         this.mSelectionBar.setSelection(selectedItems);
874     }
875
876     /**
877      * {@inheritDoc}
878      */
879     @Override
880     public void onRequestMenu(NavigationView navView, FileSystemObject item) {
881         // Show the actions dialog
882         openActionsDialog(item, false);
883     }
884
885     /**
886      * Method that shows a popup with a menu associated a {@link FileManagerSettings}.
887      *
888      * @param anchor The action button that was pressed
889      * @param settings The array of settings associated with the action button
890      */
891     private void showSettingsPopUp(View anchor, List<FileManagerSettings> settings) {
892         //Create the adapter
893         final MenuSettingsAdapter adapter = new MenuSettingsAdapter(this, settings);
894
895         //Create a show the popup menu
896         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
897         popup.setOnItemClickListener(new OnItemClickListener() {
898             @Override
899             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
900                 FileManagerSettings setting =
901                         ((MenuSettingsAdapter)parent.getAdapter()).getSetting(position);
902                 final int value = ((MenuSettingsAdapter)parent.getAdapter()).getId(position);
903                 popup.dismiss();
904                 try {
905                     if (setting.compareTo(FileManagerSettings.SETTINGS_LAYOUT_MODE) == 0) {
906                         //Need to change the layout
907                         getCurrentNavigationView().changeViewMode(
908                                 NavigationLayoutMode.fromId(value));
909                     } else {
910                         //Save and refresh
911                         if (setting.getDefaultValue() instanceof Enum<?>) {
912                             //Enumeration
913                             Preferences.savePreference(setting, new ObjectIdentifier() {
914                                 @Override
915                                 public int getId() {
916                                     return value;
917                                 }
918                             }, false);
919                         } else {
920                             //Boolean
921                             boolean newval =
922                                     Preferences.getSharedPreferences().
923                                         getBoolean(
924                                             setting.getId(),
925                                             ((Boolean)setting.getDefaultValue()).booleanValue());
926                             Preferences.savePreference(setting, Boolean.valueOf(!newval), false);
927                         }
928                         getCurrentNavigationView().refresh();
929                     }
930                 } catch (Exception e) {
931                     Log.e(TAG, "Error applying navigation option", e); //$NON-NLS-1$
932                     NavigationActivity.this.mHandler.post(new Runnable() {
933                         @Override
934                         public void run() {
935                             DialogHelper.showToast(
936                                     NavigationActivity.this,
937                                     R.string.msgs_settings_save_failure, Toast.LENGTH_SHORT);
938                         }
939                     });
940
941                 } finally {
942                     adapter.dispose();
943                     getCurrentNavigationView().getCustomTitle().restoreView();
944                 }
945
946             }
947         });
948         popup.setOnDismissListener(new PopupWindow.OnDismissListener() {
949             @Override
950             public void onDismiss() {
951                 adapter.dispose();
952             }
953         });
954         popup.show();
955     }
956
957     /**
958      * Method that shows a popup with the activity main menu.
959      *
960      * @param anchor The action button that was pressed
961      */
962     private void showOverflowPopUp(View anchor) {
963         SimpleMenuListAdapter adapter =
964                 new HighlightedSimpleMenuListAdapter(this, R.menu.navigation);
965         Menu menu = adapter.getMenu();
966         int cc = this.mActionBar.getChildCount();
967         for (int i = 0, j = this.mActionBar.getChildCount() - 1; i < cc; i++, j--) {
968             View child = this.mActionBar.getChildAt(i);
969             boolean visible = child.getVisibility() == View.VISIBLE;
970             if (visible) {
971                 menu.removeItem(menu.getItem(j).getItemId());
972             }
973         }
974
975         // Check if console selection is allowed
976         if (this.mChRooted) {
977             menu.removeItem(R.id.mnu_console);
978         }
979
980         final ListPopupWindow popup = DialogHelper.createListPopupWindow(this, adapter, anchor);
981         popup.setOnItemClickListener(new OnItemClickListener() {
982             @Override
983             public void onItemClick(
984                     final AdapterView<?> parent, final View v, final int position, final long id) {
985
986                 final int itemId = (int)id;
987                 NavigationActivity.this.mHandler.post(new Runnable() {
988                     @Override
989                     public void run() {
990                         popup.dismiss();
991                         switch (itemId) {
992                             case R.id.mnu_settings:
993                                 //Settings
994                                 Intent settings = new Intent(
995                                         NavigationActivity.this, SettingsPreferences.class);
996                                 startActivity(settings);
997                                 break;
998
999                             case R.id.mnu_console:
1000                                 //Console
1001                                 ChooseConsoleDialog dialog =
1002                                     new ChooseConsoleDialog(NavigationActivity.this);
1003                                 dialog.show();
1004                                 break;
1005
1006                             case R.id.mnu_history:
1007                                 //History
1008                                 openHistory();
1009                                 popup.dismiss();
1010                                 break;
1011
1012                             case R.id.mnu_bookmarks:
1013                                 //Bookmarks
1014                                 openBookmarks();
1015                                 popup.dismiss();
1016                                 break;
1017
1018                             case R.id.mnu_search:
1019                                 //Search
1020                                 openSearch();
1021                                 popup.dismiss();
1022                                 break;
1023                             default:
1024                                 break;
1025                         }
1026                     }
1027                 });
1028             }
1029         });
1030         popup.show();
1031     }
1032
1033     /**
1034      * Method that show the information of a filesystem mount point.
1035      *
1036      * @param mp The mount point info
1037      * @param du The disk usage of the mount point
1038      */
1039     private void showMountPointInfo(MountPoint mp, DiskUsage du) {
1040         //Has mount point info?
1041         if (mp == null) {
1042             //There is no information
1043             AlertDialog alert =
1044                     DialogHelper.createWarningDialog(this, R.string.filesystem_info_warning_msg);
1045             alert.show();
1046             return;
1047         }
1048
1049         //Show a the filesystem info dialog
1050         FilesystemInfoDialog dialog = new FilesystemInfoDialog(this, mp, du);
1051         dialog.setOnMountListener(new OnMountListener() {
1052             @Override
1053             public void onRemount(MountPoint mountPoint) {
1054                 //Update the statistics of breadcrumb, only if mount point is the same
1055                 Breadcrumb breadcrumb = getCurrentNavigationView().getBreadcrumb();
1056                 if (breadcrumb.getMountPointInfo().compareTo(mountPoint) == 0) {
1057                     breadcrumb.updateMountPointInfo();
1058                 }
1059             }
1060         });
1061         dialog.show();
1062     }
1063
1064     /**
1065      * Method that checks the action that must be realized when the
1066      * back button is pushed.
1067      *
1068      * @return boolean Indicates if the action must be intercepted
1069      */
1070     private boolean checkBackAction() {
1071         //Check if the configuration view is showing. In this case back
1072         //action must be "close configuration"
1073         if (getCurrentNavigationView().getCustomTitle().isConfigurationViewShowing()) {
1074             getCurrentNavigationView().getCustomTitle().restoreView();
1075             return true;
1076         }
1077
1078         //Do back operation over the navigation history
1079         boolean flag = this.mExitFlag;
1080
1081         this.mExitFlag = !back();
1082
1083         // Retrieve if the exit status timeout has expired
1084         long now = System.currentTimeMillis();
1085         boolean timeout = (this.mExitBackTimeout == -1 ||
1086                             (now - this.mExitBackTimeout) > RELEASE_EXIT_CHECK_TIMEOUT);
1087
1088         //Check if there no history and if the user was advised in the last back action
1089         if (this.mExitFlag && (this.mExitFlag != flag || timeout)) {
1090             //Communicate the user that the next time the application will be closed
1091             this.mExitBackTimeout = System.currentTimeMillis();
1092             DialogHelper.showToast(this, R.string.msgs_push_again_to_exit, Toast.LENGTH_SHORT);
1093             return true;
1094         }
1095
1096         //Back action not applied
1097         return !this.mExitFlag;
1098     }
1099
1100     /**
1101      * {@inheritDoc}
1102      */
1103     @Override
1104     public boolean onSearchRequested() {
1105         Bundle bundle = new Bundle();
1106         bundle.putString(
1107                 SearchActivity.EXTRA_SEARCH_DIRECTORY,
1108                 getCurrentNavigationView().getCurrentDir());
1109         // TODO VoiceSearch icon is not shown. This must be a bug of CM. Verify with a test app.
1110         startSearch(Preferences.getLastSearch(), true, bundle, false);
1111         return true;
1112     }
1113
1114     /**
1115      * Method that returns the history size.
1116      */
1117     private void clearHistory() {
1118         this.mHistory.clear();
1119         onCheckHistory();
1120     }
1121
1122     /**
1123      * Method that navigates to the passed history reference.
1124      *
1125      * @param history The history reference
1126      * @return boolean A problem occurs while navigate
1127      */
1128     public boolean navigateToHistory(History history) {
1129         try {
1130             //Gets the history
1131             History realHistory = this.mHistory.get(history.getPosition());
1132
1133             //Navigate to item. Check what kind of history is
1134             if (realHistory.getItem() instanceof NavigationViewInfoParcelable) {
1135                 //Navigation
1136                 NavigationViewInfoParcelable info =
1137                         (NavigationViewInfoParcelable)realHistory.getItem();
1138                 int viewId = info.getId();
1139                 NavigationView view = getNavigationView(viewId);
1140                 view.onRestoreState(info);
1141
1142             } else if (realHistory.getItem() instanceof SearchInfoParcelable) {
1143                 //Search (open search with the search results)
1144                 SearchInfoParcelable info = (SearchInfoParcelable)realHistory.getItem();
1145                 Intent searchIntent = new Intent(this, SearchActivity.class);
1146                 searchIntent.setAction(SearchActivity.ACTION_RESTORE);
1147                 searchIntent.putExtra(SearchActivity.EXTRA_SEARCH_RESTORE, (Parcelable)info);
1148                 startActivityForResult(searchIntent, INTENT_REQUEST_SEARCH);
1149             } else {
1150                 //The type is unknown
1151                 throw new IllegalArgumentException("Unknown history type"); //$NON-NLS-1$
1152             }
1153
1154             //Remove the old history
1155             int cc = realHistory.getPosition();
1156             for (int i = this.mHistory.size() - 1; i >= cc; i--) {
1157                 this.mHistory.remove(i);
1158             }
1159             if (this.mHistory.size() == 0) {
1160                 getActionBar().setDisplayHomeAsUpEnabled(false);
1161                 getActionBar().setHomeButtonEnabled(false);
1162             }
1163
1164             //Navigate
1165             return true;
1166
1167         } catch (Throwable ex) {
1168             if (history != null) {
1169                 Log.e(TAG,
1170                         String.format("Failed to navigate to history %d: %s", //$NON-NLS-1$
1171                                 Integer.valueOf(history.getPosition()),
1172                                 history.getItem().getTitle()), ex);
1173             } else {
1174                 Log.e(TAG,
1175                         String.format("Failed to navigate to history: null", ex)); //$NON-NLS-1$
1176             }
1177             this.mHandler.post(new Runnable() {
1178                 @Override
1179                 public void run() {
1180                     DialogHelper.showToast(
1181                             NavigationActivity.this,
1182                             R.string.msgs_history_unknown, Toast.LENGTH_LONG);
1183                 }
1184             });
1185
1186             //Not change directory
1187             return false;
1188         }
1189     }
1190
1191     /**
1192      * Method that request a back action over the navigation history.
1193      *
1194      * @return boolean If a back action was applied
1195      */
1196     public boolean back() {
1197         // Check that has valid history
1198         while (this.mHistory.size() > 0) {
1199             History h = this.mHistory.get(this.mHistory.size() - 1);
1200             if (h.getItem() instanceof NavigationViewInfoParcelable) {
1201                 // Verify that the path exists
1202                 String path = ((NavigationViewInfoParcelable)h.getItem()).getCurrentDir();
1203
1204                 try {
1205                     FileSystemObject info = CommandHelper.getFileInfo(this, path, null);
1206                     if (info != null) {
1207                         break;
1208                     }
1209                     this.mHistory.remove(this.mHistory.size() - 1);
1210                 } catch (Exception e) {
1211                     ExceptionUtil.translateException(this, e, true, false);
1212                     this.mHistory.remove(this.mHistory.size() - 1);
1213                 }
1214             } else {
1215                 break;
1216             }
1217         }
1218
1219         //Extract a history from the
1220         if (this.mHistory.size() > 0) {
1221             //Navigate to history
1222             return navigateToHistory(this.mHistory.get(this.mHistory.size() - 1));
1223         }
1224
1225         //Nothing to apply
1226         return false;
1227     }
1228
1229     /**
1230      * Method that opens the actions dialog
1231      *
1232      * @param item The path or the {@link FileSystemObject}
1233      * @param global If the menu to display is the one with global actions
1234      */
1235     private void openActionsDialog(Object item, boolean global) {
1236         // Resolve the full path
1237         String path = String.valueOf(item);
1238         if (item instanceof FileSystemObject) {
1239             path = ((FileSystemObject)item).getFullPath();
1240         }
1241
1242         // Prior to show the dialog, refresh the item reference
1243         FileSystemObject fso = null;
1244         try {
1245             fso = CommandHelper.getFileInfo(this, path, false, null);
1246             if (fso == null) {
1247                 throw new NoSuchFileOrDirectory(path);
1248             }
1249
1250         } catch (Exception e) {
1251             // Notify the user
1252             ExceptionUtil.translateException(this, e);
1253
1254             // Remove the object
1255             if (e instanceof FileNotFoundException || e instanceof NoSuchFileOrDirectory) {
1256                 // If have a FileSystemObject reference then there is no need to search
1257                 // the path (less resources used)
1258                 if (item instanceof FileSystemObject) {
1259                     getCurrentNavigationView().removeItem((FileSystemObject)item);
1260                 } else {
1261                     getCurrentNavigationView().removeItem((String)item);
1262                 }
1263             }
1264             return;
1265         }
1266
1267         // Show the dialog
1268         ActionsDialog dialog = new ActionsDialog(this, fso, global, false);
1269         dialog.setOnRequestRefreshListener(this);
1270         dialog.setOnSelectionListener(getCurrentNavigationView());
1271         dialog.show();
1272     }
1273
1274     /**
1275      * Method that opens the bookmarks activity.
1276      * @hide
1277      */
1278     void openBookmarks() {
1279         Intent bookmarksIntent = new Intent(this, BookmarksActivity.class);
1280         bookmarksIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1281         startActivityForResult(bookmarksIntent, INTENT_REQUEST_BOOKMARK);
1282     }
1283
1284     /**
1285      * Method that opens the history activity.
1286      * @hide
1287      */
1288     void openHistory() {
1289         Intent historyIntent = new Intent(this, HistoryActivity.class);
1290         historyIntent.putExtra(HistoryActivity.EXTRA_HISTORY_LIST, (Serializable)this.mHistory);
1291         historyIntent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
1292         startActivityForResult(historyIntent, INTENT_REQUEST_HISTORY);
1293     }
1294
1295     /**
1296      * Method that opens the search activity.
1297      * @hide
1298      */
1299     void openSearch() {
1300         onSearchRequested();
1301     }
1302
1303     /**
1304      * Method that remove the {@link FileSystemObject} from the history
1305      */
1306     private void removeFromHistory(FileSystemObject fso) {
1307         if (this.mHistory != null) {
1308             int cc = this.mHistory.size();
1309             for (int i = cc-1; i >= 0 ; i--) {
1310                 History history = this.mHistory.get(i);
1311                 if (history.getItem() instanceof NavigationViewInfoParcelable) {
1312                     String p0 = fso.getFullPath();
1313                     String p1 =
1314                             ((NavigationViewInfoParcelable)history.getItem()).getCurrentDir();
1315                     if (p0.compareTo(p1) == 0) {
1316                         this.mHistory.remove(i);
1317                     }
1318                 }
1319             }
1320         }
1321     }
1322
1323     /**
1324      * Method that ask the user to change to to advanced console
1325      * @hide
1326      */
1327     void askOrExit() {
1328         //Show a dialog asking the user
1329         AlertDialog dialog =
1330             DialogHelper.createYesNoDialog(
1331                 this, R.string.msgs_change_to_advanced_console_mode,
1332                 new DialogInterface.OnClickListener() {
1333                     @Override
1334                     public void onClick(DialogInterface alertDialog, int which) {
1335                         if (which == DialogInterface.BUTTON_NEGATIVE) {
1336                             // We don't have any console
1337                             // Show exception and exists
1338                             DialogHelper.showToast(
1339                                     NavigationActivity.this,
1340                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1341                             exit();
1342                             return;
1343                         }
1344
1345                         // Ok. Now try to change to advanced selection console. Any crash
1346                         // here is a fatal error. We won't have any console to operate.
1347                         try {
1348                             // Change console
1349                             ConsoleBuilder.changeToNonPrivilegedConsole(NavigationActivity.this);
1350
1351                             // Save preferences
1352                             Preferences.savePreference(
1353                                     FileManagerSettings.SETTINGS_ADVANCE_MODE,
1354                                     Boolean.TRUE, true);
1355                             Preferences.savePreference(
1356                                     FileManagerSettings.SETTINGS_SUPERUSER_MODE,
1357                                     Boolean.FALSE, true);
1358
1359                         } catch (Exception e) {
1360                             //Show exception and exists
1361                             Log.e(TAG, getString(R.string.msgs_cant_create_console), e);
1362                             DialogHelper.showToast(
1363                                     NavigationActivity.this,
1364                                     R.string.msgs_cant_create_console, Toast.LENGTH_LONG);
1365                             exit();
1366                         }
1367                     }
1368                });
1369         dialog.show();
1370     }
1371
1372     /**
1373      * Method that creates a ChRooted environment, protecting the user to break anything in
1374      * the device
1375      * @hide
1376      */
1377     void createChRooted() {
1378         // If we are in a ChRooted mode, then do nothing
1379         if (this.mChRooted) return;
1380         this.mChRooted = true;
1381
1382         int cc = this.mNavigationViews.length;
1383         for (int i = 0; i < cc; i++) {
1384             this.mNavigationViews[i].createChRooted();
1385         }
1386
1387         // Remove the selection
1388         cc = this.mNavigationViews.length;
1389         for (int i = 0; i < cc; i++) {
1390             getCurrentNavigationView().onDeselectAll();
1391         }
1392
1393         // Remove the history (don't allow to access to previous data)
1394         clearHistory();
1395     }
1396
1397     /**
1398      * Method that exits from a ChRooted
1399      * @hide
1400      */
1401     void exitChRooted() {
1402         // If we aren't in a ChRooted mode, then do nothing
1403         if (!this.mChRooted) return;
1404         this.mChRooted = false;
1405
1406         int cc = this.mNavigationViews.length;
1407         for (int i = 0; i < cc; i++) {
1408             this.mNavigationViews[i].exitChRooted();
1409         }
1410     }
1411
1412     /**
1413      * Method called when a controlled exit is required
1414      * @hide
1415      */
1416     void exit() {
1417         try {
1418             FileManagerApplication.destroyBackgroundConsole();
1419         } catch (Throwable ex) {
1420             /**NON BLOCK**/
1421         }
1422         try {
1423             ConsoleBuilder.destroyConsole();
1424         } catch (Throwable ex) {
1425             /**NON BLOCK**/
1426         }
1427         finish();
1428     }
1429
1430 }