diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d0f189d338cb02ea4a850c92019280b1f76ef3db..e0236fb97e4a47ff3167aee996d47065edbcc6db 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,6 +28,9 @@
android:protectionLevel="signature"
tools:ignore="ReservedSystemPermission" />
+
+
-
-
-
-
-
+
@@ -114,6 +109,14 @@
+
+
+
+
+
diff --git a/app/src/main/java/foundation/e/drive/account/AccountSetupWorker.kt b/app/src/main/java/foundation/e/drive/account/AccountSetupWorker.kt
new file mode 100644
index 0000000000000000000000000000000000000000..af4d331c5ec7160e0deb4a0150b8f1cb854fd6c0
--- /dev/null
+++ b/app/src/main/java/foundation/e/drive/account/AccountSetupWorker.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright © MURENA SAS 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.account
+
+import android.accounts.Account
+import android.accounts.AccountManager
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.work.WorkManager
+import androidx.work.Worker
+import androidx.work.WorkerParameters
+import foundation.e.drive.R
+import foundation.e.drive.models.SyncedFolder
+import foundation.e.drive.utils.AppConstants
+import foundation.e.drive.utils.CommonUtils
+import foundation.e.drive.utils.DavClientProvider
+import foundation.e.drive.utils.RootSyncedFolderProvider.getSyncedFolderRoots
+import timber.log.Timber
+
+const val accountNameKey = AccountManager.KEY_ACCOUNT_NAME
+const val accountTypeKey = AccountManager.KEY_ACCOUNT_TYPE
+
+/**
+ * @author Vincent Bourgmayer
+ */
+class AccountSetupWorker(private val context: Context, private val workerParams: WorkerParameters) :
+ Worker(context, workerParams) {
+
+ private var account: Account? = null
+
+ override fun doWork(): Result {
+ val accountName = workerParams.inputData.getString(accountNameKey)
+ val accountType = workerParams.inputData.getString(accountTypeKey)
+
+ val prefs = context.getSharedPreferences(
+ AppConstants.SHARED_PREFERENCE_NAME,
+ Context.MODE_PRIVATE)
+
+ if (checkStartConditions(accountName, accountType, prefs)) {
+
+ startSyncWorkers()
+
+ prefs.edit()
+ .putString(AccountManager.KEY_ACCOUNT_NAME, accountName)
+ .apply()
+
+ }
+
+ DavClientProvider.getInstance().cleanUp()
+ return Result.success()
+ }
+
+
+ /**
+ * Check that conditions to start are met:
+ * - Setup has not already been done or not achieved
+ * - AccountName is not empty
+ * - AccountType is /e/ account
+ * - the account is effectively available through accountManager
+ */
+ private fun checkStartConditions(accountName:String?, accountType:String?, prefs:SharedPreferences): Boolean {
+ val alreadyStoredAccountName = prefs.getString(AccountManager.KEY_ACCOUNT_NAME, "")
+ if (!alreadyStoredAccountName.isNullOrEmpty()) { //if no accountName found, next setup cannot have been done
+ val setupAlreadyDone =
+ prefs.getBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, false)
+ if (setupAlreadyDone) return false
+
+ if (accountName != alreadyStoredAccountName) {
+ Timber.w("An account was already added but not fully setup")
+ //todo: check with Aude or Jonathan
+ // what to do if alreadyStoredAccountName & accountName are different.
+ // Which one to choose ?
+ }
+ }
+
+ if (!isValidAccountType(accountType)) return false
+ if (accountName.isNullOrEmpty() || accountType.isNullOrEmpty()) return false
+
+ account = CommonUtils.getAccount(accountName, accountType, AccountManager.get(context))
+ if (account == null) {
+ Timber.w("got Invalid %s account for username: %s ", accountType, accountName)
+ return false
+ }
+
+ return true
+ }
+
+ private fun isValidAccountType(accountType: String?): Boolean {
+ val expectedAccountType = context.getString(R.string.eelo_account_type)
+ return accountType != null && accountType == expectedAccountType
+ }
+
+ private fun startSyncWorkers() {
+ CommonUtils.registerPeriodicUserInfoChecking(WorkManager.getInstance(context))
+
+ val syncedFolders: List = getSyncedFolderRoots(
+ applicationContext
+ )
+ CommonUtils.registerInitializationWorkers(
+ syncedFolders, WorkManager.getInstance(
+ applicationContext
+ )
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/foundation/e/drive/account/receivers/AccountAddedReceiver.kt b/app/src/main/java/foundation/e/drive/account/receivers/AccountAddedReceiver.kt
new file mode 100644
index 0000000000000000000000000000000000000000..75716fa4ef1010d9bcafa0010d586e14f53e4e74
--- /dev/null
+++ b/app/src/main/java/foundation/e/drive/account/receivers/AccountAddedReceiver.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright © MURENA SAS 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.account.receivers
+
+import android.accounts.AccountManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
+import foundation.e.drive.account.AccountSetupWorker
+import foundation.e.drive.utils.AppConstants
+import timber.log.Timber
+
+/**
+ * Entry point for eDrive
+ * @author Vincent Bourgmayer
+ */
+class AccountAddedReceiver() : BroadcastReceiver(){
+ override fun onReceive(context: Context?, intent: Intent?) {
+ Timber.d("Received account added intent request")
+
+ if (context == null || intent == null) return
+
+ val data = prepareWorkerInputData(intent.extras) ?: return
+
+ //register worker for setup
+ val workRequest = OneTimeWorkRequestBuilder()
+ .setInputData(data)
+ .addTag(AppConstants.WORK_GENERIC_TAG)
+ .build()
+
+ WorkManager.getInstance(context).enqueue(workRequest)
+ /**
+ * as it is an experimentation right now it will be enough. But for final implementation we
+ * should answer the following design question
+ * 1. Shouldn't we rather use enqueueUniqueWork with replace/Ignore policy for older worker ?
+ * 2. Shouldn't we chain other worker required after account setup instead of triggering them from
+ * accountSetupWorker ?
+ */
+
+
+ Timber.i("Account setup worker enqueued")
+ }
+
+ private fun prepareWorkerInputData(extras: Bundle?): Data? {
+ val extras = extras ?: return null
+
+ val accountName = extras.getString(AccountManager.KEY_ACCOUNT_NAME, "")
+ val accountType = extras.getString(AccountManager.KEY_ACCOUNT_TYPE, "")
+
+ return Data.Builder()
+ .putString(AccountManager.KEY_ACCOUNT_NAME, accountName)
+ .putString(AccountManager.KEY_ACCOUNT_TYPE, accountType)
+ .build()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java b/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java
index fc7293f74ab57c99652d53801fd0c6cb5a68a999..09d5a6787b897ab5ea44ca879776532e90051c15 100644
--- a/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java
+++ b/app/src/main/java/foundation/e/drive/receivers/AccountRemoveCallbackReceiver.java
@@ -26,7 +26,6 @@ import java.io.File;
import foundation.e.drive.EdriveApplication;
import foundation.e.drive.database.DbHelper;
import foundation.e.drive.database.FailedSyncPrefsManager;
-import foundation.e.drive.services.InitializerService;
import foundation.e.drive.services.ObserverService;
import foundation.e.drive.services.SynchronizationService;
import foundation.e.drive.utils.AppConstants;
@@ -100,9 +99,9 @@ public class AccountRemoveCallbackReceiver extends BroadcastReceiver {
boolean observerServiceStopResult = applicationContext.stopService(observerServiceIntent);
Timber.d("stop ObserverService: %s", observerServiceStopResult);
- Intent initializerServiceIntent = new Intent(applicationContext, InitializerService.class);
- boolean initServiceStopResult = applicationContext.stopService(initializerServiceIntent);
- Timber.d("stop InitializerService: %s", initServiceStopResult);
+ //Todo Intent initializerServiceIntent = new Intent(applicationContext, InitializerService.class);
+ //boolean initServiceStopResult = applicationContext.stopService(initializerServiceIntent);
+ //Timber.d("stop InitializerService: %s", initServiceStopResult);
Intent synchronizationServiceIntent = new Intent(applicationContext, SynchronizationService.class);
boolean syncServiceStopResult = applicationContext.stopService(synchronizationServiceIntent);
diff --git a/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java b/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java
index 12593beed998e4aeb44a896bae643a08d63572b0..5616d55e3518b2c9e43ded1dd7eb093559e130ed 100644
--- a/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java
+++ b/app/src/main/java/foundation/e/drive/receivers/BootCompletedReceiver.java
@@ -18,7 +18,6 @@ import androidx.annotation.NonNull;
import foundation.e.drive.BuildConfig;
import foundation.e.drive.database.DbHelper;
-import foundation.e.drive.services.InitializerService;
import foundation.e.drive.utils.AppConstants;
import foundation.e.drive.utils.CommonUtils;
import timber.log.Timber;
@@ -72,7 +71,7 @@ public class BootCompletedReceiver extends BroadcastReceiver {
.putBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, false)
.apply();
- context.startService(new Intent(context, InitializerService.class));
+ //Todo context.startService(new Intent(context, InitializerService.class));
forceDBUpdate(context);
}
diff --git a/app/src/main/java/foundation/e/drive/services/InitializerService.java b/app/src/main/java/foundation/e/drive/services/InitializerService.java
deleted file mode 100644
index 7492739990b54bd593eceb2747fd8acb6b3b70ec..0000000000000000000000000000000000000000
--- a/app/src/main/java/foundation/e/drive/services/InitializerService.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright © CLEUS SAS 2018-2019.
- * Copyright © ECORP 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.services;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.IBinder;
-
-import java.io.File;
-import java.util.List;
-
-import foundation.e.drive.models.SyncedFolder;
-import foundation.e.drive.utils.AppConstants;
-import foundation.e.drive.utils.CommonUtils;
-import foundation.e.drive.utils.DavClientProvider;
-import foundation.e.drive.utils.RootSyncedFolderProvider;
-import timber.log.Timber;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.work.WorkManager;
-
-/**
- * @author Vincent Bourgmayer
- * @author Jonathan Klee
- * @author Abhishek Aggarwal
- */
-public class InitializerService extends Service {
- private Account account;
-
- @Override
- public void onCreate() {
- Timber.tag(InitializerService.class.getSimpleName());
- super.onCreate();
- }
-
- @Override
- public int onStartCommand(@NonNull Intent intent, int flags, int startId) {
- Timber.i("onStartCommand()");
- DavClientProvider.getInstance().cleanUp();
- CommonUtils.setServiceUnCaughtExceptionHandler(this);
-
- //Get account
- final SharedPreferences prefs = this.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE);
-
- String accountName = prefs.getString(AccountManager.KEY_ACCOUNT_NAME, "");
- String accountType = prefs.getString(AccountManager.KEY_ACCOUNT_TYPE, "");
-
- if (accountName.isEmpty() && accountType.isEmpty() && intent.getExtras() != null) {
-
- accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME, "");
- accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE, "");
-
- prefs.edit().putString(AccountManager.KEY_ACCOUNT_NAME, accountName)
- .putString(AccountManager.KEY_ACCOUNT_TYPE, accountType)
- .apply();
- }
-
- if (checkStartConditions(prefs, accountName, accountType)) {
- start();
- }
- return super.onStartCommand(intent, flags, startId);
- }
-
- /**
- * Check if condition are present to start
- * - Initialization not already done
- * - AccountName is not empty
- * - Account available
- * @return true if condition are met
- */
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- public boolean checkStartConditions(@NonNull final SharedPreferences prefs,
- @NonNull final String accountName, @NonNull final String accountType) {
- if (prefs.getBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, false)) {
- Timber.w("Initialization has already been done");
- return false;
- }
-
- if (accountName.isEmpty()) {
- Timber.w("No account Name available");
- return false;
- }
-
- account = CommonUtils.getAccount(accountName, accountType, AccountManager.get(this));
- if (account == null) {
- Timber.w("got Invalid %s account for username: %s ", accountType, accountName);
- return false;
- }
- return true;
- }
-
- /**
- * Set up base component for eDrive:
- * - Register basic worker
- * - build root folders to sync
- */
- private void start() {
- Timber.d("start()");
- CommonUtils.registerPeriodicUserInfoChecking(WorkManager.getInstance(this));
-
- final List syncedFolders = RootSyncedFolderProvider.INSTANCE.getSyncedFolderRoots(getApplicationContext());
- CommonUtils.registerInitializationWorkers(syncedFolders, WorkManager.getInstance(getApplicationContext()) );
- }
-
- @Nullable
- @Override
- public IBinder onBind(@Nullable Intent intent) {
- return null;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/foundation/e/drive/services/ObserverService.java b/app/src/main/java/foundation/e/drive/services/ObserverService.java
index 8b1d6747c01413d0dd5d87d276e4be22f200eb89..de186c0b3d174a9d00cc4e8caef7a9b5f15def51 100644
--- a/app/src/main/java/foundation/e/drive/services/ObserverService.java
+++ b/app/src/main/java/foundation/e/drive/services/ObserverService.java
@@ -152,8 +152,8 @@ public class ObserverService extends Service implements OnRemoteOperationListene
if (!prefs.getBoolean(INITIALIZATION_HAS_BEEN_DONE, false)) {
Timber.d("Initialization hasn't been done");
- Intent initializerIntent = new Intent(this, InitializerService.class);
- startService(initializerIntent);
+ //Todo Intent initializerIntent = new Intent(this, InitializerService.class);
+ //startService(initializerIntent);
return false;
}
diff --git a/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java b/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java
deleted file mode 100644
index ca5febde32ca4d45688701e970af2035ffb5371b..0000000000000000000000000000000000000000
--- a/app/src/test/java/foundation/e/drive/services/InitializerServiceTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package foundation.e.drive.services;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.accounts.AccountManager;
-import android.app.job.JobScheduler;
-import android.content.Context;
-import android.net.ConnectivityManager;
-
-import androidx.test.core.app.ApplicationProvider;
-import org.junit.Test;
-import org.robolectric.Robolectric;
-
-import foundation.e.drive.TestUtils;
-import foundation.e.drive.database.DbHelper;
-import foundation.e.drive.utils.AppConstants;
-
-public class InitializerServiceTest extends AbstractServiceIT{
-
- public InitializerServiceTest(){
- mServiceController = Robolectric.buildService(InitializerService.class);
- mService = mServiceController.get();
- context = ApplicationProvider.getApplicationContext();
- accountManager = AccountManager.get(context);
- jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
- contentResolver = context.getContentResolver();
- sharedPreferences = context.getSharedPreferences( AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE);
- connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
- dbHelper = new DbHelper(context);
- TestUtils.initializeWorkmanager(context);
- init_done = false;
- TestUtils.loadServerCredentials();
- TestUtils.prepareValidAccount(accountManager);
- }
-
- @Test
- public void checkStartConditions_noAccountInIntent_NorInPrefs_falseExpected() {
- registerSharedPref();
- final boolean canStart = mService.checkStartConditions(sharedPreferences, "", "");
- assertFalse("InitializerService.checkStartConditions without any available account info should return false but returned true", canStart);
- }
-
- @Test
- public void checkStartConditions_trueExpected() {
- registerSharedPref();
- final boolean canStart = mService.checkStartConditions(sharedPreferences, TestUtils.TEST_ACCOUNT_NAME, TestUtils.TEST_ACCOUNT_TYPE);
- assertTrue("InitializerService.checkStartConditions with invalid account should return false but returned true", canStart);
- }
-
- @Test
- public void checkStartConditions_withFakeAccountNameOrType_falseExpected() {
- registerSharedPref();
- final boolean canStart = mService.checkStartConditions(sharedPreferences, "any", "any");
- assertFalse("InitializerService.checkStartConditions with invalid account should return false but returned true", canStart);
- }
-
- @Test
- public void checkStartConditions_withInitDone_falseExpected() {
- registerSharedPref();
- sharedPreferences.edit().putBoolean(AppConstants.INITIALIZATION_HAS_BEEN_DONE, true).apply();
- final boolean canStart = mService.checkStartConditions(sharedPreferences, TestUtils.TEST_ACCOUNT_NAME, TestUtils.TEST_ACCOUNT_TYPE);
- assertFalse("InitializerService.checkStartConditions with valid account but init already done should return false but returned true", canStart);
- }
-}
diff --git a/app/src/test/java/foundation/e/drive/services/ObserverServiceTest.java b/app/src/test/java/foundation/e/drive/services/ObserverServiceTest.java
index bb9ff1ad2c6988ca46ed7dd90a86752dc151e2b1..2ee0142b218cfd735577979216082d9897bf34f3 100644
--- a/app/src/test/java/foundation/e/drive/services/ObserverServiceTest.java
+++ b/app/src/test/java/foundation/e/drive/services/ObserverServiceTest.java
@@ -267,10 +267,10 @@ public class ObserverServiceTest extends AbstractServiceIT {
mServiceController.create().startCommand(0, 0);
//How to assert this... ?
- Intent expectedIntent = new Intent(mService, InitializerService.class);
- Intent actualIntent = shadowOf(RuntimeEnvironment.application).getNextStartedService();
+ //Todo Intent expectedIntent = new Intent(mService, InitializerService.class);
+ //Intent actualIntent = shadowOf(RuntimeEnvironment.application).getNextStartedService();
- assertEquals("Checked intent not the expected one", expectedIntent.getComponent(), actualIntent.getComponent());
+ //assertEquals("Checked intent not the expected one", expectedIntent.getComponent(), actualIntent.getComponent());
List logs = ShadowLog.getLogs();
ShadowLog.LogItem lastLog = logs.get(logs.size()-1);