Merge remote-tracking branch 'upstream/develop' into navigationDrawer_update
authortobiasKaminsky <tobias@kaminsky.me>
Thu, 21 May 2015 19:12:44 +0000 (21:12 +0200)
committertobiasKaminsky <tobias@kaminsky.me>
Thu, 21 May 2015 19:12:44 +0000 (21:12 +0200)
22 files changed:
1  2 
res/layout/files.xml
res/layout/uploader_layout.xml
res/layout/uploader_list_item_layout.xml
res/menu/main_menu.xml
res/values/colors.xml
res/values/strings.xml
res/xml/preferences.xml
src/com/owncloud/android/MainApp.java
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/operations/RefreshFolderOperation.java
src/com/owncloud/android/operations/SynchronizeFolderOperation.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/FolderPickerActivity.java
src/com/owncloud/android/ui/activity/Preferences.java
src/com/owncloud/android/ui/activity/UploadPathActivity.java
src/com/owncloud/android/ui/activity/Uploader.java
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
src/com/owncloud/android/utils/BitmapUtils.java

diff --combined res/layout/files.xml
@@@ -1,9 -1,9 +1,9 @@@
  <?xml version="1.0" encoding="utf-8"?>\r
 -<!-- \r
 +<!--\r
    ownCloud Android client application\r
  \r
    Copyright (C) 2012  Bartek Przybylski\r
-   Copyright (C) 2012-2013 ownCloud Inc.\r
+   Copyright (C) 2015 ownCloud Inc.\r
  \r
    This program is free software: you can redistribute it and/or modify\r
    it under the terms of the GNU General Public License version 2,\r
  \r
    You should have received a copy of the GNU General Public License\r
    along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
 - -->\r
 -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
 +  -->\r
 +<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
 +    android:id="@+id/drawer_layout"\r
      android:layout_width="match_parent"\r
      android:layout_height="match_parent"\r
 -    android:background="@color/background_color"\r
 -    android:orientation="horizontal"\r
 -    android:baselineAligned="false"\r
 -    >\r
 -\r
 -      <FrameLayout \r
 -              android:layout_width="0dp"\r
 -              android:layout_height="match_parent"\r
 -              android:layout_weight="1"\r
 -              android:id="@+id/left_fragment_container"\r
 -          />\r
 -      \r
 -      <FrameLayout \r
 -              android:layout_width="0dp"\r
 -              android:layout_height="match_parent"\r
 -              android:layout_weight="2"\r
 -              android:id="@+id/right_fragment_container"\r
 -          />\r
 -      \r
 - </LinearLayout>
 +    android:clickable="true" >\r
 +\r
 +    <!-- The main content view -->\r
 +    <LinearLayout\r
 +        xmlns:android="http://schemas.android.com/apk/res/android"\r
 +        android:layout_width="match_parent"\r
 +        android:layout_height="match_parent"\r
 +        android:background="@color/background_color"\r
 +        android:baselineAligned="false"\r
 +        android:orientation="horizontal" >\r
 +\r
 +        \r
 +        <FrameLayout\r
 +            android:id="@+id/left_fragment_container"\r
 +            android:layout_width="0dp"\r
 +            android:layout_height="match_parent"\r
 +            android:layout_weight="1" />\r
 +\r
 +        <FrameLayout\r
 +            android:id="@+id/right_fragment_container"\r
 +            android:layout_width="0dp"\r
 +            android:layout_height="match_parent"\r
 +            android:layout_weight="2" />\r
 +    </LinearLayout>\r
 +\r
 +    \r
 +         <LinearLayout\r
 +             xmlns:android="http://schemas.android.com/apk/res/android"\r
 +             android:id="@+id/left_drawer"\r
 +             android:layout_width="240dp"\r
 +             android:layout_height="match_parent"\r
 +             android:layout_gravity="start"\r
 +             android:background="@color/background_color"\r
 +             android:baselineAligned="false"\r
 +             android:clickable="true"\r
 +             android:orientation="vertical">\r
 +\r
 +    <LinearLayout\r
 +        android:layout_width="match_parent"\r
 +        android:layout_height="wrap_content"\r
 +        android:layout_margin="5dp">\r
 +\r
 +        <ImageView\r
 +            android:id="@+id/drawer_userIcon"\r
 +            android:layout_width="40dp"\r
 +            android:layout_height="40dp"\r
 +            android:src="@drawable/abs__ab_solid_dark_holo" />\r
 +\r
 +        <TextView\r
 +            android:id="@+id/drawer_username"\r
 +            android:layout_width="wrap_content"\r
 +            android:layout_height="wrap_content"\r
 +            android:layout_gravity="center_vertical"\r
 +            android:layout_marginLeft="5dp"\r
 +            android:layout_marginStart="5dp"\r
 +            android:textAppearance="?android:attr/textAppearanceLarge" />\r
 +\r
 +    </LinearLayout>\r
 +\r
 +    <TextView\r
 +        android:layout_width="fill_parent"\r
 +        android:layout_height="2dip"\r
 +        android:background="@color/list_item_lastmod_and_filesize_text" />\r
 +\r
 +    <ListView\r
 +        android:id="@+id/drawer_list"\r
 +        android:layout_width="fill_parent"\r
 +        android:layout_height="match_parent"\r
 +        android:background="@color/background_color"\r
 +        android:choiceMode="singleChoice"\r
 +        />\r
 +</LinearLayout>\r
 +</android.support.v4.widget.DrawerLayout>
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
        android:layout_width="wrap_content" android:background="#fefefe"
        android:gravity="center">
        <TextView android:layout_width="fill_parent" android:text="@string/uploader_top_message"
 -              android:layout_height="wrap_content" android:id="@+id/textView1" android:textColor="@android:color/black"
 +              android:layout_height="wrap_content" android:id="@+id/drawer_username" android:textColor="@android:color/black"
                android:gravity="center_horizontal"></TextView>
        <FrameLayout android:layout_height="fill_parent"
                android:layout_width="fill_parent" android:id="@+id/frameLayout1"
 -              android:layout_below="@+id/textView1" android:layout_above="@+id/linearLayout1">
 +              android:layout_below="@+id/drawer_username" android:layout_above="@+id/linearLayout1">
                <ListView android:id="@android:id/list" android:layout_width="fill_parent"
                        android:layout_height="fill_parent" android:divider="@drawable/uploader_list_separator"
                        android:dividerHeight="1dip"></ListView>
        </FrameLayout>
-       <LinearLayout android:id="@+id/linearLayout1"
-               android:layout_width="fill_parent" android:layout_alignParentBottom="true" android:layout_height="wrap_content" android:orientation="vertical">
-               <Button android:layout_gravity="bottom" android:layout_height="wrap_content"
-                       android:layout_width="fill_parent" android:id="@+id/uploader_choose_folder"
-                       android:text="@string/uploader_btn_upload_text"/>
+       <LinearLayout
+           android:id="@+id/linearLayout1"
+           android:layout_width="fill_parent"
+           android:layout_height="wrap_content"
+           android:layout_alignParentBottom="true"
+           android:orientation="horizontal" >
+               <Button
+                   android:id="@+id/uploader_new_folder"
+                   android:layout_width="fill_parent"
+                   android:layout_height="wrap_content"
+                   android:layout_gravity="bottom"
+                   android:layout_weight="1"
+                   android:text="@string/uploader_btn_new_folder_text" />
+               
+               <Button
+                   android:id="@+id/uploader_choose_folder"
+                   android:layout_width="fill_parent"
+                   android:layout_height="wrap_content"
+                   android:layout_gravity="bottom"
+                   android:layout_weight="1"
+                   android:text="@string/uploader_btn_upload_text" />
        </LinearLayout>
  </RelativeLayout>
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
          android:layout_gravity="center_vertical|center"
          android:layout_margin="4dp"
          android:src="@drawable/ic_menu_archive" 
-         android:id="@+id/drawer_userIcon" />
+         android:id="@+id/thumbnail" />
      
      <TextView 
          android:text="TextView" 
          android:layout_width="fill_parent" 
 -        android:id="@+id/textView1
 +        android:id="@+id/drawer_username
          android:layout_height="wrap_content" 
          android:textColor="@android:color/black"
                android:layout_gravity="center_vertical"
diff --combined res/menu/main_menu.xml
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
          android:icon="@drawable/ic_action_upload"
          android:orderInCategory="2"
          android:showAsAction="always"
-         android:title="@string/actionbar_upload"/>
+         android:title="@string/actionbar_upload"
+         android:contentDescription="@string/actionbar_upload"/>
      <item
          android:id="@+id/action_create_dir"
          android:icon="@drawable/ic_action_create_dir"
          android:orderInCategory="2"
          android:showAsAction="always"
-         android:title="@string/actionbar_mkdir"/>
+         android:title="@string/actionbar_mkdir"
+         android:contentDescription="@string/actionbar_mkdir"/>
      <item
 -        android:id="@+id/action_sync_account"
 -        android:icon="@drawable/ic_action_refresh"
 -        android:orderInCategory="2"
 -        android:showAsAction="never"
 -        android:title="@string/actionbar_sync"
 -        android:contentDescription="@string/actionbar_sync"/>
 -    <item
 -        android:id="@+id/action_settings"
 -        android:icon="@drawable/ic_action_settings"
 -        android:orderInCategory="2"
 -        android:showAsAction="never"
 -        android:title="@string/actionbar_settings"
 -        android:contentDescription="@string/actionbar_settings"/>
 -    <item
 -        android:id="@+id/action_logger"
 -        android:icon="@drawable/ic_action_settings"
 -        android:orderInCategory="2"
 -        android:showAsAction="never"
 -        android:title="@string/actionbar_logger"
 -        android:contentDescription="@string/actionbar_logger"/>
 -      <item
          android:id="@+id/action_sort"
 -        android:icon="@android:drawable/ic_menu_sort_alphabetically"
 +        android:icon="@android:drawable/ic_menu_sort_by_size"
          android:orderInCategory="2"
 -        android:showAsAction="never"
 +        android:showAsAction="always"
-         android:title="@string/actionbar_sort"/>
+         android:title="@string/actionbar_sort"
 -        android:contentDescription="@string/actionbar_sort"/>
++        android:contentDescription="@string/actionbar_sort"/>/>
  
      <!-- <item android:id="@+id/search" android:title="@string/actionbar_search" android:icon="@drawable/ic_action_search"></item> -->
  
diff --combined res/values/colors.xml
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
@@@ -22,6 -22,7 +22,8 @@@
      <color name="filelist_icon_backgorund">#DDDDDD</color>
      <color name="owncloud_blue_bright">#00ddff</color>
      <color name="list_item_lastmod_and_filesize_text">#989898</color>
 +    <color name="black">#000000</color>
+     <color name="textColor">#303030</color>
+     <color name="list_divider_background">#fff0f0f0</color>
      
  </resources>
diff --combined res/values/strings.xml
        <!-- TODO re-enable when server-side folder size calculation is available   
        <item>Biggest - Smallest</item>  -->
      </string-array>
 +    <string-array name="drawer_items">
 +        <item>Accounts</item>
 +          <item>All Files</item>
 +          <item>On device</item>
 +          <item>Settings</item>
 +    </string-array>
 +    <string name="drawer_open">ownCloud</string>
 +      <string name="drawer_close">Close</string>
      <string name="prefs_category_general">General</string>
      <string name="prefs_category_more">More</string>
      <string name="prefs_accounts">Accounts</string>
      <string name="prefs_manage_accounts">Manage Accounts</string>
-     <string name="prefs_pincode">App PIN</string>
-     <string name="prefs_pincode_summary">Protect your client</string>
+     <string name="prefs_passcode">Passcode lock</string>
      <string name="prefs_instant_upload">Instant picture uploads</string>
      <string name="prefs_instant_upload_summary">Instantly upload pictures taken by camera</string>
      <string name="prefs_instant_video_upload">Instant video uploads</string>
@@@ -61,6 -52,7 +60,7 @@@
      <string name="sync_string_files">Files</string>
      <string name="setup_btn_connect">Connect</string>
      <string name="uploader_btn_upload_text">Upload</string>
+     <string name="uploader_btn_new_folder_text">New folder</string>
      <string name="uploader_top_message">Choose upload folder:</string>
      <string name="uploader_wrn_no_account_title">No account found</string>
      <string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please setup an account first.</string>
      <string name="foreign_files_local_text">"Local: %1$s"</string>
      <string name="foreign_files_remote_text">"Remote: %1$s"</string>
      <string name="upload_query_move_foreign_files">There is not space enough to copy the selected files into the %1$s folder. Would you like to move them instead? </string>
-     <string name="pincode_enter_pin_code">Please, insert your App PIN</string>
+     <string name="pass_code_enter_pass_code">Please, insert your passcode</string>
      
-     <string name="pincode_configure_your_pin">Enter your App PIN</string>
-     <string name="pincode_configure_your_pin_explanation">The PIN will be requested every time the app is started</string>
-     <string name="pincode_reenter_your_pincode">Please, reenter your App PIN</string>
-     <string name="pincode_remove_your_pincode">Remove your App PIN</string>
-     <string name="pincode_mismatch">The App PINs are not the same</string>
-     <string name="pincode_wrong">Incorrect App PIN</string>
-     <string name="pincode_removed">App PIN removed</string>
-     <string name="pincode_stored">App PIN stored</string>
+     <string name="pass_code_configure_your_pass_code">Enter your passcode</string>
+     <string name="pass_code_configure_your_pass_code_explanation">The passcode will be requested every time the app is started</string>
+     <string name="pass_code_reenter_your_pass_code">Please, reenter your passcode</string>
+     <string name="pass_code_remove_your_pass_code">Remove your passcode</string>
+     <string name="pass_code_mismatch">The passcodes are not the same</string>
+     <string name="pass_code_wrong">Incorrect passcode</string>
+     <string name="pass_code_removed">Passcode removed</string>
+     <string name="pass_code_stored">Passcode stored</string>
      
      <string name="media_notif_ticker">"%1$s music player"</string>
      <string name="media_state_playing">"%1$s (playing)"</string>
        <string name="auth_no_net_conn_title">No network connection</string>
        <string name="auth_nossl_plain_ok_title">Secure connection unavailable.</string>
        <string name="auth_connection_established">Connection established</string>
-       <string name="auth_testing_connection">Testing connection&#8230;</string>
+       <string name="auth_testing_connection">Testing connection</string>
        <string name="auth_not_configured_title">Malformed server configuration</string>
        <string name="auth_account_not_new">An account for the same user and server already exists in the device</string>
        <string name="auth_account_not_the_same">The entered user does not match the user of this account</string>
        <string name="auth_fail_get_user_name">Your server is not returning a correct user id, please contact an administrator
        </string>
        <string name="auth_can_not_auth_against_server">Cannot authenticate against this server</string>
+     <string name="auth_account_does_not_exist">Account does not exist in the device yet</string>
      
      <string name="fd_keep_in_sync">Keep file up to date</string>
      <string name="common_rename">Rename</string>
      <string name="filedisplay_unexpected_bad_get_content">"Unexpected problem ; please select the file from a different app"</string>
      <string name="filedisplay_no_file_selected">No file was selected</string>
      <string name="activity_chooser_title">Send link to &#8230;</string>
+     <string name="wait_for_tmp_copy_from_private_storage">Copying file from private storage</string>
      
      <string name="oauth_check_onoff">Login with oAuth2</string> 
      <string name="oauth_login_connection">Connecting to oAuth2 server…</string>    
        <string name="share_link_file_error">An error occurred while trying to share this file or folder</string>
        <string name="unshare_link_file_no_exist">Unable to unshare. Please check whether the file exists</string>
        <string name="unshare_link_file_error">An error occurred while trying to unshare this file or folder</string>
+     <string name="share_link_password_title">Enter a password</string>
+     <string name="share_link_empty_password">You must enter a password</string>
  
        <string name="activity_chooser_send_file_title">Send</string>
  
        <string name="prefs_category_security">Security</string>
  
        <string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
+     <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
  
 -      <string name="subject_token">%1$s shared \"%2$s\" with you</string>
 +      <string name="shared_subject_header">shared</string>
 +      <string name="with_you_subject_header">with you</string>
++    
 +      <string name="subject_token">%1$s %2$s &gt;&gt;%3$s&lt;&lt; %4$s</string>
-       <string name="username">Username</string>
  
+     <string name="auth_refresh_button">Refresh connection</string>
+     <string name="auth_host_address">Server address</string>
+     <string name="common_error_out_memory">Not enough memory</string>
++    <string name="username">Username</string>
  </resources>
diff --combined res/xml/preferences.xml
@@@ -3,7 -3,7 +3,7 @@@
    ownCloud Android client application
  
    Copyright (C) 2012  Bartek Przybylski
-   Copyright (C) 2012-2013 ownCloud Inc.
+   Copyright (C) 2015 ownCloud Inc.
  
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 2,
      </PreferenceCategory>
      
        <PreferenceCategory android:title="@string/prefs_category_security">
-           <!-- ListPreference
-               android:key="select_oc_account"
-               android:title="@string/prefs_select_oc_account"
-               android:summary="@string/prefs_summary_select_oc_account"
-               / -->
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:title="@string/prefs_pincode" android:key="set_pincode" 
-                         android:summary="@string/prefs_pincode_summary"/>
+           <android.preference.CheckBoxPreference android:title="@string/prefs_passcode" android:key="set_pincode" />
        </PreferenceCategory>
  
-     <PreferenceCategory android:title="@string/prefs_category_instant_uploading">
-         <com.owncloud.android.ui.PreferenceWithLongSummary
-                                                       android:title="@string/prefs_instant_upload_path_title"
-                                                       android:key="instant_upload_path" />
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
+     <PreferenceCategory android:title="@string/prefs_category_instant_uploading" android:key="instant_uploading_category">
+          <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
                                android:title="@string/prefs_instant_upload"
                                android:summary="@string/prefs_instant_upload_summary"/>
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_uploading"
-                                               android:disableDependentsState="true"
+          <com.owncloud.android.ui.PreferenceWithLongSummary
+                                                       android:title="@string/prefs_instant_upload_path_title"
+                                                       android:key="instant_upload_path" />
+           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
                                                android:title="@string/instant_upload_on_wifi"
                                                android:key="instant_upload_on_wifi"/>
+           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_video_uploading"
+                               android:title="@string/prefs_instant_video_upload"
+                               android:summary="@string/prefs_instant_video_upload_summary" />
            <com.owncloud.android.ui.PreferenceWithLongSummary
                                                        android:title="@string/prefs_instant_video_upload_path_title"
                                                        android:key="instant_video_upload_path" />
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_video_uploading"
-                               android:title="@string/prefs_instant_video_upload"
-                               android:summary="@string/prefs_instant_video_upload_summary"/>
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:dependency="instant_video_uploading"
-                                               android:disableDependentsState="true"
+           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
                                                android:title="@string/instant_video_upload_on_wifi"
                                                android:key="instant_video_upload_on_wifi"/>
            <!-- DISABLED FOR RELEASE UNTIL FIXED
@@@ -64,7 -56,6 +56,7 @@@
        
        <PreferenceCategory android:title="@string/prefs_category_more" android:key="more">
      <Preference android:title="@string/prefs_help" android:key="help" />
 +    <Preference android:title="@string/actionbar_logger" android:key="log" />
      <Preference android:title="@string/prefs_recommend" android:key="recommend" />
      <Preference android:title="@string/prefs_feedback" android:key="feedback" />
      <Preference android:title="@string/prefs_imprint" android:key="imprint" />
@@@ -1,5 -1,9 +1,9 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2013 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author masensio
+  *   @author David A. Velasco
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
   */
  package com.owncloud.android;
  
+ import android.app.Activity;
  import android.app.Application;
  import android.content.Context;
+ import android.content.pm.PackageInfo;
+ import android.content.pm.PackageManager;
+ import android.os.Build;
+ import android.os.Bundle;
  
+ import com.owncloud.android.authentication.PassCodeManager;
  import com.owncloud.android.datamodel.ThumbnailsCacheManager;
  import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
  import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
  import com.owncloud.android.lib.common.utils.Log_OC;
  /**
   * Main Application of the project
   * 
   * Contains methods to build the "static" strings. These strings were before constants in different
   * classes
-  * 
-  * @author masensio
-  * @author David A. Velasco
   */
  public class MainApp extends Application {
-     
+     private static final String TAG = MainApp.class.getSimpleName();
      private static final String AUTH_ON = "on";
-     
      @SuppressWarnings("unused")
      private static final String POLICY_SINGLE_SESSION_PER_ACCOUNT = "single session per account";
      @SuppressWarnings("unused")
  
      private static Context mContext;
      
 +    // TODO better place
 +    private static boolean mOnlyOnDevice = false;
 +
 +    
      public void onCreate(){
          super.onCreate();
          MainApp.mContext = getApplicationContext();
          
          boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
-         
-         if (isSamlAuth) {   
+         OwnCloudClientManagerFactory.setUserAgent(getUserAgent());
+         if (isSamlAuth) {
              OwnCloudClientManagerFactory.setDefaultPolicy(Policy.SINGLE_SESSION_PER_ACCOUNT);
-             
          } else {
              OwnCloudClientManagerFactory.setDefaultPolicy(Policy.ALWAYS_NEW_CLIENT);
          }
              Log_OC.startLogging();
              Log_OC.d("Debug", "start logging");
          }
+         // register global protection with pass code
+         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+             this.registerActivityLifecycleCallbacks( new ActivityLifecycleCallbacks() {
+                 @Override
+                 public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+                     Log_OC.d(activity.getClass().getSimpleName(),  "onCreate(Bundle) starting" );
+                     PassCodeManager.getPassCodeManager().onActivityCreated(activity);
+                 }
+                 @Override
+                 public void onActivityStarted(Activity activity) {
+                     Log_OC.d(activity.getClass().getSimpleName(),  "onStart() starting" );
+                     PassCodeManager.getPassCodeManager().onActivityStarted(activity);
+                 }
+                 @Override
+                 public void onActivityResumed(Activity activity) {
+                     Log_OC.d(activity.getClass().getSimpleName(), "onResume() starting" );
+                 }
+                 @Override
+                 public void onActivityPaused(Activity activity) {
+                     Log_OC.d(activity.getClass().getSimpleName(), "onPause() ending");
+                 }
+                 @Override
+                 public void onActivityStopped(Activity activity) {
+                     Log_OC.d(activity.getClass().getSimpleName(), "onStop() ending" );
+                     PassCodeManager.getPassCodeManager().onActivityStopped(activity);
+                 }
+                 @Override
+                 public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+                     Log_OC.d(activity.getClass().getSimpleName(), "onSaveInstanceState(Bundle) starting" );
+                 }
+                 @Override
+                 public void onActivityDestroyed(Activity activity) {
+                     Log_OC.d(activity.getClass().getSimpleName(), "onDestroy() ending" );
+                 }
+             });
+         }
      }
  
      public static Context getAppContext() {
      public static String getLogName() {
          return getAppContext().getResources().getString(R.string.log_name);
      }
 +    
 +    public static void showOnlyFilesOnDevice(boolean state){
 +        mOnlyOnDevice = state;
 +    }
 +    
 +    public static boolean getOnlyOnDevice(){
 +        return mOnlyOnDevice;
 +    }
+     // user agent
+     public static String getUserAgent() {
+         String appString = getAppContext().getResources().getString(R.string.user_agent);
+         String packageName = getAppContext().getPackageName();
+         String version = "";
+         PackageInfo pInfo = null;
+         try {
+             pInfo = getAppContext().getPackageManager().getPackageInfo(packageName, 0);
+             if (pInfo != null) {
+                 version = pInfo.versionName;
+             }
+         } catch (PackageManager.NameNotFoundException e) {
+             Log_OC.e(TAG, "Trying to get packageName", e.getCause());
+         }
+         // Mozilla/5.0 (Android) ownCloud-android/1.7.0
+         String userAgent = String.format(appString, version);
+         return userAgent;
+     }
  }
@@@ -1,6 -1,8 +1,8 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
   *   Copyright (C) 2012  Bartek Przybylski
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -26,6 -28,14 +28,6 @@@ import java.util.Iterator
  import java.util.List;
  import java.util.Vector;
  
 -import com.owncloud.android.MainApp;
 -import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 -import com.owncloud.android.lib.common.utils.Log_OC;
 -import com.owncloud.android.lib.resources.shares.OCShare;
 -import com.owncloud.android.lib.resources.shares.ShareType;
 -import com.owncloud.android.lib.resources.files.FileUtils;
 -import com.owncloud.android.utils.FileStorageUtils;
 -
  import android.accounts.Account;
  import android.content.ContentProviderClient;
  import android.content.ContentProviderOperation;
@@@ -38,15 -48,8 +40,16 @@@ import android.content.OperationApplica
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.RemoteException;
+ import android.provider.MediaStore;
  
 +import com.owncloud.android.MainApp;
 +import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 +import com.owncloud.android.lib.common.utils.Log_OC;
 +import com.owncloud.android.lib.resources.files.FileUtils;
 +import com.owncloud.android.lib.resources.shares.OCShare;
 +import com.owncloud.android.lib.resources.shares.ShareType;
 +import com.owncloud.android.utils.FileStorageUtils;
 +
  public class FileDataStorageManager {
  
      public static final int ROOT_PARENT_ID = 0;
      }
  
      
 -    public Vector<OCFile> getFolderContent(OCFile f) {
 +    public Vector<OCFile> getFolderContent(OCFile f, boolean onlyOnDevice) {
          if (f != null && f.isFolder() && f.getFileId() != -1) {
 -            return getFolderContent(f.getFileId());
 +            return getFolderContent(f.getFileId(), onlyOnDevice);
  
          } else {
              return new Vector<OCFile>();
      }
      
      
 -    public Vector<OCFile> getFolderImages(OCFile folder) {
 +    public Vector<OCFile> getFolderImages(OCFile folder, boolean onlyOnDevice) {
          Vector<OCFile> ret = new Vector<OCFile>(); 
          if (folder != null) {
              // TODO better implementation, filtering in the access to database instead of here 
 -            Vector<OCFile> tmp = getFolderContent(folder);
 +            Vector<OCFile> tmp = getFolderContent(folder, onlyOnDevice);
              OCFile current = null; 
              for (int i=0; i<tmp.size(); i++) {
                  current = tmp.get(i);
          return ret;
      }
  
-     
      public boolean saveFile(OCFile file) {
          boolean overriden = false;
          ContentValues cv = new ContentValues();
          cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
          cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
          cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
+         cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
          
          boolean sameRemotePath = fileExists(file.getRemotePath());
          if (sameRemotePath ||
       * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
       *  
       * @param folder
-      * @param files
-      * @param removeNotUpdated
+      * @param updatedFiles
+      * @param filesToRemove
       */
      public void saveFolder(
              OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
              cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
              cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
              cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
+             cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
  
              boolean existsByPath = fileExists(file.getRemotePath());
              if (existsByPath || fileExists(file.getFileId())) {
                  if (removeLocalCopy && file.isDown() && localPath != null && success) {
                      success = new File(localPath).delete();
                      if (success) {
-                         triggerMediaScan(localPath);
+                         deleteFileInMediaScan(localPath);
                      }
                      if (!removeDBData && success) {
                          // maybe unnecessary, but should be checked TODO remove if unnecessary
  
      private boolean removeLocalFolder(OCFile folder) {
          boolean success = true;
-         File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
+         String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder);
+         File localFolder = new File(localFolderPath);
          if (localFolder.exists()) {
              // stage 1: remove the local files already registered in the files database
 -            Vector<OCFile> files = getFolderContent(folder.getFileId());
 +            Vector<OCFile> files = getFolderContent(folder.getFileId(), false);
              if (files != null) {
                  for (OCFile file : files) {
                      if (file.isFolder()) {
                          success &= removeLocalFolder(file);
                      } else {
                          if (file.isDown()) {
-                             String path = file.getStoragePath();
                              File localFile = new File(file.getStoragePath());
                              success &= localFile.delete();
                              if (success) {
+                                 // notify MediaScanner about removed file
+                                 deleteFileInMediaScan(file.getStoragePath());
                                  file.setStoragePath(null);
                                  saveFile(file);
-                                 triggerMediaScan(path); // notify MediaScanner about removed file
                              }
                          }
                      }
                  } else {
                      String path = localFile.getAbsolutePath();
                      success &= localFile.delete();
-                     triggerMediaScan(path); // notify MediaScanner about removed file
                  }
              }
          }
                  Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
                  while (it.hasNext()) {
                      // Notify MediaScanner about removed file
-                     triggerMediaScan(it.next());
+                     deleteFileInMediaScan(it.next());
                  }
                  it = newPathsToTriggerMediaScan.iterator();
                  while (it.hasNext()) {
      }
      
      
 -    private Vector<OCFile> getFolderContent(long parentId) {
 +    private Vector<OCFile> getFolderContent(long parentId, boolean onlyOnDevice) {
  
          Vector<OCFile> ret = new Vector<OCFile>();
  
          if (c.moveToFirst()) {
              do {
                  OCFile child = createFileInstance(c);
 -                ret.add(child);
 +                if (child.isFolder() || !onlyOnDevice || onlyOnDevice && child.isDown()){
 +                    ret.add(child);
 +                }
              } while (c.moveToNext());
          }
  
              file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
              file.setNeedsUpdateThumbnail(c.getInt(
                      c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
+             file.setDownloading(c.getInt(
+                     c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
                      
          }
          return file;
                      ProviderTableMeta.FILE_UPDATE_THUMBNAIL, 
                      file.needsUpdateThumbnail() ? 1 : 0
                  );
+                 cv.put(
+                         ProviderTableMeta.FILE_IS_DOWNLOADING,
+                         file.isDownloading() ? 1 : 0
+                 );
  
                  boolean existsByPath = fileExists(file.getRemotePath());
                  if (existsByPath || fileExists(file.getFileId())) {
      }
  
      private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
 -            OCFile folder, ArrayList<ContentProviderOperation> preparedOperations
 -            ) {
 +            OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
          if (folder != null) {
              String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " 
                      + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
              String [] whereArgs = new String[]{ "", mAccount.name };
              
 -            Vector<OCFile> files = getFolderContent(folder);
 +            Vector<OCFile> files = getFolderContent(folder, false);
              
              for (OCFile file : files) {
                  whereArgs[0] = file.getRemotePath();
          MainApp.getAppContext().sendBroadcast(intent);
      }
  
+     public void deleteFileInMediaScan(String path) {
+         String mimetypeString = FileStorageUtils.getMimeTypeFromName(path);
+         ContentResolver contentResolver = getContentResolver();
+         if (contentResolver != null) {
+             if (mimetypeString.startsWith("image/")) {
+                 // Images
+                 contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                         MediaStore.Images.Media.DATA + "=?", new String[]{path});
+             } else if (mimetypeString.startsWith("audio/")) {
+                 // Audio
+                 contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+                         MediaStore.Audio.Media.DATA + "=?", new String[]{path});
+             } else if (mimetypeString.startsWith("video/")) {
+                 // Video
+                 contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                         MediaStore.Video.Media.DATA + "=?", new String[]{path});
+             }
+         } else {
+             ContentProviderClient contentProviderClient = getContentProviderClient();
+             try {
+                 if (mimetypeString.startsWith("image/")) {
+                     // Images
+                     contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                             MediaStore.Images.Media.DATA + "=?", new String[]{path});
+                 } else if (mimetypeString.startsWith("audio/")) {
+                     // Audio
+                     contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+                             MediaStore.Audio.Media.DATA + "=?", new String[]{path});
+                 } else if (mimetypeString.startsWith("video/")) {
+                     // Video
+                     contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                             MediaStore.Video.Media.DATA + "=?", new String[]{path});
+                 }
+             } catch (RemoteException e) {
+                 Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage());
+             }
+         }
+     }
  }
index 0000000,50a35fd..ecc642e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,613 +1,613 @@@
 -                mChildren = mStorageManager.getFolderContent(mLocalFolder);
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015 ownCloud Inc.
+  *
+  *   This program is free software: you can redistribute it and/or modify
+  *   it under the terms of the GNU General Public License version 2,
+  *   as published by the Free Software Foundation.
+  *
+  *   This program is distributed in the hope that it will be useful,
+  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  *   GNU General Public License for more details.
+  *
+  *   You should have received a copy of the GNU General Public License
+  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  *
+  */
+ package com.owncloud.android.operations;
+ import java.io.File;
+ import java.io.FileInputStream;
+ import java.io.FileOutputStream;
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
+ import java.util.ArrayList;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Vector;
+ import org.apache.http.HttpStatus;
+ import android.accounts.Account;
+ import android.content.Context;
+ import android.content.Intent;
+ import android.util.Log;
+ //import android.support.v4.content.LocalBroadcastManager;
+ import com.owncloud.android.MainApp;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.lib.common.OwnCloudClient;
+ import com.owncloud.android.lib.resources.shares.OCShare;
+ import com.owncloud.android.lib.common.operations.RemoteOperation;
+ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
+ import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
+ import com.owncloud.android.lib.resources.files.FileUtils;
+ import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
+ import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
+ import com.owncloud.android.lib.resources.files.RemoteFile;
+ import com.owncloud.android.syncadapter.FileSyncAdapter;
+ import com.owncloud.android.utils.FileStorageUtils;
+ /**
+  *  Remote operation performing the synchronization of the list of files contained 
+  *  in a folder identified with its remote path.
+  *  
+  *  Fetches the list and properties of the files contained in the given folder, including their 
+  *  properties, and updates the local database with them.
+  *  
+  *  Does NOT enter in the child folders to synchronize their contents also.
+  */
+ public class RefreshFolderOperation extends RemoteOperation {
+     private static final String TAG = RefreshFolderOperation.class.getSimpleName();
+     public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED  = 
+             RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
+     public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED    = 
+             RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
+     
+     /** Time stamp for the synchronization process in progress */
+     private long mCurrentSyncTime;
+     
+     /** Remote folder to synchronize */
+     private OCFile mLocalFolder;
+     
+     /** Access to the local database */
+     private FileDataStorageManager mStorageManager;
+     
+     /** Account where the file to synchronize belongs */
+     private Account mAccount;
+     
+     /** Android context; necessary to send requests to the download service */
+     private Context mContext;
+     
+     /** Files and folders contained in the synchronized folder after a successful operation */
+     private List<OCFile> mChildren;
+     /** Counter of conflicts found between local and remote files */
+     private int mConflictsFound;
+     /** Counter of failed operations in synchronization of kept-in-sync files */
+     private int mFailsInFavouritesFound;
+     /**
+      * Map of remote and local paths to files that where locally stored in a location 
+      * out of the ownCloud folder and couldn't be copied automatically into it 
+      **/
+     private Map<String, String> mForgottenLocalFiles;
+     /** 'True' means that this operation is part of a full account synchronization */ 
+     private boolean mSyncFullAccount;
+     /** 'True' means that Share resources bound to the files into should be refreshed also */
+     private boolean mIsShareSupported;
+     
+     /** 'True' means that the remote folder changed and should be fetched */
+     private boolean mRemoteFolderChanged;
+     /** 'True' means that Etag will be ignored */
+     private boolean mIgnoreETag;
+     
+     /**
+      * Creates a new instance of {@link RefreshFolderOperation}.
+      * 
+      * @param   folder                  Folder to synchronize.
+      * @param   currentSyncTime         Time stamp for the synchronization process in progress.
+      * @param   syncFullAccount         'True' means that this operation is part of a full account 
+      *                                  synchronization.
+      * @param   isShareSupported        'True' means that the server supports the sharing API.           
+      * @param   ignoreETag              'True' means that the content of the remote folder should
+      *                                  be fetched and updated even though the 'eTag' did not 
+      *                                  change.  
+      * @param   dataStorageManager      Interface with the local database.
+      * @param   account                 ownCloud account where the folder is located. 
+      * @param   context                 Application context.
+      */
+     public RefreshFolderOperation(OCFile folder,
+                                   long currentSyncTime,
+                                   boolean syncFullAccount,
+                                   boolean isShareSupported,
+                                   boolean ignoreETag,
+                                   FileDataStorageManager dataStorageManager,
+                                   Account account,
+                                   Context context) {
+         mLocalFolder = folder;
+         mCurrentSyncTime = currentSyncTime;
+         mSyncFullAccount = syncFullAccount;
+         mIsShareSupported = isShareSupported;
+         mStorageManager = dataStorageManager;
+         mAccount = account;
+         mContext = context;
+         mForgottenLocalFiles = new HashMap<String, String>();
+         mRemoteFolderChanged = false;
+         mIgnoreETag = ignoreETag;
+     }
+     
+     
+     public int getConflictsFound() {
+         return mConflictsFound;
+     }
+     
+     public int getFailsInFavouritesFound() {
+         return mFailsInFavouritesFound;
+     }
+     
+     public Map<String, String> getForgottenLocalFiles() {
+         return mForgottenLocalFiles;
+     }
+     
+     /**
+      * Returns the list of files and folders contained in the synchronized folder, 
+      * if called after synchronization is complete.
+      * 
+      * @return  List of files and folders contained in the synchronized folder.
+      */
+     public List<OCFile> getChildren() {
+         return mChildren;
+     }
+     
+     /**
+      * Performs the synchronization.
+      * 
+      * {@inheritDoc}
+      */
+     @Override
+     protected RemoteOperationResult run(OwnCloudClient client) {
+         RemoteOperationResult result = null;
+         mFailsInFavouritesFound = 0;
+         mConflictsFound = 0;
+         mForgottenLocalFiles.clear();
+         
+         if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
+             updateOCVersion(client);
+         }
+         
+         result = checkForChanges(client);
+         
+         if (result.isSuccess()) {
+             if (mRemoteFolderChanged) {
+                 result = fetchAndSyncRemoteFolder(client);
+             } else {
 -        List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder);
++                mChildren = mStorageManager.getFolderContent(mLocalFolder, false);
+             }
+         }
+         
+         if (!mSyncFullAccount) {            
+             sendLocalBroadcast(
+                     EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result
+             );
+         }
+         
+         if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) {
+             refreshSharesForFolder(client); // share result is ignored 
+         }
+         
+         if (!mSyncFullAccount) {            
+             sendLocalBroadcast(
+                     EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result
+             );
+         }
+         
+         return result;
+         
+     }
+     private void updateOCVersion(OwnCloudClient client) {
+         UpdateOCVersionOperation update = new UpdateOCVersionOperation(mAccount, mContext);
+         RemoteOperationResult result = update.execute(client);
+         if (result.isSuccess()) {
+             mIsShareSupported = update.getOCVersion().isSharedSupported();
+         }
+     }
+     
+     private RemoteOperationResult checkForChanges(OwnCloudClient client) {
+         mRemoteFolderChanged = true;
+         RemoteOperationResult result = null;
+         String remotePath = null;
+         remotePath = mLocalFolder.getRemotePath();
+         Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
+         
+         // remote request 
+         ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath);
+         result = operation.execute(client);
+         if (result.isSuccess()){
+             OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
+             if (!mIgnoreETag) {
+                 // check if remote and local folder are different
+                 mRemoteFolderChanged = 
+                         !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
+             }
+             result = new RemoteOperationResult(ResultCode.OK);
+         
+             Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+                     (mRemoteFolderChanged ? "changed" : "not changed"));
+             
+         } else {
+             // check failed
+             if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
+                 removeLocalFolder();
+             }
+             if (result.isException()) {
+                 Log_OC.e(TAG, "Checked " + mAccount.name + remotePath  + " : " + 
+                         result.getLogMessage(), result.getException());
+             } else {
+                 Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+                         result.getLogMessage());
+             }
+         }
+         
+         return result;
+     }
+     private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) {
+         String remotePath = mLocalFolder.getRemotePath();
+         ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath);
+         RemoteOperationResult result = operation.execute(client);
+         Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
+         
+         if (result.isSuccess()) {
+             synchronizeData(result.getData(), client);
+             if (mConflictsFound > 0  || mFailsInFavouritesFound > 0) { 
+                 result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);   
+                     // should be a different result code, but will do the job
+             }
+         } else {
+             if (result.getCode() == ResultCode.FILE_NOT_FOUND)
+                 removeLocalFolder();
+         }
+         
+         return result;
+     }
+     
+     private void removeLocalFolder() {
+         if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
+             String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
+             mStorageManager.removeFolder(
+                     mLocalFolder, 
+                     true, 
+                     (   mLocalFolder.isDown() && 
+                             mLocalFolder.getStoragePath().startsWith(currentSavePath)
+                     )
+             );
+         }
+     }
+     /**
+      *  Synchronizes the data retrieved from the server about the contents of the target folder 
+      *  with the current data in the local database.
+      *  
+      *  Grants that mChildren is updated with fresh data after execution.
+      *  
+      *  @param folderAndFiles   Remote folder and children files in Folder 
+      *  
+      *  @param client           Client instance to the remote server where the data were 
+      *                          retrieved.  
+      *  @return                 'True' when any change was made in the local data, 'false' otherwise
+      */
+     private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client) {
+         // get 'fresh data' from the database
+         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
+         // parse data from remote folder 
+         OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
+         remoteFolder.setParentId(mLocalFolder.getParentId());
+         remoteFolder.setFileId(mLocalFolder.getFileId());
+         
+         Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() 
+                 + " changed - starting update of local data ");
+         
+         List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
+         List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
+         // get current data about local contents of the folder to synchronize
++        List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder, true);
+         Map<String, OCFile> localFilesMap = new HashMap<String, OCFile>(localFiles.size());
+         for (OCFile file : localFiles) {
+             localFilesMap.put(file.getRemotePath(), file);
+         }
+         
+         // loop to update every child
+         OCFile remoteFile = null, localFile = null;
+         for (int i=1; i<folderAndFiles.size(); i++) {
+             /// new OCFile instance with the data from the server
+             remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
+             remoteFile.setParentId(mLocalFolder.getFileId());
+             /// retrieve local data for the read file 
+             //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
+             localFile = localFilesMap.remove(remoteFile.getRemotePath());
+             
+             /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
+             remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
+             if (localFile != null) {
+                 // some properties of local state are kept unmodified
+                 remoteFile.setFileId(localFile.getFileId());
+                 remoteFile.setKeepInSync(localFile.keepInSync());
+                 remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
+                 remoteFile.setModificationTimestampAtLastSyncForData(
+                         localFile.getModificationTimestampAtLastSyncForData()
+                 );
+                 remoteFile.setStoragePath(localFile.getStoragePath());
+                 // eTag will not be updated unless contents are synchronized 
+                 //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
+                 remoteFile.setEtag(localFile.getEtag());    
+                 if (remoteFile.isFolder()) {
+                     remoteFile.setFileLength(localFile.getFileLength()); 
+                         // TODO move operations about size of folders to FileContentProvider
+                 } else if (mRemoteFolderChanged && remoteFile.isImage() &&
+                         remoteFile.getModificationTimestamp() !=
+                                 localFile.getModificationTimestamp()) {
+                     remoteFile.setNeedsUpdateThumbnail(true);
+                     Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
+                 }
+                 remoteFile.setPublicLink(localFile.getPublicLink());
+                 remoteFile.setShareByLink(localFile.isShareByLink());
+             } else {
+                 // remote eTag will not be updated unless contents are synchronized 
+                 //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
+                 remoteFile.setEtag(""); 
+             }
+             /// check and fix, if needed, local storage path
+             checkAndFixForeignStoragePath(remoteFile);      // policy - local files are COPIED 
+                                                             // into the ownCloud local folder;
+             searchForLocalFileInDefaultPath(remoteFile);    // legacy   
+             /// prepare content synchronization for kept-in-sync files
+             if (remoteFile.keepInSync()) {
+                 SynchronizeFileOperation operation = new SynchronizeFileOperation(  localFile,        
+                                                                                     remoteFile, 
+                                                                                     mAccount, 
+                                                                                     true, 
+                                                                                     mContext
+                                                                                     );
+                 
+                 filesToSyncContents.add(operation);
+             }
+             
+             updatedFiles.add(remoteFile);
+         }
+         // save updated contents in local database
+         mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
+         // request for the synchronization of file contents AFTER saving current remote properties
+         startContentSynchronizations(filesToSyncContents, client);
+         mChildren = updatedFiles;
+     }
+     /**
+      * Performs a list of synchronization operations, determining if a download or upload is needed
+      * or if exists conflict due to changes both in local and remote contents of the each file.
+      * 
+      * If download or upload is needed, request the operation to the corresponding service and goes 
+      * on.
+      * 
+      * @param filesToSyncContents       Synchronization operations to execute.
+      * @param client                    Interface to the remote ownCloud server.
+      */
+     private void startContentSynchronizations(
+             List<SynchronizeFileOperation> filesToSyncContents, OwnCloudClient client
+         ) {
+         RemoteOperationResult contentsResult = null;
+         for (SynchronizeFileOperation op: filesToSyncContents) {
+             contentsResult = op.execute(mStorageManager, mContext);   // async
+             if (!contentsResult.isSuccess()) {
+                 if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) {
+                     mConflictsFound++;
+                 } else {
+                     mFailsInFavouritesFound++;
+                     if (contentsResult.getException() != null) {
+                         Log_OC.e(TAG, "Error while synchronizing favourites : " 
+                                 +  contentsResult.getLogMessage(), contentsResult.getException());
+                     } else {
+                         Log_OC.e(TAG, "Error while synchronizing favourites : " 
+                                 + contentsResult.getLogMessage());
+                     }
+                 }
+             }   // won't let these fails break the synchronization process
+         }
+     }
+     public boolean isMultiStatus(int status) {
+         return (status == HttpStatus.SC_MULTI_STATUS); 
+     }
+     /**
+      * Creates and populates a new {@link OCFile} object with the data read from the server.
+      * 
+      * @param remote    remote file read from the server (remote file or folder).
+      * @return          New OCFile instance representing the remote resource described by we.
+      */
+     private OCFile fillOCFile(RemoteFile remote) {
+         OCFile file = new OCFile(remote.getRemotePath());
+         file.setCreationTimestamp(remote.getCreationTimestamp());
+         file.setFileLength(remote.getLength());
+         file.setMimetype(remote.getMimeType());
+         file.setModificationTimestamp(remote.getModifiedTimestamp());
+         file.setEtag(remote.getEtag());
+         file.setPermissions(remote.getPermissions());
+         file.setRemoteId(remote.getRemoteId());
+         return file;
+     }
+     
+     /**
+      * Checks the storage path of the OCFile received as parameter. 
+      * If it's out of the local ownCloud folder, tries to copy the file inside it. 
+      * 
+      * If the copy fails, the link to the local file is nullified. The account of forgotten 
+      * files is kept in {@link #mForgottenLocalFiles}
+      *) 
+      * @param file      File to check and fix.
+      */
+     private void checkAndFixForeignStoragePath(OCFile file) {
+         String storagePath = file.getStoragePath();
+         String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
+         if (storagePath != null && !storagePath.equals(expectedPath)) {
+             /// fix storagePaths out of the local ownCloud folder
+             File originalFile = new File(storagePath);
+             if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
+                 mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
+                 file.setStoragePath(null);
+                     
+             } else {
+                 InputStream in = null;
+                 OutputStream out = null;
+                 try {
+                     File expectedFile = new File(expectedPath);
+                     File expectedParent = expectedFile.getParentFile();
+                     expectedParent.mkdirs();
+                     if (!expectedParent.isDirectory()) {
+                         throw new IOException(
+                                 "Unexpected error: parent directory could not be created"
+                         );
+                     }
+                     expectedFile.createNewFile();
+                     if (!expectedFile.isFile()) {
+                         throw new IOException("Unexpected error: target file could not be created");
+                     }                    
+                     in = new FileInputStream(originalFile);
+                     out = new FileOutputStream(expectedFile);
+                     byte[] buf = new byte[1024];
+                     int len;
+                     while ((len = in.read(buf)) > 0){
+                         out.write(buf, 0, len);
+                     }
+                     file.setStoragePath(expectedPath);
+                     
+                 } catch (Exception e) {
+                     Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e);
+                     mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
+                     file.setStoragePath(null);
+                     
+                 } finally {
+                     try {
+                         if (in != null) in.close();
+                     } catch (Exception e) {
+                         Log_OC.d(TAG, "Weird exception while closing input stream for " 
+                                 + storagePath + " (ignoring)", e);
+                     }
+                     try {
+                         if (out != null) out.close();
+                     } catch (Exception e) {
+                         Log_OC.d(TAG, "Weird exception while closing output stream for " 
+                                 + expectedPath + " (ignoring)", e);
+                     }
+                 }
+             }
+         }
+     }
+     
+     
+     private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
+         RemoteOperationResult result = null;
+         
+         // remote request 
+         GetRemoteSharesForFileOperation operation = 
+                 new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true);
+         result = operation.execute(client);
+         
+         if (result.isSuccess()) {
+             // update local database
+             ArrayList<OCShare> shares = new ArrayList<OCShare>();
+             for(Object obj: result.getData()) {
+                 shares.add((OCShare) obj);
+             }
+             mStorageManager.saveSharesInFolder(shares, mLocalFolder);
+         }
+         return result;
+     }
+     
+     /**
+      * Scans the default location for saving local copies of files searching for
+      * a 'lost' file with the same full name as the {@link OCFile} received as 
+      * parameter.
+      *  
+      * @param file      File to associate a possible 'lost' local file.
+      */
+     private void searchForLocalFileInDefaultPath(OCFile file) {
+         if (file.getStoragePath() == null && !file.isFolder()) {
+             File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
+             if (f.exists()) {
+                 file.setStoragePath(f.getAbsolutePath());
+                 file.setLastSyncDateForData(f.lastModified());
+             }
+         }
+     }
+     
+     /**
+      * Sends a message to any application component interested in the progress 
+      * of the synchronization.
+      * 
+      * @param event
+      * @param dirRemotePath     Remote path of a folder that was just synchronized 
+      *                          (with or without success)
+      * @param result
+      */
+     private void sendLocalBroadcast(
+             String event, String dirRemotePath, RemoteOperationResult result
+         ) {
+         Log_OC.d(TAG, "Send broadcast " + event);
+         Intent intent = new Intent(event);
+         intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name);
+         if (dirRemotePath != null) {
+             intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath);
+         }
+         intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result);
+         mContext.sendStickyBroadcast(intent);
+         //LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
+     }
+     public boolean getRemoteFolderChanged() {
+         return mRemoteFolderChanged;
+     }
+ }
@@@ -1,5 -1,8 +1,8 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
  
  package com.owncloud.android.operations;
  
 +import java.io.File;
 +import java.io.FileInputStream;
 +import java.io.FileOutputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.io.OutputStream;
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Vector;
 +
 +import org.apache.http.HttpStatus;
 +
  import android.accounts.Account;
  import android.content.Context;
  import android.content.Intent;
  import android.util.Log;
- //import android.support.v4.content.LocalBroadcastManager;
  
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.files.services.FileDownloader;
  import com.owncloud.android.lib.common.OwnCloudClient;
+ import com.owncloud.android.lib.common.operations.OperationCancelledException;
 +import com.owncloud.android.lib.common.operations.RemoteOperation;
  import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.lib.common.utils.Log_OC;
 +import com.owncloud.android.lib.resources.files.FileUtils;
  import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
  import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
  import com.owncloud.android.lib.resources.files.RemoteFile;
 +import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
 +import com.owncloud.android.lib.resources.shares.OCShare;
 +import com.owncloud.android.syncadapter.FileSyncAdapter;
+ import com.owncloud.android.operations.common.SyncOperation;
+ import com.owncloud.android.services.OperationsService;
  import com.owncloud.android.utils.FileStorageUtils;
  
+ import java.io.File;
+ import java.util.ArrayList;
+ import java.util.HashMap;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Vector;
+ import java.util.concurrent.atomic.AtomicBoolean;
+ //import android.support.v4.content.LocalBroadcastManager;
  
  
  /**
   *  properties, and updates the local database with them.
   *  
   *  Does NOT enter in the child folders to synchronize their contents also.
-  * 
-  *  @author David A. Velasco
   */
- public class SynchronizeFolderOperation extends RemoteOperation {
+ public class SynchronizeFolderOperation extends SyncOperation {
  
      private static final String TAG = SynchronizeFolderOperation.class.getSimpleName();
  
-     public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED  = 
-             SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
-     public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED    = 
-             SynchronizeFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
-     
      /** Time stamp for the synchronization process in progress */
      private long mCurrentSyncTime;
-     
-     /** Remote folder to synchronize */
-     private OCFile mLocalFolder;
-     
-     /** Access to the local database */
-     private FileDataStorageManager mStorageManager;
+     /** Remote path of the folder to synchronize */
+     private String mRemotePath;
      
      /** Account where the file to synchronize belongs */
      private Account mAccount;
-     
      /** Android context; necessary to send requests to the download service */
      private Context mContext;
-     
+     /** Locally cached information about folder to synchronize */
+     private OCFile mLocalFolder;
      /** Files and folders contained in the synchronized folder after a successful operation */
-     private List<OCFile> mChildren;
+     //private List<OCFile> mChildren;
  
      /** Counter of conflicts found between local and remote files */
      private int mConflictsFound;
  
      /** Counter of failed operations in synchronization of kept-in-sync files */
-     private int mFailsInFavouritesFound;
+     private int mFailsInFileSyncsFound;
  
-     /**
-      * Map of remote and local paths to files that where locally stored in a location 
-      * out of the ownCloud folder and couldn't be copied automatically into it 
-      **/
-     private Map<String, String> mForgottenLocalFiles;
-     /** 'True' means that this operation is part of a full account synchronization */ 
-     private boolean mSyncFullAccount;
-     /** 'True' means that Share resources bound to the files into should be refreshed also */
-     private boolean mIsShareSupported;
-     
      /** 'True' means that the remote folder changed and should be fetched */
      private boolean mRemoteFolderChanged;
  
-     /** 'True' means that Etag will be ignored */
-     private boolean mIgnoreETag;
+     private List<OCFile> mFilesForDirectDownload;
+         // to avoid extra PROPFINDs when there was no change in the folder
      
+     private List<SyncOperation> mFilesToSyncContentsWithoutUpload;
+         // this will go out when 'folder synchronization' replaces 'folder download'; step by step  
+     private List<SyncOperation> mFavouriteFilesToSyncContents;
+         // this will be used for every file when 'folder synchronization' replaces 'folder download' 
+     private final AtomicBoolean mCancellationRequested;
      /**
       * Creates a new instance of {@link SynchronizeFolderOperation}.
-      * 
-      * @param   folder                  Folder to synchronize.
-      * @param   currentSyncTime         Time stamp for the synchronization process in progress.
-      * @param   syncFullAccount         'True' means that this operation is part of a full account 
-      *                                  synchronization.
-      * @param   isShareSupported        'True' means that the server supports the sharing API.           
-      * @param   ignoreEtag              'True' means that the content of the remote folder should
-      *                                  be fetched and updated even though the 'eTag' did not 
-      *                                  change.  
-      * @param   dataStorageManager      Interface with the local database.
-      * @param   account                 ownCloud account where the folder is located. 
+      *
       * @param   context                 Application context.
+      * @param   remotePath              Path to synchronize.
+      * @param   account                 ownCloud account where the folder is located.
+      * @param   currentSyncTime         Time stamp for the synchronization process in progress.
       */
-     public SynchronizeFolderOperation(  OCFile folder, 
-                                         long currentSyncTime, 
-                                         boolean syncFullAccount,
-                                         boolean isShareSupported,
-                                         boolean ignoreETag,
-                                         FileDataStorageManager dataStorageManager, 
-                                         Account account, 
-                                         Context context ) {
-         mLocalFolder = folder;
+     public SynchronizeFolderOperation(Context context, String remotePath, Account account,
+                                       long currentSyncTime){
+         mRemotePath = remotePath;
          mCurrentSyncTime = currentSyncTime;
-         mSyncFullAccount = syncFullAccount;
-         mIsShareSupported = isShareSupported;
-         mStorageManager = dataStorageManager;
          mAccount = account;
          mContext = context;
-         mForgottenLocalFiles = new HashMap<String, String>();
          mRemoteFolderChanged = false;
-         mIgnoreETag = ignoreETag;
+         mFilesForDirectDownload = new Vector<OCFile>();
+         mFilesToSyncContentsWithoutUpload = new Vector<SyncOperation>();
+         mFavouriteFilesToSyncContents = new Vector<SyncOperation>();
+         mCancellationRequested = new AtomicBoolean(false);
      }
-     
-     
      public int getConflictsFound() {
          return mConflictsFound;
      }
-     
-     public int getFailsInFavouritesFound() {
-         return mFailsInFavouritesFound;
-     }
-     
-     public Map<String, String> getForgottenLocalFiles() {
-         return mForgottenLocalFiles;
-     }
-     
-     /**
-      * Returns the list of files and folders contained in the synchronized folder, 
-      * if called after synchronization is complete.
-      * 
-      * @return  List of files and folders contained in the synchronized folder.
-      */
-     public List<OCFile> getChildren() {
-         return mChildren;
+     public int getFailsInFileSyncsFound() {
+         return mFailsInFileSyncsFound;
      }
-     
      /**
       * Performs the synchronization.
-      * 
+      *
       * {@inheritDoc}
       */
      @Override
      protected RemoteOperationResult run(OwnCloudClient client) {
          RemoteOperationResult result = null;
-         mFailsInFavouritesFound = 0;
+         mFailsInFileSyncsFound = 0;
          mConflictsFound = 0;
-         mForgottenLocalFiles.clear();
-         
-         if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
-             updateOCVersion(client);
-         }
-         
-         result = checkForChanges(client);
          
-         if (result.isSuccess()) {
-             if (mRemoteFolderChanged) {
-                 result = fetchAndSyncRemoteFolder(client);
-             } else {
-                 mChildren = mStorageManager.getFolderContent(mLocalFolder, false);
+         try {
+             // get locally cached information about folder 
+             mLocalFolder = getStorageManager().getFileByPath(mRemotePath);   
+             
+             result = checkForChanges(client);
+     
+             if (result.isSuccess()) {
+                 if (mRemoteFolderChanged) {
+                     result = fetchAndSyncRemoteFolder(client);
+                     
+                 } else {
+                     prepareOpsFromLocalKnowledge();
+                 }
+                 
+                 if (result.isSuccess()) {
+                     syncContents(client);
+                 }
              }
+             
+             if (mCancellationRequested.get()) {
+                 throw new OperationCancelledException();
+             }
+             
+         } catch (OperationCancelledException e) {
+             result = new RemoteOperationResult(e);
          }
-         
-         if (!mSyncFullAccount) {            
-             sendLocalBroadcast(
-                     EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result
-             );
-         }
-         
-         if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) {
-             refreshSharesForFolder(client); // share result is ignored 
-         }
-         
-         if (!mSyncFullAccount) {            
-             sendLocalBroadcast(
-                     EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result
-             );
-         }
-         
-         return result;
-         
-     }
  
+         return result;
  
-     private void updateOCVersion(OwnCloudClient client) {
-         UpdateOCVersionOperation update = new UpdateOCVersionOperation(mAccount, mContext);
-         RemoteOperationResult result = update.execute(client);
-         if (result.isSuccess()) {
-             mIsShareSupported = update.getOCVersion().isSharedSupported();
-         }
      }
  
-     
-     private RemoteOperationResult checkForChanges(OwnCloudClient client) {
+     private RemoteOperationResult checkForChanges(OwnCloudClient client)
+             throws OperationCancelledException {
+         Log_OC.d(TAG, "Checking changes in " + mAccount.name + mRemotePath);
          mRemoteFolderChanged = true;
          RemoteOperationResult result = null;
-         String remotePath = null;
-         remotePath = mLocalFolder.getRemotePath();
-         Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
          
-         // remote request 
-         ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath);
+         if (mCancellationRequested.get()) {
+             throw new OperationCancelledException();
+         }
+         
+         // remote request
+         ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mRemotePath);
          result = operation.execute(client);
          if (result.isSuccess()){
              OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
  
-             if (!mIgnoreETag) {
-                 // check if remote and local folder are different
-                 mRemoteFolderChanged = 
+             // check if remote and local folder are different
+             mRemoteFolderChanged =
                          !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
-             }
  
              result = new RemoteOperationResult(ResultCode.OK);
-         
-             Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+             Log_OC.i(TAG, "Checked " + mAccount.name + mRemotePath + " : " +
                      (mRemoteFolderChanged ? "changed" : "not changed"));
-             
          } else {
              // check failed
              if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
                  removeLocalFolder();
              }
              if (result.isException()) {
-                 Log_OC.e(TAG, "Checked " + mAccount.name + remotePath  + " : " + 
+                 Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath  + " : " +
                          result.getLogMessage(), result.getException());
              } else {
-                 Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+                 Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " +
                          result.getLogMessage());
              }
          }
-         
          return result;
      }
  
  
-     private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) {
-         String remotePath = mLocalFolder.getRemotePath();
-         ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath);
-         RemoteOperationResult result = operation.execute(client);
-         Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
+     private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client)
+             throws OperationCancelledException {
+         if (mCancellationRequested.get()) {
+             throw new OperationCancelledException();
+         }
          
+         ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(mRemotePath);
+         RemoteOperationResult result = operation.execute(client);
+         Log_OC.d(TAG, "Synchronizing " + mAccount.name + mRemotePath);
          if (result.isSuccess()) {
              synchronizeData(result.getData(), client);
-             if (mConflictsFound > 0  || mFailsInFavouritesFound > 0) { 
-                 result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);   
+             if (mConflictsFound > 0  || mFailsInFileSyncsFound > 0) {
+                 result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
                      // should be a different result code, but will do the job
              }
          } else {
                  removeLocalFolder();
          }
          
          return result;
      }
  
-     
      private void removeLocalFolder() {
-         if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
+         FileDataStorageManager storageManager = getStorageManager();
+         if (storageManager.fileExists(mLocalFolder.getFileId())) {
              String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
-             mStorageManager.removeFolder(
-                     mLocalFolder, 
-                     true, 
-                     (   mLocalFolder.isDown() && 
+             storageManager.removeFolder(
+                     mLocalFolder,
+                     true,
+                     (   mLocalFolder.isDown() &&        // TODO: debug, I think this is
+                                                         // always false for folders
                              mLocalFolder.getStoragePath().startsWith(currentSavePath)
                      )
              );
  
  
      /**
-      *  Synchronizes the data retrieved from the server about the contents of the target folder 
+      *  Synchronizes the data retrieved from the server about the contents of the target folder
       *  with the current data in the local database.
-      *  
+      *
       *  Grants that mChildren is updated with fresh data after execution.
-      *  
-      *  @param folderAndFiles   Remote folder and children files in Folder 
-      *  
-      *  @param client           Client instance to the remote server where the data were 
-      *                          retrieved.  
+      *
+      *  @param folderAndFiles   Remote folder and children files in Folder
+      *
+      *  @param client           Client instance to the remote server where the data were
+      *                          retrieved.
       *  @return                 'True' when any change was made in the local data, 'false' otherwise
       */
-     private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client) {
-         // get 'fresh data' from the database
-         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
-         // parse data from remote folder 
+     private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client)
+             throws OperationCancelledException {
+         FileDataStorageManager storageManager = getStorageManager();
+         
+         // parse data from remote folder
          OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
          remoteFolder.setParentId(mLocalFolder.getParentId());
          remoteFolder.setFileId(mLocalFolder.getFileId());
-         
-         Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() 
+         Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath()
                  + " changed - starting update of local data ");
-         
          List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
-         List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
+         mFilesForDirectDownload.clear();
+         mFilesToSyncContentsWithoutUpload.clear();
+         mFavouriteFilesToSyncContents.clear();
+         if (mCancellationRequested.get()) {
+             throw new OperationCancelledException();
+         }
  
          // get current data about local contents of the folder to synchronize
-         List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder, false);
 -        List<OCFile> localFiles = storageManager.getFolderContent(mLocalFolder);
++        List<OCFile> localFiles = storageManager.getFolderContent(mLocalFolder, true);
          Map<String, OCFile> localFilesMap = new HashMap<String, OCFile>(localFiles.size());
          for (OCFile file : localFiles) {
              localFilesMap.put(file.getRemotePath(), file);
          }
-         
-         // loop to update every child
+         // loop to synchronize every child
          OCFile remoteFile = null, localFile = null;
          for (int i=1; i<folderAndFiles.size(); i++) {
              /// new OCFile instance with the data from the server
              remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
              remoteFile.setParentId(mLocalFolder.getFileId());
  
-             /// retrieve local data for the read file 
+             /// retrieve local data for the read file
              //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
              localFile = localFilesMap.remove(remoteFile.getRemotePath());
-             
              /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
              remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
              if (localFile != null) {
                          localFile.getModificationTimestampAtLastSyncForData()
                  );
                  remoteFile.setStoragePath(localFile.getStoragePath());
-                 // eTag will not be updated unless contents are synchronized 
+                 // eTag will not be updated unless contents are synchronized
                  //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                 remoteFile.setEtag(localFile.getEtag());    
+                 remoteFile.setEtag(localFile.getEtag());
                  if (remoteFile.isFolder()) {
-                     remoteFile.setFileLength(localFile.getFileLength()); 
+                     remoteFile.setFileLength(localFile.getFileLength());
                          // TODO move operations about size of folders to FileContentProvider
                  } else if (mRemoteFolderChanged && remoteFile.isImage() &&
-                         remoteFile.getModificationTimestamp() != localFile.getModificationTimestamp()) {
+                         remoteFile.getModificationTimestamp() !=
+                                 localFile.getModificationTimestamp()) {
                      remoteFile.setNeedsUpdateThumbnail(true);
                      Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                  }
                  remoteFile.setPublicLink(localFile.getPublicLink());
                  remoteFile.setShareByLink(localFile.isShareByLink());
              } else {
-                 // remote eTag will not be updated unless contents are synchronized 
+                 // remote eTag will not be updated unless contents are synchronized
                  //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                 remoteFile.setEtag(""); 
+                 remoteFile.setEtag("");
              }
  
              /// check and fix, if needed, local storage path
-             checkAndFixForeignStoragePath(remoteFile);      // policy - local files are COPIED 
-                                                             // into the ownCloud local folder;
-             searchForLocalFileInDefaultPath(remoteFile);    // legacy   
-             /// prepare content synchronization for kept-in-sync files
-             if (remoteFile.keepInSync()) {
-                 SynchronizeFileOperation operation = new SynchronizeFileOperation(  localFile,        
-                                                                                     remoteFile, 
-                                                                                     mAccount, 
-                                                                                     true, 
-                                                                                     mContext
-                                                                                     );
+             searchForLocalFileInDefaultPath(remoteFile);
+             
+             /// classify file to sync/download contents later
+             if (remoteFile.isFolder()) {
+                 /// to download children files recursively
+                 synchronized(mCancellationRequested) {
+                     if (mCancellationRequested.get()) {
+                         throw new OperationCancelledException();
+                     }
+                     startSyncFolderOperation(remoteFile.getRemotePath());
+                 }
+             } else if (remoteFile.keepInSync()) {
+                 /// prepare content synchronization for kept-in-sync files
+                 SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                         localFile,
+                         remoteFile,
+                         mAccount,
+                         true,
+                         mContext
+                     );
+                 mFavouriteFilesToSyncContents.add(operation);
                  
-                 filesToSyncContents.add(operation);
+             } else {
+                 /// prepare limited synchronization for regular files
+                 SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                         localFile,
+                         remoteFile,
+                         mAccount,
+                         true,
+                         false,
+                         mContext
+                     );
+                 mFilesToSyncContentsWithoutUpload.add(operation);
              }
-             
              updatedFiles.add(remoteFile);
          }
  
          // save updated contents in local database
-         mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
+         storageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
+     }
+     
+     
+     private void prepareOpsFromLocalKnowledge() throws OperationCancelledException {
 -        List<OCFile> children = getStorageManager().getFolderContent(mLocalFolder);
++        // TODO TOBI ist das richtig?
++        List<OCFile> children = getStorageManager().getFolderContent(mLocalFolder, true);
+         for (OCFile child : children) {
+             /// classify file to sync/download contents later
+             if (child.isFolder()) {
+                 /// to download children files recursively
+                 synchronized(mCancellationRequested) {
+                     if (mCancellationRequested.get()) {
+                         throw new OperationCancelledException();
+                     }
+                     startSyncFolderOperation(child.getRemotePath());
+                 }
  
-         // request for the synchronization of file contents AFTER saving current remote properties
-         startContentSynchronizations(filesToSyncContents, client);
+             } else {
+                 /// prepare limited synchronization for regular files
+                 if (!child.isDown()) {
+                     mFilesForDirectDownload.add(child);
+                 }
+             }
+         }
+     }
  
-         mChildren = updatedFiles;
+     private void syncContents(OwnCloudClient client) throws OperationCancelledException {
+         startDirectDownloads();
+         startContentSynchronizations(mFilesToSyncContentsWithoutUpload, client);
+         startContentSynchronizations(mFavouriteFilesToSyncContents, client);
+     }
+     
+     private void startDirectDownloads() throws OperationCancelledException {
+         for (OCFile file : mFilesForDirectDownload) {
+             synchronized(mCancellationRequested) {
+                 if (mCancellationRequested.get()) {
+                     throw new OperationCancelledException();
+                 }
+                 Intent i = new Intent(mContext, FileDownloader.class);
+                 i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);
+                 i.putExtra(FileDownloader.EXTRA_FILE, file);
+                 mContext.startService(i);
+             }
+         }
      }
  
      /**
       * Performs a list of synchronization operations, determining if a download or upload is needed
       * or if exists conflict due to changes both in local and remote contents of the each file.
-      * 
-      * If download or upload is needed, request the operation to the corresponding service and goes 
+      *
+      * If download or upload is needed, request the operation to the corresponding service and goes
       * on.
-      * 
+      *
       * @param filesToSyncContents       Synchronization operations to execute.
       * @param client                    Interface to the remote ownCloud server.
       */
-     private void startContentSynchronizations(
-             List<SynchronizeFileOperation> filesToSyncContents, OwnCloudClient client
-         ) {
+     private void startContentSynchronizations(List<SyncOperation> filesToSyncContents,
+                                               OwnCloudClient client)
+             throws OperationCancelledException {
+         Log_OC.v(TAG, "Starting content synchronization... ");
          RemoteOperationResult contentsResult = null;
-         for (SynchronizeFileOperation op: filesToSyncContents) {
-             contentsResult = op.execute(mStorageManager, mContext);   // async
+         for (SyncOperation op: filesToSyncContents) {
+             if (mCancellationRequested.get()) {
+                 throw new OperationCancelledException();
+             }
+             contentsResult = op.execute(getStorageManager(), mContext);
              if (!contentsResult.isSuccess()) {
                  if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) {
                      mConflictsFound++;
                  } else {
-                     mFailsInFavouritesFound++;
+                     mFailsInFileSyncsFound++;
                      if (contentsResult.getException() != null) {
-                         Log_OC.e(TAG, "Error while synchronizing favourites : " 
+                         Log_OC.e(TAG, "Error while synchronizing file : "
                                  +  contentsResult.getLogMessage(), contentsResult.getException());
                      } else {
-                         Log_OC.e(TAG, "Error while synchronizing favourites : " 
+                         Log_OC.e(TAG, "Error while synchronizing file : "
                                  + contentsResult.getLogMessage());
                      }
                  }
+                 // TODO - use the errors count in notifications
              }   // won't let these fails break the synchronization process
          }
      }
  
-     public boolean isMultiStatus(int status) {
-         return (status == HttpStatus.SC_MULTI_STATUS); 
-     }
+     
      /**
-      * Creates and populates a new {@link OCFile} object with the data read from the server.
-      * 
+      * Creates and populates a new {@link com.owncloud.android.datamodel.OCFile}
+      * object with the data read from the server.
+      *
       * @param remote    remote file read from the server (remote file or folder).
       * @return          New OCFile instance representing the remote resource described by we.
       */
          file.setRemoteId(remote.getRemoteId());
          return file;
      }
-     
  
-     /**
-      * Checks the storage path of the OCFile received as parameter. 
-      * If it's out of the local ownCloud folder, tries to copy the file inside it. 
-      * 
-      * If the copy fails, the link to the local file is nullified. The account of forgotten 
-      * files is kept in {@link #mForgottenLocalFiles}
-      *) 
-      * @param file      File to check and fix.
-      */
-     private void checkAndFixForeignStoragePath(OCFile file) {
-         String storagePath = file.getStoragePath();
-         String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
-         if (storagePath != null && !storagePath.equals(expectedPath)) {
-             /// fix storagePaths out of the local ownCloud folder
-             File originalFile = new File(storagePath);
-             if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
-                 mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                 file.setStoragePath(null);
-                     
-             } else {
-                 InputStream in = null;
-                 OutputStream out = null;
-                 try {
-                     File expectedFile = new File(expectedPath);
-                     File expectedParent = expectedFile.getParentFile();
-                     expectedParent.mkdirs();
-                     if (!expectedParent.isDirectory()) {
-                         throw new IOException(
-                                 "Unexpected error: parent directory could not be created"
-                         );
-                     }
-                     expectedFile.createNewFile();
-                     if (!expectedFile.isFile()) {
-                         throw new IOException("Unexpected error: target file could not be created");
-                     }                    
-                     in = new FileInputStream(originalFile);
-                     out = new FileOutputStream(expectedFile);
-                     byte[] buf = new byte[1024];
-                     int len;
-                     while ((len = in.read(buf)) > 0){
-                         out.write(buf, 0, len);
-                     }
-                     file.setStoragePath(expectedPath);
-                     
-                 } catch (Exception e) {
-                     Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e);
-                     mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                     file.setStoragePath(null);
-                     
-                 } finally {
-                     try {
-                         if (in != null) in.close();
-                     } catch (Exception e) {
-                         Log_OC.d(TAG, "Weird exception while closing input stream for " 
-                                 + storagePath + " (ignoring)", e);
-                     }
-                     try {
-                         if (out != null) out.close();
-                     } catch (Exception e) {
-                         Log_OC.d(TAG, "Weird exception while closing output stream for " 
-                                 + expectedPath + " (ignoring)", e);
-                     }
-                 }
-             }
-         }
-     }
-     
-     
-     private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
-         RemoteOperationResult result = null;
-         
-         // remote request 
-         GetRemoteSharesForFileOperation operation = 
-                 new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true);
-         result = operation.execute(client);
-         
-         if (result.isSuccess()) {
-             // update local database
-             ArrayList<OCShare> shares = new ArrayList<OCShare>();
-             for(Object obj: result.getData()) {
-                 shares.add((OCShare) obj);
-             }
-             mStorageManager.saveSharesInFolder(shares, mLocalFolder);
-         }
-         return result;
-     }
-     
  
      /**
       * Scans the default location for saving local copies of files searching for
-      * a 'lost' file with the same full name as the {@link OCFile} received as 
-      * parameter.
+      * a 'lost' file with the same full name as the {@link com.owncloud.android.datamodel.OCFile}
+      * received as parameter.
       *  
       * @param file      File to associate a possible 'lost' local file.
       */
  
      
      /**
-      * Sends a message to any application component interested in the progress 
-      * of the synchronization.
-      * 
-      * @param event
-      * @param dirRemotePath     Remote path of a folder that was just synchronized 
-      *                          (with or without success)
-      * @param result
+      * Cancel operation
       */
-     private void sendLocalBroadcast(
-             String event, String dirRemotePath, RemoteOperationResult result
-         ) {
-         Log_OC.d(TAG, "Send broadcast " + event);
-         Intent intent = new Intent(event);
-         intent.putExtra(FileSyncAdapter.EXTRA_ACCOUNT_NAME, mAccount.name);
-         if (dirRemotePath != null) {
-             intent.putExtra(FileSyncAdapter.EXTRA_FOLDER_PATH, dirRemotePath);
-         }
-         intent.putExtra(FileSyncAdapter.EXTRA_RESULT, result);
-         mContext.sendStickyBroadcast(intent);
-         //LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
+     public void cancel() {
+         mCancellationRequested.set(true);
      }
  
+     public String getFolderPath() {
+         String path = mLocalFolder.getStoragePath();
+         if (path != null && path.length() > 0) {
+             return path;
+         }
+         return FileStorageUtils.getDefaultSavePathFor(mAccount.name, mLocalFolder);
+     }
  
-     public boolean getRemoteFolderChanged() {
-         return mRemoteFolderChanged;
+     private void startSyncFolderOperation(String path){
+         Intent intent = new Intent(mContext, OperationsService.class);
+         intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
+         intent.putExtra(OperationsService.EXTRA_ACCOUNT, mAccount);
+         intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, path);
+         mContext.startService(intent);
      }
  
+     public String getRemotePath() {
+         return mRemotePath;
+     }
  }
@@@ -1,6 -1,10 +1,10 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author David A. Velasco
   *   Copyright (C) 2011  Bartek Przybylski
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
  package com.owncloud.android.ui.activity;
  
  import java.io.File;
- import java.io.IOException;
  
  import android.accounts.Account;
  import android.accounts.AccountManager;
  import android.accounts.AuthenticatorException;
 +import android.accounts.OperationCanceledException;
  import android.annotation.TargetApi;
  import android.app.AlertDialog;
- import android.app.Dialog;
- import android.app.ProgressDialog;
  import android.content.BroadcastReceiver;
  import android.content.ComponentName;
  import android.content.ContentResolver;
- import android.content.ContentUris;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.Intent;
@@@ -40,33 -39,20 +40,30 @@@ import android.content.IntentFilter
  import android.content.ServiceConnection;
  import android.content.SharedPreferences;
  import android.content.SyncRequest;
 +import android.content.res.Configuration;
  import android.content.res.Resources.NotFoundException;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.Build;
  import android.os.Bundle;
- import android.os.Environment;
  import android.os.IBinder;
  import android.preference.PreferenceManager;
- import android.provider.DocumentsContract;
- import android.provider.MediaStore;
  import android.provider.OpenableColumns;
 +import android.support.v4.app.ActionBarDrawerToggle;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.support.v4.app.FragmentTransaction;
 +import android.support.v4.view.GravityCompat;
 +import android.support.v4.widget.DrawerLayout;
 +import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;
 +import android.widget.AdapterView;
 +import android.widget.AdapterView.OnItemClickListener;
  import android.widget.ArrayAdapter;
 +import android.widget.ImageView;
 +import android.widget.LinearLayout;
 +import android.widget.ListView;
  import android.widget.TextView;
  import android.widget.Toast;
  
@@@ -76,9 -62,9 +73,9 @@@ import com.actionbarsherlock.view.Menu
  import com.actionbarsherlock.view.MenuInflater;
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
 -import com.owncloud.android.BuildConfig;
  import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
 +import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.files.services.FileDownloader;
  import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
@@@ -100,15 -86,15 +97,17 @@@ import com.owncloud.android.operations.
  import com.owncloud.android.operations.RemoveFileOperation;
  import com.owncloud.android.operations.RenameFileOperation;
  import com.owncloud.android.operations.SynchronizeFileOperation;
- import com.owncloud.android.operations.SynchronizeFolderOperation;
+ import com.owncloud.android.operations.RefreshFolderOperation;
  import com.owncloud.android.operations.UnshareLinkOperation;
  import com.owncloud.android.services.observer.FileObserverService;
  import com.owncloud.android.syncadapter.FileSyncAdapter;
 +import com.owncloud.android.ui.adapter.FileListListAdapter;
 +import com.owncloud.android.ui.adapter.NavigationDrawerListAdapter;
+ import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
  import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
  import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
  import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener;
+ import com.owncloud.android.ui.dialog.UploadSourceDialogFragment;
  import com.owncloud.android.ui.fragment.FileDetailFragment;
  import com.owncloud.android.ui.fragment.FileFragment;
  import com.owncloud.android.ui.fragment.OCFileListFragment;
@@@ -118,14 -104,12 +117,12 @@@ import com.owncloud.android.ui.preview.
  import com.owncloud.android.ui.preview.PreviewVideoActivity;
  import com.owncloud.android.utils.DisplayUtils;
  import com.owncloud.android.utils.ErrorMessageAdapter;
+ import com.owncloud.android.utils.FileStorageUtils;
  import com.owncloud.android.utils.UriUtils;
  
  
  /**
   * Displays, what files the user has available in his ownCloud.
-  * 
-  * @author Bartek Przybylski
-  * @author David A. Velasco
   */
  
  public class FileDisplayActivity extends HookActivity implements
@@@ -147,14 -131,10 +144,10 @@@ OnSslUntrustedCertListener, OnEnforceab
      private static final String KEY_SYNC_IN_PROGRESS = "SYNC_IN_PROGRESS";
      private static final String KEY_WAITING_TO_SEND = "WAITING_TO_SEND";
  
-     public static final int DIALOG_SHORT_WAIT = 0;
-     private static final int DIALOG_CHOOSE_UPLOAD_SOURCE = 1;
-     private static final int DIALOG_CERT_NOT_SAVED = 2;
-     
      public static final String ACTION_DETAILS = "com.owncloud.android.ui.activity.action.DETAILS";
  
-     private static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
-     private static final int ACTION_SELECT_MULTIPLE_FILES = 2;
+     public static final int ACTION_SELECT_CONTENT_FROM_APPS = 1;
+     public static final int ACTION_SELECT_MULTIPLE_FILES = 2;
      public static final int ACTION_MOVE_FILES = 3;
  
      private static final String TAG = FileDisplayActivity.class.getSimpleName();
      
      private boolean mSyncInProgress = false;
  
-     private String DIALOG_UNTRUSTED_CERT;
-     
+     private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT";
+     private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER";
+     private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE";
+     private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED";
      private OCFile mWaitingToSend;
      
-     
 +    private DrawerLayout mDrawerLayout;
 +    private ActionBarDrawerToggle mDrawerToggle;
 +    private boolean showAccounts = false;
 +    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
-         Log_OC.d(TAG, "onCreate() start");
+         Log_OC.v(TAG, "onCreate() start");
          requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
 -
 +        
          super.onCreate(savedInstanceState); // this calls onAccountChanged() when ownCloud Account is valid
  
-         // PIN CODE request ;  best location is to decide, let's try this first
-         if (getIntent().getAction() != null && getIntent().getAction().equals(Intent.ACTION_MAIN) && savedInstanceState == null) {
-             requestPinCode();
-         } else if (getIntent().getAction() == null && savedInstanceState == null) {
-             requestPinCode();
-         }
-         /// grant that FileObserverService is watching favourite files
+         /// grant that FileObserverService is watching favorite files
          if (savedInstanceState == null) {
              Intent initObserversIntent = FileObserverService.makeInitIntent(this);
              startService(initObserversIntent);
          /// USER INTERFACE
  
          // Inflate and set the layout view
 -        setContentView(R.layout.files);    
 +        setContentView(R.layout.files);
 +        
 +        // TODO move to another place that all activity can use it
 +        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
 +        
 +        mDrawerToggle = new ActionBarDrawerToggle(
 +                this,                  
 +                mDrawerLayout,         
 +                R.drawable.ic_drawer,  
 +                R.string.drawer_open,  
 +                R.string.empty  
 +                ) {
 +
 +            /** Called when a drawer has settled in a completely closed state. */
 +            public void onDrawerClosed(View view) {
 +                super.onDrawerClosed(view);
 +                getSupportActionBar().setDisplayShowTitleEnabled(true);
 +                getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
 +                initFragmentsWithFile();
 +                invalidateOptionsMenu();
 +            }
 +
 +            /** Called when a drawer has settled in a completely open state. */
 +            public void onDrawerOpened(View drawerView) {
 +                super.onDrawerOpened(drawerView);
 +                getSupportActionBar().setTitle(R.string.drawer_open);
 +                getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
 +                invalidateOptionsMenu();
 +            }
 +        };
 +        
 +        mDrawerToggle.setDrawerIndicatorEnabled(true);
 +        
 +        // Notification Drawer
 +        LinearLayout notificatonDrawer = (LinearLayout) findViewById(R.id.left_drawer);
 +        
 +        // ListView
 +        ListView listView = (ListView) notificatonDrawer.findViewById(R.id.drawer_list);
 +        final NavigationDrawerListAdapter adapter = new NavigationDrawerListAdapter(getApplicationContext(), this);
 +        
 +        listView.setAdapter(adapter);
 +        
 +        listView.setOnItemClickListener(new OnItemClickListener() {
 +            @Override
 +            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 +                if (showAccounts && position > 0){
 +                    position = position - 1;
 +                }
 +                switch (position){
 +                case 0:
 +                    showAccounts = !showAccounts;
 +                    adapter.setShowAccounts(showAccounts);
 +                    adapter.notifyDataSetChanged();
 +                    break;
 +                case 1:
 +                    MainApp.showOnlyFilesOnDevice(false);
 +                    mDrawerLayout.closeDrawers();
 +                    break;
 +                case 2:
 +                    MainApp.showOnlyFilesOnDevice(true);
 +                    mDrawerLayout.closeDrawers();
 +                    break;
 +                case 3:
 +                    Intent settingsIntent = new Intent(getApplicationContext(), Preferences.class);
 +                    startActivity(settingsIntent);
 +                    break;
 +                }
 +            }
 +        });
 +        
 +        // User-Icon
 +        ImageView userIcon = (ImageView) notificatonDrawer.findViewById(R.id.drawer_userIcon);
 +        userIcon.setImageResource(DisplayUtils.getSeasonalIconId());
 +        
 +        // Username
 +        TextView username = (TextView) notificatonDrawer.findViewById(R.id.drawer_username);
 +        Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
 +        int lastAtPos = account.name.lastIndexOf("@");
 +        username.setText(account.name.substring(0, lastAtPos));
 +
 +        // Set the drawer toggle as the DrawerListener
 +        mDrawerLayout.setDrawerListener(mDrawerToggle);
 +
          mDualPane = getResources().getBoolean(R.bool.large_land_layout);
          mLeftFragmentContainer = findViewById(R.id.left_fragment_container);
          mRightFragmentContainer = findViewById(R.id.right_fragment_container);
  
          // Action bar setup
          mDirectories = new CustomArrayAdapter<String>(this, R.layout.sherlock_spinner_dropdown_item);
 +        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
          getSupportActionBar().setHomeButtonEnabled(true);       // mandatory since Android ICS, according to the official documentation
 +        getSupportActionBar().setDisplayShowCustomEnabled(true); // CRUCIAL - for displaying your custom actionbar
 +        getSupportActionBar().setDisplayShowTitleEnabled(true);
          setSupportProgressBarIndeterminateVisibility(mSyncInProgress /*|| mRefreshSharesInProgress*/);    // always AFTER setContentView(...) ; to work around bug in its implementation
          
 +        mDrawerToggle.syncState();
 +        
          setBackgroundText();
  
-         Log_OC.d(TAG, "onCreate() end");
+         Log_OC.v(TAG, "onCreate() end");
      }
      
      @Override
      protected void onStart() {
+         Log_OC.v(TAG, "onStart() start");
          super.onStart();
          getSupportActionBar().setIcon(DisplayUtils.getSeasonalIconId());
+         Log_OC.v(TAG, "onStart() end");
      }
 +    
 +    @Override
 +    protected void onPostCreate(Bundle savedInstanceState) {
 +        super.onPostCreate(savedInstanceState);
 +        // Sync the toggle state after onRestoreInstanceState has occurred.
 +        mDrawerToggle.syncState();
 +    }
 +    
 +    @Override
 +    public void onConfigurationChanged(Configuration newConfig) {
 +        super.onConfigurationChanged(newConfig);
 +        mDrawerToggle.onConfigurationChanged(newConfig);
 +    }
  
      @Override
      protected void onDestroy() {
+         Log_OC.v(TAG, "onDestroy() start");
          super.onDestroy();
+         Log_OC.v(TAG, "onDestroy() end");
      }
  
      /**
              setNavigationListWithFolder(file);
              
              if (!stateWasRecovered) {
-                 Log_OC.e(TAG, "Initializing Fragments in onAccountChanged..");
+                 Log_OC.d(TAG, "Initializing Fragments in onAccountChanged..");
                  initFragmentsWithFile();
                  if (file.isFolder()) {
                      startSyncFolderOperation(file, false);
              /// First fragment
              OCFileListFragment listOfFiles = getListOfFilesFragment(); 
              if (listOfFiles != null) {
 -                listOfFiles.listDirectory(getCurrentDir());   
 +                listOfFiles.listDirectory(getCurrentDir(), MainApp.getOnlyOnDevice());   
              } else {
                  Log_OC.e(TAG, "Still have a chance to lose the initializacion of list fragment >(");
              }
      protected void refreshListOfFilesFragment() {
          OCFileListFragment fileListFragment = getListOfFilesFragment();
          if (fileListFragment != null) { 
 -            fileListFragment.listDirectory();
 +            fileListFragment.listDirectory(MainApp.getOnlyOnDevice());
          }
      }
  
  
      @Override
      public boolean onPrepareOptionsMenu(Menu menu) {
 -        if (BuildConfig.DEBUG) {
 -            menu.findItem(R.id.action_logger).setVisible(true);
 -        } else {
 -            menu.findItem(R.id.action_logger).setVisible(false);
 -        }
 +        boolean drawerOpen = mDrawerLayout.isDrawerOpen(GravityCompat.START);
 +        menu.findItem(R.id.action_upload).setVisible(!drawerOpen);
 +        menu.findItem(R.id.action_create_dir).setVisible(!drawerOpen);
 +        menu.findItem(R.id.action_sort).setVisible(!drawerOpen);
 +        
          return super.onPrepareOptionsMenu(menu);
      }
  
          inflater.inflate(R.menu.main_menu, menu);
          return true;
      }
 +    
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          boolean retval = true;
          switch (item.getItemId()) {
          case R.id.action_create_dir: {
-             CreateFolderDialogFragment dialog = 
-                     CreateFolderDialogFragment.newInstance(getCurrentDir());
-             dialog.show(getSupportFragmentManager(), "createdirdialog");
+             CreateFolderDialogFragment dialog = CreateFolderDialogFragment.newInstance(getCurrentDir());
+             dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER);
              break;
          }
 -        case R.id.action_sync_account: {
 -            startSynchronization();
 -            break;
 -        }
          case R.id.action_upload: {
-             showDialog(DIALOG_CHOOSE_UPLOAD_SOURCE);
+             UploadSourceDialogFragment dialog = UploadSourceDialogFragment.newInstance(getAccount());
+             dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE);
              break;
          }
 -        case R.id.action_settings: {
 -            Intent settingsIntent = new Intent(this, Preferences.class);
 -            startActivity(settingsIntent);
 -            break;
 -        }
 -        case R.id.action_logger: {
 -            Intent loggerIntent = new Intent(getApplicationContext(),LogHistoryActivity.class);
 -            startActivity(loggerIntent);
 -            break;
 -        }
          case android.R.id.home: {
 -            FileFragment second = getSecondFragment();
 -            OCFile currentDir = getCurrentDir();
 -            if((currentDir != null && currentDir.getParentId() != 0) || 
 -                    (second != null && second.getFile() != null)) {                
 -                onBackPressed(); 
 -                
 +            if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
 +                mDrawerLayout.closeDrawer(GravityCompat.START);
 +            } else {
 +                mDrawerLayout.openDrawer(GravityCompat.START);
              }
 +            // TODO add hamburger to left of android.R.id.home
              break;
          }
          case R.id.action_sort: {
              
              // Read sorting order, default to sort by name ascending
              Integer sortOrder = appPreferences
-                     .getInt("sortOrder", FileListListAdapter.SORT_NAME);
+                     .getInt("sortOrder", FileStorageUtils.SORT_NAME);
              
              AlertDialog.Builder builder = new AlertDialog.Builder(this);
              builder.setTitle(R.string.actionbar_sort_title)
                          sortByDate(false);
                          break;
                          
- // TODO re-enable when server-side folder size calculation is available                       
- //                    case 2:
- //                        sortBySize(false);
- //                        break;
                      }
                      
                      dialog.dismiss();
      }
  
      private void startSynchronization() {
-         Log_OC.e(TAG, "Got to start sync");
+         Log_OC.d(TAG, "Got to start sync");
          if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) {
-             Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority());
+             Log_OC.d(TAG, "Canceling all syncs for " + MainApp.getAuthority());
              ContentResolver.cancelSync(null, MainApp.getAuthority());   // cancel the current synchronizations of any ownCloud account
              Bundle bundle = new Bundle();
              bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
              bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
-             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
+             Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority());
              ContentResolver.requestSync(
                      getAccount(),
                      MainApp.getAuthority(), bundle);
          } else {
-             Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
+             Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API");
              SyncRequest.Builder builder = new SyncRequest.Builder();
              builder.setSyncAdapter(getAccount(), MainApp.getAuthority());
              builder.setExpedited(true);
       *
       */
      @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+     @Override
      protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-         super.onActivityResult(requestCode, resultCode, data);
  
          if (requestCode == ACTION_SELECT_CONTENT_FROM_APPS && (resultCode == RESULT_OK || resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)) {
              //getClipData is only supported on api level 16+, Jelly Bean
                  }, 
                  DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS
              );
+         } else {
+             super.onActivityResult(requestCode, resultCode, data);
          }
      }
  
      private void requestMultipleUpload(Intent data, int resultCode) {
          if (filePaths != null) {
              String[] remotePaths = new String[filePaths.length];
              String remotePathBase = "";
              for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
                  remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
              }
  
  
      private void requestSimpleUpload(Intent data, int resultCode) {
-         String filepath = null;
+         String filePath = null;
          String mimeType = null;
  
          Uri selectedImageUri = data.getData();
          try {
              mimeType = getContentResolver().getType(selectedImageUri);
  
-             String filemanagerstring = selectedImageUri.getPath();
-             String selectedImagePath = getPath(selectedImageUri);
+             String fileManagerString = selectedImageUri.getPath();
+             String selectedImagePath = UriUtils.getLocalPath(selectedImageUri, this);
  
              if (selectedImagePath != null)
-                 filepath = selectedImagePath;
+                 filePath = selectedImagePath;
              else
-                 filepath = filemanagerstring;
+                 filePath = fileManagerString;
  
          } catch (Exception e) {
              Log_OC.e(TAG, "Unexpected exception when trying to read the result of Intent.ACTION_GET_CONTENT", e);
-             e.printStackTrace();
  
          } finally {
-             if (filepath == null) {
-                 Log_OC.e(TAG, "Couldnt resolve path to file");
-                 Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG);
+             if (filePath == null) {
+                 Log_OC.e(TAG, "Couldn't resolve path to file");
+                 Toast t = Toast.makeText(
+                         this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG
+                 );
                  t.show();
                  return;
              }
          }
  
          Intent i = new Intent(this, FileUploader.class);
-         i.putExtra(FileUploader.KEY_ACCOUNT,
-                 getAccount());
-         String remotepath = new String();
-         for (int j = mDirectories.getCount() - 2; j >= 0; --j) {
-             remotepath += OCFile.PATH_SEPARATOR + mDirectories.getItem(j);
-         }
-         if (!remotepath.endsWith(OCFile.PATH_SEPARATOR))
-             remotepath += OCFile.PATH_SEPARATOR;
-         if (filepath.startsWith(UriUtils.URI_CONTENT_SCHEME)) {
-             Cursor cursor = MainApp.getAppContext().getContentResolver()
-                     .query(Uri.parse(filepath), null, null, null, null, null);
+         i.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
+         OCFile currentDir = getCurrentDir();
+         String remotePath =  (currentDir != null) ? currentDir.getRemotePath() : OCFile.ROOT_PATH;
  
+         if (filePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) {
+             Cursor cursor = getContentResolver().query(Uri.parse(filePath), null, null, null, null);
              try {
                  if (cursor != null && cursor.moveToFirst()) {
-                     String displayName = cursor.getString(
-                             cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
-                     Log.i(TAG, "Display Name: " + displayName + "; mimeType: " + mimeType);
+                     String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+                     Log_OC.v(TAG, "Display Name: " + displayName );
  
                      displayName.replace(File.separatorChar, '_');
                      displayName.replace(File.pathSeparatorChar, '_');
-                     remotepath += displayName + DisplayUtils.getComposedFileExtension(filepath);
+                     remotePath += displayName + DisplayUtils.getComposedFileExtension(filePath);
  
                  }
+                 // and what happens in case of error?; wrong target name for the upload
              } finally {
                  cursor.close();
              }
  
          } else {
-             remotepath += new File(filepath).getName();
+             remotePath += new File(filePath).getName();
          }
  
-         i.putExtra(FileUploader.KEY_LOCAL_FILE, filepath);
-         i.putExtra(FileUploader.KEY_REMOTE_FILE, remotepath);
+         i.putExtra(FileUploader.KEY_LOCAL_FILE, filePath);
+         i.putExtra(FileUploader.KEY_REMOTE_FILE, remotePath);
          i.putExtra(FileUploader.KEY_MIME_TYPE, mimeType);
          i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
          if (resultCode == UploadFilesActivity.RESULT_OK_AND_MOVE)
-             i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
+         i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
          startService(i);
      }
  
      @Override
      protected void onSaveInstanceState(Bundle outState) {
          // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved
-         Log_OC.e(TAG, "onSaveInstanceState() start");
+         Log_OC.v(TAG, "onSaveInstanceState() start");
          super.onSaveInstanceState(outState);
          outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview);
          outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress);
          //outState.putBoolean(FileDisplayActivity.KEY_REFRESH_SHARES_IN_PROGRESS, mRefreshSharesInProgress);
          outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_SEND, mWaitingToSend);
  
-         Log_OC.d(TAG, "onSaveInstanceState() end");
+         Log_OC.v(TAG, "onSaveInstanceState() end");
      }
      
  
  
      @Override
      protected void onResume() {
+         Log_OC.v(TAG, "onResume() start");
          super.onResume();
-         Log_OC.e(TAG, "onResume() start");
-         
          // refresh list of files
          refreshListOfFilesFragment();
  
          IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
          mSyncBroadcastReceiver = new SyncBroadcastReceiver();
          registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
          //LocalBroadcastManager.getInstance(this).registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
          mDownloadFinishReceiver = new DownloadFinishReceiver();
          registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
          
-         Log_OC.d(TAG, "onResume() end");
+         Log_OC.v(TAG, "onResume() end");
      }
  
  
      @Override
      protected void onPause() {
-         Log_OC.e(TAG, "onPause() start");
+         Log_OC.v(TAG, "onPause() start");
          if (mSyncBroadcastReceiver != null) {
              unregisterReceiver(mSyncBroadcastReceiver);
              //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver);
              mDownloadFinishReceiver = null;
          }
          
-         
-         Log_OC.d(TAG, "onPause() end");
          super.onPause();
-     }
-     @Override
-     protected Dialog onCreateDialog(int id) {
-         Dialog dialog = null;
-         AlertDialog.Builder builder;
-         switch (id) {
-         case DIALOG_SHORT_WAIT: {
-             ProgressDialog working_dialog = new ProgressDialog(this);
-             working_dialog.setMessage(getResources().getString(
-                     R.string.wait_a_moment));
-             working_dialog.setIndeterminate(true);
-             working_dialog.setCancelable(false);
-             dialog = working_dialog;
-             break;
-         }
-         case DIALOG_CHOOSE_UPLOAD_SOURCE: {
-             String[] allTheItems = { getString(R.string.actionbar_upload_files),
-                     getString(R.string.actionbar_upload_from_apps) };
-             builder = new AlertDialog.Builder(this);
-             builder.setTitle(R.string.actionbar_upload);
-             builder.setItems(allTheItems, new DialogInterface.OnClickListener() {
-                 public void onClick(DialogInterface dialog, int item) {
-                     if (item == 0) {
-                         // if (!mDualPane) {
-                             Intent action = new Intent(FileDisplayActivity.this, UploadFilesActivity.class);
-                             action.putExtra(UploadFilesActivity.EXTRA_ACCOUNT, FileDisplayActivity.this.getAccount());
-                             startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES);
-                             // } else {
-                             // TODO create and handle new fragment
-                             // LocalFileListFragment
-                             // }
-                     } else if (item == 1) {
-                         Intent action = new Intent(Intent.ACTION_GET_CONTENT);
-                         action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE);
-                         //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean
-                         if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                             action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                         }
-                         startActivityForResult(Intent.createChooser(action, getString(R.string.upload_chooser_title)),
-                                 ACTION_SELECT_CONTENT_FROM_APPS);
-                     }
-                 }
-             });
-             dialog = builder.create();
-             break;
-         }
-         case DIALOG_CERT_NOT_SAVED: {
-             builder = new AlertDialog.Builder(this);
-             builder.setMessage(getResources().getString(R.string.ssl_validator_not_saved));
-             builder.setCancelable(false);
-             builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
-                 @Override
-                 public void onClick(DialogInterface dialog, int which) {
-                     dialog.dismiss();
-                 };
-             });
-             dialog = builder.create();
-             break;
-         }
-         default:
-             dialog = null;
-         }
-         return dialog;
-     }
-     /**
-      * Translates a content URI of an content to a physical path on the disk
-      * 
-      * @param uri The URI to resolve
-      * @return The path to the content or null if it could not be found
-      */
-     public String getPath(Uri uri) {
-         final boolean isKitKatOrLater = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
-         // DocumentProvider
-         if (isKitKatOrLater && DocumentsContract.isDocumentUri(getApplicationContext(), uri)) {
-             // ExternalStorageProvider
-             if (UriUtils.isExternalStorageDocument(uri)) {
-                 final String docId = DocumentsContract.getDocumentId(uri);
-                 final String[] split = docId.split(":");
-                 final String type = split[0];
-                 if ("primary".equalsIgnoreCase(type)) {
-                     return Environment.getExternalStorageDirectory() + "/" + split[1];
-                 }
-             }
-             // DownloadsProvider
-             else if (UriUtils.isDownloadsDocument(uri)) {
-                 final String id = DocumentsContract.getDocumentId(uri);
-                 final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),
-                         Long.valueOf(id));
-                 return UriUtils.getDataColumn(getApplicationContext(), contentUri, null, null);
-             }
-             // MediaProvider
-             else if (UriUtils.isMediaDocument(uri)) {
-                 final String docId = DocumentsContract.getDocumentId(uri);
-                 final String[] split = docId.split(":");
-                 final String type = split[0];
-                 Uri contentUri = null;
-                 if ("image".equals(type)) {
-                     contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
-                 } else if ("video".equals(type)) {
-                     contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
-                 } else if ("audio".equals(type)) {
-                     contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
-                 }
-                 final String selection = "_id=?";
-                 final String[] selectionArgs = new String[] { split[1] };
-                 return UriUtils.getDataColumn(getApplicationContext(), contentUri, selection, selectionArgs);
-             }
-             // Documents providers returned as content://...
-             else if (UriUtils.isContentDocument(uri)) {
-                 return uri.toString();
-             }
-         }
-         // MediaStore (and general)
-         else if ("content".equalsIgnoreCase(uri.getScheme())) {
-             // Return the remote address
-             if (UriUtils.isGooglePhotosUri(uri))
-                 return uri.getLastPathSegment();
-             return UriUtils.getDataColumn(getApplicationContext(), uri, null, null);
-         }
-         // File
-         else if ("file".equalsIgnoreCase(uri.getScheme())) {
-             return uri.getPath();
-         }
-         return null;
+         Log_OC.v(TAG, "onPause() end");
      }
  
      /**
                              if (synchFolderRemotePath != null && currentDir.getRemotePath().equals(synchFolderRemotePath)) {
                                  OCFileListFragment fileListFragment = getListOfFilesFragment();
                                  if (fileListFragment != null) {
 -                                    fileListFragment.listDirectory(currentDir);
 +                                    fileListFragment.listDirectory(currentDir, MainApp.getOnlyOnDevice());
                                  }
                              }
                              setFile(currentFile);
                          }
                          
-                         mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
+                         mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
                                  
-                         if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
+                         if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
                                      equals(event) &&
                                  /// TODO refactor and make common
                                  synchResult != null && !synchResult.isSuccess() &&  
                                      (synchResult.isException() && synchResult.getException() 
                                              instanceof AuthenticatorException))) {
  
-                             OwnCloudClient client = null;
                              try {
-                                 OwnCloudAccount ocAccount = 
+                                 OwnCloudClient client;
+                                 OwnCloudAccount ocAccount =
                                          new OwnCloudAccount(getAccount(), context);
                                  client = (OwnCloudClientManagerFactory.getDefaultSingleton().
                                          removeClientFor(ocAccount));
-                                 // TODO get rid of these exceptions
-                             } catch (AccountNotFoundException e) {
-                                 e.printStackTrace();
-                             } catch (AuthenticatorException e) {
-                                 e.printStackTrace();
-                             } catch (OperationCanceledException e) {
-                                 e.printStackTrace();
-                             } catch (IOException e) {
-                                 e.printStackTrace();
-                             }
-                             
-                             if (client != null) {
-                                 OwnCloudCredentials cred = client.getCredentials();
-                                 if (cred != null) {
-                                     AccountManager am = AccountManager.get(context);
-                                     if (cred.authTokenExpires()) {
-                                         am.invalidateAuthToken(
-                                                 getAccount().type, 
-                                                 cred.getAuthToken()
-                                         );
-                                     } else {
-                                         am.clearPassword(getAccount());
+                                 if (client != null) {
+                                     OwnCloudCredentials cred = client.getCredentials();
+                                     if (cred != null) {
+                                         AccountManager am = AccountManager.get(context);
+                                         if (cred.authTokenExpires()) {
+                                             am.invalidateAuthToken(
+                                                     getAccount().type,
+                                                     cred.getAuthToken()
+                                             );
+                                         } else {
+                                             am.clearPassword(getAccount());
+                                         }
                                      }
                                  }
+                                 requestCredentialsUpdate();
+                             } catch (AccountNotFoundException e) {
+                                 Log_OC.e(TAG, "Account " + getAccount() + " was removed!", e);
                              }
-                             
-                             requestCredentialsUpdate();
-                             
                          }
                      }
                      removeStickyBroadcast(intent);
  
  
      /**
-      * Class waiting for broadcast events from the {@link FielDownloader} service.
+      * Class waiting for broadcast events from the {@link FileDownloader} service.
       * 
       * Updates the UI when a download is started or finished, provided that it is relevant for the
       * current folder.
       */
      private class DownloadFinishReceiver extends BroadcastReceiver {
+         //int refreshCounter = 0;
          @Override
          public void onReceive(Context context, Intent intent) {
              try {
                  boolean sameAccount = isSameAccount(context, intent);
                  String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
                  boolean isDescendant = isDescendant(downloadedRemotePath);
-     
                  if (sameAccount && isDescendant) {
-                     refreshListOfFilesFragment();
-                     refreshSecondFragment(intent.getAction(), downloadedRemotePath, intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
+                     String linkedToRemotePath = intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
+                         //Log_OC.v(TAG, "refresh #" + ++refreshCounter);
+                         refreshListOfFilesFragment();
+                     }
+                     refreshSecondFragment(
+                             intent.getAction(),
+                             downloadedRemotePath,
+                             intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)
+                     );
                  }
      
                  if (mWaitingToSend != null) {
-                     mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath()); // Update the file to send
+                     mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
                      if (mWaitingToSend.isDown()) { 
                          sendDownloadedFile();
                      }
  
          private boolean isDescendant(String downloadedRemotePath) {
              OCFile currentDir = getCurrentDir();
-             return (currentDir != null && downloadedRemotePath != null && downloadedRemotePath.startsWith(currentDir.getRemotePath()));
+             return (
+                 currentDir != null &&
+                 downloadedRemotePath != null &&
+                 downloadedRemotePath.startsWith(currentDir.getRemotePath())
+             );
+         }
+         private boolean isAscendant(String linkedToRemotePath) {
+             OCFile currentDir = getCurrentDir();
+             return (
+                 currentDir != null &&
+                 currentDir.getRemotePath().startsWith(linkedToRemotePath)
+             );
          }
  
          private boolean isSameAccount(Context context, Intent intent) {
                  popDirname();
              }
              OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
 -            listOfFiles.listDirectory(root);
 +            listOfFiles.listDirectory(root, MainApp.getOnlyOnDevice());
              setFile(listOfFiles.getCurrentFile());
              startSyncFolderOperation(root, false);
          }
          OCFileListFragment listOfFiles = getListOfFilesFragment(); 
          if (listOfFiles != null) {
              setNavigationListWithFolder(folder);
 -            listOfFiles.listDirectory(folder);
 +            listOfFiles.listDirectory(folder, MainApp.getOnlyOnDevice());
              setFile(listOfFiles.getCurrentFile());
              startSyncFolderOperation(folder, false);
          } else {
       * TODO
       */
      private void updateNavigationElementsInActionBar(OCFile chosenFile) {
-         ActionBar actionBar = getSupportActionBar(); 
+         ActionBar actionBar = getSupportActionBar();
+         // For adding content description tag to a title field in the action bar
+         int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
          if (chosenFile == null || mDualPane) {
              // only list of files - set for browsing through folders
              OCFile currentDir = getCurrentDir();
              boolean noRoot = (currentDir != null && currentDir.getParentId() != 0);
 -            actionBar.setDisplayHomeAsUpEnabled(noRoot);
 -            actionBar.setDisplayShowTitleEnabled(!noRoot); 
 +//            actionBar.setDisplayHomeAsUpEnabled(noRoot);
 +//            actionBar.setDisplayShowTitleEnabled(!noRoot); 
 +            actionBar.setDisplayHomeAsUpEnabled(true);
 +            actionBar.setDisplayShowTitleEnabled(true);
              if (!noRoot) {
                  actionBar.setTitle(getString(R.string.default_display_name_for_root_folder));
+                 View actionBarTitleView = getWindow().getDecorView().findViewById(actionBarTitleId);
+                 if (actionBarTitleView != null) {    // it's null in Android 2.x
+                     actionBarTitleView.setContentDescription(getString(R.string.default_display_name_for_root_folder));
+                 }
              }
              actionBar.setNavigationMode(!noRoot ? ActionBar.NAVIGATION_MODE_STANDARD : ActionBar.NAVIGATION_MODE_LIST);
              actionBar.setListNavigationCallbacks(mDirectories, this);   // assuming mDirectories is updated
              actionBar.setDisplayShowTitleEnabled(true);
              actionBar.setTitle(chosenFile.getFileName());
              actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+             View actionBarTitleView = getWindow().getDecorView().findViewById(actionBarTitleId);
+             if (actionBarTitleView != null) {    // it's null in Android 2.x
+                 getWindow().getDecorView().findViewById(actionBarTitleId).
+                         setContentDescription(chosenFile.getFileName());
+             }
          }
      }
  
              // a new chance to get the mDownloadBinder through getFileDownloadBinder() - THIS IS A MESS
              OCFileListFragment listOfFiles = getListOfFilesFragment(); 
              if (listOfFiles != null) {
 -                listOfFiles.listDirectory();
 +                listOfFiles.listDirectory(MainApp.getOnlyOnDevice());
              }
              FileFragment secondFragment = getSecondFragment();
              if (secondFragment != null && secondFragment instanceof FileDetailFragment) {
          }
      };    
  
-     /**
-      * Launch an intent to request the PIN code to the user before letting him use the app
-      */
-     private void requestPinCode() {
-         boolean pinStart = false;
-         SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
-         pinStart = appPrefs.getBoolean("set_pincode", false);
-         if (pinStart) {
-             Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
-             i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "FileDisplayActivity");
-             startActivity(i);
-         }
-     }
      @Override
      public void onSavedCertificate() {
          startSyncFolderOperation(getCurrentDir(), false);
  
      @Override
      public void onFailedSavingCertificate() {
-         showDialog(DIALOG_CERT_NOT_SAVED);
+         ConfirmationDialogFragment dialog = ConfirmationDialogFragment.newInstance(
+                 R.string.ssl_validator_not_saved, new String[]{}, R.string.common_ok, -1, -1
+         );
+         dialog.show(getSupportFragmentManager(), DIALOG_CERT_NOT_SAVED);
      }
  
      @Override
  
      private void requestForDownload() {
          Account account = getAccount();
+         //if (!mWaitingToPreview.isDownloading()) {
          if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
              Intent i = new Intent(this, FileDownloader.class);
              i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
              if (file.isFolder()) {
                  return file;
              } else if (getStorageManager() != null) {
-                 String parentPath = file.getRemotePath().substring(0, file.getRemotePath().lastIndexOf(file.getFileName()));
+                 String parentPath = file.getRemotePath().substring(0,
+                         file.getRemotePath().lastIndexOf(file.getFileName()));
                  return getStorageManager().getFileByPath(parentPath);
              }
          }
          mSyncInProgress = true;
                  
          // perform folder synchronization
-         RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
+         RemoteOperation synchFolderOp = new RefreshFolderOperation( folder,
                                                                          currentSyncTime, 
                                                                          false,
                                                                          getFileOperationsHelper().isSharedSupported(),
                                                                          getAccount(), 
                                                                          getApplicationContext()
                                                                        );
-         synchFolderOp.execute(getAccount(), this, null, null);
+         synchFolderOp.execute(getAccount(), MainApp.getAppContext(), this, null, null);
          
          setSupportProgressBarIndeterminateVisibility(true);
  
       */
      public void showUntrustedCertDialog(RemoteOperationResult result) {
          // Show a dialog with the certificate info
-         SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError((CertificateCombinedException)result.getException());
+         SslUntrustedCertDialog dialog = SslUntrustedCertDialog.newInstanceForFullSslError(
 -                (CertificateCombinedException)result.getException());
++                (CertificateCombinedException) result.getException());
          FragmentManager fm = getSupportFragmentManager();
          FragmentTransaction ft = fm.beginTransaction();
          dialog.show(ft, DIALOG_UNTRUSTED_CERT);
      
      private void requestForDownload(OCFile file) {
          Account account = getAccount();
-         if (!mDownloaderBinder.isDownloading(account, file)) {
+         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
              Intent i = new Intent(this, FileDownloader.class);
              i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
              i.putExtra(FileDownloader.EXTRA_FILE, file);
      private void sortByName(boolean ascending){
          getListOfFilesFragment().sortByName(ascending);
      }
 +    
 +    public void restart(){
 +        Intent i = new Intent(this, FileDisplayActivity.class);
 +        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 +        startActivity(i);
 +    }
 +
 +    public void closeDrawer() {
 +        mDrawerLayout.closeDrawers();
 +    }
  }
@@@ -1,5 -1,7 +1,7 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -43,6 -45,7 +45,7 @@@ import com.actionbarsherlock.view.Menu
  import com.actionbarsherlock.view.MenuInflater;
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
+ import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.lib.common.OwnCloudAccount;
@@@ -55,7 -58,7 +58,7 @@@ import com.owncloud.android.lib.common.
  import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
  import com.owncloud.android.lib.common.utils.Log_OC;
  import com.owncloud.android.operations.CreateFolderOperation;
- import com.owncloud.android.operations.SynchronizeFolderOperation;
+ import com.owncloud.android.operations.RefreshFolderOperation;
  import com.owncloud.android.syncadapter.FileSyncAdapter;
  import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
  import com.owncloud.android.ui.fragment.FileFragment;
@@@ -139,7 -142,7 +142,7 @@@ public class FolderPickerActivity exten
              
              if (!stateWasRecovered) {
                  OCFileListFragment listOfFolders = getListOfFilesFragment(); 
 -                listOfFolders.listDirectory(folder);   
 +                listOfFolders.listDirectory(folder, false);   
                  
                  startSyncFolderOperation(folder, false);
              }
          mSyncInProgress = true;
                  
          // perform folder synchronization
-         RemoteOperation synchFolderOp = new SynchronizeFolderOperation( folder,  
+         RemoteOperation synchFolderOp = new RefreshFolderOperation( folder,
                                                                          currentSyncTime, 
                                                                          false,
                                                                          getFileOperationsHelper().isSharedSupported(),
          IntentFilter syncIntentFilter = new IntentFilter(FileSyncAdapter.EVENT_FULL_SYNC_START);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_END);
          syncIntentFilter.addAction(FileSyncAdapter.EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
-         syncIntentFilter.addAction(SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED);
+         syncIntentFilter.addAction(RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED);
          mSyncBroadcastReceiver = new SyncBroadcastReceiver();
          registerReceiver(mSyncBroadcastReceiver, syncIntentFilter);
          
          MenuInflater inflater = getSherlock().getMenuInflater();
          inflater.inflate(R.menu.main_menu, menu);
          menu.findItem(R.id.action_upload).setVisible(false);
 -        menu.findItem(R.id.action_settings).setVisible(false);
 -        menu.findItem(R.id.action_sync_account).setVisible(false);
 -        menu.findItem(R.id.action_logger).setVisible(false);
          menu.findItem(R.id.action_sort).setVisible(false);
          return true;
      }
      protected void refreshListOfFilesFragment() {
          OCFileListFragment fileListFragment = getListOfFilesFragment();
          if (fileListFragment != null) { 
 -            fileListFragment.listDirectory();
 +            fileListFragment.listDirectory(false);
          }
      }
  
          OCFileListFragment listOfFiles = getListOfFilesFragment(); 
          if (listOfFiles != null) {  // should never be null, indeed
              OCFile root = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
 -            listOfFiles.listDirectory(root);
 +            listOfFiles.listDirectory(root, false);
              setFile(listOfFiles.getCurrentFile());
              updateNavigationElementsInActionBar();
              startSyncFolderOperation(root, false);
                                      equals(synchFolderRemotePath)) {
                                  OCFileListFragment fileListFragment = getListOfFilesFragment();
                                  if (fileListFragment != null) {
 -                                    fileListFragment.listDirectory(currentDir);
 +                                    fileListFragment.listDirectory(currentDir, false);
                                  }
                              }
                              setFile(currentFile);
                          }
                          
                          mSyncInProgress = (!FileSyncAdapter.EVENT_FULL_SYNC_END.equals(event) && 
-                                 !SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
+                                 !RefreshFolderOperation.EVENT_SINGLE_FOLDER_SHARES_SYNCED.equals(event));
                                  
-                         if (SynchronizeFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
+                         if (RefreshFolderOperation.EVENT_SINGLE_FOLDER_CONTENTS_SYNCED.
                                      equals(event) &&
                                  /// TODO refactor and make common
                                  synchResult != null && !synchResult.isSuccess() &&  
                                      (synchResult.isException() && synchResult.getException() 
                                              instanceof AuthenticatorException))) {
  
-                             OwnCloudClient client = null;
                              try {
-                                 OwnCloudAccount ocAccount = 
+                                 OwnCloudClient client;
+                                 OwnCloudAccount ocAccount =
                                          new OwnCloudAccount(getAccount(), context);
                                  client = (OwnCloudClientManagerFactory.getDefaultSingleton().
                                          removeClientFor(ocAccount));
-                                 // TODO get rid of these exceptions
-                             } catch (AccountNotFoundException e) {
-                                 e.printStackTrace();
-                             } catch (AuthenticatorException e) {
-                                 e.printStackTrace();
-                             } catch (OperationCanceledException e) {
-                                 e.printStackTrace();
-                             } catch (IOException e) {
-                                 e.printStackTrace();
-                             }
-                             
-                             if (client != null) {
-                                 OwnCloudCredentials cred = client.getCredentials();
-                                 if (cred != null) {
-                                     AccountManager am = AccountManager.get(context);
-                                     if (cred.authTokenExpires()) {
-                                         am.invalidateAuthToken(
-                                                 getAccount().type, 
-                                                 cred.getAuthToken()
-                                         );
-                                     } else {
-                                         am.clearPassword(getAccount());
+                                 if (client != null) {
+                                     OwnCloudCredentials cred = client.getCredentials();
+                                     if (cred != null) {
+                                         AccountManager am = AccountManager.get(context);
+                                         if (cred.authTokenExpires()) {
+                                             am.invalidateAuthToken(
+                                                     getAccount().type,
+                                                     cred.getAuthToken()
+                                             );
+                                         } else {
+                                             am.clearPassword(getAccount());
+                                         }
                                      }
                                  }
+                                 requestCredentialsUpdate();
+                             } catch (AccountNotFoundException e) {
+                                 Log_OC.e(TAG, "Account " + getAccount() + " was removed!", e);
                              }
-                             
-                             requestCredentialsUpdate();
-                             
                          }
                      }
                      removeStickyBroadcast(intent);
@@@ -1,6 -1,10 +1,10 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author David A. Velasco
   *   Copyright (C) 2011  Bartek Przybylski
-  *   Copyright (C) 2012-2013 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -21,13 -25,17 +25,17 @@@ import android.accounts.Account
  import android.accounts.AccountManager;
  import android.accounts.AccountManagerCallback;
  import android.accounts.AccountManagerFuture;
+ import android.content.ComponentName;
+ import android.content.Context;
  import android.content.Intent;
+ import android.content.ServiceConnection;
  import android.content.SharedPreferences;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager.NameNotFoundException;
  import android.net.Uri;
  import android.os.Bundle;
  import android.os.Handler;
+ import android.os.IBinder;
  import android.preference.CheckBoxPreference;
  import android.preference.Preference;
  import android.preference.Preference.OnPreferenceChangeListener;
@@@ -46,25 -54,27 +54,28 @@@ import com.actionbarsherlock.app.Action
  import com.actionbarsherlock.app.SherlockPreferenceActivity;
  import com.actionbarsherlock.view.Menu;
  import com.actionbarsherlock.view.MenuItem;
 +import com.owncloud.android.BuildConfig;
  import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.authentication.AuthenticatorActivity;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.db.DbHandler;
+ import com.owncloud.android.files.FileOperationsHelper;
+ import com.owncloud.android.files.services.FileDownloader;
+ import com.owncloud.android.files.services.FileUploader;
  import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.services.OperationsService;
  import com.owncloud.android.ui.RadioButtonPreference;
  import com.owncloud.android.utils.DisplayUtils;
  
  
  /**
   * An Activity that allows the user to change the application's settings.
-  * 
-  * @author Bartek Przybylski
-  * @author David A. Velasco
   */
- public class Preferences extends SherlockPreferenceActivity implements AccountManagerCallback<Boolean> {
+ public class Preferences extends SherlockPreferenceActivity
+         implements AccountManagerCallback<Boolean>, ComponentsGetter {
      
      private static final String TAG = "OwnCloudPreferences";
  
      private String mAccountName;
      private boolean mShowContextMenu = false;
      private String mUploadPath;
+     private PreferenceCategory mPrefInstantUploadCategory;
+     private Preference mPrefInstantUpload;
      private Preference mPrefInstantUploadPath;
+     private Preference mPrefInstantUploadPathWiFi;
+     private Preference mPrefInstantVideoUpload;
      private Preference mPrefInstantVideoUploadPath;
+     private Preference mPrefInstantVideoUploadPathWiFi;
      private String mUploadVideoPath;
  
+     protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
+     protected FileUploader.FileUploaderBinder mUploaderBinder = null;
+     private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
      @SuppressWarnings("deprecation")
      @Override
      public void onCreate(Bundle savedInstanceState) {
          actionBar.setDisplayHomeAsUpEnabled(true);
          actionBar.setTitle(R.string.actionbar_settings);
  
+         // For adding content description tag to a title field in the action bar
+         int actionBarTitleId = getResources().getIdentifier("action_bar_title", "id", "android");
+         View actionBarTitleView = getWindow().getDecorView().findViewById(actionBarTitleId);
+         if (actionBarTitleView != null) {    // it's null in Android 2.x
+             getWindow().getDecorView().findViewById(actionBarTitleId).
+                     setContentDescription(getString(R.string.actionbar_settings));
+         }
          // Load the accounts category for adding the list of accounts
          mAccountsPrefCategory = (PreferenceCategory) findPreference("accounts_category");
  
              pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                  @Override
                  public boolean onPreferenceChange(Preference preference, Object newValue) {
-                     Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
-                     i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "preferences");
-                     i.putExtra(PinCodeActivity.EXTRA_NEW_STATE, newValue.toString());
+                     Intent i = new Intent(getApplicationContext(), PassCodeActivity.class);
+                     Boolean enable = (Boolean) newValue;
+                     i.setAction(
+                             enable.booleanValue() ? PassCodeActivity.ACTION_ENABLE : PassCodeActivity.ACTION_DISABLE
+                     );
                      startActivity(i);
                      
                      return true;
              
          }
          
 -       
 +        if (BuildConfig.DEBUG) {
 +            Preference pLog =  findPreference("log");
 +            if (pLog != null ){
 +                pLog.setOnPreferenceClickListener(new OnPreferenceClickListener() {
 +                    @Override
 +                    public boolean onPreferenceClick(Preference preference) {
 +                        Intent loggerIntent = new Intent(getApplicationContext(),LogHistoryActivity.class);
 +                        startActivity(loggerIntent);
 +                        return true;
 +                    }
 +                });
 +            } 
 +        }
 +        
         boolean recommendEnabled = getResources().getBoolean(R.bool.recommend_enabled);
         Preference pRecommend =  findPreference("recommend");
          if (pRecommend != null){
                          String username = currentAccount.name.substring(0, currentAccount.name.lastIndexOf('@'));
                          
                          String recommendSubject = String.format(getString(R.string.recommend_subject), appName);
-                         String recommendText = String.format(getString(R.string.recommend_text), appName, downloadUrl, username);
+                         String recommendText = String.format(getString(R.string.recommend_text),
+                                 appName, downloadUrl, username);
                          
                          intent.putExtra(Intent.EXTRA_SUBJECT, recommendSubject);
                          intent.putExtra(Intent.EXTRA_TEXT, recommendText);
                          startActivity(intent);
  
                          return(true);
  
                      }
                      }
                  });
          }
+         
+         mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
+         
+         mPrefInstantUploadPathWiFi =  findPreference("instant_upload_on_wifi");
+         mPrefInstantUpload = findPreference("instant_uploading");
+         
+         toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
+         
+         mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+             
+             @Override
+             public boolean onPreferenceChange(Preference preference, Object newValue) {
+                 toggleInstantPictureOptions((Boolean) newValue);
+                 return true;
+             }
+         });
+        
          mPrefInstantVideoUploadPath =  findPreference("instant_video_upload_path");
          if (mPrefInstantVideoUploadPath != null){
  
                      }
                  });
          }
+         
+         mPrefInstantVideoUploadPathWiFi =  findPreference("instant_video_upload_on_wifi");
+         mPrefInstantVideoUpload = findPreference("instant_video_uploading");
+         toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked());
+         
+         mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+             
+             @Override
+             public boolean onPreferenceChange(Preference preference, Object newValue) {
+                 toggleInstantVideoOptions((Boolean) newValue);
+                 return true;
+             }
+         });
              
          /* About App */
         pAboutApp = (Preference) findPreference("about_app");
         loadInstantUploadPath();
         loadInstantUploadVideoPath();
  
-     }
+         /* ComponentsGetter */
+         mDownloadServiceConnection = newTransferenceServiceConnection();
+         if (mDownloadServiceConnection != null) {
+             bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
+                     Context.BIND_AUTO_CREATE);
+         }
+         mUploadServiceConnection = newTransferenceServiceConnection();
+         if (mUploadServiceConnection != null) {
+             bindService(new Intent(this, FileUploader.class), mUploadServiceConnection,
+                     Context.BIND_AUTO_CREATE);
+         }
  
-     @Override
-     protected void onPause() {
-         super.onPause();
+     }
+     
+     private void toggleInstantPictureOptions(Boolean value){
+         if (value){
+             mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi);
+             mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath);
+         } else {
+             mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi);
+             mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath);
+         }
+     }
+     
+     private void toggleInstantVideoOptions(Boolean value){
+         if (value){
+             mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi);
+             mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath);
+         } else {
+             mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi);
+             mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath);
+         }
      }
  
      @Override
  
                      // Remove account
                      am.removeAccount(a, this, mHandler);
+                     Log_OC.d(TAG, "Remove an account " + a.name);
                  }
              }
          }
      @Override
      public void run(AccountManagerFuture<Boolean> future) {
          if (future.isDone()) {
+             // after remove account
+             Account account = new Account(mAccountName, MainApp.getAccountType());
+             if (!AccountUtils.exists(account, MainApp.getAppContext())) {
+                 // Cancel tranfers
+                 if (mUploaderBinder != null) {
+                     mUploaderBinder.cancel(account);
+                 }
+                 if (mDownloaderBinder != null) {
+                     mDownloaderBinder.cancel(account);
+                 }
+             }
              Account a = AccountUtils.getCurrentOwnCloudAccount(this);
              String accountName = "";
              if (a == null) {
      @Override
      protected void onDestroy() {
          mDbHandler.close();
+         if (mDownloadServiceConnection != null) {
+             unbindService(mDownloadServiceConnection);
+             mDownloadServiceConnection = null;
+         }
+         if (mUploadServiceConnection != null) {
+             unbindService(mUploadServiceConnection);
+             mUploadServiceConnection = null;
+         }
          super.onDestroy();
      }
  
                                              FileDisplayActivity.class
                                      );
                                      i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                                     i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
                                      startActivity(i);
                                  } else {
                                      finish();
          editor.putString("instant_video_upload_path", mUploadVideoPath);
          editor.commit();
      }
+     // Methods for ComponetsGetter
+     @Override
+     public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
+         return mDownloaderBinder;
+     }
+     @Override
+     public FileUploader.FileUploaderBinder getFileUploaderBinder() {
+         return mUploaderBinder;
+     }
+     @Override
+     public OperationsService.OperationsServiceBinder getOperationsServiceBinder() {
+         return null;
+     }
+     @Override
+     public FileDataStorageManager getStorageManager() {
+         return null;
+     }
+     @Override
+     public FileOperationsHelper getFileOperationsHelper() {
+         return null;
+     }
+     protected ServiceConnection newTransferenceServiceConnection() {
+         return new PreferencesServiceConnection();
+     }
+     /** Defines callbacks for service binding, passed to bindService() */
+     private class PreferencesServiceConnection implements ServiceConnection {
+         @Override
+         public void onServiceConnected(ComponentName component, IBinder service) {
+             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
+                 mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
+             } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
+                 Log_OC.d(TAG, "Upload service connected");
+                 mUploaderBinder = (FileUploader.FileUploaderBinder) service;
+             } else {
+                 return;
+             }
+         }
+         @Override
+         public void onServiceDisconnected(ComponentName component) {
+             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
+                 Log_OC.d(TAG, "Download service suddenly disconnected");
+                 mDownloaderBinder = null;
+             } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
+                 Log_OC.d(TAG, "Upload service suddenly disconnected");
+                 mUploaderBinder = null;
+             }
+         }
+     };
  }
@@@ -1,5 -1,7 +1,7 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -18,6 -20,7 +20,6 @@@
  package com.owncloud.android.ui.activity;
  
  import android.accounts.Account;
 -
  import android.os.Bundle;
  import android.view.View.OnClickListener;
  
@@@ -65,7 -68,7 +67,7 @@@ public class UploadPathActivity extend
  
              if (!stateWasRecovered) {
                  OCFileListFragment listOfFolders = getListOfFilesFragment();
 -                listOfFolders.listDirectory(folder);
 +                listOfFolders.listDirectory(folder, false);
  
                  startSyncFolderOperation(folder, false);
              }
@@@ -1,6 -1,10 +1,10 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author masensio
   *   Copyright (C) 2012  Bartek Przybylski
-  *   Copyright (C) 2012-2013 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -26,6 -30,7 +30,7 @@@ import java.util.List
  import java.util.Stack;
  import java.util.Vector;
  
  import android.accounts.Account;
  import android.accounts.AccountManager;
  import android.app.AlertDialog;
@@@ -38,52 -43,67 +43,74 @@@ import android.content.DialogInterface.
  import android.content.DialogInterface.OnClickListener;
  import android.content.Intent;
  import android.content.SharedPreferences;
+ import android.content.res.Resources.NotFoundException;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.Bundle;
  import android.os.Parcelable;
  import android.preference.PreferenceManager;
+ import android.provider.MediaStore;
  import android.provider.MediaStore.Audio;
  import android.provider.MediaStore.Images;
  import android.provider.MediaStore.Video;
+ import android.support.v4.app.Fragment;
+ import android.support.v4.app.FragmentManager;
+ import android.support.v4.app.FragmentTransaction;
  import android.view.View;
  import android.widget.AdapterView;
  import android.widget.AdapterView.OnItemClickListener;
  import android.widget.Button;
  import android.widget.EditText;
+ import android.widget.ListView;
  import android.widget.SimpleAdapter;
  import android.widget.Toast;
  
  import com.actionbarsherlock.app.ActionBar;
- import com.actionbarsherlock.app.SherlockListActivity;
  import com.actionbarsherlock.view.MenuItem;
  import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountAuthenticator;
 +import com.owncloud.android.datamodel.FileDataStorageManager;
 +import com.owncloud.android.datamodel.OCFile;
 +import com.owncloud.android.files.services.FileUploader;
 +import com.owncloud.android.lib.common.utils.Log_OC;
++import com.owncloud.android.MainApp;
++import com.owncloud.android.R;
++import com.owncloud.android.authentication.AccountAuthenticator;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.files.services.FileUploader;
+ import com.owncloud.android.lib.common.operations.RemoteOperation;
+ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+ import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.operations.CreateFolderOperation;
+ import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
+ import com.owncloud.android.ui.dialog.LoadingDialog;
+ import com.owncloud.android.utils.CopyTmpFileAsyncTask;
  import com.owncloud.android.utils.DisplayUtils;
+ import com.owncloud.android.utils.ErrorMessageAdapter;
  
  /**
   * This can be used to upload things to an ownCloud instance.
-  * 
-  * @author Bartek Przybylski
-  * 
   */
- public class Uploader extends SherlockListActivity implements OnItemClickListener, android.view.View.OnClickListener {
-     private static final String TAG = "ownCloudUploader";
+ public class Uploader extends FileActivity
+         implements OnItemClickListener, android.view.View.OnClickListener,
+         CopyTmpFileAsyncTask.OnCopyTmpFileTaskListener {
+     private static final String TAG = Uploader.class.getSimpleName();
  
-     private Account mAccount;
      private AccountManager mAccountManager;
      private Stack<String> mParents;
      private ArrayList<Parcelable> mStreamsToUpload;
      private boolean mCreateDir;
      private String mUploadPath;
-     private FileDataStorageManager mStorageManager;
      private OCFile mFile;
+     private boolean mAccountSelected;
+     private boolean mAccountSelectionShowing;
  
+     private ArrayList<String> mRemoteCacheData;
+     private int mNumCacheFile;
+     
      private final static int DIALOG_NO_ACCOUNT = 0;
      private final static int DIALOG_WAITING = 1;
      private final static int DIALOG_NO_STREAM = 2;
  
      private final static int REQUEST_CODE_SETUP_ACCOUNT = 0;
  
+     private final static String KEY_PARENTS = "PARENTS";
+     private final static String KEY_FILE = "FILE";
+     private final static String KEY_ACCOUNT_SELECTED = "ACCOUNT_SELECTED";
+     private final static String KEY_ACCOUNT_SELECTION_SHOWING = "ACCOUNT_SELECTION_SHOWING";
+     private final static String KEY_NUM_CACHE_FILE = "NUM_CACHE_FILE";
+     private final static String KEY_REMOTE_CACHE_DATA = "REMOTE_CACHE_DATA";
+     private static final String DIALOG_WAIT_COPY_FILE = "DIALOG_WAIT_COPY_FILE";
      @Override
      protected void onCreate(Bundle savedInstanceState) {
+         prepareStreamsToUpload();
+         if (savedInstanceState == null) {
+             mParents = new Stack<String>();
+             mAccountSelected = false;
+             mAccountSelectionShowing = false;
+             mNumCacheFile = 0;
+             // ArrayList for files with path in private storage
+             mRemoteCacheData = new ArrayList<String>();
+         } else {
+             mParents = (Stack<String>) savedInstanceState.getSerializable(KEY_PARENTS);
+             mFile = savedInstanceState.getParcelable(KEY_FILE);
+             mAccountSelected = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTED);
+             mAccountSelectionShowing = savedInstanceState.getBoolean(KEY_ACCOUNT_SELECTION_SHOWING);
+             mNumCacheFile = savedInstanceState.getInt(KEY_NUM_CACHE_FILE);
+             mRemoteCacheData = savedInstanceState.getStringArrayList(KEY_REMOTE_CACHE_DATA);
+         }
          super.onCreate(savedInstanceState);
-         mParents = new Stack<String>();
+         if (mAccountSelected) {
+             setAccount((Account) savedInstanceState.getParcelable(FileActivity.EXTRA_ACCOUNT));
+         }
  
          ActionBar actionBar = getSupportActionBar();
          actionBar.setIcon(DisplayUtils.getSeasonalIconId());
  
-         if (prepareStreamsToUpload()) {
+     }
+     @Override
+     protected void setAccount(Account account, boolean savedAccount) {
+         if (somethingToUpload()) {
              mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
              Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
              if (accounts.length == 0) {
                  Log_OC.i(TAG, "No ownCloud account is available");
                  showDialog(DIALOG_NO_ACCOUNT);
-             } else if (accounts.length > 1) {
-                 Log_OC.i(TAG, "More then one ownCloud is available");
+             } else if (accounts.length > 1 && !mAccountSelected && !mAccountSelectionShowing) {
+                 Log_OC.i(TAG, "More than one ownCloud is available");
                  showDialog(DIALOG_MULTIPLE_ACCOUNT);
+                 mAccountSelectionShowing = true;
              } else {
-                 mAccount = accounts[0];
-                 mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                 initTargetFolder();
-                 populateDirectoryList();
-                 
+                 if (!savedAccount) {
+                     setAccount(accounts[0]);
+                 }
              }
-             
          } else {
              showDialog(DIALOG_NO_STREAM);
          }
+         super.setAccount(account, savedAccount);
      }
-     
+     @Override
+     protected void onAccountSet(boolean stateWasRecovered) {
+         super.onAccountSet(mAccountWasRestored);
+         initTargetFolder();
+         populateDirectoryList();
+     }
+     @Override
+     protected void onSaveInstanceState(Bundle outState) {
+          Log_OC.d(TAG, "onSaveInstanceState() start");
+         super.onSaveInstanceState(outState);
+         outState.putSerializable(KEY_PARENTS, mParents);
+         //outState.putParcelable(KEY_ACCOUNT, mAccount);
+         outState.putParcelable(KEY_FILE, mFile);
+         outState.putBoolean(KEY_ACCOUNT_SELECTED, mAccountSelected);
+         outState.putBoolean(KEY_ACCOUNT_SELECTION_SHOWING, mAccountSelectionShowing);
+         outState.putInt(KEY_NUM_CACHE_FILE, mNumCacheFile);
+         outState.putStringArrayList(KEY_REMOTE_CACHE_DATA, mRemoteCacheData);
+         outState.putParcelable(FileActivity.EXTRA_ACCOUNT, getAccount());
+         Log_OC.d(TAG, "onSaveInstanceState() end");
+     }
      @Override
      protected Dialog onCreateDialog(final int id) {
          final AlertDialog.Builder builder = new Builder(this);
          case DIALOG_NO_ACCOUNT:
              builder.setIcon(android.R.drawable.ic_dialog_alert);
              builder.setTitle(R.string.uploader_wrn_no_account_title);
-             builder.setMessage(String.format(getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
+             builder.setMessage(String.format(
+                     getString(R.string.uploader_wrn_no_account_text), getString(R.string.app_name)));
              builder.setCancelable(false);
              builder.setPositiveButton(R.string.uploader_wrn_no_account_setup_btn_text, new OnClickListener() {
                  @Override
              });
              return builder.create();
          case DIALOG_MULTIPLE_ACCOUNT:
-             CharSequence ac[] = new CharSequence[mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
+             CharSequence ac[] = new CharSequence[
+                     mAccountManager.getAccountsByType(MainApp.getAccountType()).length];
              for (int i = 0; i < ac.length; ++i) {
-                 ac[i] = DisplayUtils.convertIdn(mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false);
+                 ac[i] = DisplayUtils.convertIdn(
+                         mAccountManager.getAccountsByType(MainApp.getAccountType())[i].name, false);
              }
              builder.setTitle(R.string.common_choose_account);
              builder.setItems(ac, new OnClickListener() {
                  @Override
                  public void onClick(DialogInterface dialog, int which) {
-                     mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
-                     mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
-                     initTargetFolder();
-                     populateDirectoryList();
+                     setAccount(mAccountManager.getAccountsByType(MainApp.getAccountType())[which]);
+                     onAccountSet(mAccountWasRestored);
+                     dialog.dismiss();
+                     mAccountSelected = true;
+                     mAccountSelectionShowing = false;
                  }
              });
              builder.setCancelable(true);
              builder.setOnCancelListener(new OnCancelListener() {
                  @Override
                  public void onCancel(DialogInterface dialog) {
+                     mAccountSelectionShowing = false;
                      dialog.cancel();
                      finish();
                  }
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
          // click on folder in the list
          Log_OC.d(TAG, "on item click");
-         Vector<OCFile> tmpfiles = mStorageManager.getFolderContent(mFile, false);
 -        Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile);
++        Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile, false);
          if (tmpfiles.size() <= 0) return;
          // filter on dirtype
          Vector<OCFile> files = new Vector<OCFile>();
          // click on button
          switch (v.getId()) {
          case R.id.uploader_choose_folder:
-             mUploadPath = "";   // first element in mParents is root dir, represented by ""; init mUploadPath with "/" results in a "//" prefix
+             mUploadPath = "";   // first element in mParents is root dir, represented by "";
+                                 // init mUploadPath with "/" results in a "//" prefix
              for (String p : mParents)
                  mUploadPath += p + OCFile.PATH_SEPARATOR;
              Log_OC.d(TAG, "Uploading file to dir " + mUploadPath);
              uploadFiles();
  
              break;
+             
+         case R.id.uploader_new_folder:
+             CreateFolderDialogFragment dialog = CreateFolderDialogFragment.newInstance(mFile);
+             dialog.show(getSupportFragmentManager(), "createdirdialog");
+             break;
+             
+             
          default:
              throw new IllegalArgumentException("Wrong element clicked");
          }
                  // there is no need for checking for is there more then one
                  // account at this point
                  // since account setup can set only one account at time
-                 mAccount = accounts[0];
+                 setAccount(accounts[0]);
                  populateDirectoryList();
              }
          }
  
      private void populateDirectoryList() {
          setContentView(R.layout.uploader_layout);
+         
+         ListView mListView = (ListView) findViewById(android.R.id.list);
  
          String current_dir = mParents.peek();
          if(current_dir.equals("")){
          actionBar.setHomeButtonEnabled(notRoot);
  
          String full_path = generatePath(mParents);
-         
          Log_OC.d(TAG, "Populating view with content of : " + full_path);
  
-         mFile = mStorageManager.getFileByPath(full_path);
+         mFile = getStorageManager().getFileByPath(full_path);
          if (mFile != null) {
-             Vector<OCFile> files = mStorageManager.getFolderContent(mFile, false);
 -            Vector<OCFile> files = getStorageManager().getFolderContent(mFile);
++            Vector<OCFile> files = getStorageManager().getFolderContent(mFile, false);
              List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
              for (OCFile f : files) {
                  HashMap<String, Object> h = new HashMap<String, Object>();
                                                  data,
                                                  R.layout.uploader_list_item_layout,
                                                  new String[] {"dirname"},
-                                                 new int[] {R.id.drawer_username});
-             setListAdapter(sa);
-             Button btn = (Button) findViewById(R.id.uploader_choose_folder);
-             btn.setOnClickListener(this);
-             getListView().setOnItemClickListener(this);
+                                                 new int[] {R.id.textView1});
+             
+             mListView.setAdapter(sa);
+             Button btnChooseFolder = (Button) findViewById(R.id.uploader_choose_folder);
+             btnChooseFolder.setOnClickListener(this);
+             
+             Button btnNewFolder = (Button) findViewById(R.id.uploader_new_folder);
+             btnNewFolder.setOnClickListener(this);
+             
+             mListView.setOnItemClickListener(this);
          }
      }
  
          return full_path;
      }
  
-     private boolean prepareStreamsToUpload() {
+     private void prepareStreamsToUpload() {
          if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
              mStreamsToUpload = new ArrayList<Parcelable>();
              mStreamsToUpload.add(getIntent().getParcelableExtra(Intent.EXTRA_STREAM));
          } else if (getIntent().getAction().equals(Intent.ACTION_SEND_MULTIPLE)) {
              mStreamsToUpload = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM);
          }
+     }
+     private boolean somethingToUpload() {
          return (mStreamsToUpload != null && mStreamsToUpload.get(0) != null);
      }
  
      public void uploadFiles() {
          try {
  
+             // ArrayList for files with path in external storage
              ArrayList<String> local = new ArrayList<String>();
              ArrayList<String> remote = new ArrayList<String>();
              
              for (Parcelable mStream : mStreamsToUpload) {
                  
                  Uri uri = (Uri) mStream;
-                 if (uri !=null) {
+                 String data = null;
+                 String filePath = "";
+                 if (uri != null) {
                      if (uri.getScheme().equals("content")) {
-                         
-                        String mimeType = getContentResolver().getType(uri);
-                        
-                        if (mimeType.contains("image")) {
-                            String[] CONTENT_PROJECTION = { Images.Media.DATA, Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE, Images.Media.SIZE};
-                            Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
-                            c.moveToFirst();
-                            int index = c.getColumnIndex(Images.Media.DATA);
-                            String data = c.getString(index);
-                            local.add(data);
-                            remote.add(mUploadPath + c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME)));
-                        
-                        }
-                        else if (mimeType.contains("video")) {
-                            String[] CONTENT_PROJECTION = { Video.Media.DATA, Video.Media.DISPLAY_NAME, Video.Media.MIME_TYPE, Video.Media.SIZE, Video.Media.DATE_MODIFIED };
-                            Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
-                            c.moveToFirst();
-                            int index = c.getColumnIndex(Video.Media.DATA);
-                            String data = c.getString(index);
-                            local.add(data);
-                            remote.add(mUploadPath + c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME)));
+                         String mimeType = getContentResolver().getType(uri);
+                         if (mimeType.contains("image")) {
+                             String[] CONTENT_PROJECTION = { Images.Media.DATA,
+                                     Images.Media.DISPLAY_NAME, Images.Media.MIME_TYPE,
+                                     Images.Media.SIZE };
+                             Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
+                                     null, null);
+                             c.moveToFirst();
+                             int index = c.getColumnIndex(Images.Media.DATA);
+                             data = c.getString(index);
+                             filePath = mUploadPath +
+                                     c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME));
+                         } else if (mimeType.contains("video")) {
+                             String[] CONTENT_PROJECTION = { Video.Media.DATA,
+                                    Video.Media.DISPLAY_NAME, Video.Media.MIME_TYPE,
+                                    Video.Media.SIZE, Video.Media.DATE_MODIFIED };
+                             Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
+                                    null, null);
+                             c.moveToFirst();
+                             int index = c.getColumnIndex(Video.Media.DATA);
+                             data = c.getString(index);
+                             filePath = mUploadPath +
+                                    c.getString(c.getColumnIndex(Video.Media.DISPLAY_NAME));
                            
-                        }
-                        else if (mimeType.contains("audio")) {
-                            String[] CONTENT_PROJECTION = { Audio.Media.DATA, Audio.Media.DISPLAY_NAME, Audio.Media.MIME_TYPE, Audio.Media.SIZE };
-                            Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null, null, null);
-                            c.moveToFirst();
-                            int index = c.getColumnIndex(Audio.Media.DATA);
-                            String data = c.getString(index);
-                            local.add(data);
-                            remote.add(mUploadPath + c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME)));
-                         
-                        }
-                        else {
-                            String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "");
-                            // cut everything whats before mnt. It occured to me that sometimes apps send their name into the URI
-                            if (filePath.contains("mnt")) {
-                               String splitedFilePath[] = filePath.split("/mnt");
-                               filePath = splitedFilePath[1];
-                            }
-                            final File file = new File(filePath);
-                            local.add(file.getAbsolutePath());
-                            remote.add(mUploadPath + file.getName());
-                        }
-                         
+                         } else if (mimeType.contains("audio")) {
+                             String[] CONTENT_PROJECTION = { Audio.Media.DATA,
+                                    Audio.Media.DISPLAY_NAME, Audio.Media.MIME_TYPE,
+                                    Audio.Media.SIZE };
+                             Cursor c = getContentResolver().query(uri, CONTENT_PROJECTION, null,
+                                    null, null);
+                             c.moveToFirst();
+                             int index = c.getColumnIndex(Audio.Media.DATA);
+                             data = c.getString(index);
+                             filePath = mUploadPath +
+                                    c.getString(c.getColumnIndex(Audio.Media.DISPLAY_NAME));
+                         } else  {
+                             Cursor cursor = getContentResolver().query(uri,
+                                    new String[]{MediaStore.MediaColumns.DISPLAY_NAME},
+                                    null, null, null);
+                             cursor.moveToFirst();
+                             int nameIndex = cursor.getColumnIndex(cursor.getColumnNames()[0]);
+                             if (nameIndex >= 0) {
+                                filePath = mUploadPath + cursor.getString(nameIndex);
+                             }
+                         }
                      } else if (uri.getScheme().equals("file")) {
-                         String filePath = Uri.decode(uri.toString()).replace(uri.getScheme() + "://", "");
+                         filePath = Uri.decode(uri.toString()).replace(uri.getScheme() +
+                                 "://", "");
                          if (filePath.contains("mnt")) {
                             String splitedFilePath[] = filePath.split("/mnt");
                             filePath = splitedFilePath[1];
                          }
                          final File file = new File(filePath);
-                         local.add(file.getAbsolutePath());
-                         remote.add(mUploadPath + file.getName());
+                         data = file.getAbsolutePath();
+                         filePath = mUploadPath + file.getName();
                      }
                      else {
                          throw new SecurityException();
                      }
+                     if (data == null) {
+                         mRemoteCacheData.add(filePath);
+                         CopyTmpFileAsyncTask copyTask = new CopyTmpFileAsyncTask(this);
+                         Object[] params = { uri, filePath, mRemoteCacheData.size()-1,
+                                 getAccount().name, getContentResolver()};
+                         mNumCacheFile++;
+                         showWaitingCopyDialog();
+                         copyTask.execute(params);
+                     } else {
+                         remote.add(filePath);
+                         local.add(data);
+                     }
                  }
                  else {
                      throw new SecurityException();
                  }
-            
-             Intent intent = new Intent(getApplicationContext(), FileUploader.class);
-             intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
-             intent.putExtra(FileUploader.KEY_LOCAL_FILE, local.toArray(new String[local.size()]));
-             intent.putExtra(FileUploader.KEY_REMOTE_FILE, remote.toArray(new String[remote.size()]));
-             intent.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
-             startService(intent);
  
-             //Save the path to shared preferences
-             SharedPreferences.Editor appPrefs = PreferenceManager
-                     .getDefaultSharedPreferences(getApplicationContext()).edit();
-             appPrefs.putString("last_upload_path", mUploadPath);
-             appPrefs.apply();
+                 Intent intent = new Intent(getApplicationContext(), FileUploader.class);
+                 intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_MULTIPLE_FILES);
+                 intent.putExtra(FileUploader.KEY_LOCAL_FILE, local.toArray(new String[local.size()]));
+                 intent.putExtra(FileUploader.KEY_REMOTE_FILE,
+                         remote.toArray(new String[remote.size()]));
+                 intent.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
+                 startService(intent);
+                 //Save the path to shared preferences
+                 SharedPreferences.Editor appPrefs = PreferenceManager
+                         .getDefaultSharedPreferences(getApplicationContext()).edit();
+                 appPrefs.putString("last_upload_path", mUploadPath);
+                 appPrefs.apply();
  
-             finish();
+                 finish();
              }
              
          } catch (SecurityException e) {
-             String message = String.format(getString(R.string.uploader_error_forbidden_content), getString(R.string.app_name));
+             String message = String.format(getString(R.string.uploader_error_forbidden_content),
+                     getString(R.string.app_name));
              Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
          }
      }
      
+     @Override
+     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+         super.onRemoteOperationFinish(operation, result);
+         
+       
+         if (operation instanceof CreateFolderOperation) {
+             onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
+         }
+         
+     }
+     
+     /**
+      * Updates the view associated to the activity after the finish of an operation
+      * trying create a new folder
+      * 
+      * @param operation     Creation operation performed.
+      * @param result        Result of the creation.
+      */
+     private void onCreateFolderOperationFinish(CreateFolderOperation operation,
+                                                RemoteOperationResult result) {
+         if (result.isSuccess()) {
+             dismissLoadingDialog();
+             populateDirectoryList();
+         } else {
+             dismissLoadingDialog();
+             try {
+                 Toast msg = Toast.makeText(this, 
+                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
+                         Toast.LENGTH_LONG); 
+                 msg.show();
+             } catch (NotFoundException e) {
+                 Log_OC.e(TAG, "Error while trying to show fail message " , e);
+             }
+         }
+     }
+     
+     
      /**
       *  Loads the target folder initialize shown to the user.
       * 
       *  The target account has to be chosen before this method is called. 
       */
      private void initTargetFolder() {
-         if (mStorageManager == null) {
-             throw new IllegalStateException("Do not call this method before initializing mStorageManager");
+         if (getStorageManager() == null) {
+             throw new IllegalStateException("Do not call this method before " +
+                     "initializing mStorageManager");
          }
          
          SharedPreferences appPreferences = PreferenceManager
          // "/" equals root-directory
          if(last_path.equals("/")) {
              mParents.add("");
-         }
-         else{
+         } else{
              String[] dir_names = last_path.split("/");
              for (String dir : dir_names)
                  mParents.add(dir);
          }
          //Make sure that path still exists, if it doesn't pop the stack and try the previous path
-             while(!mStorageManager.fileExists(generatePath(mParents)) && mParents.size() > 1){
-                 mParents.pop();
-             }
+         while(!getStorageManager().fileExists(generatePath(mParents)) && mParents.size() > 1){
+             mParents.pop();
+         }
      }
  
      
      public boolean onOptionsItemSelected(MenuItem item) {
          boolean retval = true;
          switch (item.getItemId()) {
-         case android.R.id.home: {
-             if((mParents.size() > 1)) {                
-                 onBackPressed(); 
-             }
-             break;
-         }
-         default:
-             retval = super.onOptionsItemSelected(item);
+             case android.R.id.home:
+                 if((mParents.size() > 1)) {
+                     onBackPressed();
+                 }
+                 break;
+             default:
+                 retval = super.onOptionsItemSelected(item);
          }
          return retval;
      }
  
-     
+     /**
+      * Process the result of CopyTmpFileAsyncTask
+      * @param result
+      * @param index
+      */
+     @Override
+     public void onTmpFileCopied(String result, int index) {
+         if (mNumCacheFile -- == 0) {
+             dismissWaitingCopyDialog();
+         }
+         if (result != null) {
+             Intent intent = new Intent(getApplicationContext(), FileUploader.class);
+             intent.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
+             intent.putExtra(FileUploader.KEY_LOCAL_FILE, result);
+             intent.putExtra(FileUploader.KEY_REMOTE_FILE, mRemoteCacheData.get(index));
+             intent.putExtra(FileUploader.KEY_ACCOUNT, getAccount());
+             startService(intent);
+         } else {
+             String message = String.format(getString(R.string.uploader_error_forbidden_content),
+                     getString(R.string.app_name));
+             Toast.makeText(this, message, Toast.LENGTH_LONG).show();
+             Log_OC.d(TAG, message);
+         }
+     }
+ /**
+      * Show waiting for copy dialog
+      */
+     public void showWaitingCopyDialog() {
+         // Construct dialog
+         LoadingDialog loading = new LoadingDialog(
+                 getResources().getString(R.string.wait_for_tmp_copy_from_private_storage));
+         FragmentManager fm = getSupportFragmentManager();
+         FragmentTransaction ft = fm.beginTransaction();
+         loading.show(ft, DIALOG_WAIT_COPY_FILE);
+     }
+     /**
+      * Dismiss waiting for copy dialog
+      */
+     public void dismissWaitingCopyDialog(){
+         Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_COPY_FILE);
+         if (frag != null) {
+             LoadingDialog loading = (LoadingDialog) frag;
+             loading.dismiss();
+         }
+     }
  }
@@@ -1,6 -1,11 +1,11 @@@
- /* ownCloud Android client application\r
+ /**\r
+  *   ownCloud Android client application\r
+  *\r
+  *   @author Bartek Przybylski\r
+  *   @author Tobias Kaminsky\r
+  *   @author David A. Velasco\r
   *   Copyright (C) 2011  Bartek Przybylski\r
-  *   Copyright (C) 2012-2014 ownCloud Inc.\r
+  *   Copyright (C) 2015 ownCloud Inc.\r
   *\r
   *   This program is free software: you can redistribute it and/or modify\r
   *   it under the terms of the GNU General Public License version 2,\r
   */\r
  package com.owncloud.android.ui.adapter;\r
  \r
\r
  import java.io.File;\r
- import java.util.Collections;\r
- import java.util.Comparator;\r
  import java.util.Vector;\r
  \r
- import third_parties.daveKoeller.AlphanumComparator;\r
  import android.accounts.Account;\r
  import android.content.Context;\r
  import android.content.SharedPreferences;\r
  import android.graphics.Bitmap;\r
+ import android.os.Build;\r
  import android.preference.PreferenceManager;\r
  import android.text.format.DateUtils;\r
  import android.view.LayoutInflater;\r
  import android.view.View;\r
  import android.view.ViewGroup;\r
+ import android.widget.AbsListView;\r
  import android.widget.BaseAdapter;\r
  import android.widget.ImageView;\r
+ import android.widget.LinearLayout;\r
  import android.widget.ListAdapter;\r
- import android.widget.ListView;\r
  import android.widget.TextView;\r
  \r
  import com.owncloud.android.R;\r
@@@ -44,65 -48,60 +48,60 @@@ import com.owncloud.android.authenticat
  import com.owncloud.android.datamodel.FileDataStorageManager;\r
  import com.owncloud.android.datamodel.OCFile;\r
  import com.owncloud.android.datamodel.ThumbnailsCacheManager;\r
- import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncDrawable;\r
  import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;\r
  import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;\r
+ import com.owncloud.android.services.OperationsService.OperationsServiceBinder;\r
  import com.owncloud.android.ui.activity.ComponentsGetter;\r
  import com.owncloud.android.utils.DisplayUtils;\r
  import com.owncloud.android.utils.FileStorageUtils;\r
\r
  \r
  /**\r
   * This Adapter populates a ListView with all files and folders in an ownCloud\r
   * instance.\r
-  * \r
-  * @author Bartek Przybylski\r
-  * @author Tobias Kaminsky\r
-  * @author David A. Velasco\r
   */\r
- public class FileListListAdapter extends BaseAdapter implements ListAdapter {
+ public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
      private final static String PERMISSION_SHARED_WITH_ME = "S";\r
-     \r
\r
      private Context mContext;\r
      private OCFile mFile = null;\r
      private Vector<OCFile> mFiles = null;\r
+     private Vector<OCFile> mFilesOrig = new Vector<OCFile>();\r
      private boolean mJustFolders;\r
  \r
-     private FileDataStorageManager mStorageManager;
-     private Account mAccount;
+     private FileDataStorageManager mStorageManager;\r
+     private Account mAccount;\r
      private ComponentsGetter mTransferServiceGetter;\r
-     private Integer mSortOrder;\r
-     public static final Integer SORT_NAME = 0;\r
-     public static final Integer SORT_DATE = 1;\r
-     public static final Integer SORT_SIZE = 2;\r
-     private Boolean mSortAscending;\r
+     private boolean mGridMode;\r
\r
+     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };\r
\r
      private SharedPreferences mAppPreferences;\r
      \r
      public FileListListAdapter(\r
              boolean justFolders, \r
-             Context context, \r
+             Context context,\r
              ComponentsGetter transferServiceGetter\r
              ) {\r
\r
+         \r
          mJustFolders = justFolders;\r
          mContext = context;\r
          mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
-         mTransferServiceGetter = transferServiceGetter;
-         \r
+         mTransferServiceGetter = transferServiceGetter;\r
\r
          mAppPreferences = PreferenceManager\r
                  .getDefaultSharedPreferences(mContext);\r
          \r
          // Read sorting order, default to sort by name ascending\r
-         mSortOrder = mAppPreferences\r
-                 .getInt("sortOrder", 0);\r
-         mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+         FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);\r
+         FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);\r
          \r
          // initialise thumbnails cache on background thread\r
          new ThumbnailsCacheManager.InitDiskCacheTask().execute();\r
  \r
+         mGridMode = false;\r
      }\r
-     
+     \r
      @Override\r
      public boolean areAllItemsEnabled() {\r
          return true;\r
  \r
      @Override\r
      public View getView(int position, View convertView, ViewGroup parent) {\r
\r
          View view = convertView;\r
-         if (view == null) {\r
-             LayoutInflater inflator = (LayoutInflater) mContext\r
-                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
-             view = inflator.inflate(R.layout.list_item, null);\r
-         }\r
-          \r
+         OCFile file = null;\r
+         LayoutInflater inflator = (LayoutInflater) mContext\r
+                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);\r
\r
          if (mFiles != null && mFiles.size() > position) {\r
-             OCFile file = mFiles.get(position);\r
-             TextView fileName = (TextView) view.findViewById(R.id.Filename);           \r
-             String name = file.getFileName();\r
+             file = mFiles.get(position);\r
+         }\r
\r
+         // Find out which layout should be displayed\r
+         ViewType viewType;\r
+         if (!mGridMode){\r
+             viewType = ViewType.LIST_ITEM;\r
+         } else if (file.isImage()){\r
+             viewType = ViewType.GRID_IMAGE;\r
+         } else {\r
+             viewType = ViewType.GRID_ITEM;\r
+         }\r
\r
+         // create view only if differs, otherwise reuse\r
+         if (convertView == null || (convertView != null && convertView.getTag() != viewType)) {\r
+             switch (viewType) {\r
+                 case GRID_IMAGE:\r
+                     view = inflator.inflate(R.layout.grid_image, null);\r
+                     view.setTag(ViewType.GRID_IMAGE);\r
+                     break;\r
+                 case GRID_ITEM:\r
+                     view = inflator.inflate(R.layout.grid_item, null);\r
+                     view.setTag(ViewType.GRID_ITEM);\r
+                     break;\r
+                 case LIST_ITEM:\r
+                     view = inflator.inflate(R.layout.list_item, null);\r
+                     view.setTag(ViewType.LIST_ITEM);\r
+                     break;\r
+             }\r
+         }\r
\r
+         view.invalidate();\r
\r
+         if (file != null){\r
\r
+             ImageView fileIcon = (ImageView) view.findViewById(R.id.thumbnail);\r
  \r
-             fileName.setText(name);\r
-             ImageView fileIcon = (ImageView) view.findViewById(R.id.drawer_userIcon);\r
              fileIcon.setTag(file.getFileId());\r
-             ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
-             ImageView sharedWithMeIconV = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
-             sharedWithMeIconV.setVisibility(View.GONE);\r
\r
-             ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
-             localStateView.bringToFront();\r
-             FileDownloaderBinder downloaderBinder = \r
-                     mTransferServiceGetter.getFileDownloaderBinder();\r
-             FileUploaderBinder uploaderBinder = mTransferServiceGetter.getFileUploaderBinder();\r
-             if (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, file)) {\r
-                 localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else if (uploaderBinder != null && uploaderBinder.isUploading(mAccount, file)) {\r
-                 localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else if (file.isDown()) {\r
-                 localStateView.setImageResource(R.drawable.local_file_indicator);\r
-                 localStateView.setVisibility(View.VISIBLE);\r
-             } else {\r
-                 localStateView.setVisibility(View.INVISIBLE);\r
+             TextView fileName;\r
+             String name = file.getFileName();\r
\r
+             LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.ListItemLayout);\r
+             linearLayout.setContentDescription("LinearLayout-" + name);\r
\r
+             switch (viewType){\r
+                 case LIST_ITEM:\r
+                     TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
+                     TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
+                     ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
\r
+                     lastModV.setVisibility(View.VISIBLE);\r
+                     lastModV.setText(showRelativeTimestamp(file));\r
\r
+                     checkBoxV.setVisibility(View.GONE);\r
\r
+                     fileSizeV.setVisibility(View.VISIBLE);\r
+                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
\r
+                     if (!file.isFolder()) {\r
+                         AbsListView parentList = (AbsListView)parent;\r
+                         if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+                             if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+                                 checkBoxV.setVisibility(View.GONE);\r
+                             } else {\r
+                                 if (parentList.isItemChecked(position)) {\r
+                                     checkBoxV.setImageResource(\r
+                                             android.R.drawable.checkbox_on_background);\r
+                                 } else {\r
+                                     checkBoxV.setImageResource(\r
+                                             android.R.drawable.checkbox_off_background);\r
+                                 }\r
+                                 checkBoxV.setVisibility(View.VISIBLE);\r
+                             }\r
+                         }\r
\r
+                     } else { //Folder\r
+                         fileSizeV.setVisibility(View.INVISIBLE);\r
+                     }\r
\r
+                 case GRID_ITEM:\r
+                     // filename\r
+                     fileName = (TextView) view.findViewById(R.id.Filename);\r
+                     name = file.getFileName();\r
+                     fileName.setText(name);\r
\r
+                 case GRID_IMAGE:\r
+                     // sharedIcon\r
+                     ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
+                     if (file.isShareByLink()) {\r
+                         sharedIconV.setVisibility(View.VISIBLE);\r
+                         sharedIconV.bringToFront();\r
+                     } else {\r
+                         sharedIconV.setVisibility(View.GONE);\r
+                     }\r
\r
+                     // local state\r
+                     ImageView localStateView = (ImageView) view.findViewById(R.id.localFileIndicator);\r
+                     localStateView.bringToFront();\r
+                     FileDownloaderBinder downloaderBinder =\r
+                             mTransferServiceGetter.getFileDownloaderBinder();\r
+                     FileUploaderBinder uploaderBinder =\r
+                             mTransferServiceGetter.getFileUploaderBinder();\r
+                     boolean downloading = (downloaderBinder != null &&\r
+                             downloaderBinder.isDownloading(mAccount, file));\r
+                     OperationsServiceBinder opsBinder =\r
+                             mTransferServiceGetter.getOperationsServiceBinder();\r
+                     downloading |= (opsBinder != null &&\r
+                             opsBinder.isSynchronizing(mAccount, file.getRemotePath()));\r
+                     if (downloading) {\r
+                         localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else if (uploaderBinder != null &&\r
+                             uploaderBinder.isUploading(mAccount, file)) {\r
+                         localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else if (file.isDown()) {\r
+                         localStateView.setImageResource(R.drawable.local_file_indicator);\r
+                         localStateView.setVisibility(View.VISIBLE);\r
+                     } else {\r
+                         localStateView.setVisibility(View.INVISIBLE);\r
+                     }\r
\r
+                     // share with me icon\r
+                     if (!file.isFolder()) {\r
+                         ImageView sharedWithMeIconV = (ImageView)\r
+                                 view.findViewById(R.id.sharedWithMeIcon);\r
+                         sharedWithMeIconV.bringToFront();\r
+                         if (checkIfFileIsSharedWithMe(file)) {\r
+                             sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                         } else {\r
+                             sharedWithMeIconV.setVisibility(View.GONE);\r
+                         }\r
+                     }\r
\r
+                     break;\r
              }\r
              \r
-             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
-             TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
-             ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+             // For all Views\r
+             \r
+             // this if-else is needed even though favorite icon is visible by default\r
+             // because android reuses views in listview\r
+             if (!file.keepInSync()) {\r
+                 view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);\r
+             } else {\r
+                 view.findViewById(R.id.favoriteIcon).setVisibility(View.VISIBLE);\r
+             }\r
              \r
+             // No Folder\r
              if (!file.isFolder()) {\r
-                 fileSizeV.setVisibility(View.VISIBLE);\r
-                 fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
-                 lastModV.setVisibility(View.VISIBLE);\r
-                 lastModV.setText(showRelativeTimestamp(file));\r
-                 // this if-else is needed even thoe fav icon is visible by default\r
-                 // because android reuses views in listview\r
-                 if (!file.keepInSync()) {\r
-                     view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
-                 } else {\r
-                     view.findViewById(R.id.imageView3).setVisibility(View.VISIBLE);\r
-                 }\r
-                 \r
-                 ListView parentList = (ListView)parent;\r
-                 if (parentList.getChoiceMode() == ListView.CHOICE_MODE_NONE) { \r
-                     checkBoxV.setVisibility(View.GONE);\r
-                 } else {\r
-                     if (parentList.isItemChecked(position)) {\r
-                         checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);\r
-                     } else {\r
-                         checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);\r
-                     }\r
-                     checkBoxV.setVisibility(View.VISIBLE);\r
-                 }               \r
-                 \r
-                 // get Thumbnail if file is image\r
                  if (file.isImage() && file.getRemoteId() != null){\r
-                      // Thumbnail in Cache?\r
+                     // Thumbnail in Cache?\r
                      Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
                              String.valueOf(file.getRemoteId())\r
-                     );\r
+                             );\r
                      if (thumbnail != null && !file.needsUpdateThumbnail()){\r
                          fileIcon.setImageBitmap(thumbnail);\r
                      } else {\r
                          // generate new Thumbnail\r
                          if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
-                             final ThumbnailsCacheManager.ThumbnailGenerationTask task = \r
+                             final ThumbnailsCacheManager.ThumbnailGenerationTask task =\r
                                      new ThumbnailsCacheManager.ThumbnailGenerationTask(\r
                                              fileIcon, mStorageManager, mAccount\r
-                                     );\r
+                                             );\r
                              if (thumbnail == null) {\r
                                  thumbnail = ThumbnailsCacheManager.mDefaultImg;\r
                              }\r
-                             final AsyncDrawable asyncDrawable = new AsyncDrawable(\r
+                             final ThumbnailsCacheManager.AsyncDrawable asyncDrawable =\r
+                                     new ThumbnailsCacheManager.AsyncDrawable(\r
                                      mContext.getResources(), \r
                                      thumbnail, \r
                                      task\r
-                             );\r
+                                     );\r
                              fileIcon.setImageDrawable(asyncDrawable);\r
                              task.execute(file);\r
                          }\r
                      }\r
                  } else {\r
-                     fileIcon.setImageResource(\r
-                             DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
-                     );\r
-                 }\r
-                 if (checkIfFileIsSharedWithMe(file)) {\r
-                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                     fileIcon.setImageResource(DisplayUtils.getFileTypeIconId(file.getMimetype(),\r
+                             file.getFileName()));\r
                  }\r
-             } \r
-             else {\r
-                   // TODO Re-enable when server supports folder-size calculation\r
- //                if (FileStorageUtils.getDefaultSavePathFor(mAccount.name, file) != null){\r
- //                    fileSizeV.setVisibility(View.VISIBLE);\r
- //                    fileSizeV.setText(getFolderSizeHuman(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)));\r
- //                } else {\r
-                     fileSizeV.setVisibility(View.INVISIBLE);\r
- //                }\r
-                 lastModV.setVisibility(View.VISIBLE);\r
-                 lastModV.setText(showRelativeTimestamp(file));\r
-                 checkBoxV.setVisibility(View.GONE);\r
-                 view.findViewById(R.id.imageView3).setVisibility(View.GONE);\r
  \r
+             } else {\r
+                 // Folder\r
                  if (checkIfFileIsSharedWithMe(file)) {\r
                      fileIcon.setImageResource(R.drawable.shared_with_me_folder);\r
-                     sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                 } else if (file.isShareByLink()) {\r
+                     // If folder is sharedByLink, icon folder must be changed to\r
+                     // folder-public one\r
+                     fileIcon.setImageResource(R.drawable.folder_public);\r
                  } else {\r
                      fileIcon.setImageResource(\r
-                             DisplayUtils.getResourceId(file.getMimetype(), file.getFileName())\r
+                             DisplayUtils.getFileTypeIconId(file.getMimetype(), file.getFileName())\r
                      );\r
                  }\r
\r
-                 // If folder is sharedByLink, icon folder must be changed to\r
-                 // folder-public one\r
-                 if (file.isShareByLink()) {\r
-                     fileIcon.setImageResource(R.drawable.folder_public);\r
-                 }\r
-             }\r
\r
-             if (file.isShareByLink()) {\r
-                 sharedIconV.setVisibility(View.VISIBLE);\r
-             } else {\r
-                 sharedIconV.setVisibility(View.GONE);\r
              }\r
          }\r
  \r
          return view;\r
      }\r
\r
      /**\r
       * Local Folder size in human readable format\r
       * \r
          File dir = new File(path);\r
  \r
          if (dir.exists()) {\r
-             long bytes = getFolderSize(dir);\r
+             long bytes = FileStorageUtils.getFolderSize(dir);\r
              return DisplayUtils.bytesToHumanReadable(bytes);\r
          }\r
  \r
              return result;\r
          }\r
          return 0;\r
-     } 
+     } \r
\r
      @Override\r
      public int getViewTypeCount() {\r
          return 1;\r
       * @param updatedStorageManager     Optional updated storage manager; used to replace \r
       *                                  mStorageManager if is different (and not NULL)\r
       */\r
 -    public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager) {\r
 +    public void swapDirectory(OCFile directory, FileDataStorageManager updatedStorageManager, boolean onlyOnDevice) {\r
          mFile = directory;\r
          if (updatedStorageManager != null && updatedStorageManager != mStorageManager) {\r
              mStorageManager = updatedStorageManager;\r
              mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);\r
          }\r
          if (mStorageManager != null) {\r
-             mFiles = mStorageManager.getFolderContent(mFile, onlyOnDevice);\r
 -            mFiles = mStorageManager.getFolderContent(mFile);\r
++            mFiles = mStorageManager.getFolderContent(mFile, false);\r
+             mFilesOrig.clear();\r
+             mFilesOrig.addAll(mFiles);\r
+             \r
              if (mJustFolders) {\r
                  mFiles = getFolders(mFiles);\r
              }\r
              mFiles = null;\r
          }\r
  \r
-         sortDirectory();\r
-     }\r
-     \r
-     /**\r
-      * Sorts all filenames, regarding last user decision \r
-      */\r
-     private void sortDirectory(){\r
-         switch (mSortOrder){\r
-         case 0:\r
-             sortByName(mSortAscending);\r
-             break;\r
-         case 1:\r
-             sortByDate(mSortAscending);\r
-             break;\r
-         case 2: \r
-             sortBySize(mSortAscending);\r
-             break;\r
-         }\r
-         \r
+         mFiles = FileStorageUtils.sortFolder(mFiles);\r
          notifyDataSetChanged();\r
      }\r
      \r
-     \r
\r
      /**\r
       * Filter for getting only the folders\r
       * @param files\r
                  && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
      }\r
  \r
-     /**\r
-      * Sorts list by Date\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortByDate(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
-         \r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     Long obj1 = o1.getModificationTimestamp();\r
-                     return val * obj1.compareTo(o2.getModificationTimestamp());\r
-                 }\r
-                 else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 } else if (o1.getModificationTimestamp() == 0 || o2.getModificationTimestamp() == 0){\r
-                     return 0;\r
-                 } else {\r
-                     Long obj1 = o1.getModificationTimestamp();\r
-                     return val * obj1.compareTo(o2.getModificationTimestamp());\r
-                 }\r
-             }\r
-         });\r
-     }\r
\r
-     /**\r
-      * Sorts list by Size\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortBySize(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
-         \r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     Long obj1 = getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o1)));\r
-                     return val * obj1.compareTo(getFolderSize(new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, o2))));\r
-                 }\r
-                 else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 } else if (o1.getFileLength() == 0 || o2.getFileLength() == 0){\r
-                     return 0;\r
-                 } else {\r
-                     Long obj1 = o1.getFileLength();\r
-                     return val * obj1.compareTo(o2.getFileLength());\r
-                 }\r
-             }\r
-         });\r
-     }\r
\r
-     /**\r
-      * Sorts list by Name\r
-      * @param sortAscending true: ascending, false: descending\r
-      */\r
-     private void sortByName(boolean sortAscending){\r
-         final Integer val;\r
-         if (sortAscending){\r
-             val = 1;\r
-         } else {\r
-             val = -1;\r
-         }\r
\r
-         Collections.sort(mFiles, new Comparator<OCFile>() {\r
-             public int compare(OCFile o1, OCFile o2) {\r
-                 if (o1.isFolder() && o2.isFolder()) {\r
-                     return val * o1.getRemotePath().toLowerCase().compareTo(o2.getRemotePath().toLowerCase());\r
-                 } else if (o1.isFolder()) {\r
-                     return -1;\r
-                 } else if (o2.isFolder()) {\r
-                     return 1;\r
-                 }\r
-                 return val * new AlphanumComparator().compare(o1, o2);\r
-             }\r
-         });\r
-     }\r
\r
      public void setSortOrder(Integer order, boolean ascending) {\r
          SharedPreferences.Editor editor = mAppPreferences.edit();\r
          editor.putInt("sortOrder", order);\r
          editor.putBoolean("sortAscending", ascending);\r
          editor.commit();\r
          \r
-         mSortOrder = order;\r
-         mSortAscending = ascending;\r
+         FileStorageUtils.mSortOrder = order;\r
+         FileStorageUtils.mSortAscending = ascending;\r
          \r
-         sortDirectory();\r
-     }    \r
\r
+         mFiles = FileStorageUtils.sortFolder(mFiles);\r
+         notifyDataSetChanged();\r
\r
+     }\r
      \r
      private CharSequence showRelativeTimestamp(OCFile file){\r
          return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),\r
                  DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);\r
-     }
+     }\r
\r
+     public void setGridMode(boolean gridMode) {\r
+         mGridMode = gridMode;\r
+     }\r
  }\r
@@@ -1,5 -1,8 +1,8 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2014 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -20,9 -23,7 +23,7 @@@ package com.owncloud.android.ui.dialog
  /**
   *  Dialog requiring confirmation before removing a given OCFile.  
   * 
-  *  Triggers the removal according to the user response. 
-  *  
-  *  @author David A. Velasco
+  *  Triggers the removal according to the user response.
   */
  import java.util.Vector;
  
@@@ -111,7 -112,7 +112,7 @@@ implements ConfirmationDialogFragmentLi
          
          boolean containsKeepInSync = false;
          if (mTargetFile.isFolder()) {
 -            Vector<OCFile> files = storageManager.getFolderContent(mTargetFile);
 +            Vector<OCFile> files = storageManager.getFolderContent(mTargetFile, false);
              for(OCFile file: files) {
                  containsKeepInSync = file.keepInSync() || containsKeepInSync;
  
@@@ -1,6 -1,11 +1,11 @@@
- /* ownCloud Android client application
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author Bartek Przybylski
+  *   @author masensio
+  *   @author David A. Velasco
   *   Copyright (C) 2011  Bartek Przybylski
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
  package com.owncloud.android.ui.fragment;
  
  import java.io.File;
- import java.util.Vector;
  
  import android.app.Activity;
- import android.content.Context;
  import android.content.Intent;
  import android.os.Bundle;
  import android.support.v4.widget.SwipeRefreshLayout;
  import android.view.ContextMenu;
 +import android.view.LayoutInflater;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.widget.AdapterView;
  import android.widget.AdapterView.AdapterContextMenuInfo;
 +import android.widget.TextView;
  
 +import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
@@@ -49,15 -49,12 +52,12 @@@ import com.owncloud.android.ui.dialog.R
  import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
+ import com.owncloud.android.utils.FileStorageUtils;
  
  /**
   * A Fragment that lists all files and folders in a given path.
   * 
   * TODO refactorize to get rid of direct dependency on FileDisplayActivity
-  * 
-  * @author Bartek Przybylski
-  * @author masensio
-  * @author David A. Velasco
   */
  public class OCFileListFragment extends ExtendedListFragment {
      
              
      private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
  
+     private final static Double THUMBNAIL_THRESHOLD = 0.5;
      private FileFragment.ContainerActivity mContainerActivity;
     
      private OCFile mFile = null;
      private FileListListAdapter mAdapter;
-     private View mFooterView;
+     private boolean mJustFolders;
      
      private OCFile mTargetFile;
 -
 +    
 +   
      
      /**
       * {@inheritDoc}
              mFile = savedInstanceState.getParcelable(KEY_FILE);
          }
  
-         mFooterView = ((LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
-                         R.layout.list_footer, null, false);
-         setFooterView(mFooterView);
+         if (mJustFolders) {
+             setFooterEnabled(false);
+         } else {
+             setFooterEnabled(true);
+         }
  
          Bundle args = getArguments();
-         boolean justFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false); 
+         mJustFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false);
          mAdapter = new FileListListAdapter(
-                 justFolders,
-                 getSherlockActivity(), 
+                 mJustFolders,
+                 getSherlockActivity(),
                  mContainerActivity
                  );
          setListAdapter(mAdapter);
  
-         registerForContextMenu(getListView());
-         getListView().setOnCreateContextMenuListener(this);
-     }
+         registerForContextMenu();
+   }
  
      /**
       * Saves the current listed folder.
              }   // exit is granted because storageManager.getFileByPath("/") never returns null
              mFile = parentDir;
              
 -            listDirectory(mFile);
 +            listDirectory(mFile, MainApp.getOnlyOnDevice());
  
              onRefresh(false);
              
          if (file != null) {
              if (file.isFolder()) { 
                  // update state and view of this fragment
 -                listDirectory(file);
 +                listDirectory(file, MainApp.getOnlyOnDevice());
                  // then, notify parent activity to let it update its state and view
                  mContainerActivity.onBrowsedDownTo(file);
                  // save index and top position
      /**
       * Calls {@link OCFileListFragment#listDirectory(OCFile)} with a null parameter
       */
 -    public void listDirectory(){
 -        listDirectory(null);
 +    public void listDirectory(boolean onlyOnDevice){
 +        listDirectory(null, onlyOnDevice);
 +    }
 +    
 +    public void refreshDirectory(){
 +        listDirectory(getCurrentFile(), MainApp.getOnlyOnDevice());
      }
      
      /**
       * 
       * @param directory File to be listed
       */
 -    public void listDirectory(OCFile directory) {
 +    public void listDirectory(OCFile directory, boolean onlyOnDevice) {
          FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
          if (storageManager != null) {
  
                  directory = storageManager.getFileById(directory.getParentId());
              }
  
 -            mAdapter.swapDirectory(directory, storageManager);
 +            mAdapter.swapDirectory(directory, storageManager, onlyOnDevice);
              if (mFile == null || !mFile.equals(directory)) {
-                 mList.setSelectionFromTop(0, 0);
+                 mCurrentListView.setSelection(0);
              }
              mFile = directory;
-             
-             // Update Footer
-             TextView footerText = (TextView) mFooterView.findViewById(R.id.footerText);
-             Log_OC.d("footer", String.valueOf(System.currentTimeMillis()));
-             footerText.setText(generateFooterText(directory, onlyOnDevice));
-             Log_OC.d("footer", String.valueOf(System.currentTimeMillis()));
+             updateLayout();
          }
      }
-     
-     private String generateFooterText(OCFile directory, boolean onlyOnDevice) {
-         Integer files = 0;
-         Integer folders = 0;
  
-         FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-         Vector<OCFile> mFiles = storageManager.getFolderContent(mFile, onlyOnDevice);
+     private void updateLayout() {
+         if (!mJustFolders) {
+             int filesCount = 0, foldersCount = 0, imagesCount = 0;
+             int count = mAdapter.getCount();
+             OCFile file;
+             for (int i=0; i < count ; i++) {
+                 file = (OCFile) mAdapter.getItem(i);
+                 if (file.isFolder()) {
+                     foldersCount++;
+                 } else {
+                     filesCount++;
+                     if (file.isImage()){
+                         imagesCount++;
+                     }
+                 }
+             }
+             // set footer text
+             setFooterText(generateFooterText(filesCount, foldersCount));
  
-         for (OCFile ocFile : mFiles) {
-             if (ocFile.isFolder()) {
-                 folders++;
+             // decide grid vs list view
+             if (((double)imagesCount / (double)filesCount) >= THUMBNAIL_THRESHOLD) {
+                 switchToGridView();
              } else {
-                 files++;
+                 switchToListView();
              }
          }
+     }
  
+     private String generateFooterText(int filesCount, int foldersCount) {
          String output = "";
-        
-         if (files > 0){
-             if (files == 1) {
-                 output = output + files.toString() + " " + getResources().getString(R.string.file_list_file);
+         if (filesCount > 0){
+             if (filesCount == 1) {
+                 output = output + filesCount + " " + getResources().getString(R.string.file_list_file);
              } else {
-                 output = output + files.toString() + " " + getResources().getString(R.string.file_list_files);
+                 output = output + filesCount + " " + getResources().getString(R.string.file_list_files);
              }
          }
-         if (folders > 0 && files > 0){
+         if (foldersCount > 0 && filesCount > 0){
              output = output + ", ";
          }
-         if (folders == 1) {
-             output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folder);
-         } else if (folders > 1) {
-             output = output + folders.toString() + " " + getResources().getString(R.string.file_list_folders);
+         if (foldersCount == 1) {
+             output = output + foldersCount + " " + getResources().getString(R.string.file_list_folder);
+         } else if (foldersCount > 1) {
+             output = output + foldersCount + " " + getResources().getString(R.string.file_list_folders);
          }
-         
          return output;
      }
-     
      public void sortByName(boolean descending) {
-         mAdapter.setSortOrder(FileListListAdapter.SORT_NAME, descending);
+         mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
      }
  
      public void sortByDate(boolean descending) {
-         mAdapter.setSortOrder(FileListListAdapter.SORT_DATE, descending);
+         mAdapter.setSortOrder(FileStorageUtils.SORT_DATE, descending);
      }
  
      public void sortBySize(boolean descending) {
-         mAdapter.setSortOrder(FileListListAdapter.SORT_SIZE, descending);
+         mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
      }  
 -
 +    
 +   
 +    
  }
@@@ -1,5 -1,8 +1,8 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2013  ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015  ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -23,13 -26,11 +26,11 @@@ import android.content.Context
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.ServiceConnection;
- import android.content.SharedPreferences;
  import android.os.Build;
  import android.os.Bundle;
  import android.os.Handler;
  import android.os.IBinder;
  import android.os.Message;
- import android.preference.PreferenceManager;
  import android.support.v4.view.ViewPager;
  import android.view.View;
  
@@@ -37,7 -38,6 +38,7 @@@ import com.actionbarsherlock.app.Action
  import com.actionbarsherlock.view.MenuItem;
  import com.actionbarsherlock.view.Window;
  import com.ortiz.touch.ExtendedViewPager;
 +import com.owncloud.android.MainApp;
  import com.owncloud.android.R;
  import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.datamodel.FileDataStorageManager;
@@@ -56,15 -56,12 +57,12 @@@ import com.owncloud.android.operations.
  import com.owncloud.android.operations.UnshareLinkOperation;
  import com.owncloud.android.ui.activity.FileActivity;
  import com.owncloud.android.ui.activity.FileDisplayActivity;
- import com.owncloud.android.ui.activity.PinCodeActivity;
  import com.owncloud.android.ui.fragment.FileFragment;
  import com.owncloud.android.utils.DisplayUtils;
  
  
  /**
   *  Holds a swiping galley where image files contained in an ownCloud directory are shown
-  *  
-  *  @author David A. Velasco
   */
  public class PreviewImageActivity extends FileActivity implements 
   FileFragment.ContainerActivity,
@@@ -90,7 -87,7 +88,7 @@@ ViewPager.OnPageChangeListener, OnRemot
      
      private View mFullScreenAnchorView;
      
-     
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          actionBar.setIcon(DisplayUtils.getSeasonalIconId());
          actionBar.setDisplayHomeAsUpEnabled(true);
          actionBar.hide();
-         
-         // PIN CODE request
-         if (getIntent().getExtras() != null && savedInstanceState == null && fromNotification()) {
-             requestPinCode();
-         }
  
          // Make sure we're running on Honeycomb or higher to use FullScreen and
          // Immersive Mode
              // should not be necessary
              parentFolder = getStorageManager().getFileByPath(OCFile.ROOT_PATH);
          }
 -        mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), getStorageManager());
 +        mPreviewImagePagerAdapter = new PreviewImagePagerAdapter(getSupportFragmentManager(), parentFolder, getAccount(), getStorageManager(), MainApp.getOnlyOnDevice());
          mViewPager = (ExtendedViewPager) findViewById(R.id.fragmentPager);
          int position = mHasSavedPosition ? mSavedPosition : mPreviewImagePagerAdapter.getFilePosition(getFile());
          position = (position >= 0) ? position : 0;
      @Override
      protected void onResume() {
          super.onResume();
-         //Log_OC.e(TAG, "ACTIVITY, ONRESUME");
          mDownloadFinishReceiver = new DownloadFinishReceiver();
          
          IntentFilter filter = new IntentFilter(FileDownloader.getDownloadFinishMessage());
  
      @Override
      protected void onPostResume() {
-         //Log_OC.e(TAG, "ACTIVITY, ONPOSTRESUME");
          super.onPostResume();
      }
      
      @Override
      public void onPause() {
-         unregisterReceiver(mDownloadFinishReceiver);
-         mDownloadFinishReceiver = null;
+         if (mDownloadFinishReceiver != null){
+             unregisterReceiver(mDownloadFinishReceiver);
+             mDownloadFinishReceiver = null;
+         }
+         
          super.onPause();
      }
      
      
  
      /**
-      * Class waiting for broadcast events from the {@link FielDownloader} service.
+      * Class waiting for broadcast events from the {@link FileDownloader} service.
       * 
       * Updates the UI when a download is started or finished, provided that it is relevant for the
       * folder displayed in the gallery.
              }
          }
      }
-     
-     
-     /**
-      * Launch an intent to request the PIN code to the user before letting him use the app
-      */
-     private void requestPinCode() {
-         boolean pinStart = false;
-         SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
-         pinStart = appPrefs.getBoolean("set_pincode", false);
-         if (pinStart) {
-             Intent i = new Intent(getApplicationContext(), PinCodeActivity.class);
-             i.putExtra(PinCodeActivity.EXTRA_ACTIVITY, "PreviewImageActivity");
-             startActivity(i);
-         }
-     }
  
      @Override
      public void onBrowsedDownTo(OCFile folder) {
          }
          return false;
      }
  }
@@@ -1,5 -1,8 +1,8 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2013  ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015  ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -16,6 -19,8 +19,8 @@@
   */
  package com.owncloud.android.ui.preview;
  
+ import java.util.Collections;
+ import java.util.Comparator;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Iterator;
@@@ -31,12 -36,12 +36,12 @@@ import android.view.ViewGroup
  
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.ui.adapter.FileListListAdapter;
  import com.owncloud.android.ui.fragment.FileFragment;
+ import com.owncloud.android.utils.FileStorageUtils;
  
  /**
-  * Adapter class that provides Fragment instances  
-  * 
-  * @author David A. Velasco
+  * Adapter class that provides Fragment instances
   */
  //public class PreviewImagePagerAdapter extends PagerAdapter {
  public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
@@@ -57,7 -62,7 +62,7 @@@
       * @param parentFolder      Folder where images will be searched for.
       * @param storageManager    Bridge to database.
       */
 -    public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, FileDataStorageManager storageManager) {
 +    public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, FileDataStorageManager storageManager, boolean onlyOnDevice) {
          super(fragmentManager);
          
          if (fragmentManager == null) {
  
          mAccount = account;
          mStorageManager = storageManager;
-         mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice); 
 -        mImageFiles = mStorageManager.getFolderImages(parentFolder); 
++        mImageFiles = mStorageManager.getFolderImages(parentFolder, false);
+         
+         mImageFiles = FileStorageUtils.sortFolder(mImageFiles);
+         
          mObsoleteFragments = new HashSet<Object>();
          mObsoletePositions = new HashSet<Integer>();
          mDownloadErrors = new HashSet<Integer>();
          //mFragmentManager = fragmentManager;
          mCachedFragments = new HashMap<Integer, FileFragment>();
      }
      
      /**
       * Returns the image files handled by the adapter.
          OCFile file = mImageFiles.get(i);
          Fragment fragment = null;
          if (file.isDown()) {
-             fragment = new PreviewImageFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
+             fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(Integer.valueOf(i)));
              
          } else if (mDownloadErrors.contains(Integer.valueOf(i))) {
-             fragment = new FileDownloadFragment(file, mAccount, true);
+             fragment = FileDownloadFragment.newInstance(file, mAccount, true);
              ((FileDownloadFragment)fragment).setError(true);
              mDownloadErrors.remove(Integer.valueOf(i));
              
          } else {
-             fragment = new FileDownloadFragment(file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)));
+             fragment = FileDownloadFragment.newInstance(
+                     file, mAccount, mObsoletePositions.contains(Integer.valueOf(i))
+             );
          }
          mObsoletePositions.remove(Integer.valueOf(i));
          return fragment;
@@@ -1,5 -1,8 +1,8 @@@
- /* ownCloud Android client application
-  *   Copyright (C) 2012-2014 ownCloud Inc.
+ /**
+  *   ownCloud Android client application
+  *
+  *   @author David A. Velasco
+  *   Copyright (C) 2015 ownCloud Inc.
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License version 2,
@@@ -23,11 -26,13 +26,13 @@@ import android.graphics.BitmapFactory
  import android.graphics.Matrix;
  import android.graphics.BitmapFactory.Options;
  import android.media.ExifInterface;
+ import android.net.Uri;
+ import android.webkit.MimeTypeMap;
+ import java.io.File;
  
  /**
   * Utility class with methods for decoding Bitmaps.
-  * 
-  * @author David A. Velasco
   */
  public class BitmapUtils {
      
@@@ -90,7 -95,9 +95,9 @@@
          if (height > reqHeight || width > reqWidth) {
              final int halfHeight = height / 2;
              final int halfWidth = width / 2;
-     
+             // calculates the largest inSampleSize value (for smallest sample) that is a power of 2 and keeps both
+             // height and width **larger** than the requested height and width.
              while ((halfHeight / inSampleSize) > reqHeight
                      && (halfWidth / inSampleSize) > reqWidth) {
                  inSampleSize *= 2;
      }
  
      /**
 +     * Converts an HSL color value to RGB. Conversion formula
 +     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.
 +     * Assumes h, s, and l are contained in the set [0, 1] and
 +     * returns r, g, and b in the set [0, 255].
 +     * from: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
 +     *
 +     * @param   integer  h       The hue
 +     * @param   Integer  s       The saturation
 +     * @param   Integer  l       The lightness
 +     * @return  Array           The RGB representation
 +     */
 +    public static int[] hslToRgb(Double h, Double s, Double l){
 +        Double r, g, b;
 +
 +        if(s == 0){
 +            r = g = b = l; // achromatic
 +        } else {
 +            Double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
 +            Double p = 2 * l - q;
 +            r = hue2rgb(p, q, h + 1/3) * 255;
 +            g = hue2rgb(p, q, h) * 255;
 +            b = hue2rgb(p, q, h - 1/3) * 255;
 +        }
 +
 +
 +        int[] array = {r.intValue(), g.intValue(), b.intValue()};
 +        return array;
 +    }
 +
 +    private static Double hue2rgb(Double p, Double q, Double t){
 +        if(t < 0) t += 1;
 +        if(t > 1) t -= 1;
 +        if(t < 1/6) return p + (q - p) * 6 * t;
 +        if(t < 1/2) return q;
 +        if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
 +        return p;
 +    }
 +    
++
++    /**
+      * Checks if file passed is an image
+      * @param file
+      * @return true/false
+      */
+     public static boolean isImage(File file) {
+         Uri selectedUri = Uri.fromFile(file);
+         String fileExtension = MimeTypeMap.getFileExtensionFromUrl(selectedUri.toString().toLowerCase());
+         String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileExtension);
+         return (mimeType != null && mimeType.startsWith("image/"));
+     }
      
  }