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

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

Merge branch '1128-replace_reset_service_with_account_remove_broadcast' into 'main'

1128-replace_reset_service_with_account_remove_broadcast

See merge request !211
parents 5de066f6 3ddd15da
Loading
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -83,14 +83,6 @@
                <action android:name="drive.services.InitializerService" />
            </intent-filter>
        </service>
        <service
            android:name=".services.ResetService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="drive.services.ResetService" />
            </intent-filter>
        </service>
        <service
            android:name=".services.ObserverService"
            android:enabled="true" />
@@ -113,5 +105,13 @@
                <action android:name="foundation.e.drive.action.FULL_LOG_ON_PROD"/>
            </intent-filter>
        </receiver>

        <receiver android:name=".receivers.AccountRemoveCallbackReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.accounts.action.ACCOUNT_REMOVED"/>
            </intent-filter>
        </receiver>
    </application>
</manifest>
 No newline at end of file
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright © ECORP 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.receivers;

import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER;
import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE;

import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import androidx.annotation.NonNull;

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;
import timber.log.Timber;

public class AccountRemoveCallbackReceiver extends BroadcastReceiver {

    @SuppressLint("UnsafeProtectedBroadcastReceiver")
    @Override
    public void onReceive(Context context, Intent intent) {
        if (context == null || intent == null) {
            return;
        }

        final Context applicationContext = context.getApplicationContext();

        final SharedPreferences preferences = applicationContext.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE);

        if (!shouldProceedWithRemoval(intent, preferences)) {
            return;
        }

        stopRecursiveFileObserver(applicationContext);
        stopAllServices(applicationContext);
        deleteDatabase(applicationContext);
        cleanSharedPreferences(applicationContext, preferences);
        removeCachedFiles(applicationContext);
    }

    private void deleteDatabase(@NonNull Context applicationContext) {
        final boolean result = applicationContext.deleteDatabase(DbHelper.DATABASE_NAME);
        Timber.d("Remove Database: %s", result);
    }

    private void stopRecursiveFileObserver(@NonNull Context applicationContext) {
        if (applicationContext instanceof EdriveApplication) {
            ((EdriveApplication) applicationContext).stopRecursiveFileObserver();
        }
    }

    private boolean shouldProceedWithRemoval(@NonNull Intent intent, @NonNull SharedPreferences preferences) {
        if (isInvalidAction(intent)) {
            return false;
        }

        String currentAccount = preferences.getString(AccountManager.KEY_ACCOUNT_NAME, "");
        String currentAccountType = preferences.getString(AccountManager.KEY_ACCOUNT_TYPE, "");

        if (currentAccount.isEmpty() || currentAccountType.isEmpty()) {
            return false;
        }

        final String accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
        final String accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);

        return (currentAccount.equals(accountName) && currentAccountType.equals(accountType));
    }

    private boolean isInvalidAction(@NonNull Intent intent) {
        return !"android.accounts.action.ACCOUNT_REMOVED".equals(intent.getAction());
    }

    private void stopAllServices(@NonNull Context applicationContext) {
        Intent observerServiceIntent = new Intent(applicationContext, ObserverService.class);
        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);

        Intent synchronizationServiceIntent = new Intent(applicationContext, SynchronizationService.class);
        boolean syncServiceStopResult = applicationContext.stopService(synchronizationServiceIntent);
        Timber.d("stop SynchronizationService: %s", syncServiceStopResult);
    }

    private void cleanSharedPreferences(@NonNull Context applicationContext, @NonNull SharedPreferences prefs) {
        if (!applicationContext.deleteSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME)) {
            //If removal failed, clear all data inside
            prefs.edit().remove(AccountManager.KEY_ACCOUNT_NAME)
                    .remove(AccountManager.KEY_ACCOUNT_TYPE)
                    .remove(INITIALIZATION_HAS_BEEN_DONE)
                    .remove(INITIALFOLDERS_NUMBER)
                    .remove(AppConstants.KEY_LAST_SYNC_TIME)
                    .apply();
        }

        applicationContext.deleteSharedPreferences(FailedSyncPrefsManager.PREF_NAME);
    }

    private void removeCachedFiles(@NonNull Context applicationContext) {
        final File[] cachedFiles = applicationContext.getExternalCacheDir().listFiles();
        if (cachedFiles == null) {
            Timber.w("listFiles() returned null. preventing a NPE");
            return;
        }

        for (File file : cachedFiles) {
            try {
                boolean removed = file.delete();
                if (!removed) {
                    Timber.w("Failed to remove the cached file: %s", file.getName());
                }
            } catch (SecurityException e) {
                Timber.e(e, "failed to delete cached file on account removal call");
            }
        }
    }
}
+0 −116
Original line number Diff line number Diff line
/*
 * Copyright © CLEUS SAS 2018-2019.
 * Copyright © ECORP SAS 2022.
 * 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.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 foundation.e.drive.EdriveApplication;
import foundation.e.drive.database.DbHelper;
import foundation.e.drive.database.FailedSyncPrefsManager;
import foundation.e.drive.utils.AppConstants;
import timber.log.Timber;

import static foundation.e.drive.utils.AppConstants.INITIALFOLDERS_NUMBER;
import static foundation.e.drive.utils.AppConstants.INITIALIZATION_HAS_BEEN_DONE;

import androidx.annotation.Nullable;
import androidx.work.WorkManager;

/**
 * @author Vincent Bourgmayer
 * Service which stop others, remove DB, clear sharedPrefs and unregister ScreenOffReceiver
 */
public class ResetService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Timber.tag(ResetService.class.getSimpleName()).i("onStartCommand()");
        if ( intent.getExtras() != null ) {
            final String intent_accountName = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME, "");
            final String intent_accountType = intent.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE, "");

            if (!intent_accountName.isEmpty() && !intent_accountType.isEmpty()) {
                final SharedPreferences prefs = this.getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE);

                if (intent_accountName.equals(prefs.getString(AccountManager.KEY_ACCOUNT_NAME, ""))
                        && intent_accountType.equals(prefs.getString(AccountManager.KEY_ACCOUNT_TYPE, ""))) {
                    WorkManager.getInstance(this).cancelAllWorkByTag(AppConstants.WORK_GENERIC_TAG);
                    ( (EdriveApplication) this.getApplication() ).stopRecursiveFileObserver();

                    stopAllServices();

                    final boolean result = deleteDatabase(DbHelper.DATABASE_NAME);
                    Timber.d("Remove Database: %s", result);

                    cleanSharedPreferences(prefs);
                    removeCachedFiles();
                }
            }
        }
        stopSelf();
        return super.onStartCommand(intent, flags, startId);
    }


    private void stopAllServices() {
        Intent stopperIntent = new Intent(getApplicationContext(), ObserverService.class);
        boolean result = getApplicationContext().stopService( stopperIntent );
        Timber.d("stop ObserverService: %s", result);

        stopperIntent = new Intent(getApplicationContext(), InitializerService.class);
        result = getApplicationContext().stopService( stopperIntent );
        Timber.d("stop InitializerService: %s", result);

        stopperIntent = new Intent(getApplicationContext(), SynchronizationService.class);
        result = getApplicationContext().stopService( stopperIntent );

        Timber.d("stop SynchronizationService: %s", result);
    }

    private void cleanSharedPreferences(SharedPreferences prefs) {
        if (!this.deleteSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME)) {

            //If removal failed, clear all data inside
            prefs.edit().remove(AccountManager.KEY_ACCOUNT_NAME)
                    .remove(AccountManager.KEY_ACCOUNT_TYPE)
                    .putBoolean(INITIALIZATION_HAS_BEEN_DONE, false)
                    .remove(INITIALFOLDERS_NUMBER)
                    .remove(AppConstants.KEY_LAST_SYNC_TIME)
                    .apply();
        }

        deleteSharedPreferences(FailedSyncPrefsManager.PREF_NAME);
    }

    private void removeCachedFiles() {
        final File[] cachedFiles =  this.getApplicationContext().getExternalCacheDir().listFiles();
        if (cachedFiles == null) {
            Timber.e("listFiles() returned null. preventing a NPE");
            return;
        }

        for (File f : cachedFiles) {
            f.delete();
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
 No newline at end of file