Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3894a8b9 authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Merge branch '5373-o-fixHiddenFileDetection' into 'v1-oreo'

Prevent detection of hidden file by FileObserver

See merge request !157
parents 7f7324dd 1b97ba4e
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ plugins {

def versionMajor = 1
def versionMinor = 2
def versionPatch = 0
def versionPatch = 1



+0 −1
Original line number Diff line number Diff line
@@ -94,7 +94,6 @@
            android:name=".services.ObserverService"
            android:enabled="true" />
        <service android:name=".services.SynchronizationService" />

        <receiver
            android:name=".receivers.BootCompletedReceiver"
            android:enabled="true"
+100 −36
Original line number Diff line number Diff line
@@ -42,24 +42,64 @@ public class FileEventListener {
    }

    public void onEvent(int event, File file) {
        if (event == FileObserver.DELETE) {
        if (file.isHidden()) return;

        if (file.isDirectory()) {
                handleDirectoryDelete(file);
            handleDirectoryEvent(event, file);
        } else {
                handleFileDelete(file);
            handleFileEvent(event, file);
        }
    }
        } else if (event == FileObserver.CLOSE_WRITE) {

            if (file.isDirectory()) {
                handleDirectoryCloseWrite(file);
            } else {
    /**
     * Handle some file event for a file which is not a directory
     * @param event the event mask. CLOSE_WRITE, DELETE & MOVE_SELF are handled
     * @param file the file concerned by the event
     */
    private void handleFileEvent(int event, File file) {
        switch(event) {
            case FileObserver.CLOSE_WRITE: //todo it is called two times per file except if screenshot by example or take a picture
                handleFileCloseWrite(file);
            }
        } else if (event == FileObserver.MOVE_SELF){
                break;
            case FileObserver.DELETE:
                handleFileDelete(file);
                break;
            case FileObserver.MOVE_SELF: //todo to be able to catch that, we probably need a buffer to catch a succession (MOVE_FROM, MOVE_TO, then MOVE_SELF).
                Log.d(TAG, file.getAbsolutePath() + " has been moved. Not handled yet");
                break;
            default:
                break;
        }
    }

    /**
     * Handle FileEvent for a directory
     * @param event FileEvent mask. CREATE, CLOSE_WRITE, DELETE, MOVE_SELF
     * @param dir directory concerned by file event
     */
    private void handleDirectoryEvent(int event, File dir) {
        switch(event) {
            case FileObserver.CREATE:
                handleDirectoryCreate(dir);
                break;
            case FileObserver.CLOSE_WRITE:
                handleDirectoryCloseWrite(dir);
                break;
            case FileObserver.DELETE: //todo #1 Fix: never used. when done on a dir, it triggers handleFileEvent. Why ?!
                handleDirectoryDelete(dir);
                break;
            case FileObserver.MOVE_SELF:
                Log.d(TAG, dir.getAbsolutePath() + " has been moved. Not handled yet");
                break;
            default:
                break;
        }
    }

    /**
     * Send syncRequest to SynchronizationService
     * @param request
     */
    private void sendSyncRequestToSynchronizationService(SyncRequest request) {
        Log.d(TAG, "Sending a SyncRequest for " + request.getSyncedFileState().getName());
        if (serviceConnection.isBoundToSynchronizationService()) {
@@ -70,23 +110,42 @@ public class FileEventListener {
        }
    }

    private void handleDirectoryCloseWrite(File directory) {
        final String fileLocalPath = CommonUtils.getLocalPath(directory);
        Log.d(TAG, "handleDirectoryCloseWrite(" + fileLocalPath + ")");
        SyncedFolder folder = DbHelper.getSyncedFolderByLocalPath(fileLocalPath, appContext);
        if (folder == null) { //it's a directory creation
    /**
     * When a new directory is detected, it must be inserted in database
     * if it's parent directory is already in the database
     * @param directory
     */
    private void handleDirectoryCreate(File directory) {
        Log.d(TAG, "handleDirectoryCreate(" + directory.getAbsolutePath() + ")");
        final String parentPath = CommonUtils.getLocalPath(directory.getParentFile());
            SyncedFolder parentFolder = DbHelper.getSyncedFolderByLocalPath(parentPath, appContext);
            if (parentFolder != null) { //if parent is in the DB
                folder = new SyncedFolder(parentFolder, directory.getName() + FileUtils.PATH_SEPARATOR, directory.lastModified(), "");
        final SyncedFolder parentFolder = DbHelper.getSyncedFolderByLocalPath(parentPath, appContext);
        if (parentFolder != null) {
            final SyncedFolder folder = new SyncedFolder(parentFolder, directory.getName() + FileUtils.PATH_SEPARATOR, directory.lastModified(), "");
            DbHelper.insertSyncedFolder(folder, appContext);
        }
    }

    /**
     * Handle CLOSE_WRITE event for a directory
     * todo: check in which condition a directory can generate a close_write
     * @param directory
     */
    private void handleDirectoryCloseWrite(File directory) {
        final String fileLocalPath = CommonUtils.getLocalPath(directory);
        Log.d(TAG, "handleDirectoryCloseWrite(" + fileLocalPath + ")");
        final SyncedFolder folder = DbHelper.getSyncedFolderByLocalPath(fileLocalPath, appContext);
        if (folder == null) {
            handleDirectoryCreate(directory); //todo check if really relevant
        } else {  //It's a directory update
            folder.setLastModified(directory.lastModified());
            DbHelper.updateSyncedFolder(folder, appContext);
        }
    }

    /**
     * Handle a file deletion event for a directory
     * @param directory
     */
    private void handleDirectoryDelete(File directory) {
        final String fileLocalPath = CommonUtils.getLocalPath(directory);
        Log.d(TAG, "handleDirectoryDelete("+fileLocalPath+")");
@@ -94,20 +153,23 @@ public class FileEventListener {
        if (folder == null) {
            //look for parent
            final String parentPath = CommonUtils.getLocalPath(directory.getParentFile());
            SyncedFolder parentFolder = DbHelper.getSyncedFolderByLocalPath(parentPath, appContext);
            if (parentFolder != null ) { //if parent is in the DB
            final SyncedFolder parentFolder = DbHelper.getSyncedFolderByLocalPath(parentPath, appContext);
            if (parentFolder == null ) { //if parent is not in the DB
                return;
            }
            folder = new SyncedFolder(parentFolder, directory.getName()+ FileUtils.PATH_SEPARATOR, directory.lastModified(), "");
            folder.setEnabled(false);
            DbHelper.insertSyncedFolder(folder, appContext);
            }
        } else {  //If already in DB
            if (folder.isEnabled()) {
        } else if (folder.isEnabled()) {
            folder.setEnabled(false);
            DbHelper.updateSyncedFolder(folder, appContext);
        }
    }
    }

    /**
     * handle a file close_write event for a file which is not a directory
     * @param file
     */
    private void handleFileCloseWrite(File file) {
        final String fileLocalPath = CommonUtils.getLocalPath(file);
        Log.d(TAG, "handleFileCloseWrite("+fileLocalPath+")");
@@ -146,13 +208,16 @@ public class FileEventListener {
        }
    }

    /**
     * Handle a file deletion event for a file which is not a directory
     * @param file
     */
    private void handleFileDelete(File file) {
        final String fileLocalPath = CommonUtils.getLocalPath(file);
        Log.d(TAG, "handleFileDelete("+fileLocalPath+")");
        SyncedFileState fileState = DbHelper.loadSyncedFile( appContext, fileLocalPath, true);
        final SyncedFileState fileState = DbHelper.loadSyncedFile( appContext, fileLocalPath, true);
        if (fileState == null) {
            Log.d(TAG, "Ignore event because file is not already in database");
            return;
            return; //Todo #1: should we call handleDirectoryDelete before to return ?
        }

        //If already in DB
@@ -170,7 +235,6 @@ public class FileEventListener {
    }

    public void bindToSynchronizationService(){
        Log.d(TAG, "bindToSynchronizationService()");
        final Intent SynchronizationServiceIntent = new Intent(appContext, SynchronizationService.class);
        appContext.bindService(SynchronizationServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
    }
+12 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ package foundation.e.drive.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

@@ -324,4 +325,15 @@ public final class DbHelper extends SQLiteOpenHelper {
        }
        Log.e(TAG,"Failed to dump Database");
    }

    /**
     * Remove syncedFileState for hidden file inserted in previous version
     * @param context
     * @throws SQLiteException if database can't be open
     */
    public static void removeHiddenSyncedFileState(Context context) throws SQLiteException {
        SyncedFileStateDAO dao = openSyncedFileStateDAO(context, true);
        dao.deleteHiddenFileState();
        dao.close();
    }
}
+9 −0
Original line number Diff line number Diff line
@@ -102,6 +102,15 @@ class SyncedFileStateDAO {
                + " = " + id, null);
    }


    /**
     * Remove SyncedFileState for hidden file (starting with '.')
     * @return number of deleted input
     */
    public int deleteHiddenFileState() {
        return mDB.delete(TABLE_NAME, FILE_NAME + " LIKE ?", new String[]{".%"});
    }

    /**
     * Delete each syncedFileState which is bound to syncedFOlder with specified ID
     * @param folderId syncedFolder's id used as foreign key
Loading