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

Commit 65aa4d30 authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Merge branch '240-implement-workRequestFactory' into 'v1-oreo'

Implement WorkRequestFactory to clean code from CommonUtils

See merge request !148
parents e0d59f47 f3145ba4
Loading
Loading
Loading
Loading
Loading
+11 −86
Original line number Diff line number Diff line
@@ -39,35 +39,19 @@ import java.text.StringCharacterIterator;
import java.util.Locale;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import foundation.e.drive.R;
import foundation.e.drive.models.SyncedFolder;
import foundation.e.drive.work.AccountUserInfoWorker;
import foundation.e.drive.work.CreateRemoteFolderWorker;
import foundation.e.drive.work.FirstStartWorker;
import foundation.e.drive.work.FullScanWorker;
import foundation.e.drive.work.WorkRequestFactory;

import static foundation.e.drive.utils.AppConstants.MEDIASYNC_PROVIDER_AUTHORITY;
import static foundation.e.drive.utils.AppConstants.METERED_NETWORK_ALLOWED_AUTHORITY;
import static foundation.e.drive.utils.AppConstants.SETTINGSYNC_PROVIDER_AUTHORITY;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_ENABLE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_ID;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LAST_ETAG;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LAST_MODIFIED;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LIBELLE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LOCAL_PATH;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_MEDIATYPE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_REMOTE_PATH;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_SCAN_LOCAL;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_SCAN_REMOTE;

import androidx.annotation.NonNull;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
@@ -323,20 +307,9 @@ public abstract class CommonUtils {
     * @param workManager the instance of workManager
     */
    public static void registerPeriodicFullScanWorker(WorkManager workManager) {
        final Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .setRequiresBatteryNotLow(true)
                .build();

        final PeriodicWorkRequest periodicFullScanRequest =
                new PeriodicWorkRequest.Builder(FullScanWorker.class,
                        31, TimeUnit.MINUTES,
                        5, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .addTag(AppConstants.WORK_GENERIC_TAG)
                        .build();

        workManager.enqueueUniquePeriodicWork(FullScanWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.KEEP, periodicFullScanRequest);
        workManager.enqueueUniquePeriodicWork(FullScanWorker.UNIQUE_WORK_NAME,
                ExistingPeriodicWorkPolicy.KEEP,
                WorkRequestFactory.getPeriodicWorkRequest(WorkRequestFactory.WorkType.FULL_SCAN));
    }


@@ -361,38 +334,15 @@ public abstract class CommonUtils {
            return;
        }
        
        final Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .setRequiresBatteryNotLow(true)
                .build();

        final OneTimeWorkRequest getUserInfoRequest = new OneTimeWorkRequest.Builder(AccountUserInfoWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                .addTag(AppConstants.WORK_GENERIC_TAG)
                .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                .setConstraints(constraints)
                .build();
        final OneTimeWorkRequest getUserInfoRequest = WorkRequestFactory.getOneTimeWorkRequest(WorkRequestFactory.WorkType.ONE_TIME_USER_INFO, null);

        final List<OneTimeWorkRequest> workRequests = new ArrayList<>();

        for (SyncedFolder folder : syncedFolders) {
            final OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(
                    CreateRemoteFolderWorker.class)
                    .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                    .setInputData(createDataFromSyncedFolder(folder))
                    .addTag(AppConstants.WORK_GENERIC_TAG)
                    .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                    .setConstraints(constraints)
                    .build();

            workRequests.add(oneTimeWorkRequest);
            final OneTimeWorkRequest createRemoteFolderWorkRequest = WorkRequestFactory.getOneTimeWorkRequest(WorkRequestFactory.WorkType.CREATE_REMOTE_DIR, folder);
            workRequests.add(createRemoteFolderWorkRequest);
        }

        final OneTimeWorkRequest firstStartRequest = new OneTimeWorkRequest.Builder(FirstStartWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                .addTag(AppConstants.WORK_GENERIC_TAG)
                .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                .build();
        final OneTimeWorkRequest firstStartRequest = WorkRequestFactory.getOneTimeWorkRequest(WorkRequestFactory.WorkType.FIRST_START, null);

        workManager.beginWith(getUserInfoRequest)
                .then(workRequests)
@@ -401,21 +351,6 @@ public abstract class CommonUtils {
    }


    private static Data createDataFromSyncedFolder(SyncedFolder folder) {
        return new Data.Builder()
                .putInt(DATA_KEY_ID, folder.getId())
                .putString(DATA_KEY_LIBELLE, folder.getLibelle())
                .putString(DATA_KEY_LOCAL_PATH, folder.getLocalFolder())
                .putString(DATA_KEY_REMOTE_PATH, folder.getRemoteFolder())
                .putString(DATA_KEY_LAST_ETAG, folder.getLastEtag())
                .putLong(DATA_KEY_LAST_MODIFIED, folder.getLastModified())
                .putBoolean(DATA_KEY_SCAN_LOCAL, folder.isScanLocal())
                .putBoolean(DATA_KEY_SCAN_REMOTE, folder.isScanRemote())
                .putBoolean(DATA_KEY_ENABLE, folder.isEnabled())
                .putBoolean(DATA_KEY_MEDIATYPE, folder.isMediaType())
                .build();
    }

    public static void createNotificationChannel(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            final CharSequence name = context.getString(R.string.notif_channel_name);
@@ -446,18 +381,8 @@ public abstract class CommonUtils {
     * @param workManager
     */
    public static void registerPeriodicUserInfoChecking(WorkManager workManager) {
        final Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();

        final PeriodicWorkRequest periodicUserInfoScanRequest =
                new PeriodicWorkRequest.Builder(AccountUserInfoWorker.class,
                        30, TimeUnit.MINUTES)
                        .addTag(AppConstants.WORK_GENERIC_TAG)
                        .setConstraints(constraints)
                        .build();

        workManager.enqueueUniquePeriodicWork(AccountUserInfoWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, periodicUserInfoScanRequest);
        final PeriodicWorkRequest workRequest = WorkRequestFactory.getPeriodicWorkRequest(WorkRequestFactory.WorkType.PERIODIC_USER_INFO);
        workManager.enqueueUniquePeriodicWork(AccountUserInfoWorker.UNIQUE_WORK_NAME, ExistingPeriodicWorkPolicy.REPLACE, workRequest);
    }

    /**
+196 −0
Original line number Diff line number Diff line
package foundation.e.drive.work;

import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_ENABLE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_ID;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LAST_ETAG;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LAST_MODIFIED;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LIBELLE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_LOCAL_PATH;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_MEDIATYPE;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_REMOTE_PATH;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_SCAN_LOCAL;
import static foundation.e.drive.work.CreateRemoteFolderWorker.DATA_KEY_SCAN_REMOTE;

import androidx.annotation.Nullable;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.PeriodicWorkRequest;

import java.security.InvalidParameterException;
import java.util.concurrent.TimeUnit;

import foundation.e.drive.models.SyncedFolder;
import foundation.e.drive.utils.AppConstants;

public class WorkRequestFactory {
    public enum WorkType {
        FULL_SCAN,
        PERIODIC_USER_INFO,
        ONE_TIME_USER_INFO,
        CREATE_REMOTE_DIR,
        FIRST_START
    }

    /**
     * Build an instance of PeriodicWorkRequest depending of the work type specified
     * @param type WorkType. Should be FULL_SCAN or PERIODIC_USER_INFO.
     *  If not, it will throw an InvalidParameterException
     * @return Periodic WorkRequest
     */
    public static PeriodicWorkRequest getPeriodicWorkRequest(WorkType type) {
        switch (type) {
            case FULL_SCAN:
                return createPeriodicFullScanWorkRequest();
            case PERIODIC_USER_INFO:
                return createPeriodicGetUserInfoWorkRequest();
            default:
                throw new InvalidParameterException("Unsupported Work Type: " + type);
        }
    }

    /**
     * Build an instance of OneTimeWorkRequest depending of the work type specified.
     * @param type Should be ONE_TIME_USER_INFO, or FIRST_START, or CREATE_REMOTE_DIR
     * or it will throw InvalidParameterException
     * @param syncedFolder this parameter is required for CREATE_REMOTE_DIR work type. If null it will throw an NPE.
     * @return OneTimeWorkRequest's instance.
     */
    public static OneTimeWorkRequest getOneTimeWorkRequest(WorkType type, @Nullable SyncedFolder syncedFolder) {
        switch (type) {
            case ONE_TIME_USER_INFO:
                return createOneTimeGetUserInfoWorkRequest();
            case FIRST_START:
                return createOneTimeFirstStartWorkRequest();
            case CREATE_REMOTE_DIR:
                if (syncedFolder == null) throw new NullPointerException("Synced folder is null");
                return createOneTimeCreateRemoteFolderWorkRequest(syncedFolder);
            default:
                throw new InvalidParameterException("Unsupported Work Type: " + type);
        }
    }


    /**
     * Create a PeridocWorkRequest instance for
     * a Full scan with constraints on network (should
     * be unmetered) and battery (shouldn't be low)
     * @return instance of PeriodicWorkRequest
     */
    private static PeriodicWorkRequest createPeriodicFullScanWorkRequest() {
        final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints();

        final PeriodicWorkRequest workRequest =
                new PeriodicWorkRequest.Builder(FullScanWorker.class,
                        31, TimeUnit.MINUTES,
                        5, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .addTag(AppConstants.WORK_GENERIC_TAG)
                        .build();
        return workRequest;
    }

    /**
     * Create a periodic work request to get userInfo
     * @return instance of PeriodicWorkRequest
     */
    private static PeriodicWorkRequest createPeriodicGetUserInfoWorkRequest() {
        final Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build();

        final PeriodicWorkRequest workRequest =
                new PeriodicWorkRequest.Builder(AccountUserInfoWorker.class,
                        30, TimeUnit.MINUTES)
                        .addTag(AppConstants.WORK_GENERIC_TAG)
                        .setConstraints(constraints)
                        .build();
        return workRequest;
    }

    /**
     * Instanciate a OneTimeWorkRequest to retrieve user info
     * @return instance of OneTimeWorkRequest
     */
    private static OneTimeWorkRequest createOneTimeGetUserInfoWorkRequest() {
        final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints();

        final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(AccountUserInfoWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                .addTag(AppConstants.WORK_GENERIC_TAG)
                .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                .setConstraints(constraints)
                .build();
        return workRequest;
    }

    /**
     * Create a OneTime workRequest to create a remote folder
     * With constraints on network (unmetered) and battery (not low)
     * @param syncedFolder SyncedFolder instance with data about folder to create
     * @return Instance OneTimeWorkRequest
     */
    private static OneTimeWorkRequest createOneTimeCreateRemoteFolderWorkRequest(SyncedFolder syncedFolder) {
        final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints();

        final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(
                CreateRemoteFolderWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                .setInputData(createDataFromSyncedFolder(syncedFolder))
                .addTag(AppConstants.WORK_GENERIC_TAG)
                .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                .setConstraints(constraints)
                .build();
        return workRequest;
    }

    /**
     * Create a OneTime WorkRequest which start eDrive
     * after initialization
     * @return Instance of OneTimeWorkRequest
     */
    private static OneTimeWorkRequest createOneTimeFirstStartWorkRequest() {
        final OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(FirstStartWorker.class)
                .setBackoffCriteria(BackoffPolicy.LINEAR, 2, TimeUnit.MINUTES)
                .addTag(AppConstants.WORK_GENERIC_TAG)
                .addTag(AppConstants.WORK_INITIALIZATION_TAG)
                .build();
        return workRequest;
    }

    /**
     * Create Constraints for unmetered network
     * and battery not low
     * @return instance of Constraints
     */
    private static Constraints createUnmeteredNetworkAndHighBatteryConstraints() {
        final Constraints constraint = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .setRequiresBatteryNotLow(true)
                .build();
        return constraint;
    }


    /**
     * Parse SyncedFolder instance in Data, used as data for WorkRequest
     * @param folder SyncedFolder instance
     * @return Data instance
     */
    private static Data createDataFromSyncedFolder(SyncedFolder folder) {
        return new Data.Builder()
                .putInt(DATA_KEY_ID, folder.getId())
                .putString(DATA_KEY_LIBELLE, folder.getLibelle())
                .putString(DATA_KEY_LOCAL_PATH, folder.getLocalFolder())
                .putString(DATA_KEY_REMOTE_PATH, folder.getRemoteFolder())
                .putString(DATA_KEY_LAST_ETAG, folder.getLastEtag())
                .putLong(DATA_KEY_LAST_MODIFIED, folder.getLastModified())
                .putBoolean(DATA_KEY_SCAN_LOCAL, folder.isScanLocal())
                .putBoolean(DATA_KEY_SCAN_REMOTE, folder.isScanRemote())
                .putBoolean(DATA_KEY_ENABLE, folder.isEnabled())
                .putBoolean(DATA_KEY_MEDIATYPE, folder.isMediaType())
                .build();
    }
}