[android] stop livecycle before delete app data and exit cleanly

Fixes #1380
This commit is contained in:
Torsten Grote
2019-03-01 16:49:19 -03:00
parent dbe46d60fd
commit 31d3324701
4 changed files with 56 additions and 18 deletions

View File

@@ -12,11 +12,15 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.util.IoUtils; import org.briarproject.bramble.util.IoUtils;
import java.io.File; import java.io.File;
import java.util.HashSet;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
class AndroidAccountManager extends AccountManagerImpl class AndroidAccountManager extends AccountManagerImpl
implements AccountManager { implements AccountManager {
@@ -90,19 +94,27 @@ class AndroidAccountManager extends AccountManagerImpl
} }
// Delete files, except lib and shared_prefs directories // Delete files, except lib and shared_prefs directories
File dataDir = new File(appContext.getApplicationInfo().dataDir); File dataDir = new File(appContext.getApplicationInfo().dataDir);
File[] children = dataDir.listFiles(); HashSet<File> files = new HashSet<>(asList(dataDir.listFiles()));
if (children == null) { if (files.isEmpty()) {
LOG.warning("Could not list files in app data dir"); LOG.warning("Could not list files in app data dir");
} else { }
for (File child : children) { files.add(appContext.getFilesDir());
String name = child.getName(); files.add(appContext.getCacheDir());
if (!name.equals("lib") && !name.equals("shared_prefs")) { files.add(appContext.getExternalCacheDir());
IoUtils.deleteFileOrDir(child); if (SDK_INT >= 19) {
} files.addAll(asList(appContext.getExternalCacheDirs()));
}
if (SDK_INT >= 21) {
files.addAll(asList(appContext.getExternalMediaDirs()));
}
for (File file : files) {
String name = file.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
IoUtils.deleteFileOrDir(file);
} }
} }
// Recreate the cache dir as some OpenGL drivers expect it to exist // Recreate the cache dir as some OpenGL drivers expect it to exist
if (!new File(dataDir, "cache").mkdir()) if (!new File(dataDir, "cache").mkdirs())
LOG.warning("Could not recreate cache dir"); LOG.warning("Could not recreate cache dir");
} }
} }

View File

@@ -112,6 +112,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
// Other directories should be deleted // Other directories should be deleted
File potatoDir = new File(testDir, ".potato"); File potatoDir = new File(testDir, ".potato");
File potatoFile = new File(potatoDir, "file"); File potatoFile = new File(potatoDir, "file");
File filesDir = new File(testDir, "filesDir");
File externalCacheDir = new File(testDir, "externalCacheDir");
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(prefs).edit(); oneOf(prefs).edit();
@@ -128,6 +130,12 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(true)); will(returnValue(true));
oneOf(app).getApplicationInfo(); oneOf(app).getApplicationInfo();
will(returnValue(applicationInfo)); will(returnValue(applicationInfo));
oneOf(app).getFilesDir();
will(returnValue(filesDir));
oneOf(app).getCacheDir();
will(returnValue(cacheDir));
oneOf(app).getExternalCacheDir();
will(returnValue(externalCacheDir));
}}); }});
assertTrue(dbDir.mkdirs()); assertTrue(dbDir.mkdirs());
@@ -140,6 +148,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertTrue(cacheFile.createNewFile()); assertTrue(cacheFile.createNewFile());
assertTrue(potatoDir.mkdirs()); assertTrue(potatoDir.mkdirs());
assertTrue(potatoFile.createNewFile()); assertTrue(potatoFile.createNewFile());
assertTrue(filesDir.mkdirs());
assertTrue(externalCacheDir.mkdirs());
accountManager.deleteAccount(); accountManager.deleteAccount();
@@ -153,6 +163,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(cacheFile.exists()); assertFalse(cacheFile.exists());
assertFalse(potatoDir.exists()); assertFalse(potatoDir.exists());
assertFalse(potatoFile.exists()); assertFalse(potatoFile.exists());
assertFalse(filesDir.exists());
assertFalse(externalCacheDir.exists());
} }
@After @After

View File

@@ -168,6 +168,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
@Override @Override
public void stopServices() { public void stopServices() {
if (state == STOPPING) return;
try { try {
startStopSemaphore.acquire(); startStopSemaphore.acquire();
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@@ -6,12 +6,16 @@ import android.os.Bundle;
import android.support.v7.preference.PreferenceManager; import android.support.v7.preference.PreferenceManager;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.activity.BriarActivity;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import info.guardianproject.GuardianProjectRSA4096; import info.guardianproject.GuardianProjectRSA4096;
@@ -20,21 +24,27 @@ import info.guardianproject.panic.PanicResponder;
import info.guardianproject.trustedintents.TrustedIntents; import info.guardianproject.trustedintents.TrustedIntents;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK; import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_LOCK;
import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE; import static org.briarproject.briar.android.panic.PanicPreferencesFragment.KEY_PURGE;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class PanicResponderActivity extends BriarActivity { public class PanicResponderActivity extends BriarActivity {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(PanicResponderActivity.class.getName()); Logger.getLogger(PanicResponderActivity.class.getName());
@Inject
protected LifecycleManager lifecycleManager;
@Inject @Inject
protected AccountManager accountManager; protected AccountManager accountManager;
@Inject @Inject
protected AndroidExecutor androidExecutor; protected AndroidExecutor androidExecutor;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
TrustedIntents trustedIntents = TrustedIntents.get(this); TrustedIntents trustedIntents = TrustedIntents.get(this);
@@ -83,14 +93,17 @@ public class PanicResponderActivity extends BriarActivity {
private void deleteAllData() { private void deleteAllData() {
androidExecutor.runOnBackgroundThread(() -> { androidExecutor.runOnBackgroundThread(() -> {
accountManager.deleteAccount(); lifecycleManager.stopServices();
// TODO somehow delete/shred the database more thoroughly try {
PanicResponder.deleteAllAppData(PanicResponderActivity.this); lifecycleManager.waitForShutdown();
} catch (InterruptedException e) {
// nothing left to do after everything is deleted, logException(LOG, WARNING, e);
// so still sign out } finally {
LOG.info("Signing out..."); accountManager.deleteAccount();
signOut(true); // nothing left to do after everything is deleted, so sign out
LOG.info("Signing out...");
signOut(true);
}
}); });
} }
} }