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

Commit e248aa37 authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

Merge branch '2032-periodicWorkers-start-on-any-network' into '115-epic'

[eDrive][feature changes]Make periodic file scan to be triggered on any network type

See merge request !282
parents 9a395b5d 342c07d6
Loading
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -8,9 +8,6 @@

package foundation.e.drive.periodicScan;

import static foundation.e.drive.work.WorkRequestFactory.WorkType.ONE_TIME_APP_LIST;
import static foundation.e.drive.work.WorkRequestFactory.WorkType.ONE_TIME_FULL_SCAN;

import android.content.Context;

import androidx.annotation.NonNull;
@@ -23,6 +20,7 @@ import androidx.work.WorkerParameters;
import java.util.ArrayList;
import java.util.List;

import foundation.e.drive.work.OneTimeWorkType;
import foundation.e.drive.work.WorkRequestFactory;
import timber.log.Timber;

@@ -43,10 +41,11 @@ public class PeriodicScanWorker extends Worker {
    public Result doWork() {
        try {
            final WorkManager workManager = WorkManager.getInstance(getApplicationContext());
            final WorkRequestFactory workRequestFactory = WorkRequestFactory.INSTANCE;

            final List<OneTimeWorkRequest> workRequestsLists = new ArrayList<>();
            workRequestsLists.add(WorkRequestFactory.getOneTimeWorkRequest(ONE_TIME_APP_LIST, null));
            workRequestsLists.add(WorkRequestFactory.getOneTimeWorkRequest(ONE_TIME_FULL_SCAN, null));
            workRequestsLists.add(workRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.LIST_APPS, null));
            workRequestsLists.add(workRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.FULL_SCAN, null));

            workManager.beginUniqueWork(FullScanWorker.UNIQUE_WORK_NAME, ExistingWorkPolicy.KEEP, workRequestsLists)
                    .enqueue();
+12 −13
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ import foundation.e.drive.periodicScan.FullScanWorker
import foundation.e.drive.periodicScan.PeriodicScanWorker
import foundation.e.drive.synchronization.SyncWorker
import foundation.e.drive.utils.RootSyncedFolderProvider
import foundation.e.drive.work.WorkRequestFactory.WorkType

/**
 * @author Vincent Bourgmayer
@@ -40,7 +39,7 @@ class WorkLauncher private constructor(context: Context) {
    }

    fun enqueuePeriodicUserInfoFetching() {
        val request = WorkRequestFactory.getPeriodicWorkRequest(WorkType.PERIODIC_USER_INFO)
        val request = WorkRequestFactory.createPeriodicWorkRequest(PeriodicWorkType.FETCH_USER_INFO)
        workManager.enqueueUniquePeriodicWork(
            AccountUserInfoWorker.UNIQUE_WORK_NAME,
            ExistingPeriodicWorkPolicy.UPDATE,
@@ -49,7 +48,7 @@ class WorkLauncher private constructor(context: Context) {
    }

    fun enqueuePeriodicFullScan() {
        val request = WorkRequestFactory.getPeriodicWorkRequest(WorkType.PERIODIC_SCAN)
        val request = WorkRequestFactory.createPeriodicWorkRequest(PeriodicWorkType.PERIODIC_SCAN)
        workManager.enqueueUniquePeriodicWork(PeriodicScanWorker.UNIQUE_WORK_NAME,
            ExistingPeriodicWorkPolicy.KEEP,
            request)
@@ -57,7 +56,7 @@ class WorkLauncher private constructor(context: Context) {

    fun enqueueOneTimeFullScan(isForced: Boolean) {
        if (isForced) {
            val request = WorkRequestFactory.getOneTimeWorkRequest(WorkType.ONE_TIME_FORCED_FULL_SCAN,
            val request = WorkRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.USER_TRIGGERED_FULL_SCAN,
                null)
            workManager.enqueueUniqueWork(FullScanWorker.UNIQUE_WORK_NAME,
                ExistingWorkPolicy.REPLACE,
@@ -65,7 +64,7 @@ class WorkLauncher private constructor(context: Context) {
            return
        }

        val request = WorkRequestFactory.getOneTimeWorkRequest(WorkType.ONE_TIME_FULL_SCAN,
        val request = WorkRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.FULL_SCAN,
            null)
        workManager.enqueueUniqueWork(FullScanWorker.UNIQUE_WORK_NAME,
            ExistingWorkPolicy.KEEP,
@@ -73,13 +72,13 @@ class WorkLauncher private constructor(context: Context) {
    }

    fun enqueueOneTimeAppListGenerator() {
        val request = WorkRequestFactory.getOneTimeWorkRequest(WorkType.ONE_TIME_APP_LIST,
        val request = WorkRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.LIST_APPS,
            null)
        workManager.enqueue(request)
    }

    fun enqueueOneTimeSync() {
        val request = WorkRequestFactory.getOneTimeWorkRequest(WorkType.ONE_TIME_SYNC, null)
        val request = WorkRequestFactory.createOneTimeWorkRequest(OneTimeWorkType.ONE_TIME_SYNC, null)
        workManager.enqueueUniqueWork(SyncWorker.UNIQUE_WORK_NAME, ExistingWorkPolicy.KEEP, request)
    }

@@ -90,13 +89,13 @@ class WorkLauncher private constructor(context: Context) {
            return false
        }

        val getUserInfoRequest = WorkRequestFactory.getOneTimeWorkRequest(
            WorkType.ONE_TIME_USER_INFO,
        val getUserInfoRequest = WorkRequestFactory.createOneTimeWorkRequest(
            OneTimeWorkType.FETCH_USER_INFO,
            null
        )

        val finishSetupRequest = WorkRequestFactory.getOneTimeWorkRequest(
            WorkType.ONE_TIME_FINISH_SETUP,
        val finishSetupRequest = WorkRequestFactory.createOneTimeWorkRequest(
            OneTimeWorkType.FINISH_SETUP,
            null
        )

@@ -119,8 +118,8 @@ class WorkLauncher private constructor(context: Context) {
            RootSyncedFolderProvider.getSyncedFolderRoots(context)

        return rootSyncedFolderList.map {
            WorkRequestFactory.getOneTimeWorkRequest(
                WorkType.ONE_TIME_ROOT_FOLDER_SETUP,
            WorkRequestFactory.createOneTimeWorkRequest(
                OneTimeWorkType.ROOT_FOLDER_SETUP,
                it
            )
        }
+0 −280
Original line number Diff line number Diff line
/*
 * Copyright © MURENA SAS 2022-2023.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 */

package foundation.e.drive.work;

import static androidx.work.BackoffPolicy.LINEAR;
import static java.util.concurrent.TimeUnit.MINUTES;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_ENABLE;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_ID;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_LAST_ETAG;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_LAST_MODIFIED;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_LIBELLE;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_LOCAL_PATH;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_MEDIATYPE;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_REMOTE_PATH;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_SCAN_LOCAL;
import static foundation.e.drive.account.setup.RootFolderSetupWorker.DATA_KEY_SCAN_REMOTE;
import static foundation.e.drive.utils.AppConstants.WORK_GENERIC_TAG;
import static foundation.e.drive.utils.AppConstants.WORK_SETUP_TAG;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
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 foundation.e.drive.account.AccountUserInfoWorker;
import foundation.e.drive.account.setup.FinishSetupWorker;
import foundation.e.drive.account.setup.RootFolderSetupWorker;
import foundation.e.drive.models.SyncedFolder;
import foundation.e.drive.periodicScan.FullScanWorker;
import foundation.e.drive.periodicScan.ListAppsWorker;
import foundation.e.drive.periodicScan.PeriodicScanWorker;
import foundation.e.drive.synchronization.SyncWorker;

public class WorkRequestFactory {
    public enum WorkType {
        PERIODIC_USER_INFO,
        PERIODIC_SCAN,
        ONE_TIME_FULL_SCAN,
        ONE_TIME_FORCED_FULL_SCAN,
        ONE_TIME_APP_LIST,
        ONE_TIME_USER_INFO,
        ONE_TIME_ROOT_FOLDER_SETUP,
        ONE_TIME_FINISH_SETUP,
        ONE_TIME_SYNC
    }

    private final static int PERIODIC_WORK_REPEAT_INTERVAL = 30;
    private final static int PERIODIC_SCAN_FLEX_TIME = 5;

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

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

        final PeriodicWorkRequest.Builder workRequestBuilder = new PeriodicWorkRequest.Builder(
                PeriodicScanWorker.class,
                PERIODIC_WORK_REPEAT_INTERVAL, MINUTES,
                PERIODIC_SCAN_FLEX_TIME, MINUTES);

        return workRequestBuilder.setConstraints(constraints)
                .addTag(WORK_GENERIC_TAG)
                .build();
    }

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

        final PeriodicWorkRequest.Builder workRequestBuilder = new PeriodicWorkRequest.Builder(AccountUserInfoWorker.class,
                PERIODIC_WORK_REPEAT_INTERVAL, MINUTES);

        return workRequestBuilder.addTag(WORK_GENERIC_TAG)
                .setConstraints(constraints)
                .build();
    }

    /**
     * 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.
     */
    @NonNull
    public static OneTimeWorkRequest getOneTimeWorkRequest(@NonNull WorkType type, @Nullable SyncedFolder syncedFolder) {
        switch (type) {
            case ONE_TIME_APP_LIST:
                return createAppListGenerationWorkRequest();
            case ONE_TIME_FULL_SCAN:
                return createFullScanWorkRequest(false);
            case ONE_TIME_FORCED_FULL_SCAN:
                return createFullScanWorkRequest(true);
            case ONE_TIME_USER_INFO:
                return createGetUserInfoWorkRequest();
            case ONE_TIME_FINISH_SETUP:
                return createFinishSetupWorkRequest();
            case ONE_TIME_ROOT_FOLDER_SETUP:
                if (syncedFolder == null) throw new NullPointerException("Synced folder is null");
                return createRootFolderSetupWorkRequest(syncedFolder);
            case ONE_TIME_SYNC:
                return createSyncWorkRequest();
            default:
                throw new InvalidParameterException("Unsupported Work Type: " + type);
        }
    }

    private static OneTimeWorkRequest createSyncWorkRequest() {
        final Constraints constraints = new Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .setRequiresBatteryNotLow(true)
                .build();

        final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(SyncWorker.class);

        return builder.setBackoffCriteria(LINEAR, 2, MINUTES).addTag(WORK_GENERIC_TAG)
                .setConstraints(constraints)
                .build();
    }

    /**
     * Create a workRequest to generate file which contains list of installed apps
     * @return the workRequest
     */
    @NonNull
    private static OneTimeWorkRequest createAppListGenerationWorkRequest() {
        final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(ListAppsWorker.class);

        return builder.setBackoffCriteria(LINEAR, 2, MINUTES)
                .addTag(WORK_GENERIC_TAG)
                .build();
    }

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

        final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(FullScanWorker.class);

        final Data data = new Data.Builder()
                .putBoolean(FullScanWorker.ACTION_FORCED_SYNC_KEY, forced)
                .build();

        return builder.setBackoffCriteria(LINEAR, 2, MINUTES)
                .setConstraints(constraints)
                .setInputData(data)
                .addTag(WORK_GENERIC_TAG)
                .build();
    }


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

        final OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(AccountUserInfoWorker.class);

        return builder.setBackoffCriteria(LINEAR, 2, MINUTES)
                .addTag(WORK_GENERIC_TAG)
                .addTag(WORK_SETUP_TAG)
                .setConstraints(constraints)
                .build();
    }

    /**
     * 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
     */
    @NonNull
    private static OneTimeWorkRequest createRootFolderSetupWorkRequest(@NonNull SyncedFolder syncedFolder) {
        final Constraints constraints = createUnmeteredNetworkAndHighBatteryConstraints();

        return new OneTimeWorkRequest.Builder(
                RootFolderSetupWorker.class)
                .setBackoffCriteria(LINEAR, 2, MINUTES)
                .setInputData(createDataFromSyncedFolder(syncedFolder))
                .addTag(WORK_GENERIC_TAG)
                .addTag(WORK_SETUP_TAG)
                .setConstraints(constraints)
                .build();
    }

    /**
     * Create a OneTime WorkRequest which finish setup process
     * @return Instance of OneTimeWorkRequest
     */
    @NonNull
    private static OneTimeWorkRequest createFinishSetupWorkRequest() {
        return new OneTimeWorkRequest.Builder(FinishSetupWorker.class)
                .setBackoffCriteria(LINEAR, 2, MINUTES)
                .addTag(WORK_GENERIC_TAG)
                .addTag(WORK_SETUP_TAG)
                .build();
    }

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

    /**
     * Parse SyncedFolder instance in Data, used as data for WorkRequest
     * @param folder SyncedFolder instance
     * @return Data instance
     */
    @NonNull
    private static Data createDataFromSyncedFolder(@NonNull 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();
    }
}
 No newline at end of file
+247 −0

File added.

Preview size limit exceeded, changes collapsed.